From 92cccad89d1c12b39165d5f0ed7ccd2d44965a1a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 23:41:43 +0200 Subject: Adding upstream version 0.9.2. Signed-off-by: Daniel Baumann --- src/Makefile.am | 638 +++ src/compiler.h | 49 + src/disabled_interface.c | 111 + src/libtpms.syms | 39 + src/test.syms | 9 + src/tpm12/tpm_admin.c | 2010 +++++++ src/tpm12/tpm_admin.h | 141 + src/tpm12/tpm_audit.c | 1271 +++++ src/tpm12/tpm_audit.h | 117 + src/tpm12/tpm_auth.c | 2301 ++++++++ src/tpm12/tpm_auth.h | 180 + src/tpm12/tpm_commands.h | 51 + src/tpm12/tpm_constants.h | 1652 ++++++ src/tpm12/tpm_counter.c | 1565 ++++++ src/tpm12/tpm_counter.h | 140 + src/tpm12/tpm_crypto.c | 3088 +++++++++++ src/tpm12/tpm_crypto.h | 223 + src/tpm12/tpm_crypto_freebl.c | 2652 ++++++++++ src/tpm12/tpm_cryptoh.c | 5427 +++++++++++++++++++ src/tpm12/tpm_cryptoh.h | 362 ++ src/tpm12/tpm_daa.c | 5729 ++++++++++++++++++++ src/tpm12/tpm_daa.h | 405 ++ src/tpm12/tpm_delegate.c | 3944 ++++++++++++++ src/tpm12/tpm_delegate.h | 257 + src/tpm12/tpm_digest.c | 162 + src/tpm12/tpm_digest.h | 64 + src/tpm12/tpm_error.c | 43 + src/tpm12/tpm_global.c | 252 + src/tpm12/tpm_global.h | 103 + src/tpm12/tpm_identity.c | 1448 ++++++ src/tpm12/tpm_identity.h | 138 + src/tpm12/tpm_init.c | 1144 ++++ src/tpm12/tpm_init.h | 136 + src/tpm12/tpm_io.h | 71 + src/tpm12/tpm_key.c | 5529 ++++++++++++++++++++ src/tpm12/tpm_key.h | 457 ++ src/tpm12/tpm_libtpms_io.c | 70 + src/tpm12/tpm_load.c | 309 ++ src/tpm12/tpm_load.h | 80 + src/tpm12/tpm_maint.c | 1304 +++++ src/tpm12/tpm_maint.h | 89 + src/tpm12/tpm_migration.c | 4287 +++++++++++++++ src/tpm12/tpm_migration.h | 218 + src/tpm12/tpm_nonce.c | 157 + src/tpm12/tpm_nonce.h | 60 + src/tpm12/tpm_nvram.c | 3747 ++++++++++++++ src/tpm12/tpm_nvram.h | 201 + src/tpm12/tpm_nvram_const.h | 138 + src/tpm12/tpm_openssl_helpers.c | 135 + src/tpm12/tpm_openssl_helpers.h | 50 + src/tpm12/tpm_owner.c | 1968 +++++++ src/tpm12/tpm_owner.h | 107 + src/tpm12/tpm_pcr.c | 3800 ++++++++++++++ src/tpm12/tpm_pcr.h | 367 ++ src/tpm12/tpm_permanent.c | 1333 +++++ src/tpm12/tpm_permanent.h | 108 + src/tpm12/tpm_platform.c | 175 + src/tpm12/tpm_platform.h | 64 + src/tpm12/tpm_process.c | 6051 ++++++++++++++++++++++ src/tpm12/tpm_process.h | 298 ++ src/tpm12/tpm_secret.c | 166 + src/tpm12/tpm_secret.h | 62 + src/tpm12/tpm_session.c | 5540 ++++++++++++++++++++ src/tpm12/tpm_session.h | 276 + src/tpm12/tpm_sizedbuffer.c | 374 ++ src/tpm12/tpm_sizedbuffer.h | 75 + src/tpm12/tpm_startup.c | 1446 ++++++ src/tpm12/tpm_startup.h | 136 + src/tpm12/tpm_storage.c | 3593 +++++++++++++ src/tpm12/tpm_storage.h | 167 + src/tpm12/tpm_store.c | 598 +++ src/tpm12/tpm_store.h | 111 + src/tpm12/tpm_structures.h | 2630 ++++++++++ src/tpm12/tpm_svnrevision.c | 1 + src/tpm12/tpm_svnrevision.h | 46 + src/tpm12/tpm_ticks.c | 913 ++++ src/tpm12/tpm_ticks.h | 97 + src/tpm12/tpm_time.c | 80 + src/tpm12/tpm_time.h | 49 + src/tpm12/tpm_transport.c | 2935 +++++++++++ src/tpm12/tpm_transport.h | 211 + src/tpm12/tpm_ver.c | 273 + src/tpm12/tpm_ver.h | 76 + src/tpm2/ACT.h | 257 + src/tpm2/ACTCommands.c | 81 + src/tpm2/ACT_SetTimeout_fp.h | 79 + src/tpm2/ACT_spt.c | 317 ++ src/tpm2/ACT_spt_fp.h | 95 + src/tpm2/ActivateCredential_fp.h | 88 + src/tpm2/AlgorithmCap.c | 244 + src/tpm2/AlgorithmCap_fp.h | 78 + src/tpm2/AlgorithmTests.c | 964 ++++ src/tpm2/AlgorithmTests_fp.h | 73 + src/tpm2/AsymmetricCommands.c | 299 ++ src/tpm2/Attest_spt.c | 209 + src/tpm2/Attest_spt_fp.h | 92 + src/tpm2/AttestationCommands.c | 544 ++ src/tpm2/AuditCommands.c | 112 + src/tpm2/BackwardsCompatibility.h | 49 + src/tpm2/BackwardsCompatibilityObject.c | 238 + src/tpm2/BackwardsCompatibilityObject.h | 47 + src/tpm2/BaseTypes.h | 85 + src/tpm2/Bits.c | 114 + src/tpm2/Bits_fp.h | 98 + src/tpm2/BnConvert.c | 299 ++ src/tpm2/BnMath.c | 651 +++ src/tpm2/BnMemory.c | 205 + src/tpm2/Cancel.c | 100 + src/tpm2/Capabilities.h | 76 + src/tpm2/CapabilityCommands.c | 215 + src/tpm2/CertifyCreation_fp.h | 95 + src/tpm2/CertifyX509_fp.h | 93 + src/tpm2/Certify_fp.h | 93 + src/tpm2/ChangeEPS_fp.h | 79 + src/tpm2/ChangePPS_fp.h | 79 + src/tpm2/ClearControl_fp.h | 79 + src/tpm2/Clear_fp.h | 78 + src/tpm2/Clock.c | 346 ++ src/tpm2/ClockCommands.c | 109 + src/tpm2/ClockRateAdjust_fp.h | 81 + src/tpm2/ClockSet_fp.h | 81 + src/tpm2/CommandAttributeData.h | 958 ++++ src/tpm2/CommandAttributes.h | 88 + src/tpm2/CommandAudit.c | 262 + src/tpm2/CommandAudit_fp.h | 97 + src/tpm2/CommandCodeAttributes.c | 559 ++ src/tpm2/CommandCodeAttributes_fp.h | 125 + src/tpm2/CommandDispatchData.h | 4623 +++++++++++++++++ src/tpm2/CommandDispatcher.c | 409 ++ src/tpm2/CommandDispatcher_fp.h | 75 + src/tpm2/Commit_fp.h | 94 + src/tpm2/CompilerDependencies.h | 193 + src/tpm2/ContextCommands.c | 458 ++ src/tpm2/ContextLoad_fp.h | 84 + src/tpm2/ContextSave_fp.h | 84 + src/tpm2/Context_spt.c | 204 + src/tpm2/Context_spt_fp.h | 88 + src/tpm2/CreateLoaded_fp.h | 90 + src/tpm2/CreatePrimary_fp.h | 96 + src/tpm2/Create_fp.h | 96 + src/tpm2/CryptEccData.c | 618 +++ src/tpm2/CryptSelfTest.c | 225 + src/tpm2/CryptSelfTest_fp.h | 87 + src/tpm2/CryptUtil.c | 1739 +++++++ src/tpm2/DA.c | 240 + src/tpm2/DA_fp.h | 87 + src/tpm2/DebugHelpers.c | 160 + src/tpm2/DebugHelpers_fp.h | 83 + src/tpm2/DictionaryAttackLockReset_fp.h | 79 + src/tpm2/DictionaryAttackParameters_fp.h | 86 + src/tpm2/DictionaryCommands.c | 104 + src/tpm2/Duplicate_fp.h | 91 + src/tpm2/DuplicationCommands.c | 352 ++ src/tpm2/EACommands.c | 1164 +++++ src/tpm2/ECC_Parameters_fp.h | 84 + src/tpm2/ECDH_KeyGen_fp.h | 85 + src/tpm2/ECDH_ZGen_fp.h | 86 + src/tpm2/EC_Ephemeral_fp.h | 84 + src/tpm2/EccTestData.h | 155 + src/tpm2/EncryptDecrypt2_fp.h | 93 + src/tpm2/EncryptDecrypt_fp.h | 93 + src/tpm2/EncryptDecrypt_spt.c | 166 + src/tpm2/EncryptDecrypt_spt_fp.h | 75 + src/tpm2/Entity.c | 507 ++ src/tpm2/Entity_fp.h | 90 + src/tpm2/Entropy.c | 184 + src/tpm2/EphemeralCommands.c | 190 + src/tpm2/EventSequenceComplete_fp.h | 88 + src/tpm2/EvictControl_fp.h | 82 + src/tpm2/ExecCommand.c | 317 ++ src/tpm2/ExecCommand_fp.h | 73 + src/tpm2/FlushContext_fp.h | 78 + src/tpm2/GetCapability_fp.h | 90 + src/tpm2/GetCommandAuditDigest_fp.h | 91 + src/tpm2/GetRandom_fp.h | 84 + src/tpm2/GetSessionAuditDigest_fp.h | 93 + src/tpm2/GetTestResult_fp.h | 79 + src/tpm2/GetTime_fp.h | 91 + src/tpm2/Global.c | 83 + src/tpm2/Global.h | 1350 +++++ src/tpm2/GpMacros.h | 354 ++ src/tpm2/HMAC_Start_fp.h | 88 + src/tpm2/HMAC_fp.h | 88 + src/tpm2/Handle.c | 213 + src/tpm2/Handle_fp.h | 87 + src/tpm2/HashCommands.c | 381 ++ src/tpm2/HashSequenceStart_fp.h | 88 + src/tpm2/HashTestData.h | 210 + src/tpm2/Hash_fp.h | 89 + src/tpm2/Hierarchy.c | 273 + src/tpm2/HierarchyChangeAuth_fp.h | 80 + src/tpm2/HierarchyCommands.c | 514 ++ src/tpm2/HierarchyControl_fp.h | 83 + src/tpm2/Hierarchy_fp.h | 93 + src/tpm2/Import_fp.h | 93 + src/tpm2/IncrementalSelfTest_fp.h | 84 + src/tpm2/IntegrityCommands.c | 411 ++ src/tpm2/InternalRoutines.h | 146 + src/tpm2/IoBuffers.c | 145 + src/tpm2/IoBuffers_fp.h | 87 + src/tpm2/KdfTestData.h | 100 + src/tpm2/LibtpmsCallbacks.c | 178 + src/tpm2/LibtpmsCallbacks.h | 50 + src/tpm2/LoadExternal_fp.h | 87 + src/tpm2/Load_fp.h | 88 + src/tpm2/Locality.c | 99 + src/tpm2/LocalityPlat.c | 87 + src/tpm2/Locality_fp.h | 71 + src/tpm2/MAC_Start_fp.h | 88 + src/tpm2/MAC_fp.h | 88 + src/tpm2/MakeCredential_fp.h | 89 + src/tpm2/ManagementCommands.c | 113 + src/tpm2/Manufacture.c | 206 + src/tpm2/Manufacture_fp.h | 81 + src/tpm2/Marshal.c | 2313 +++++++++ src/tpm2/Marshal_fp.h | 400 ++ src/tpm2/MathOnByteBuffers.c | 266 + src/tpm2/MathOnByteBuffers_fp.h | 110 + src/tpm2/Memory.c | 287 + src/tpm2/Memory_fp.h | 139 + src/tpm2/MinMax.h | 73 + src/tpm2/NV.h | 162 + src/tpm2/NVCommands.c | 707 +++ src/tpm2/NVDynamic.c | 1679 ++++++ src/tpm2/NVDynamic_fp.h | 253 + src/tpm2/NVMarshal.c | 4916 ++++++++++++++++++ src/tpm2/NVMarshal.h | 61 + src/tpm2/NVMem.c | 494 ++ src/tpm2/NVReserved.c | 230 + src/tpm2/NVReserved_fp.h | 113 + src/tpm2/NV_Certify_fp.h | 98 + src/tpm2/NV_ChangeAuth_fp.h | 81 + src/tpm2/NV_DefineSpace_fp.h | 83 + src/tpm2/NV_Extend_fp.h | 83 + src/tpm2/NV_GlobalWriteLock_fp.h | 79 + src/tpm2/NV_Increment_fp.h | 81 + src/tpm2/NV_ReadLock_fp.h | 81 + src/tpm2/NV_ReadPublic_fp.h | 85 + src/tpm2/NV_Read_fp.h | 89 + src/tpm2/NV_SetBits_fp.h | 83 + src/tpm2/NV_UndefineSpaceSpecial_fp.h | 81 + src/tpm2/NV_UndefineSpace_fp.h | 81 + src/tpm2/NV_WriteLock_fp.h | 81 + src/tpm2/NV_Write_fp.h | 85 + src/tpm2/NV_spt.c | 179 + src/tpm2/NV_spt_fp.h | 87 + src/tpm2/OIDs.h | 280 + src/tpm2/Object.c | 970 ++++ src/tpm2/ObjectChangeAuth_fp.h | 89 + src/tpm2/ObjectCommands.c | 549 ++ src/tpm2/Object_fp.h | 236 + src/tpm2/Object_spt.c | 1419 +++++ src/tpm2/Object_spt_fp.h | 250 + src/tpm2/PCR.c | 1185 +++++ src/tpm2/PCR_Allocate_fp.h | 89 + src/tpm2/PCR_Event_fp.h | 85 + src/tpm2/PCR_Extend_fp.h | 81 + src/tpm2/PCR_Read_fp.h | 85 + src/tpm2/PCR_Reset_fp.h | 78 + src/tpm2/PCR_SetAuthPolicy_fp.h | 85 + src/tpm2/PCR_SetAuthValue_fp.h | 81 + src/tpm2/PCR_fp.h | 197 + src/tpm2/PP.c | 182 + src/tpm2/PPPlat.c | 112 + src/tpm2/PP_Commands_fp.h | 80 + src/tpm2/PP_fp.h | 89 + src/tpm2/PRNG_TestVectors.h | 110 + src/tpm2/Platform.h | 75 + src/tpm2/PlatformACT.c | 353 ++ src/tpm2/PlatformACT.h | 210 + src/tpm2/PlatformACT_fp.h | 104 + src/tpm2/PlatformClock.h | 89 + src/tpm2/PlatformData.c | 70 + src/tpm2/PlatformData.h | 142 + src/tpm2/Platform_fp.h | 407 ++ src/tpm2/PolicyAuthValue_fp.h | 79 + src/tpm2/PolicyAuthorizeNV_fp.h | 82 + src/tpm2/PolicyAuthorize_fp.h | 86 + src/tpm2/PolicyCommandCode_fp.h | 80 + src/tpm2/PolicyCounterTimer_fp.h | 85 + src/tpm2/PolicyCpHash_fp.h | 81 + src/tpm2/PolicyDuplicationSelect_fp.h | 85 + src/tpm2/PolicyGetDigest_fp.h | 84 + src/tpm2/PolicyLocality_fp.h | 81 + src/tpm2/PolicyNV_fp.h | 88 + src/tpm2/PolicyNameHash_fp.h | 81 + src/tpm2/PolicyNvWritten_fp.h | 81 + src/tpm2/PolicyOR_fp.h | 81 + src/tpm2/PolicyPCR_fp.h | 82 + src/tpm2/PolicyPassword_fp.h | 79 + src/tpm2/PolicyPhysicalPresence_fp.h | 78 + src/tpm2/PolicyRestart_fp.h | 79 + src/tpm2/PolicySecret_fp.h | 95 + src/tpm2/PolicySigned_fp.h | 96 + src/tpm2/PolicyTemplate_fp.h | 81 + src/tpm2/PolicyTicket_fp.h | 89 + src/tpm2/Policy_spt.c | 300 ++ src/tpm2/Policy_spt_fp.h | 110 + src/tpm2/Power.c | 109 + src/tpm2/PowerPlat.c | 128 + src/tpm2/Power_fp.h | 79 + src/tpm2/PrimeData.c | 441 ++ src/tpm2/PropertyCap.c | 610 +++ src/tpm2/PropertyCap_fp.h | 74 + src/tpm2/Quote_fp.h | 91 + src/tpm2/RSA_Decrypt_fp.h | 90 + src/tpm2/RSA_Encrypt_fp.h | 89 + src/tpm2/RandomCommands.c | 94 + src/tpm2/ReadClock_fp.h | 77 + src/tpm2/ReadPublic_fp.h | 84 + src/tpm2/Response.c | 105 + src/tpm2/ResponseCodeProcessing.c | 81 + src/tpm2/ResponseCodeProcessing_fp.h | 71 + src/tpm2/Response_fp.h | 73 + src/tpm2/Rewrap_fp.h | 92 + src/tpm2/RsaTestData.h | 425 ++ src/tpm2/RunCommand.c | 105 + src/tpm2/SelfTest.h | 130 + src/tpm2/SelfTest_fp.h | 78 + src/tpm2/SequenceComplete_fp.h | 92 + src/tpm2/SequenceUpdate_fp.h | 82 + src/tpm2/Session.c | 835 +++ src/tpm2/SessionCommands.c | 175 + src/tpm2/SessionProcess.c | 1990 +++++++ src/tpm2/SessionProcess_fp.h | 97 + src/tpm2/Session_fp.h | 158 + src/tpm2/SetAlgorithmSet_fp.h | 81 + src/tpm2/SetCommandCodeAuditStatus_fp.h | 84 + src/tpm2/SetPrimaryPolicy_fp.h | 80 + src/tpm2/Shutdown_fp.h | 79 + src/tpm2/Sign_fp.h | 89 + src/tpm2/SigningCommands.c | 156 + src/tpm2/Simulator_fp.h | 212 + src/tpm2/StartAuthSession_fp.h | 97 + src/tpm2/StartupCommands.c | 349 ++ src/tpm2/Startup_fp.h | 84 + src/tpm2/StateMarshal.c | 98 + src/tpm2/StateMarshal.h | 53 + src/tpm2/StirRandom_fp.h | 78 + src/tpm2/SupportLibraryFunctionPrototypes_fp.h | 156 + src/tpm2/SymmetricCommands.c | 350 ++ src/tpm2/SymmetricTest.h | 138 + src/tpm2/SymmetricTestData.h | 400 ++ src/tpm2/TPMB.h | 97 + src/tpm2/TPMCmdp.c | 364 ++ src/tpm2/TcpServerPosix_fp.h | 131 + src/tpm2/TestParms_fp.h | 79 + src/tpm2/TestingCommands.c | 108 + src/tpm2/Ticket.c | 236 + src/tpm2/Ticket_fp.h | 104 + src/tpm2/Time.c | 273 + src/tpm2/Time_fp.h | 99 + src/tpm2/Tpm.h | 81 + src/tpm2/TpmAlgorithmDefines.h | 405 ++ src/tpm2/TpmAsn1.c | 508 ++ src/tpm2/TpmAsn1.h | 137 + src/tpm2/TpmAsn1_fp.h | 152 + src/tpm2/TpmBuildSwitches.h | 364 ++ src/tpm2/TpmError.h | 84 + src/tpm2/TpmFail.c | 527 ++ src/tpm2/TpmFail_fp.h | 114 + src/tpm2/TpmProfile.h | 865 ++++ src/tpm2/TpmSizeChecks.c | 229 + src/tpm2/TpmSizeChecks_fp.h | 67 + src/tpm2/TpmTcpProtocol.h | 140 + src/tpm2/TpmTypes.h | 2473 +++++++++ src/tpm2/Unique.c | 109 + src/tpm2/Unmarshal.c | 4532 ++++++++++++++++ src/tpm2/Unmarshal_fp.h | 477 ++ src/tpm2/Unseal_fp.h | 83 + src/tpm2/Utils.h | 54 + src/tpm2/VendorString.h | 108 + src/tpm2/Vendor_TCG_Test.c | 76 + src/tpm2/Vendor_TCG_Test_fp.h | 79 + src/tpm2/VerifySignature_fp.h | 88 + src/tpm2/Volatile.c | 119 + src/tpm2/Volatile.h | 47 + src/tpm2/X509.h | 142 + src/tpm2/X509_ECC.c | 173 + src/tpm2/X509_ECC_fp.h | 83 + src/tpm2/X509_RSA.c | 249 + src/tpm2/X509_RSA_fp.h | 78 + src/tpm2/X509_spt.c | 318 ++ src/tpm2/X509_spt_fp.h | 98 + src/tpm2/ZGen_2Phase_fp.h | 93 + src/tpm2/_TPM_Hash_Data_fp.h | 72 + src/tpm2/_TPM_Hash_End_fp.h | 71 + src/tpm2/_TPM_Hash_Start_fp.h | 71 + src/tpm2/_TPM_Init_fp.h | 73 + src/tpm2/crypto/CryptCmac_fp.h | 86 + src/tpm2/crypto/CryptDes_fp.h | 82 + src/tpm2/crypto/CryptEcc.h | 103 + src/tpm2/crypto/CryptEccCrypt_fp.h | 67 + src/tpm2/crypto/CryptEccKeyExchange_fp.h | 78 + src/tpm2/crypto/CryptEccMain_fp.h | 232 + src/tpm2/crypto/CryptEccSignature_fp.h | 111 + src/tpm2/crypto/CryptHash.h | 343 ++ src/tpm2/crypto/CryptHash_fp.h | 219 + src/tpm2/crypto/CryptPrimeSieve_fp.h | 101 + src/tpm2/crypto/CryptPrime_fp.h | 104 + src/tpm2/crypto/CryptRand.h | 193 + src/tpm2/crypto/CryptRand_fp.h | 158 + src/tpm2/crypto/CryptRsa.h | 99 + src/tpm2/crypto/CryptRsa_fp.h | 139 + src/tpm2/crypto/CryptSelfTest_fp.h | 87 + src/tpm2/crypto/CryptSmac_fp.h | 98 + src/tpm2/crypto/CryptSym.h | 142 + src/tpm2/crypto/CryptSym_fp.h | 111 + src/tpm2/crypto/CryptTest.h | 93 + src/tpm2/crypto/CryptUtil_fp.h | 232 + src/tpm2/crypto/openssl/BnConvert_fp.h | 108 + src/tpm2/crypto/openssl/BnMath_fp.h | 163 + src/tpm2/crypto/openssl/BnMemory_fp.h | 108 + src/tpm2/crypto/openssl/BnValues.h | 329 ++ src/tpm2/crypto/openssl/ConsttimeUtils.h | 117 + src/tpm2/crypto/openssl/CryptCmac.c | 210 + src/tpm2/crypto/openssl/CryptDes.c | 189 + src/tpm2/crypto/openssl/CryptEccKeyExchange.c | 373 ++ src/tpm2/crypto/openssl/CryptEccMain.c | 866 ++++ src/tpm2/crypto/openssl/CryptEccSignature.c | 1043 ++++ src/tpm2/crypto/openssl/CryptHash.c | 871 ++++ src/tpm2/crypto/openssl/CryptPrime.c | 440 ++ src/tpm2/crypto/openssl/CryptPrimeSieve.c | 554 ++ src/tpm2/crypto/openssl/CryptRand.c | 881 ++++ src/tpm2/crypto/openssl/CryptRsa.c | 1634 ++++++ src/tpm2/crypto/openssl/CryptSmac.c | 156 + src/tpm2/crypto/openssl/CryptSym.c | 771 +++ src/tpm2/crypto/openssl/ExpDCache.c | 200 + src/tpm2/crypto/openssl/ExpDCache_fp.h | 75 + src/tpm2/crypto/openssl/Helpers.c | 625 +++ src/tpm2/crypto/openssl/Helpers_fp.h | 117 + src/tpm2/crypto/openssl/LibSupport.h | 98 + src/tpm2/crypto/openssl/TpmToOsslDesSupport.c | 119 + src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h | 83 + src/tpm2/crypto/openssl/TpmToOsslHash.h | 219 + src/tpm2/crypto/openssl/TpmToOsslMath.c | 736 +++ src/tpm2/crypto/openssl/TpmToOsslMath.h | 164 + src/tpm2/crypto/openssl/TpmToOsslMath_fp.h | 152 + src/tpm2/crypto/openssl/TpmToOsslSupport.c | 129 + src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h | 83 + src/tpm2/crypto/openssl/TpmToOsslSym.h | 197 + src/tpm2/crypto/openssl/consttime.txt | 76 + src/tpm2/crypto/openssl/consttime.txt' | 58 + src/tpm2/gensymtestsdata.sh | 195 + src/tpm2/swap.h | 120 + src/tpm_debug.c | 134 + src/tpm_debug.h | 71 + src/tpm_library.c | 677 +++ src/tpm_library_conf.h | 172 + src/tpm_library_intern.h | 149 + src/tpm_memory.c | 130 + src/tpm_nvfile.c | 418 ++ src/tpm_nvfile.h | 71 + src/tpm_tpm12_interface.c | 530 ++ src/tpm_tpm12_tis.c | 280 + src/tpm_tpm2_interface.c | 690 +++ src/tpm_tpm2_tis.c | 108 + 457 files changed, 183343 insertions(+) create mode 100644 src/Makefile.am create mode 100644 src/compiler.h create mode 100644 src/disabled_interface.c create mode 100644 src/libtpms.syms create mode 100644 src/test.syms create mode 100644 src/tpm12/tpm_admin.c create mode 100644 src/tpm12/tpm_admin.h create mode 100644 src/tpm12/tpm_audit.c create mode 100644 src/tpm12/tpm_audit.h create mode 100644 src/tpm12/tpm_auth.c create mode 100644 src/tpm12/tpm_auth.h create mode 100644 src/tpm12/tpm_commands.h create mode 100644 src/tpm12/tpm_constants.h create mode 100644 src/tpm12/tpm_counter.c create mode 100644 src/tpm12/tpm_counter.h create mode 100644 src/tpm12/tpm_crypto.c create mode 100644 src/tpm12/tpm_crypto.h create mode 100644 src/tpm12/tpm_crypto_freebl.c create mode 100644 src/tpm12/tpm_cryptoh.c create mode 100644 src/tpm12/tpm_cryptoh.h create mode 100644 src/tpm12/tpm_daa.c create mode 100644 src/tpm12/tpm_daa.h create mode 100644 src/tpm12/tpm_delegate.c create mode 100644 src/tpm12/tpm_delegate.h create mode 100644 src/tpm12/tpm_digest.c create mode 100644 src/tpm12/tpm_digest.h create mode 100644 src/tpm12/tpm_error.c create mode 100644 src/tpm12/tpm_global.c create mode 100644 src/tpm12/tpm_global.h create mode 100644 src/tpm12/tpm_identity.c create mode 100644 src/tpm12/tpm_identity.h create mode 100644 src/tpm12/tpm_init.c create mode 100644 src/tpm12/tpm_init.h create mode 100644 src/tpm12/tpm_io.h create mode 100644 src/tpm12/tpm_key.c create mode 100644 src/tpm12/tpm_key.h create mode 100644 src/tpm12/tpm_libtpms_io.c create mode 100644 src/tpm12/tpm_load.c create mode 100644 src/tpm12/tpm_load.h create mode 100644 src/tpm12/tpm_maint.c create mode 100644 src/tpm12/tpm_maint.h create mode 100644 src/tpm12/tpm_migration.c create mode 100644 src/tpm12/tpm_migration.h create mode 100644 src/tpm12/tpm_nonce.c create mode 100644 src/tpm12/tpm_nonce.h create mode 100644 src/tpm12/tpm_nvram.c create mode 100644 src/tpm12/tpm_nvram.h create mode 100644 src/tpm12/tpm_nvram_const.h create mode 100644 src/tpm12/tpm_openssl_helpers.c create mode 100644 src/tpm12/tpm_openssl_helpers.h create mode 100644 src/tpm12/tpm_owner.c create mode 100644 src/tpm12/tpm_owner.h create mode 100644 src/tpm12/tpm_pcr.c create mode 100644 src/tpm12/tpm_pcr.h create mode 100644 src/tpm12/tpm_permanent.c create mode 100644 src/tpm12/tpm_permanent.h create mode 100644 src/tpm12/tpm_platform.c create mode 100644 src/tpm12/tpm_platform.h create mode 100644 src/tpm12/tpm_process.c create mode 100644 src/tpm12/tpm_process.h create mode 100644 src/tpm12/tpm_secret.c create mode 100644 src/tpm12/tpm_secret.h create mode 100644 src/tpm12/tpm_session.c create mode 100644 src/tpm12/tpm_session.h create mode 100644 src/tpm12/tpm_sizedbuffer.c create mode 100644 src/tpm12/tpm_sizedbuffer.h create mode 100644 src/tpm12/tpm_startup.c create mode 100644 src/tpm12/tpm_startup.h create mode 100644 src/tpm12/tpm_storage.c create mode 100644 src/tpm12/tpm_storage.h create mode 100644 src/tpm12/tpm_store.c create mode 100644 src/tpm12/tpm_store.h create mode 100644 src/tpm12/tpm_structures.h create mode 100644 src/tpm12/tpm_svnrevision.c create mode 100644 src/tpm12/tpm_svnrevision.h create mode 100644 src/tpm12/tpm_ticks.c create mode 100644 src/tpm12/tpm_ticks.h create mode 100644 src/tpm12/tpm_time.c create mode 100644 src/tpm12/tpm_time.h create mode 100644 src/tpm12/tpm_transport.c create mode 100644 src/tpm12/tpm_transport.h create mode 100644 src/tpm12/tpm_ver.c create mode 100644 src/tpm12/tpm_ver.h create mode 100644 src/tpm2/ACT.h create mode 100644 src/tpm2/ACTCommands.c create mode 100644 src/tpm2/ACT_SetTimeout_fp.h create mode 100644 src/tpm2/ACT_spt.c create mode 100644 src/tpm2/ACT_spt_fp.h create mode 100644 src/tpm2/ActivateCredential_fp.h create mode 100644 src/tpm2/AlgorithmCap.c create mode 100644 src/tpm2/AlgorithmCap_fp.h create mode 100644 src/tpm2/AlgorithmTests.c create mode 100644 src/tpm2/AlgorithmTests_fp.h create mode 100644 src/tpm2/AsymmetricCommands.c create mode 100644 src/tpm2/Attest_spt.c create mode 100644 src/tpm2/Attest_spt_fp.h create mode 100644 src/tpm2/AttestationCommands.c create mode 100644 src/tpm2/AuditCommands.c create mode 100644 src/tpm2/BackwardsCompatibility.h create mode 100644 src/tpm2/BackwardsCompatibilityObject.c create mode 100644 src/tpm2/BackwardsCompatibilityObject.h create mode 100644 src/tpm2/BaseTypes.h create mode 100644 src/tpm2/Bits.c create mode 100644 src/tpm2/Bits_fp.h create mode 100644 src/tpm2/BnConvert.c create mode 100644 src/tpm2/BnMath.c create mode 100644 src/tpm2/BnMemory.c create mode 100644 src/tpm2/Cancel.c create mode 100644 src/tpm2/Capabilities.h create mode 100644 src/tpm2/CapabilityCommands.c create mode 100644 src/tpm2/CertifyCreation_fp.h create mode 100644 src/tpm2/CertifyX509_fp.h create mode 100644 src/tpm2/Certify_fp.h create mode 100644 src/tpm2/ChangeEPS_fp.h create mode 100644 src/tpm2/ChangePPS_fp.h create mode 100644 src/tpm2/ClearControl_fp.h create mode 100644 src/tpm2/Clear_fp.h create mode 100644 src/tpm2/Clock.c create mode 100644 src/tpm2/ClockCommands.c create mode 100644 src/tpm2/ClockRateAdjust_fp.h create mode 100644 src/tpm2/ClockSet_fp.h create mode 100644 src/tpm2/CommandAttributeData.h create mode 100644 src/tpm2/CommandAttributes.h create mode 100644 src/tpm2/CommandAudit.c create mode 100644 src/tpm2/CommandAudit_fp.h create mode 100644 src/tpm2/CommandCodeAttributes.c create mode 100644 src/tpm2/CommandCodeAttributes_fp.h create mode 100644 src/tpm2/CommandDispatchData.h create mode 100644 src/tpm2/CommandDispatcher.c create mode 100644 src/tpm2/CommandDispatcher_fp.h create mode 100644 src/tpm2/Commit_fp.h create mode 100644 src/tpm2/CompilerDependencies.h create mode 100644 src/tpm2/ContextCommands.c create mode 100644 src/tpm2/ContextLoad_fp.h create mode 100644 src/tpm2/ContextSave_fp.h create mode 100644 src/tpm2/Context_spt.c create mode 100644 src/tpm2/Context_spt_fp.h create mode 100644 src/tpm2/CreateLoaded_fp.h create mode 100644 src/tpm2/CreatePrimary_fp.h create mode 100644 src/tpm2/Create_fp.h create mode 100644 src/tpm2/CryptEccData.c create mode 100644 src/tpm2/CryptSelfTest.c create mode 100644 src/tpm2/CryptSelfTest_fp.h create mode 100644 src/tpm2/CryptUtil.c create mode 100644 src/tpm2/DA.c create mode 100644 src/tpm2/DA_fp.h create mode 100644 src/tpm2/DebugHelpers.c create mode 100644 src/tpm2/DebugHelpers_fp.h create mode 100644 src/tpm2/DictionaryAttackLockReset_fp.h create mode 100644 src/tpm2/DictionaryAttackParameters_fp.h create mode 100644 src/tpm2/DictionaryCommands.c create mode 100644 src/tpm2/Duplicate_fp.h create mode 100644 src/tpm2/DuplicationCommands.c create mode 100644 src/tpm2/EACommands.c create mode 100644 src/tpm2/ECC_Parameters_fp.h create mode 100644 src/tpm2/ECDH_KeyGen_fp.h create mode 100644 src/tpm2/ECDH_ZGen_fp.h create mode 100644 src/tpm2/EC_Ephemeral_fp.h create mode 100644 src/tpm2/EccTestData.h create mode 100644 src/tpm2/EncryptDecrypt2_fp.h create mode 100644 src/tpm2/EncryptDecrypt_fp.h create mode 100644 src/tpm2/EncryptDecrypt_spt.c create mode 100644 src/tpm2/EncryptDecrypt_spt_fp.h create mode 100644 src/tpm2/Entity.c create mode 100644 src/tpm2/Entity_fp.h create mode 100644 src/tpm2/Entropy.c create mode 100644 src/tpm2/EphemeralCommands.c create mode 100644 src/tpm2/EventSequenceComplete_fp.h create mode 100644 src/tpm2/EvictControl_fp.h create mode 100644 src/tpm2/ExecCommand.c create mode 100644 src/tpm2/ExecCommand_fp.h create mode 100644 src/tpm2/FlushContext_fp.h create mode 100644 src/tpm2/GetCapability_fp.h create mode 100644 src/tpm2/GetCommandAuditDigest_fp.h create mode 100644 src/tpm2/GetRandom_fp.h create mode 100644 src/tpm2/GetSessionAuditDigest_fp.h create mode 100644 src/tpm2/GetTestResult_fp.h create mode 100644 src/tpm2/GetTime_fp.h create mode 100644 src/tpm2/Global.c create mode 100644 src/tpm2/Global.h create mode 100644 src/tpm2/GpMacros.h create mode 100644 src/tpm2/HMAC_Start_fp.h create mode 100644 src/tpm2/HMAC_fp.h create mode 100644 src/tpm2/Handle.c create mode 100644 src/tpm2/Handle_fp.h create mode 100644 src/tpm2/HashCommands.c create mode 100644 src/tpm2/HashSequenceStart_fp.h create mode 100644 src/tpm2/HashTestData.h create mode 100644 src/tpm2/Hash_fp.h create mode 100644 src/tpm2/Hierarchy.c create mode 100644 src/tpm2/HierarchyChangeAuth_fp.h create mode 100644 src/tpm2/HierarchyCommands.c create mode 100644 src/tpm2/HierarchyControl_fp.h create mode 100644 src/tpm2/Hierarchy_fp.h create mode 100644 src/tpm2/Import_fp.h create mode 100644 src/tpm2/IncrementalSelfTest_fp.h create mode 100644 src/tpm2/IntegrityCommands.c create mode 100644 src/tpm2/InternalRoutines.h create mode 100644 src/tpm2/IoBuffers.c create mode 100644 src/tpm2/IoBuffers_fp.h create mode 100644 src/tpm2/KdfTestData.h create mode 100644 src/tpm2/LibtpmsCallbacks.c create mode 100644 src/tpm2/LibtpmsCallbacks.h create mode 100644 src/tpm2/LoadExternal_fp.h create mode 100644 src/tpm2/Load_fp.h create mode 100644 src/tpm2/Locality.c create mode 100644 src/tpm2/LocalityPlat.c create mode 100644 src/tpm2/Locality_fp.h create mode 100644 src/tpm2/MAC_Start_fp.h create mode 100644 src/tpm2/MAC_fp.h create mode 100644 src/tpm2/MakeCredential_fp.h create mode 100644 src/tpm2/ManagementCommands.c create mode 100644 src/tpm2/Manufacture.c create mode 100644 src/tpm2/Manufacture_fp.h create mode 100644 src/tpm2/Marshal.c create mode 100644 src/tpm2/Marshal_fp.h create mode 100644 src/tpm2/MathOnByteBuffers.c create mode 100644 src/tpm2/MathOnByteBuffers_fp.h create mode 100644 src/tpm2/Memory.c create mode 100644 src/tpm2/Memory_fp.h create mode 100644 src/tpm2/MinMax.h create mode 100644 src/tpm2/NV.h create mode 100644 src/tpm2/NVCommands.c create mode 100644 src/tpm2/NVDynamic.c create mode 100644 src/tpm2/NVDynamic_fp.h create mode 100644 src/tpm2/NVMarshal.c create mode 100644 src/tpm2/NVMarshal.h create mode 100644 src/tpm2/NVMem.c create mode 100644 src/tpm2/NVReserved.c create mode 100644 src/tpm2/NVReserved_fp.h create mode 100644 src/tpm2/NV_Certify_fp.h create mode 100644 src/tpm2/NV_ChangeAuth_fp.h create mode 100644 src/tpm2/NV_DefineSpace_fp.h create mode 100644 src/tpm2/NV_Extend_fp.h create mode 100644 src/tpm2/NV_GlobalWriteLock_fp.h create mode 100644 src/tpm2/NV_Increment_fp.h create mode 100644 src/tpm2/NV_ReadLock_fp.h create mode 100644 src/tpm2/NV_ReadPublic_fp.h create mode 100644 src/tpm2/NV_Read_fp.h create mode 100644 src/tpm2/NV_SetBits_fp.h create mode 100644 src/tpm2/NV_UndefineSpaceSpecial_fp.h create mode 100644 src/tpm2/NV_UndefineSpace_fp.h create mode 100644 src/tpm2/NV_WriteLock_fp.h create mode 100644 src/tpm2/NV_Write_fp.h create mode 100644 src/tpm2/NV_spt.c create mode 100644 src/tpm2/NV_spt_fp.h create mode 100644 src/tpm2/OIDs.h create mode 100644 src/tpm2/Object.c create mode 100644 src/tpm2/ObjectChangeAuth_fp.h create mode 100644 src/tpm2/ObjectCommands.c create mode 100644 src/tpm2/Object_fp.h create mode 100644 src/tpm2/Object_spt.c create mode 100644 src/tpm2/Object_spt_fp.h create mode 100644 src/tpm2/PCR.c create mode 100644 src/tpm2/PCR_Allocate_fp.h create mode 100644 src/tpm2/PCR_Event_fp.h create mode 100644 src/tpm2/PCR_Extend_fp.h create mode 100644 src/tpm2/PCR_Read_fp.h create mode 100644 src/tpm2/PCR_Reset_fp.h create mode 100644 src/tpm2/PCR_SetAuthPolicy_fp.h create mode 100644 src/tpm2/PCR_SetAuthValue_fp.h create mode 100644 src/tpm2/PCR_fp.h create mode 100644 src/tpm2/PP.c create mode 100644 src/tpm2/PPPlat.c create mode 100644 src/tpm2/PP_Commands_fp.h create mode 100644 src/tpm2/PP_fp.h create mode 100644 src/tpm2/PRNG_TestVectors.h create mode 100644 src/tpm2/Platform.h create mode 100644 src/tpm2/PlatformACT.c create mode 100644 src/tpm2/PlatformACT.h create mode 100644 src/tpm2/PlatformACT_fp.h create mode 100644 src/tpm2/PlatformClock.h create mode 100644 src/tpm2/PlatformData.c create mode 100644 src/tpm2/PlatformData.h create mode 100644 src/tpm2/Platform_fp.h create mode 100644 src/tpm2/PolicyAuthValue_fp.h create mode 100644 src/tpm2/PolicyAuthorizeNV_fp.h create mode 100644 src/tpm2/PolicyAuthorize_fp.h create mode 100644 src/tpm2/PolicyCommandCode_fp.h create mode 100644 src/tpm2/PolicyCounterTimer_fp.h create mode 100644 src/tpm2/PolicyCpHash_fp.h create mode 100644 src/tpm2/PolicyDuplicationSelect_fp.h create mode 100644 src/tpm2/PolicyGetDigest_fp.h create mode 100644 src/tpm2/PolicyLocality_fp.h create mode 100644 src/tpm2/PolicyNV_fp.h create mode 100644 src/tpm2/PolicyNameHash_fp.h create mode 100644 src/tpm2/PolicyNvWritten_fp.h create mode 100644 src/tpm2/PolicyOR_fp.h create mode 100644 src/tpm2/PolicyPCR_fp.h create mode 100644 src/tpm2/PolicyPassword_fp.h create mode 100644 src/tpm2/PolicyPhysicalPresence_fp.h create mode 100644 src/tpm2/PolicyRestart_fp.h create mode 100644 src/tpm2/PolicySecret_fp.h create mode 100644 src/tpm2/PolicySigned_fp.h create mode 100644 src/tpm2/PolicyTemplate_fp.h create mode 100644 src/tpm2/PolicyTicket_fp.h create mode 100644 src/tpm2/Policy_spt.c create mode 100644 src/tpm2/Policy_spt_fp.h create mode 100644 src/tpm2/Power.c create mode 100644 src/tpm2/PowerPlat.c create mode 100644 src/tpm2/Power_fp.h create mode 100644 src/tpm2/PrimeData.c create mode 100644 src/tpm2/PropertyCap.c create mode 100644 src/tpm2/PropertyCap_fp.h create mode 100644 src/tpm2/Quote_fp.h create mode 100644 src/tpm2/RSA_Decrypt_fp.h create mode 100644 src/tpm2/RSA_Encrypt_fp.h create mode 100644 src/tpm2/RandomCommands.c create mode 100644 src/tpm2/ReadClock_fp.h create mode 100644 src/tpm2/ReadPublic_fp.h create mode 100644 src/tpm2/Response.c create mode 100644 src/tpm2/ResponseCodeProcessing.c create mode 100644 src/tpm2/ResponseCodeProcessing_fp.h create mode 100644 src/tpm2/Response_fp.h create mode 100644 src/tpm2/Rewrap_fp.h create mode 100644 src/tpm2/RsaTestData.h create mode 100644 src/tpm2/RunCommand.c create mode 100644 src/tpm2/SelfTest.h create mode 100644 src/tpm2/SelfTest_fp.h create mode 100644 src/tpm2/SequenceComplete_fp.h create mode 100644 src/tpm2/SequenceUpdate_fp.h create mode 100644 src/tpm2/Session.c create mode 100644 src/tpm2/SessionCommands.c create mode 100644 src/tpm2/SessionProcess.c create mode 100644 src/tpm2/SessionProcess_fp.h create mode 100644 src/tpm2/Session_fp.h create mode 100644 src/tpm2/SetAlgorithmSet_fp.h create mode 100644 src/tpm2/SetCommandCodeAuditStatus_fp.h create mode 100644 src/tpm2/SetPrimaryPolicy_fp.h create mode 100644 src/tpm2/Shutdown_fp.h create mode 100644 src/tpm2/Sign_fp.h create mode 100644 src/tpm2/SigningCommands.c create mode 100644 src/tpm2/Simulator_fp.h create mode 100644 src/tpm2/StartAuthSession_fp.h create mode 100644 src/tpm2/StartupCommands.c create mode 100644 src/tpm2/Startup_fp.h create mode 100644 src/tpm2/StateMarshal.c create mode 100644 src/tpm2/StateMarshal.h create mode 100644 src/tpm2/StirRandom_fp.h create mode 100644 src/tpm2/SupportLibraryFunctionPrototypes_fp.h create mode 100644 src/tpm2/SymmetricCommands.c create mode 100644 src/tpm2/SymmetricTest.h create mode 100644 src/tpm2/SymmetricTestData.h create mode 100644 src/tpm2/TPMB.h create mode 100644 src/tpm2/TPMCmdp.c create mode 100644 src/tpm2/TcpServerPosix_fp.h create mode 100644 src/tpm2/TestParms_fp.h create mode 100644 src/tpm2/TestingCommands.c create mode 100644 src/tpm2/Ticket.c create mode 100644 src/tpm2/Ticket_fp.h create mode 100644 src/tpm2/Time.c create mode 100644 src/tpm2/Time_fp.h create mode 100644 src/tpm2/Tpm.h create mode 100644 src/tpm2/TpmAlgorithmDefines.h create mode 100644 src/tpm2/TpmAsn1.c create mode 100644 src/tpm2/TpmAsn1.h create mode 100644 src/tpm2/TpmAsn1_fp.h create mode 100644 src/tpm2/TpmBuildSwitches.h create mode 100644 src/tpm2/TpmError.h create mode 100644 src/tpm2/TpmFail.c create mode 100644 src/tpm2/TpmFail_fp.h create mode 100644 src/tpm2/TpmProfile.h create mode 100644 src/tpm2/TpmSizeChecks.c create mode 100644 src/tpm2/TpmSizeChecks_fp.h create mode 100644 src/tpm2/TpmTcpProtocol.h create mode 100644 src/tpm2/TpmTypes.h create mode 100644 src/tpm2/Unique.c create mode 100644 src/tpm2/Unmarshal.c create mode 100644 src/tpm2/Unmarshal_fp.h create mode 100644 src/tpm2/Unseal_fp.h create mode 100644 src/tpm2/Utils.h create mode 100644 src/tpm2/VendorString.h create mode 100644 src/tpm2/Vendor_TCG_Test.c create mode 100644 src/tpm2/Vendor_TCG_Test_fp.h create mode 100644 src/tpm2/VerifySignature_fp.h create mode 100644 src/tpm2/Volatile.c create mode 100644 src/tpm2/Volatile.h create mode 100644 src/tpm2/X509.h create mode 100644 src/tpm2/X509_ECC.c create mode 100644 src/tpm2/X509_ECC_fp.h create mode 100644 src/tpm2/X509_RSA.c create mode 100644 src/tpm2/X509_RSA_fp.h create mode 100644 src/tpm2/X509_spt.c create mode 100644 src/tpm2/X509_spt_fp.h create mode 100644 src/tpm2/ZGen_2Phase_fp.h create mode 100644 src/tpm2/_TPM_Hash_Data_fp.h create mode 100644 src/tpm2/_TPM_Hash_End_fp.h create mode 100644 src/tpm2/_TPM_Hash_Start_fp.h create mode 100644 src/tpm2/_TPM_Init_fp.h create mode 100644 src/tpm2/crypto/CryptCmac_fp.h create mode 100644 src/tpm2/crypto/CryptDes_fp.h create mode 100644 src/tpm2/crypto/CryptEcc.h create mode 100644 src/tpm2/crypto/CryptEccCrypt_fp.h create mode 100644 src/tpm2/crypto/CryptEccKeyExchange_fp.h create mode 100644 src/tpm2/crypto/CryptEccMain_fp.h create mode 100644 src/tpm2/crypto/CryptEccSignature_fp.h create mode 100644 src/tpm2/crypto/CryptHash.h create mode 100644 src/tpm2/crypto/CryptHash_fp.h create mode 100644 src/tpm2/crypto/CryptPrimeSieve_fp.h create mode 100644 src/tpm2/crypto/CryptPrime_fp.h create mode 100644 src/tpm2/crypto/CryptRand.h create mode 100644 src/tpm2/crypto/CryptRand_fp.h create mode 100644 src/tpm2/crypto/CryptRsa.h create mode 100644 src/tpm2/crypto/CryptRsa_fp.h create mode 100644 src/tpm2/crypto/CryptSelfTest_fp.h create mode 100644 src/tpm2/crypto/CryptSmac_fp.h create mode 100644 src/tpm2/crypto/CryptSym.h create mode 100644 src/tpm2/crypto/CryptSym_fp.h create mode 100644 src/tpm2/crypto/CryptTest.h create mode 100644 src/tpm2/crypto/CryptUtil_fp.h create mode 100644 src/tpm2/crypto/openssl/BnConvert_fp.h create mode 100644 src/tpm2/crypto/openssl/BnMath_fp.h create mode 100644 src/tpm2/crypto/openssl/BnMemory_fp.h create mode 100644 src/tpm2/crypto/openssl/BnValues.h create mode 100644 src/tpm2/crypto/openssl/ConsttimeUtils.h create mode 100644 src/tpm2/crypto/openssl/CryptCmac.c create mode 100644 src/tpm2/crypto/openssl/CryptDes.c create mode 100644 src/tpm2/crypto/openssl/CryptEccKeyExchange.c create mode 100644 src/tpm2/crypto/openssl/CryptEccMain.c create mode 100644 src/tpm2/crypto/openssl/CryptEccSignature.c create mode 100644 src/tpm2/crypto/openssl/CryptHash.c create mode 100644 src/tpm2/crypto/openssl/CryptPrime.c create mode 100644 src/tpm2/crypto/openssl/CryptPrimeSieve.c create mode 100644 src/tpm2/crypto/openssl/CryptRand.c create mode 100644 src/tpm2/crypto/openssl/CryptRsa.c create mode 100644 src/tpm2/crypto/openssl/CryptSmac.c create mode 100644 src/tpm2/crypto/openssl/CryptSym.c create mode 100644 src/tpm2/crypto/openssl/ExpDCache.c create mode 100644 src/tpm2/crypto/openssl/ExpDCache_fp.h create mode 100644 src/tpm2/crypto/openssl/Helpers.c create mode 100644 src/tpm2/crypto/openssl/Helpers_fp.h create mode 100644 src/tpm2/crypto/openssl/LibSupport.h create mode 100644 src/tpm2/crypto/openssl/TpmToOsslDesSupport.c create mode 100644 src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h create mode 100644 src/tpm2/crypto/openssl/TpmToOsslHash.h create mode 100644 src/tpm2/crypto/openssl/TpmToOsslMath.c create mode 100644 src/tpm2/crypto/openssl/TpmToOsslMath.h create mode 100644 src/tpm2/crypto/openssl/TpmToOsslMath_fp.h create mode 100644 src/tpm2/crypto/openssl/TpmToOsslSupport.c create mode 100644 src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h create mode 100644 src/tpm2/crypto/openssl/TpmToOsslSym.h create mode 100644 src/tpm2/crypto/openssl/consttime.txt create mode 100644 src/tpm2/crypto/openssl/consttime.txt' create mode 100755 src/tpm2/gensymtestsdata.sh create mode 100644 src/tpm2/swap.h create mode 100644 src/tpm_debug.c create mode 100644 src/tpm_debug.h create mode 100644 src/tpm_library.c create mode 100644 src/tpm_library_conf.h create mode 100644 src/tpm_library_intern.h create mode 100644 src/tpm_memory.c create mode 100644 src/tpm_nvfile.c create mode 100644 src/tpm_nvfile.h create mode 100644 src/tpm_tpm12_interface.c create mode 100644 src/tpm_tpm12_tis.c create mode 100644 src/tpm_tpm2_interface.c create mode 100644 src/tpm_tpm2_tis.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..c2759a8 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,638 @@ +# +# src/Makefile.am +# +# For the license, see the LICENSE file in the root directory. +# + +AM_CFLAGS = @AM_CFLAGS@ +AM_LDFLAGS = @AM_LDFLAGS@ $(HARDENING_LDFLAGS) $(SANITIZERS) $(FUZZER) +noinst_LTLIBRARIES = +noinst_HEADERS = + +lib_LTLIBRARIES = libtpms.la +libtpms_la_LIBADD = + +common_CFLAGS = -include tpm_library_conf.h \ + -I$(top_srcdir)/include/libtpms \ + -I$(top_builddir)/include/libtpms \ + $(AM_CFLAGS) \ + $(HARDENING_CFLAGS) \ + $(SANITIZERS) \ + $(FUZZER) \ + $(LIBCRYPTO_EXTRA_CFLAGS) + +# build with libtpms callback support +common_CFLAGS += -DTPM_LIBTPMS_CALLBACKS +# let the default NVRAM write to disk +common_CFLAGS += -DTPM_NV_DISK + +if WITH_TPM1 +# +# TPM1.2 +# + +noinst_LTLIBRARIES += libtpms_tpm12.la + +libtpms_la_LIBADD += libtpms_tpm12.la + +libtpms_tpm12_la_LIBADD = + +libtpms_tpm12_la_CFLAGS = $(common_CFLAGS) + +#Build 1.2 TPM +libtpms_tpm12_la_CFLAGS += -DTPM_V12 +# build a PC Client TPM +libtpms_tpm12_la_CFLAGS += -DTPM_PCCLIENT +# upon initialization have the TPM load the volatile state +libtpms_tpm12_la_CFLAGS += -DTPM_VOLATILE_LOAD +# build the TPM enabled and activated +libtpms_tpm12_la_CFLAGS += -DTPM_ENABLE_ACTIVATE +# build with AES support for symmetric crypto +libtpms_tpm12_la_CFLAGS += -DTPM_AES +# build a POSIX type of TPM +libtpms_tpm12_la_CFLAGS += -DTPM_POSIX +# build without maintenance commands +libtpms_tpm12_la_CFLAGS += -DTPM_NOMAINTENANCE_COMMANDS + +libtpms_tpm12_la_CFLAGS += @DEBUG_DEFINES@ + +CRYPTO_OBJFILES = + +libtpms_tpm12_la_SOURCES = \ + tpm12/tpm_admin.c \ + tpm12/tpm_audit.c \ + tpm12/tpm_auth.c \ + tpm12/tpm_cryptoh.c \ + tpm12/tpm_counter.c \ + tpm12/tpm_daa.c \ + tpm12/tpm_delegate.c \ + tpm12/tpm_digest.c \ + tpm12/tpm_error.c \ + tpm12/tpm_global.c \ + tpm12/tpm_identity.c \ + tpm12/tpm_init.c \ + tpm12/tpm_libtpms_io.c \ + tpm12/tpm_key.c \ + tpm12/tpm_load.c \ + tpm12/tpm_maint.c \ + tpm12/tpm_migration.c \ + tpm12/tpm_nonce.c \ + tpm12/tpm_nvram.c \ + tpm12/tpm_openssl_helpers.c \ + tpm12/tpm_owner.c \ + tpm12/tpm_pcr.c \ + tpm12/tpm_permanent.c \ + tpm12/tpm_platform.c \ + tpm12/tpm_process.c \ + tpm12/tpm_secret.c \ + tpm12/tpm_session.c \ + tpm12/tpm_sizedbuffer.c \ + tpm12/tpm_startup.c \ + tpm12/tpm_store.c \ + tpm12/tpm_storage.c \ + tpm12/tpm_ticks.c \ + tpm12/tpm_time.c \ + tpm12/tpm_transport.c \ + tpm12/tpm_ver.c \ + tpm12/tpm_svnrevision.c \ + tpm_tpm12_interface.c \ + tpm_tpm12_tis.c + +noinst_HEADERS += \ + tpm12/tpm_admin.h \ + tpm12/tpm_audit.h \ + tpm12/tpm_auth.h \ + tpm12/tpm_commands.h \ + tpm12/tpm_constants.h \ + tpm12/tpm_counter.h \ + tpm12/tpm_crypto.h \ + tpm12/tpm_cryptoh.h \ + tpm12/tpm_daa.h \ + tpm_debug.h \ + tpm12/tpm_delegate.h \ + tpm12/tpm_digest.h \ + tpm12/tpm_global.h \ + tpm12/tpm_identity.h \ + tpm12/tpm_init.h \ + tpm12/tpm_io.h \ + tpm12/tpm_key.h \ + tpm_library_conf.h \ + tpm_library_intern.h \ + tpm12/tpm_load.h \ + tpm12/tpm_maint.h \ + tpm12/tpm_migration.h \ + tpm12/tpm_nonce.h \ + tpm_nvfile.h \ + tpm12/tpm_nvram_const.h \ + tpm12/tpm_nvram.h \ + tpm12/tpm_openssl_helpers.h \ + tpm12/tpm_owner.h \ + tpm12/tpm_pcr.h \ + tpm12/tpm_permanent.h \ + tpm12/tpm_platform.h \ + tpm12/tpm_process.h \ + tpm12/tpm_secret.h \ + tpm12/tpm_session.h \ + tpm12/tpm_sizedbuffer.h \ + tpm12/tpm_startup.h \ + tpm12/tpm_storage.h \ + tpm12/tpm_store.h \ + tpm12/tpm_structures.h \ + tpm12/tpm_svnrevision.h \ + tpm12/tpm_ticks.h \ + tpm12/tpm_time.h \ + tpm12/tpm_transport.h \ + tpm12/tpm_ver.h + +if LIBTPMS_USE_FREEBL + +libtpms_tpm12_la_SOURCES += tpm12/tpm_crypto_freebl.c +libtpms_tpm12_la_LIBADD += -lfreebl -lgmp -lnspr4 -lnssutil3 -lnss3 + +#work-around broken freebl includes +libtpms_tpm12_la_CFLAGS += $(shell [ ! -r /usr/include/nss3/alghmac.h ] && \ + touch alghmac.h && \ + echo -I./) +# tpm12/tpm_crypto_freebl.c: work around #include "blapi.h" : should be +libtpms_tpm12_la_CFLAGS += $(shell nss-config --cflags) +#including nss3/blapi.h requires a look into nspr4 dir +libtpms_tpm12_la_CFLAGS += $(shell nspr-config --cflags) + +else + +if LIBTPMS_USE_OPENSSL + +libtpms_tpm12_la_SOURCES += tpm12/tpm_crypto.c +libtpms_tpm12_la_LIBADD += -lcrypto + +endif # LIBTPMS_USE_OPENSSL + +endif # LIBTPMS_USE_FREEBL + +endif # WITH_TPM1 + +# TPM2 +# + +if WITH_TPM2 + +noinst_LTLIBRARIES += libtpms_tpm2.la + +libtpms_la_LIBADD += libtpms_tpm2.la + +libtpms_tpm2_la_LIBADD = $(LIBRT_LIBS) + +libtpms_tpm2_la_CFLAGS = $(common_CFLAGS) + +libtpms_tpm2_la_CFLAGS += -D_POSIX_ +libtpms_tpm2_la_CFLAGS += -DTPM_POSIX + +libtpms_tpm2_la_SOURCES = \ + tpm2/ACT_spt.c \ + tpm2/ACTCommands.c \ + tpm2/AlgorithmCap.c \ + tpm2/AlgorithmTests.c \ + tpm2/AsymmetricCommands.c \ + tpm2/AttestationCommands.c \ + tpm2/Attest_spt.c \ + tpm2/AuditCommands.c \ + tpm2/Bits.c \ + tpm2/BnConvert.c \ + tpm2/BnMath.c \ + tpm2/BnMemory.c \ + tpm2/Cancel.c \ + tpm2/CapabilityCommands.c \ + tpm2/Clock.c \ + tpm2/ClockCommands.c \ + tpm2/CommandAudit.c \ + tpm2/CommandCodeAttributes.c \ + tpm2/CommandDispatcher.c \ + tpm2/ContextCommands.c \ + tpm2/Context_spt.c \ + tpm2/CryptEccData.c \ + tpm2/CryptSelfTest.c \ + tpm2/CryptUtil.c \ + tpm2/DA.c \ + tpm2/DebugHelpers.c \ + tpm2/DictionaryCommands.c \ + tpm2/DuplicationCommands.c \ + tpm2/EACommands.c \ + tpm2/EncryptDecrypt_spt.c \ + tpm2/Entity.c \ + tpm2/Entropy.c \ + tpm2/EphemeralCommands.c \ + tpm2/ExecCommand.c \ + tpm2/Global.c \ + tpm2/Handle.c \ + tpm2/HashCommands.c \ + tpm2/Hierarchy.c \ + tpm2/HierarchyCommands.c \ + tpm2/IntegrityCommands.c \ + tpm2/IoBuffers.c \ + tpm2/Locality.c \ + tpm2/LocalityPlat.c \ + tpm2/ManagementCommands.c \ + tpm2/Manufacture.c \ + tpm2/Marshal.c \ + tpm2/MathOnByteBuffers.c \ + tpm2/Memory.c \ + tpm2/NVCommands.c \ + tpm2/NVDynamic.c \ + tpm2/NVMem.c \ + tpm2/NVReserved.c \ + tpm2/NV_spt.c \ + tpm2/Object.c \ + tpm2/ObjectCommands.c \ + tpm2/Object_spt.c \ + tpm2/PCR.c \ + tpm2/PlatformACT.c \ + tpm2/PlatformData.c \ + tpm2/Policy_spt.c \ + tpm2/Power.c \ + tpm2/PowerPlat.c \ + tpm2/PP.c \ + tpm2/PPPlat.c \ + tpm2/PrimeData.c \ + tpm2/PropertyCap.c \ + tpm2/RandomCommands.c \ + tpm2/Response.c \ + tpm2/ResponseCodeProcessing.c \ + tpm2/RunCommand.c \ + tpm2/Session.c \ + tpm2/SessionCommands.c \ + tpm2/SessionProcess.c \ + tpm2/SigningCommands.c \ + tpm2/StartupCommands.c \ + tpm2/SymmetricCommands.c \ + tpm2/TestingCommands.c \ + tpm2/Ticket.c \ + tpm2/Time.c \ + tpm2/TpmAsn1.c \ + tpm2/TpmSizeChecks.c \ + tpm2/TPMCmdp.c \ + tpm2/TpmFail.c \ + tpm2/Unique.c \ + tpm2/Unmarshal.c \ + tpm2/Vendor_TCG_Test.c \ + tpm2/X509_ECC.c \ + tpm2/X509_RSA.c \ + tpm2/X509_spt.c \ + tpm_tpm2_interface.c \ + tpm_tpm2_tis.c \ + \ + tpm2/BackwardsCompatibilityObject.c \ + tpm2/LibtpmsCallbacks.c \ + tpm2/NVMarshal.c \ + tpm2/StateMarshal.c \ + tpm2/Volatile.c + +noinst_HEADERS += \ + compiler.h \ + tpm2/crypto/CryptCmac_fp.h \ + tpm2/crypto/CryptDes_fp.h \ + tpm2/crypto/CryptEcc.h \ + tpm2/crypto/CryptEccCrypt_fp.h \ + tpm2/crypto/CryptEccKeyExchange_fp.h \ + tpm2/crypto/CryptEccMain_fp.h \ + tpm2/crypto/CryptEccSignature_fp.h \ + tpm2/crypto/CryptHash_fp.h \ + tpm2/crypto/CryptHash.h \ + tpm2/crypto/CryptPrime_fp.h \ + tpm2/crypto/CryptPrimeSieve_fp.h \ + tpm2/crypto/CryptRand_fp.h \ + tpm2/crypto/CryptRand.h \ + tpm2/crypto/CryptRsa_fp.h \ + tpm2/crypto/CryptRsa.h \ + tpm2/crypto/CryptSelfTest_fp.h \ + tpm2/crypto/CryptSmac_fp.h \ + tpm2/crypto/CryptSym.h \ + tpm2/crypto/CryptSym_fp.h \ + tpm2/crypto/CryptTest.h \ + tpm2/crypto/CryptUtil_fp.h \ + tpm2/ACT.h \ + tpm2/ACT_spt_fp.h \ + tpm2/ACT_SetTimeout_fp.h \ + tpm2/ActivateCredential_fp.h \ + tpm2/AlgorithmCap_fp.h \ + tpm2/AlgorithmTests_fp.h \ + tpm2/Attest_spt_fp.h \ + tpm2/BaseTypes.h \ + tpm2/Bits_fp.h \ + tpm2/Capabilities.h \ + tpm2/CertifyCreation_fp.h \ + tpm2/CertifyX509_fp.h \ + tpm2/Certify_fp.h \ + tpm2/ChangeEPS_fp.h \ + tpm2/ChangePPS_fp.h \ + tpm2/ClearControl_fp.h \ + tpm2/Clear_fp.h \ + tpm2/ClockRateAdjust_fp.h \ + tpm2/ClockSet_fp.h \ + tpm2/CommandAttributeData.h \ + tpm2/CommandAttributes.h \ + tpm2/CommandAudit_fp.h \ + tpm2/CommandCodeAttributes_fp.h \ + tpm2/CommandDispatchData.h \ + tpm2/CommandDispatcher_fp.h \ + tpm2/Commit_fp.h \ + tpm2/CompilerDependencies.h \ + tpm2/ContextLoad_fp.h \ + tpm2/ContextSave_fp.h \ + tpm2/Context_spt_fp.h \ + tpm2/Create_fp.h \ + tpm2/CreateLoaded_fp.h \ + tpm2/CreatePrimary_fp.h \ + tpm2/CryptSelfTest_fp.h \ + tpm2/DA_fp.h \ + tpm2/DebugHelpers_fp.h \ + tpm2/DictionaryAttackLockReset_fp.h \ + tpm2/DictionaryAttackParameters_fp.h \ + tpm2/Duplicate_fp.h \ + tpm2/EccTestData.h \ + tpm2/ECC_Parameters_fp.h \ + tpm2/ECDH_KeyGen_fp.h \ + tpm2/ECDH_ZGen_fp.h \ + tpm2/EC_Ephemeral_fp.h \ + tpm2/EncryptDecrypt2_fp.h \ + tpm2/EncryptDecrypt_fp.h \ + tpm2/EncryptDecrypt_spt_fp.h \ + tpm2/Entity_fp.h \ + tpm2/EventSequenceComplete_fp.h \ + tpm2/EvictControl_fp.h \ + tpm2/ExecCommand_fp.h \ + tpm2/FlushContext_fp.h \ + tpm2/GetCapability_fp.h \ + tpm2/GetCommandAuditDigest_fp.h \ + tpm2/GetRandom_fp.h \ + tpm2/GetSessionAuditDigest_fp.h \ + tpm2/GetTestResult_fp.h \ + tpm2/GetTime_fp.h \ + tpm2/Global.h \ + tpm2/GpMacros.h \ + tpm2/Handle_fp.h \ + tpm2/Hash_fp.h \ + tpm2/HashSequenceStart_fp.h \ + tpm2/HashTestData.h \ + tpm2/HierarchyChangeAuth_fp.h \ + tpm2/HierarchyControl_fp.h \ + tpm2/Hierarchy_fp.h \ + tpm2/HMAC_fp.h \ + tpm2/HMAC_Start_fp.h \ + tpm2/Import_fp.h \ + tpm2/IncrementalSelfTest_fp.h \ + tpm2/InternalRoutines.h \ + tpm2/IoBuffers_fp.h \ + tpm2/KdfTestData.h \ + tpm2/LoadExternal_fp.h \ + tpm2/Load_fp.h \ + tpm2/Locality_fp.h \ + tpm2/MAC_fp.h \ + tpm2/MAC_Start_fp.h \ + tpm2/MakeCredential_fp.h \ + tpm2/Manufacture_fp.h \ + tpm2/Marshal_fp.h \ + tpm2/MathOnByteBuffers_fp.h \ + tpm2/Memory_fp.h \ + tpm2/MinMax.h \ + tpm2/NV_Certify_fp.h \ + tpm2/NV_ChangeAuth_fp.h \ + tpm2/NV_DefineSpace_fp.h \ + tpm2/NVDynamic_fp.h \ + tpm2/NV_Extend_fp.h \ + tpm2/NV_GlobalWriteLock_fp.h \ + tpm2/NV.h \ + tpm2/NV_Increment_fp.h \ + tpm2/NV_Read_fp.h \ + tpm2/NV_ReadLock_fp.h \ + tpm2/NV_ReadPublic_fp.h \ + tpm2/NVReserved_fp.h \ + tpm2/NV_SetBits_fp.h \ + tpm2/NV_spt_fp.h \ + tpm2/NV_UndefineSpace_fp.h \ + tpm2/NV_UndefineSpaceSpecial_fp.h \ + tpm2/NV_Write_fp.h \ + tpm2/NV_WriteLock_fp.h \ + tpm2/OIDs.h \ + tpm2/ObjectChangeAuth_fp.h \ + tpm2/Object_fp.h \ + tpm2/Object_spt_fp.h \ + tpm2/PCR_Allocate_fp.h \ + tpm2/PCR_Event_fp.h \ + tpm2/PCR_Extend_fp.h \ + tpm2/PCR_fp.h \ + tpm2/PCR_Read_fp.h \ + tpm2/PCR_Reset_fp.h \ + tpm2/PCR_SetAuthPolicy_fp.h \ + tpm2/PCR_SetAuthValue_fp.h \ + tpm2/Platform.h \ + tpm2/PlatformACT.h \ + tpm2/PlatformACT_fp.h \ + tpm2/PlatformClock.h \ + tpm2/PlatformData.h \ + tpm2/Platform_fp.h \ + tpm2/PolicyAuthorize_fp.h \ + tpm2/PolicyAuthorizeNV_fp.h \ + tpm2/PolicyAuthValue_fp.h \ + tpm2/PolicyCommandCode_fp.h \ + tpm2/PolicyCounterTimer_fp.h \ + tpm2/PolicyCpHash_fp.h \ + tpm2/PolicyDuplicationSelect_fp.h \ + tpm2/PolicyGetDigest_fp.h \ + tpm2/PolicyLocality_fp.h \ + tpm2/PolicyNameHash_fp.h \ + tpm2/PolicyNV_fp.h \ + tpm2/PolicyNvWritten_fp.h \ + tpm2/PolicyOR_fp.h \ + tpm2/PolicyPassword_fp.h \ + tpm2/PolicyPCR_fp.h \ + tpm2/PolicyPhysicalPresence_fp.h \ + tpm2/PolicyRestart_fp.h \ + tpm2/PolicySecret_fp.h \ + tpm2/PolicySigned_fp.h \ + tpm2/Policy_spt_fp.h \ + tpm2/PolicyTemplate_fp.h \ + tpm2/PolicyTicket_fp.h \ + tpm2/Power_fp.h \ + tpm2/PP_Commands_fp.h \ + tpm2/PP_fp.h \ + tpm2/PRNG_TestVectors.h \ + tpm2/PropertyCap_fp.h \ + tpm2/Quote_fp.h \ + tpm2/ReadClock_fp.h \ + tpm2/ReadPublic_fp.h \ + tpm2/ResponseCodeProcessing_fp.h \ + tpm2/Response_fp.h \ + tpm2/Rewrap_fp.h \ + tpm2/RsaTestData.h \ + tpm2/RSA_Decrypt_fp.h \ + tpm2/RSA_Encrypt_fp.h \ + tpm2/SelfTest.h \ + tpm2/SelfTest_fp.h \ + tpm2/SequenceComplete_fp.h \ + tpm2/SequenceUpdate_fp.h \ + tpm2/Session_fp.h \ + tpm2/SessionProcess_fp.h \ + tpm2/SetAlgorithmSet_fp.h \ + tpm2/SetCommandCodeAuditStatus_fp.h \ + tpm2/SetPrimaryPolicy_fp.h \ + tpm2/Shutdown_fp.h \ + tpm2/Sign_fp.h \ + tpm2/Simulator_fp.h \ + tpm2/StartAuthSession_fp.h \ + tpm2/Startup_fp.h \ + tpm2/StirRandom_fp.h \ + tpm2/SupportLibraryFunctionPrototypes_fp.h \ + tpm2/SymmetricTest.h \ + tpm2/SymmetricTestData.h \ + tpm2/swap.h \ + tpm2/TcpServerPosix_fp.h \ + tpm2/TestParms_fp.h \ + tpm2/Ticket_fp.h \ + tpm2/Time_fp.h \ + tpm2/TPMB.h \ + tpm2/TpmAlgorithmDefines.h \ + tpm2/TpmAsn1.h \ + tpm2/TpmAsn1_fp.h \ + tpm2/TpmBuildSwitches.h \ + tpm2/TpmError.h \ + tpm2/TpmFail_fp.h \ + tpm2/TpmProfile.h \ + tpm2/Tpm.h \ + tpm2/_TPM_Hash_Data_fp.h \ + tpm2/_TPM_Hash_End_fp.h \ + tpm2/_TPM_Hash_Start_fp.h \ + tpm2/_TPM_Init_fp.h \ + tpm2/TpmSizeChecks_fp.h \ + tpm2/TpmTcpProtocol.h \ + tpm2/TpmTypes.h \ + tpm2/Unmarshal_fp.h \ + tpm2/Unseal_fp.h \ + tpm2/VendorString.h \ + tpm2/Vendor_TCG_Test_fp.h \ + tpm2/VerifySignature_fp.h \ + tpm2/X509.h \ + tpm2/X509_ECC_fp.h \ + tpm2/X509_RSA_fp.h \ + tpm2/X509_spt_fp.h \ + tpm2/ZGen_2Phase_fp.h \ + \ + tpm2/BackwardsCompatibility.h \ + tpm2/BackwardsCompatibilityObject.h \ + tpm2/LibtpmsCallbacks.h \ + tpm2/NVMarshal.h \ + tpm2/StateMarshal.h \ + tpm2/Utils.h \ + tpm2/Volatile.h + +if LIBTPMS_USE_OPENSSL + +libtpms_tpm2_la_SOURCES += \ + tpm2/crypto/openssl/CryptCmac.c \ + tpm2/crypto/openssl/CryptDes.c \ + tpm2/crypto/openssl/CryptEccKeyExchange.c \ + tpm2/crypto/openssl/CryptEccMain.c \ + tpm2/crypto/openssl/CryptEccSignature.c \ + tpm2/crypto/openssl/CryptHash.c \ + tpm2/crypto/openssl/CryptPrime.c \ + tpm2/crypto/openssl/CryptPrimeSieve.c \ + tpm2/crypto/openssl/CryptRand.c \ + tpm2/crypto/openssl/CryptRsa.c \ + tpm2/crypto/openssl/CryptSmac.c \ + tpm2/crypto/openssl/CryptSym.c \ + tpm2/crypto/openssl/ExpDCache.c \ + tpm2/crypto/openssl/Helpers.c \ + tpm2/crypto/openssl/TpmToOsslDesSupport.c \ + tpm2/crypto/openssl/TpmToOsslMath.c \ + tpm2/crypto/openssl/TpmToOsslSupport.c + +noinst_HEADERS += \ + tpm2/crypto/openssl/ConsttimeUtils.h \ + tpm2/crypto/openssl/BnConvert_fp.h \ + tpm2/crypto/openssl/BnMath_fp.h \ + tpm2/crypto/openssl/BnMemory_fp.h \ + tpm2/crypto/openssl/BnValues.h \ + tpm2/crypto/openssl/ExpDCache_fp.h \ + tpm2/crypto/openssl/Helpers_fp.h \ + tpm2/crypto/openssl/LibSupport.h \ + tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h \ + tpm2/crypto/openssl/TpmToOsslHash.h \ + tpm2/crypto/openssl/TpmToOsslMath_fp.h \ + tpm2/crypto/openssl/TpmToOsslMath.h \ + tpm2/crypto/openssl/TpmToOsslSupport_fp.h \ + tpm2/crypto/openssl/TpmToOsslSym.h + +libtpms_tpm2_la_CFLAGS += \ + -I $(srcdir)/tpm2 \ + -I $(srcdir)/tpm2/crypto \ + -I $(srcdir)/tpm2/crypto/openssl + + +libtpms_tpm2_la_LIBADD += -lcrypto + +endif # LIBTPMS_USE_OPENSSL + +endif # WITH_TPM2 + +# +# Library API layer +# + +libtpms_la_SOURCES = \ + disabled_interface.c \ + tpm_debug.c \ + tpm_library.c \ + tpm_memory.c \ + tpm_nvfile.c + +libtpms_la_CFLAGS = $(common_CFLAGS) + +libtpms_la_LDFLAGS = -version-info $(LIBTPMS_VERSION_INFO) \ + -no-undefined $(AM_LDFLAGS) + +if HAVE_VERSION_SCRIPT +libtpms_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libtpms.syms +endif + +LDFLAGS_ARCH = $(findstring -m32, $(AM_CFLAGS)) +LDFLAGS_ARCH += $(findstring -m64, $(AM_CFLAGS)) +LDFLAGS_ARCH += $(findstring -m32, $(AM_LDFLAGS)) +LDFLAGS_ARCH += $(findstring -m64, $(AM_LDFLAGS)) + +check-local: SHELL?="/usr/bin/env bash" +check-local: + @case $(host_os) in \ + openbsd*) ADDLIBS="-lc" ;; \ + darwin*|freebsd*) LDFLAGS_OS="-shared" ;; \ + *) ADDLIBS="" ;; \ + esac; \ + ($(CC) $$LDFLAGS_OS $(LDFLAGS_ARCH) -nostdlib -L./.libs -ltpms $$ADDLIBS 2>/dev/null || \ + (echo "There are undefined symbols in libtpms ($$LDFLAGS_OS $(LDFLAGS_ARCH))";\ + $(CC) $$LDFLAGS_OS $(LDFLAGS_ARCH) -nostdlib -L./.libs -ltpms $$ADDLIBS 2>&1 | grep libtpms)) + @case $(host_os) in \ + openbsd*) ADDLIBS="-lc" ;; \ + darwin*|freebsd*) LDFLAGS_OS="-shared" ;; \ + *) ADDLIBS="" ;; \ + esac; \ + $(CC) $$LDFLAGS_OS $(LDFLAGS_ARCH) -nostdlib -L./.libs -ltpms $$ADDLIBS 2>/dev/null + rm a.out || true + +EXTRA_DIST = \ + tpm12/tpm_crypto_freebl.c \ + tpm12/tpm_crypto.c \ + libtpms.syms \ + test.syms + +CLEANFILES = \ + a.out \ + *.gcov \ + *.gcda \ + *.gcno \ + tpm12/*.gcov \ + tpm12/*.gcda \ + tpm12/*.gcno \ + tpm2/*.gcov \ + tpm2/*.gcda \ + tpm2/*.gcno \ + tpm2/crypto/openssl/*.gcov \ + tpm2/crypto/openssl/*.gcda \ + tpm2/crypto/openssl/*.gcno diff --git a/src/compiler.h b/src/compiler.h new file mode 100644 index 0000000..45ef51a --- /dev/null +++ b/src/compiler.h @@ -0,0 +1,49 @@ +/********************************************************************************/ +/* */ +/* Compiler-specific macros */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ +#ifndef TPMLIB_COMPILER_H +#define TPMLIB_COMPILER_H + +#ifndef __clang__ +# define ATTRIBUTE_FORMAT(STRING_IDX, FIRST_TO_CHECK) \ + __attribute__((format (printf, STRING_IDX, FIRST_TO_CHECK))) +#else +# define ATTRIBUTE_FORMAT(STRING_IDX, FIRST_TO_CHECK) \ + __attribute__((__format__ (__printf__, STRING_IDX, FIRST_TO_CHECK))) +#endif + +#endif /* TPMLIB_COMPILER_H */ diff --git a/src/disabled_interface.c b/src/disabled_interface.c new file mode 100644 index 0000000..5a4c91a --- /dev/null +++ b/src/disabled_interface.c @@ -0,0 +1,111 @@ +#include +#include "tpm_error.h" +#include "tpm_library_intern.h" + +static TPM_RESULT Disabled_MainInit(void) +{ + return TPM_FAIL; +} + +static void Disabled_Terminate(void) +{ +} + +static TPM_RESULT Disabled_Process(unsigned char **respbuffer, uint32_t *resp_size, + uint32_t *respbufsize, + unsigned char *command, uint32_t command_size) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_VolatileAllStore(unsigned char **buffer, + uint32_t *buflen) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_CancelCommand(void) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_GetTPMProperty(enum TPMLIB_TPMProperty prop, + int *result) +{ + return TPM_FAIL; +} + +static char *Disabled_GetInfo(enum TPMLIB_InfoFlags flags) +{ + return NULL; +} + +static uint32_t Disabled_SetBufferSize(uint32_t wanted_size, + uint32_t *min_size, + uint32_t *max_size) +{ + return 0; +} + +static TPM_RESULT Disabled_ValidateState(enum TPMLIB_StateType st, + unsigned int flags) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_GetState(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_SetState(enum TPMLIB_StateType st, + const unsigned char *buffer, uint32_t buflen) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_IO_Hash_Start(void) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_IO_Hash_Data(const unsigned char *data, + uint32_t data_length) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_IO_Hash_End(void) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished) +{ + return TPM_FAIL; +} + +static TPM_RESULT Disabled_IO_TpmEstablished_Reset(void) +{ + return TPM_FAIL; +} + +const struct tpm_interface DisabledInterface = { + .MainInit = Disabled_MainInit, + .Terminate = Disabled_Terminate, + .Process = Disabled_Process, + .VolatileAllStore = Disabled_VolatileAllStore, + .CancelCommand = Disabled_CancelCommand, + .GetTPMProperty = Disabled_GetTPMProperty, + .GetInfo = Disabled_GetInfo, + .TpmEstablishedGet = Disabled_IO_TpmEstablished_Get, + .TpmEstablishedReset = Disabled_IO_TpmEstablished_Reset, + .HashStart = Disabled_IO_Hash_Start, + .HashData = Disabled_IO_Hash_Data, + .HashEnd = Disabled_IO_Hash_End, + .SetBufferSize = Disabled_SetBufferSize, + .ValidateState = Disabled_ValidateState, + .SetState = Disabled_SetState, + .GetState = Disabled_GetState, +}; diff --git a/src/libtpms.syms b/src/libtpms.syms new file mode 100644 index 0000000..e385192 --- /dev/null +++ b/src/libtpms.syms @@ -0,0 +1,39 @@ +# Symbol file for the linker. For newer versions add new sections. + +LIBTPMS_0.5.1 { + global: + TPM_IO_Hash_Data; + TPM_IO_Hash_End; + TPM_IO_Hash_Start; + TPM_IO_TpmEstablished_Get; + TPMLIB_DecodeBlob; + TPMLIB_GetTPMProperty; + TPMLIB_GetVersion; + TPMLIB_MainInit; + TPMLIB_Process; + TPMLIB_RegisterCallbacks; + TPMLIB_Terminate; + TPMLIB_VolatileAll_Store; + TPM_Free; + TPM_Malloc; + TPM_Realloc; + local: + *; +}; + +LIBTPMS_0.6.0 { + global: + TPM_IO_TpmEstablished_Reset; + TPMLIB_CancelCommand; + TPMLIB_ChooseTPMVersion; + TPMLIB_GetInfo; + TPMLIB_GetState; + TPMLIB_SetBufferSize; + TPMLIB_SetDebugFD; + TPMLIB_SetDebugLevel; + TPMLIB_SetDebugPrefix; + TPMLIB_SetState; + TPMLIB_ValidateState; + local: + *; +} LIBTPMS_0.5.1; diff --git a/src/test.syms b/src/test.syms new file mode 100644 index 0000000..40cdd2e --- /dev/null +++ b/src/test.syms @@ -0,0 +1,9 @@ +# Symbol file for the linker. For testing in configure.ac only +TEST { + global: + # two work-around for a broken link + environ; + __progname; + local: + *; +}; diff --git a/src/tpm12/tpm_admin.c b/src/tpm12/tpm_admin.c new file mode 100644 index 0000000..28d33bb --- /dev/null +++ b/src/tpm12/tpm_admin.c @@ -0,0 +1,2010 @@ +/********************************************************************************/ +/* */ +/* TPM Admin Test and Opt-in */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_admin.c 4505 2011-03-20 17:43:27Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#include "tpm_auth.h" +#include "tpm_cryptoh.h" +#include "tpm_digest.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_key.h" +#include "tpm_nonce.h" +#include "tpm_permanent.h" +#include "tpm_process.h" +#include "tpm_secret.h" +#include "tpm_ticks.h" +#include "tpm_time.h" + +#include "tpm_admin.h" + +/* The Software TPM Self Test works as follows: + + TPM_LimitedSelfTestCommon(void) - self tests which affect all TPM's + TPM_LimitedSelfTestTPM(tpm_state) - self test per virtual TPM + + TPM_ContinueSelfTestCmd(tpm_state) - currently does nothing + on failure, sets tpm_state->testState to failure for the virtual TPM + + TPM_SelfTestFullCmd(tpm_state) calls + TPM_LimitedSelfTestTPM() + TPM_ContinueSelfTestCmd(tpm_state) + on failure, sets tpm_state->testState to failure for the virtual TPM + + TPM_MainInit(void) calls + TPM_LimitedSelfTestCommon(void) + TPM_LimitedSelfTestTPM(tpm_state) + + TPM_Process_ContinueSelfTest(tpm_state) calls either (depending on FIPS mode) + TPM_SelfTestFullCmd(tpm_state) + TPM_ContinueSelfTestCmd(tpm_state) + + TPM_Process_SelfTestFull(tpm_state) calls + TPM_SelfTestFullCmd(tpm_state) + + The Software TPM assumes that the coprocessor has run self tests before the application code even + begins. So this code doesn't do any real testing of the underlying hardware. This simplifies + the state machine, since TPM_Process_ContinueSelfTest doesn't require a separate thread. +*/ + +/* TPM_LimitedSelfTestCommon() provides the assurance that a selected subset of TPM commands will + perform properly. The limited nature of the self-test allows the TPM to be functional in as short + of time as possible. all the TPM tests. + + The caller is responsible for setting the shutdown state on error. +*/ + +TPM_RESULT TPM_LimitedSelfTestCommon(void) +{ + TPM_RESULT rc = 0; + uint32_t tv_sec; + uint32_t tv_usec; + + printf(" TPM_LimitedSelfTestCommon:\n"); +#if 0 + if (rc == 0) { + rc = TPM_Sbuffer_Test(); + } +#endif + if (rc == 0) { + rc = TPM_Uint64_Test(); + } + if (rc == 0) { + rc = TPM_CryptoTest(); + } + /* test time of day clock */ + if (rc == 0) { + rc = TPM_GetTimeOfDay(&tv_sec, &tv_usec); + } + if (rc != 0) { + rc = TPM_FAILEDSELFTEST; + } + return rc; +} + +TPM_RESULT TPM_LimitedSelfTestTPM(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_NONCE clrData; + TPM_SIZED_BUFFER encData; + TPM_NONCE decData; + uint32_t decLength; + + + printf(" TPM_LimitedSelfTestTPM:\n"); + TPM_SizedBuffer_Init(&encData); /* freed @1 */ + + /* 8. The TPM MUST check the following: */ + /* a. RNG functionality */ + /* NOTE Tested by coprocessor boot */ + /* b. Reading and extending the integrity registers. The self-test for the integrity registers + will leave the integrity registers in a known state. */ + /* NOTE Since there is nothing special about the PCR's, the common TPM_CryptoTest() is + sufficient */ + /* c. Testing the EK integrity, if it exists */ + /* i. This requirement specifies that the TPM will verify that the endorsement key pair can + encrypt and decrypt a known value. This tests the RSA engine. If the EK has not yet been + generated the TPM action is manufacturer specific. */ + if ((rc == 0) && + (tpm_state->tpm_permanent_data.endorsementKey.keyUsage != TPM_KEY_UNINITIALIZED)) { + /* check the key integrity */ + if (rc == 0) { + rc = TPM_Key_CheckPubDataDigest(&(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* encrypt */ + if (rc == 0) { + TPM_Nonce_Generate(clrData); + rc = TPM_RSAPublicEncrypt_Key(&encData, /* output */ + clrData, /* input */ + TPM_NONCE_SIZE, /* input */ + &(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* decrypt */ + if (rc == 0) { + rc = TPM_RSAPrivateDecryptH(decData, /* decrypted data */ + &decLength, /* length of data put into decrypt_data */ + TPM_NONCE_SIZE, /* size of decrypt_data buffer */ + encData.buffer, + encData.size, + &(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* verify */ + if (rc == 0) { + if (decLength != TPM_NONCE_SIZE) { + printf("TPM_LimitedSelfTestTPM: Error, decrypt length %u should be %u\n", + decLength, TPM_NONCE_SIZE); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + rc = TPM_Nonce_Compare(clrData, decData); + } + } + /* d. The integrity of the protected capabilities of the TPM */ + /* i. This means that the TPM must ensure that its "microcode" has not changed, and not that a + test must be run on each function. */ + /* e. Any tamper-resistance markers */ + /* i. The tests on the tamper-resistance or tamper-evident markers are under programmable + control. */ + /* There is no requirement to check tamper-evident tape or the status of epoxy surrounding the + case. */ + /* NOTE: Done by coprocessor POST */ + /* 9. The TPM SHOULD check the following: */ + /* a. The hash functionality */ + /* i. This check will hash a known value and compare it to an expected result. There is no + requirement to accept external data to perform the check. */ + /* ii. The TPM MAY support a test using external data. */ + /* NOTE: Done by TPM_CryptoTest() */ + /* b. Any symmetric algorithms */ + /* i. This check will use known data with a random key to encrypt and decrypt the data */ + /* NOTE: Done by TPM_CryptoTest() */ + /* c. Any additional asymmetric algorithms */ + /* i. This check will use known data to encrypt and decrypt. */ + /* NOTE: So far only RSA is supported */ + /* d. The key-wrapping mechanism */ + /* i. The TPM should wrap and unwrap a key. The TPM MUST NOT use the endorsement key pair for + this test. */ + /* NOTE: There is nothing special about serializing a TPM_STORE_ASYMKEY */ + /* e. Any other internal mechanisms */ + TPM_SizedBuffer_Delete(&encData); /* @1 */ + if (rc != 0) { + rc = TPM_FAILEDSELFTEST; + } + /* set the TPM test state */ + if ((rc == 0) && (tpm_state->testState != TPM_TEST_STATE_FAILURE)) { + printf(" TPM_LimitedSelfTestTPM: Set testState to %u \n", TPM_TEST_STATE_LIMITED); + tpm_state->testState = TPM_TEST_STATE_LIMITED; + } + else { + printf(" TPM_LimitedSelfTestTPM: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + return rc; +} + +/* TPM_ContinueSelfTestCmd() runs the continue self test actions + +*/ + +TPM_RESULT TPM_ContinueSelfTestCmd(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + + /* NOTE all done by limited self test */ + printf(" TPM_ContinueSelfTestCmd:\n"); + if (rc != 0) { + rc = TPM_FAILEDSELFTEST; + } + /* set the TPM test state */ + if (rc == 0) { + printf(" TPM_ContinueSelfTestCmd: Set testState to %u \n", TPM_TEST_STATE_FULL); + tpm_state->testState = TPM_TEST_STATE_FULL; + } + else { + printf(" TPM_ContinueSelfTestCmd: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + return rc; +} + +/* TPM_SelfTestFullCmd is a request to have the TPM perform another complete self-test. This test + will take some time but provides an accurate assessment of the TPM's ability to perform all + operations. + + Runs the actions of self test full. +*/ + +TPM_RESULT TPM_SelfTestFullCmd(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SelfTestFullCmd\n"); + if (rc == 0) { + rc = TPM_LimitedSelfTestTPM(tpm_state); + } + if (rc == 0) { + rc = TPM_ContinueSelfTestCmd(tpm_state); + } + return rc; +} + +/* 4.1 TPM_SelfTestFull rev 88 + + SelfTestFull tests all of the TPM capabilities. + + Unlike TPM_ContinueSelfTest, which may optionally return immediately and then perform the tests, + TPM_SelfTestFull always performs the tests and then returns success or failure. +*/ + +TPM_RESULT TPM_Process_SelfTestFull(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SelfTestFull: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SelfTestFull: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. TPM_SelfTestFull SHALL cause a TPM to perform self-test of each TPM internal function. */ + /* a. If the self-test succeeds, return TPM_SUCCESS. */ + /* b. If the self-test fails, return TPM_FAILEDSELFTEST. */ + /* 2. Failure of any test results in overall failure, and the TPM goes into failure mode. */ + /* 3. If the TPM has not executed the action of TPM_ContinueSelfTest, the TPM */ + /* a. MAY perform the full self-test. */ + /* b. MAY return TPM_NEEDS_SELFTEST. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SelfTestFullCmd(tpm_state); + } + /* + response + */ + if (rcf == 0) { + printf("TPM_Process_SelfTestFull: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 4.2 TPM_ContinueSelfTest rev 88 + + TPM_Process_ContinueSelfTest informs the TPM that it may complete the self test of all TPM + functions. + + The TPM may return success immediately and then perform the self-test, or it may perform the + self-test and then return success or failure. + + 1. Prior to executing the actions of TPM_ContinueSelfTest, if the TPM receives a command C1 that + uses an untested TPM function, the TPM MUST take one of these actions: + + a. The TPM MAY return TPM_NEEDS_SELFTEST + + i. This indicates that the TPM has not tested the internal resources required to execute C1. + + ii. The TPM does not execute C1. + + iii. The caller MUST issue TPM_ContinueSelfTest before re-issuing the command C1. + + (1) If the TPM permits TPM_SelfTestFull prior to completing the actions of TPM_ContinueSelfTest, + the caller MAY issue TPM_SelfTestFull rather than TPM_ContinueSelfTest. + + b. The TPM MAY return TPM_DOING_SELFTEST + + i. This indicates that the TPM is doing the actions of TPM_ContinueSelfTest implicitly, as if the + TPM_ContinueSelfTest command had been issued. + + ii. The TPM does not execute C1. + + iii. The caller MUST wait for the actions of TPM_ContinueSelfTest to complete before reissuing + the command C1. + + c. The TPM MAY return TPM_SUCCESS or an error code associated with C1. + + i. This indicates that the TPM has completed the actions of TPM_ContinueSelfTest and has + completed the command C1. + + ii. The error code MAY be TPM_FAILEDSELFTEST. +*/ + +TPM_RESULT TPM_Process_ContinueSelfTest(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ContinueSelfTest: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ContinueSelfTest: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + /* 1. If TPM_PERMANENT_FLAGS -> FIPS is TRUE or TPM_PERMANENT_FLAGS -> TPMpost is TRUE */ + if ((tpm_state->tpm_permanent_flags.FIPS) || + (tpm_state->tpm_permanent_flags.TPMpost)) { + /* a. The TPM MUST run ALL self-tests */ + returnCode = TPM_SelfTestFullCmd(tpm_state); + } + /* 2. Else */ + else { + /* a. The TPM MUST complete all self-tests that are outstanding */ + /* i. Instead of completing all outstanding self-tests the TPM MAY run all self-tests */ + returnCode = TPM_ContinueSelfTestCmd(tpm_state); + } + } + /* 3. The TPM either + a. MAY immediately return TPM_SUCCESS + i. When TPM_ContinueSelfTest finishes execution, it MUST NOT respond to the caller with a + return code. + b. MAY complete the self-test and then return TPM_SUCCESS or TPM_FAILEDSELFTEST. + NOTE Option 3.b. implemented + */ + /* + response + */ + if (rcf == 0) { + printf("TPM_Process_ContinueSelfTest: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 4.3 TPM_GetTestResult rev 96 + + TPM_GetTestResult provides manufacturer specific information regarding the results of the self + test. This command will work when the TPM is in self test failure mode. The reason for allowing + this command to operate in the failure mode is to allow TPM manufacturers to obtain diagnostic + information. +*/ + +TPM_RESULT TPM_Process_GetTestResult(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER outData; /* The outData this is manufacturer specific */ + + printf("TPM_Process_GetTestResult: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&outData); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + /* This command will work when the TPM is in self test failure or limited operation mode. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_NO_LOCKOUT); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetTestResult: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM SHALL respond to this command with a manufacturer specific block of information + that describes the result of the latest self test. */ + /* 2. The information MUST NOT contain any data that uniquely identifies an individual TPM. */ + /* allocate some reasonable area */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Allocate(&outData, 128); + } + /* for now, just return the state of shutdown as a printable string */ + if (returnCode == TPM_SUCCESS) { + size_t len = outData.size; + /* cast because TPM_SIZED_BUFFER is typically unsigned (binary) but snprintf expects char */ + outData.size = snprintf((char *)(outData.buffer), len, + "Shutdown %08x\n", tpm_state->testState); + if (outData.size >= len) { + printf("TPM_Process_GetTestResult: Error (fatal), buffer too small\n"); + returnCode = TPM_FAIL; + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_GetTestResult: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&outData); /* @1 */ + return rcf; +} + +/* 5.1 TPM_SetOwnerInstall rev 100 + + When enabled but without an owner this command sets the PERMANENT flag that allows or disallows + the ability to insert an owner. + */ + +TPM_RESULT TPM_Process_SetOwnerInstall(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_BOOL state; /* State to which ownership flag is to be set. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + TPM_BOOL physicalPresence; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SetOwnerInstall: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadBool(&state, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SetOwnerInstall: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + /* 1. If the TPM has a current owner, this command immediately returns with TPM_SUCCESS. */ + if (tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_Process_SetOwnerInstall: Already current owner\n"); + } + /* If the TPM does not have a current owner */ + else { + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SetOwnerInstall: No current owner\n"); + /* 2. The TPM validates the assertion of physical presence. The TPM then sets the + value of TPM_PERMANENT_FLAGS -> ownership to the value in state. + */ + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_SetOwnerInstall: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SetOwnerInstall: Setting ownership to %02x\n", state); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.ownership), /* flag */ + state); /* value */ + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + } + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SetOwnerInstall: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 5.2 TPM_OwnerSetDisable rev 107 + + The TPM owner sets the PERMANENT disable flag to TRUE or FALSE. +*/ + +TPM_RESULT TPM_Process_OwnerSetDisable(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_BOOL disableState; /* Value for disable state */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the + authorization handle */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner + authorization. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_OwnerSetDisable: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get disableState parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadBool(&disableState, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_OWNER | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_OwnerSetDisable: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. The TPM SHALL authenticate the command as coming from the TPM Owner. If unsuccessful, the + TPM SHALL return TPM_AUTHFAIL. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS -> disable flag to the value in the + disableState parameter. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OwnerSetDisable: Setting disable to %u\n", disableState); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.disable), /* flag */ + disableState); /* value */ + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_OwnerSetDisable: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + return rcf; +} + +/* 5.3 TPM_PhysicalEnable rev 87 + + Sets the PERMANENT disable flag to FALSE using physical presence as authorization. +*/ + +TPM_RESULT TPM_Process_PhysicalEnable(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + TPM_BOOL physicalPresence; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_PhysicalEnable: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_PhysicalEnable: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_PhysicalEnable: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.disable value to FALSE. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_PhysicalEnable: Setting disable to FALSE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.disable), /* flag */ + FALSE); /* value */ + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_PhysicalEnable: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 5.4 TPM_PhysicalDisable rev 87 + + Sets the PERMANENT disable flag to TRUE using physical presence as authorization +*/ + +TPM_RESULT TPM_Process_PhysicalDisable(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + TPM_BOOL physicalPresence; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_PhysicalDisable: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_ENABLED | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_PhysicalDisable: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_PhysicalDisable: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.disable value to TRUE. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_PhysicalDisable: Setting disable to TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.disable ), /* flag */ + TRUE); /* value */ + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_PhysicalDisable: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 5.5 TPM_PhysicalSetDeactivated rev 105 + + Changes the TPM persistent deactivated flag using physical presence as authorization. +*/ + +TPM_RESULT TPM_Process_PhysicalSetDeactivated(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_BOOL state; /* State to which deactivated flag is to be set. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + TPM_BOOL physicalPresence; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_PhysicalSetDeactivated: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get state parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadBool(&state, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_PhysicalSetDeactivated: state %02x\n", state); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_ENABLED | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_PhysicalSetDeactivated: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_PhysicalSetDeactivated: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.deactivated flag to the value in the state + parameter. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_PhysicalSetDeactivated: Setting deactivated to %u\n", state); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.deactivated), /* flag */ + state); /* value */ + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_PhysicalSetDeactivated: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 5.6 TPM_SetTempDeactivated rev 87 + + This command allows the operator of the platform to deactivate the TPM until the next boot of the + platform. + + This command requires operator authorization. The operator can provide the authorization by + either the assertion of physical presence or presenting the operation authorization value. +*/ + +TPM_RESULT TPM_Process_SetTempDeactivated(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* auth handle for operation validation. Session type must + be OIAP. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the + authorization handle */ + TPM_AUTHDATA operatorAuth; /* HMAC key: operatorAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; +#if TPM_V12 + TPM_BOOL physicalPresence; +#endif + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SetTempDeactivated: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_ACTIVATED | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { +#if TPM_V12 + returnCode = TPM_CheckRequestTag10(tag); +#else /* v1.1 is always auth0. This check implicitly bypasses the operatorAuth Actions below. */ + returnCode = TPM_CheckRequestTag0(tag); +#endif + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + operatorAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SetTempDeactivated: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. If tag = TPM_TAG_REQ_AUTH1_COMMAND */ + /* a. If TPM_PERMANENT_FLAGS -> operator is FALSE return TPM_NOOPERATOR */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + if (!tpm_state->tpm_permanent_flags.tpmOperator) { + printf("TPM_Process_SetTempDeactivated: Error, no operator\n"); + returnCode = TPM_NOOPERATOR; + } + } + /* b. Validate command and parameters using operatorAuth, on error return TPM_AUTHFAIL */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + printf(" TPM_Process_SetTempDeactivated: authHandle %08x\n", authHandle); + /* get the session data */ + returnCode = + TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OIAP, + 0, /* OSAP entity type */ + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.operatorAuth), /* OIAP */ + NULL); /* OSAP */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* operator HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + operatorAuth); /* Authorization digest for input */ + + } +#if TPM_V12 /* v1.1 does not require physical presence */ + /* 2. Else */ + /* a. If physical presence is not asserted the TPM MUST return TPM_BAD_PRESENCE */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (!physicalPresence) { + printf("TPM_Process_SetTempDeactivated: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } +#endif + /* 3. The TPM SHALL set the TPM_STCLEAR_FLAGS.deactivated flag to the value TRUE. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SetTempDeactivated: Setting deactivated to TRUE\n"); + tpm_state->tpm_stclear_flags.deactivated = TRUE; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SetTempDeactivated: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* operator HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 5.7 TPM_SetOperatorAuth rev 87 + + This command allows the setting of the operator authorization value. + + There is no confidentiality applied to the operator authorization as the value is sent under the + assumption of being local to the platform. If there is a concern regarding the path between the + TPM and the keyboard then unless the keyboard is using encryption and a secure channel an + attacker can read the values. +*/ + +TPM_RESULT TPM_Process_SetOperatorAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_SECRET operatorAuth; /* The operator authorization */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + TPM_BOOL physicalPresence; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SetOperatorAuth: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get operatorAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Secret_Load(operatorAuth, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SetOperatorAuth: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. If physical presence is not asserted the TPM MUST return TPM_BAD_PRESENCE */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_SetOperatorAuth: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + if (returnCode == TPM_SUCCESS) { + /* 2. The TPM SHALL set the TPM_PERSISTENT_DATA -> operatorAuth */ + TPM_Digest_Copy(tpm_state->tpm_permanent_data.operatorAuth, operatorAuth); + /* 3. The TPM SHALL set TPM_PERMANENT_FLAGS -> operator to TRUE */ + printf("TPM_Process_SetOperatorAuth: Setting operator to TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.tpmOperator), /* flag */ + TRUE); /* value */ + /* Store the permanent data and flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + TRUE, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SetOperatorAuth: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 9.3 TPM_ResetLockValue rev 96 + + Command that resets the TPM dictionary attack mitigation values + + This allows the TPM owner to cancel the effect of a number of successive authorization failures. + + If this command itself has an authorization failure, it is blocked for the remainder of the lock + out period. This prevents a dictionary attack on the owner authorization using this command. + + It is understood that this command allows the TPM owner to perform a dictionary attack on other + authorization values by alternating a trial and this command. Similarly, delegating this command + allows the owner's delegate to perform a dictionary attack. +*/ + +TPM_RESULT TPM_Process_ResetLockValue(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for TPM Owner + authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* HMAC key TPM Owner auth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ResetLockValue: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + /* Update disableResetLock. Ignore the return code since this command is not locked out */ + TPM_Authdata_CheckState(tpm_state); + /* NOTE No TPM_CHECK_NO_LOCKOUT, since this command proceeds anyway */ + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_ENABLED | + TPM_CHECK_ACTIVATED | + TPM_CHECK_OWNER)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ResetLockValue: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. If TPM_STCLEAR_DATA -> disableResetLock is TRUE return TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_stclear_data.disableResetLock) { + printf("TPM_Process_ResetLockValue: Error, command locked out\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* a. The internal dictionary attack mechanism will set TPM_STCLEAR_DATA -> disableResetLock to + FALSE when the timeout period expires */ + /* NOTE Done by TPM_Authdata_CheckState() */ + /* Validate the parameters and owner authorization for this command */ + if (returnCode == TPM_SUCCESS) { + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. If the the command and parameters validation using ownerAuth fails */ + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_ResetLockValue: Error, disabling ordinal\n"); + /* a. Set TPM_STCLEAR_DATA -> disableResetLock to TRUE */ + tpm_state->tpm_stclear_data.disableResetLock = TRUE; + /* b. Restart the TPM dictionary attack lock out period */ + /* A failure restarts it anyway with double the period.*/ + /* c. Return TPM_AUTHFAIL */ + } + } + /* 3. Reset the internal TPM dictionary attack mitigation mechanism */ + /* a. The mechanism is vendor specific and can include time outs, reboots, and other mitigation + strategies */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ResetLockValue: Resetting the failure counter\n"); + /* clear the authorization failure counter */ + tpm_state->tpm_stclear_data.authFailCount = 0; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ResetLockValue: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + return rcf; +} + diff --git a/src/tpm12/tpm_admin.h b/src/tpm12/tpm_admin.h new file mode 100644 index 0000000..f162ee4 --- /dev/null +++ b/src/tpm12/tpm_admin.h @@ -0,0 +1,141 @@ +/********************************************************************************/ +/* */ +/* TPM Admin Test and Opt-in */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_admin.h 4403 2011-02-08 18:28:22Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_ADMIN_H +#define TPM_ADMIN_H + +#include "tpm_types.h" +#include "tpm_global.h" +#include "tpm_store.h" + +TPM_RESULT TPM_LimitedSelfTestCommon(void); +TPM_RESULT TPM_LimitedSelfTestTPM(tpm_state_t *tpm_state); + +TPM_RESULT TPM_ContinueSelfTestCmd(tpm_state_t *tpm_state); +TPM_RESULT TPM_SelfTestFullCmd(tpm_state_t *tpm_state); + +TPM_RESULT TPM_Process_ContinueSelfTest(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SelfTestFull(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_GetTestResult(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SetOwnerInstall(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_OwnerSetDisable(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_PhysicalDisable(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_PhysicalEnable(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_PhysicalSetDeactivated(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SetTempDeactivated(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SetOperatorAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_ResetLockValue(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +#endif diff --git a/src/tpm12/tpm_audit.c b/src/tpm12/tpm_audit.c new file mode 100644 index 0000000..529dee3 --- /dev/null +++ b/src/tpm12/tpm_audit.c @@ -0,0 +1,1271 @@ +/********************************************************************************/ +/* */ +/* Audit Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_audit.c 4438 2011-02-13 23:03:56Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_auth.h" +#include "tpm_counter.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_global.h" +#include "tpm_key.h" +#include "tpm_nonce.h" +#include "tpm_permanent.h" +#include "tpm_process.h" + +#include "tpm_audit.h" + +/* + TPM_AUDIT_EVENT_IN +*/ + +/* TPM_AuditEventIn_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_AuditEventIn_Init(TPM_AUDIT_EVENT_IN *tpm_audit_event_in) +{ + printf(" TPM_AuditEventIn_Init:\n"); + TPM_Digest_Init(tpm_audit_event_in->inputParms); + TPM_CounterValue_Init(&(tpm_audit_event_in->auditCount)); + return; +} + +/* TPM_AuditEventIn_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_AuditEventIn_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_AUDIT_EVENT_IN *tpm_audit_event_in) +{ + TPM_RESULT rc = 0; + + printf(" TPM_AuditEventIn_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_AUDIT_EVENT_IN); + } + /* store inputParms */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_audit_event_in->inputParms); + } + /* store auditCount */ + if (rc == 0) { + rc = TPM_CounterValue_StorePublic(sbuffer, &(tpm_audit_event_in->auditCount)); + } + return rc; +} + +/* TPM_AuditEventIn_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_AuditEventIn_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_AuditEventIn_Delete(TPM_AUDIT_EVENT_IN *tpm_audit_event_in) +{ + printf(" TPM_AuditEventIn_Delete:\n"); + if (tpm_audit_event_in != NULL) { + TPM_AuditEventIn_Init(tpm_audit_event_in); + } + return; +} + +/* + TPM_AUDIT_EVENT_OUT +*/ + +/* TPM_AuditEventOut_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_AuditEventOut_Init(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out) +{ + printf(" TPM_AuditEventOut_Init:\n"); + TPM_Digest_Init(tpm_audit_event_out->outputParms); + TPM_CounterValue_Init(&(tpm_audit_event_out->auditCount)); + return; +} + +/* TPM_AuditEventOut_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_AuditEventOut_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_AUDIT_EVENT_OUT *tpm_audit_event_out) +{ + TPM_RESULT rc = 0; + + printf(" TPM_AuditEventOut_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_AUDIT_EVENT_OUT); + } + /* store outputParms */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_audit_event_out->outputParms); + } + /* store auditCount */ + if (rc == 0) { + rc = TPM_CounterValue_StorePublic(sbuffer, &(tpm_audit_event_out->auditCount)); + } + return rc; +} + +/* TPM_AuditEventOut_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_AuditEventOut_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_AuditEventOut_Delete(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out) +{ + printf(" TPM_AuditEventOut_Delete:\n"); + if (tpm_audit_event_out != NULL) { + TPM_AuditEventOut_Init(tpm_audit_event_out); + } + return; +} + +/* + ordinalAuditStatus Processing +*/ + +/* TPM_OrdinalAuditStatus_Init() initializes the TPM_PERMANENT_DATA 'ordinalAuditStatus' to the + default + + The flags are stored as a bit map to conserve NVRAM. + + The array is not written back to NVRAM. +*/ + +TPM_RESULT TPM_OrdinalAuditStatus_Init(TPM_PERMANENT_DATA *tpm_permanent_data) +{ + TPM_RESULT rc = 0; + TPM_COMMAND_CODE ord; /* iterate through all ordinals */ + TPM_BOOL auditDefault; /* result for an ordinal */ + TPM_BOOL altered; + + printf(" TPM_OrdinalAuditStatus_Init:\n"); + + for (ord = 0 ; (rc == 0) && (ord < TPM_ORDINALS_MAX) ; ord++) { + /* get the default audit state from the ordinals table */ + TPM_OrdinalTable_GetAuditDefault(&auditDefault, ord); + /* write to the TPM_PERMANENT_DATA bit map */ + rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault, ord); + } + /* hack for TSC ordinals */ + if (rc == 0) { + TPM_OrdinalTable_GetAuditDefault(&auditDefault, TSC_ORD_PhysicalPresence); + rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault, + TSC_ORD_PhysicalPresence); + } + if (rc == 0) { + TPM_OrdinalTable_GetAuditDefault(&auditDefault, TSC_ORD_ResetEstablishmentBit); + rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault, + TSC_ORD_ResetEstablishmentBit); + } + return rc; +} + +/* TPM_OrdinalAuditStatus_Store() stores a list of all ordinals being audited + */ + +TPM_RESULT TPM_OrdinalAuditStatus_Store(TPM_SIZED_BUFFER *ordinalList, + TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_COMMAND_CODE startOrdinal) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; + TPM_COMMAND_CODE ord; + TPM_BOOL auditStatus; + + printf(" TPM_OrdinalAuditStatus_Store\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* scan through the ordinals array */ + for (ord = startOrdinal ; (rc == 0) && (ord < TPM_ORDINALS_MAX) ; ord++ ) { + /* determine if the ordinal being audited */ + if (rc == 0) { + rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, ord, tpm_permanent_data); + } + /* if being audited */ + if ((rc == 0) && auditStatus) { + rc = TPM_Sbuffer_Append32(&sbuffer, ord); /* append ordinal to the list */ + } + } + /* scan the TSC ordinals */ + if (rc == 0) { + if (rc == 0) { + rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, + TSC_ORD_PhysicalPresence, + tpm_permanent_data); + } + if ((rc == 0) && auditStatus) { + rc = TPM_Sbuffer_Append32(&sbuffer, TSC_ORD_PhysicalPresence); + } + if (rc == 0) { + rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, + TSC_ORD_ResetEstablishmentBit, + tpm_permanent_data); + } + /* if being audited */ + if ((rc == 0) && auditStatus) { + rc = TPM_Sbuffer_Append32(&sbuffer, TSC_ORD_ResetEstablishmentBit); + } + } + /* convert the list to a TPM_SIZED_BUFFER */ + if (rc == 0) { + rc = TPM_SizedBuffer_SetFromStore(ordinalList, &sbuffer); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_OrdinalAuditStatus_GetAuditState() gets the audit state for the ordinal + */ + +TPM_RESULT TPM_OrdinalAuditStatus_GetAuditStatus(TPM_BOOL *auditStatus, + TPM_COMMAND_CODE ordinal, + TPM_PERMANENT_DATA *tpm_permanent_data) +{ + TPM_RESULT rc = 0; + size_t index; /* index of ordinal in array */ + unsigned int offset; /* bit position of ordinal in array */ + unsigned char bit; + + if (rc == 0) { + /* handle the TPM ordinals */ + if (ordinal < TPM_ORDINALS_MAX) { + index = ordinal/CHAR_BIT; + offset = ordinal % CHAR_BIT; + bit = 0x01 << offset; + *auditStatus = tpm_permanent_data->ordinalAuditStatus[index] & bit; + } + /* handle the TSC ordinals */ + else if (ordinal == TSC_ORD_PhysicalPresence) { + *auditStatus = tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT; + } + else if (ordinal == TSC_ORD_ResetEstablishmentBit) { + *auditStatus = tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT; + } + else { + printf("TPM_OrdinalAuditStatus_GetAuditStatus: Error (fatal) " + "ordinal %08x out of range\n", ordinal); + rc = TPM_FAIL; /* should never occur, always called with ordinal processing */ + } + } + /* trace the ordinals with auditing enabled */ + if ((rc == 0) && *auditStatus) { + printf(" TPM_OrdinalAuditStatus_GetAuditStatus: ordinal %08x status %02x\n", + ordinal, *auditStatus); + } + return rc; +} + +/* TPM_OrdinalAuditStatus_SetAuditStatus() sets the TPM_PERMANENT_DATA -> ordinalAuditStatus for the + ordinal + + The flags are stored as a bit map to conserve NVRAM. + + The array is not written back to NVRAM. On error, TPM_PERMANENT_DATA is not changed. + + altered is TRUE if the bit was changed, +*/ + +TPM_RESULT TPM_OrdinalAuditStatus_SetAuditStatus(TPM_BOOL *altered, + TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL auditStatus, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + TPM_BOOL auditable; /* TRUE if the ordinal is auditable by this TPM + implementation */ + size_t index; /* index of ordinal in array */ + unsigned int offset; /* bit position of ordinal in array */ + unsigned char bit; + + *altered = FALSE; /* default, returned on error */ +#if 0 + printf(" TPM_OrdinalAuditStatus_SetAuditStatus: ordinal %08x status %02x\n", + ordinal, auditStatus); +#endif + /* If trying to set, screen against the 'never audit' ordinal table */ + if ((rc == 0) && auditStatus) { + TPM_OrdinalTable_GetAuditable(&auditable, ordinal); + /* if it is a 'never audit' ordinal, it can not be set */ + if (!auditable) { + printf("TPM_OrdinalAuditStatus_SetAuditStatus: " + "Error, cannot audit ordinal %08x\n", ordinal); + rc = TPM_BAD_PARAMETER; + } + } + if (rc == 0) { + /* handle the TPM ordinals */ + if (ordinal < TPM_ORDINALS_MAX) { + index = ordinal/CHAR_BIT; + offset = ordinal % CHAR_BIT; + bit = 0x01 << offset; + /* determine if the bit is to be altered */ + if (((tpm_permanent_data->ordinalAuditStatus[index] & bit) && !auditStatus) || + (!(tpm_permanent_data->ordinalAuditStatus[index] & bit) && auditStatus)) { + + *altered = TRUE; + } + if (auditStatus) { + /* set the bit */ + tpm_permanent_data->ordinalAuditStatus[index] |= bit; + } + else { + /* clear the bit */ + tpm_permanent_data->ordinalAuditStatus[index] &= ~bit; + } + } + /* handle the TSC ordinals */ + else if (ordinal == TSC_ORD_PhysicalPresence) { + /* determine if the bit is to be altered */ + if (((tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT) + && !auditStatus) || + (!(tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT) + && auditStatus)) { + + *altered = TRUE; + } + if (auditStatus) { + tpm_permanent_data->tscOrdinalAuditStatus |= TSC_PHYS_PRES_AUDIT; + } + else { + tpm_permanent_data->tscOrdinalAuditStatus &= ~TSC_PHYS_PRES_AUDIT; + } + } + else if (ordinal == TSC_ORD_ResetEstablishmentBit) { + if (auditStatus) { + /* determine if the bit is to be altered */ + if (((tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT) + && !auditStatus) || + (!(tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT) + && auditStatus)) { + + *altered = TRUE; + } + tpm_permanent_data->tscOrdinalAuditStatus |= TSC_RESET_ESTAB_AUDIT; + } + else { + tpm_permanent_data->tscOrdinalAuditStatus &= ~TSC_RESET_ESTAB_AUDIT; + } + } + else { + printf("TPM_OrdinalAuditStatus_SetAuditStatus: Error ordinal %08x out of range\n", + ordinal); + rc = TPM_BADINDEX; + } + } + return rc; +} + +/* + Common Processing Functions +*/ + +/* 8.1 Audit Generation rev 109 + + TPM_AuditDigest_ExtendIn() extends the audit digest with a digest of input parameters +*/ + +TPM_RESULT TPM_AuditDigest_ExtendIn(tpm_state_t *tpm_state, + TPM_DIGEST inParamDigest) +{ + TPM_RESULT rc = 0; + TPM_AUDIT_EVENT_IN tpm_audit_event_in; + TPM_STORE_BUFFER eventIn_sbuffer; + const unsigned char *eventIn_buffer; /* serialized buffer */ + uint32_t eventIn_length; /* serialization length */ + + printf(" TPM_AuditDigest_ExtendIn:\n"); + TPM_AuditEventIn_Init(&tpm_audit_event_in); /* freed @1 */ + TPM_Sbuffer_Init(&eventIn_sbuffer); /* freed @2 */ + + if (rc == 0) { + /* b. Create A1 a TPM_AUDIT_EVENT_IN structure */ + /* NOTE Done by TPM_AuditEventIn_Init() */ + /* i. Set A1 -> inputParms to the digest of the input parameters from the command */ + /* (1) Digest value according to the HMAC digest rules of the "above the line" parameters + (i.e. the first HMAC digest calculation). */ + TPM_Digest_Copy(tpm_audit_event_in.inputParms, inParamDigest); + /* ii. Set A1 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */ + TPM_CounterValue_CopyPublic(&(tpm_audit_event_in.auditCount), + &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); + /* serialize the A1 TPM_AUDIT_EVENT_IN object */ + rc = TPM_AuditEventIn_Store(&eventIn_sbuffer, &tpm_audit_event_in); + + } + if (rc == 0) { + /* get the serialization results */ + TPM_Sbuffer_Get(&eventIn_sbuffer, &eventIn_buffer, &eventIn_length); + /* c. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A1) */ + TPM_PrintFour(" TPM_AuditDigest_ExtendIn: Previous digest", + tpm_state->tpm_stclear_data.auditDigest); + TPM_PrintAll(" TPM_AuditDigest_ExtendIn: TPM_AUDIT_EVENT_IN", eventIn_buffer, eventIn_length); + rc = TPM_SHA1(tpm_state->tpm_stclear_data.auditDigest, + TPM_DIGEST_SIZE, tpm_state->tpm_stclear_data.auditDigest, + eventIn_length, eventIn_buffer, + 0, NULL); + TPM_PrintFour(" TPM_AuditDigest_ExtendIn: Current digest (in)", + tpm_state->tpm_stclear_data.auditDigest); + } + TPM_AuditEventIn_Delete(&tpm_audit_event_in); /* @1 */ + TPM_Sbuffer_Delete(&eventIn_sbuffer); /* @2 */ + return rc; +} + +/* 8.1 Audit Generation rev 109 + + TPM_AuditDigest_ExtendOut() extends the audit digest with a digest of output parameters +*/ + +TPM_RESULT TPM_AuditDigest_ExtendOut(tpm_state_t *tpm_state, + TPM_DIGEST outParamDigest) +{ + TPM_RESULT rc = 0; + TPM_AUDIT_EVENT_OUT tpm_audit_event_out; + TPM_STORE_BUFFER eventOut_sbuffer; + const unsigned char *eventOut_buffer; /* serialized buffer */ + uint32_t eventOut_length; /* serialization length */ + + printf(" TPM_AuditDigest_ExtendOut:\n"); + TPM_AuditEventOut_Init(&tpm_audit_event_out); /* freed @1 */ + TPM_Sbuffer_Init(&eventOut_sbuffer); /* freed @2 */ + + if (rc == 0) { + /* d. Create A2 a TPM_AUDIT_EVENT_OUT structure */ + /* NOTE Done by TPM_AuditEventOut_Init() */ + /* i. Set A2 -> outputParms to the digest of the output parameters from the command */ + /* (1). Digest value according to the HMAC digest rules of the "above the line" parameters + (i.e. the first HMAC digest calculation). */ + TPM_Digest_Copy(tpm_audit_event_out.outputParms, outParamDigest); + /* ii. Set A2 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */ + TPM_CounterValue_CopyPublic(&(tpm_audit_event_out.auditCount), + &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); + /* serialize the A2 TPM_AUDIT_EVENT_OUT object */ + rc = TPM_AuditEventOut_Store(&eventOut_sbuffer, &tpm_audit_event_out); + } + if (rc == 0) { + /* get the serialization results */ + TPM_Sbuffer_Get(&eventOut_sbuffer, &eventOut_buffer, &eventOut_length); + /* e. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A2) */ + TPM_PrintFour(" TPM_AuditDigest_ExtendOut: Previous digest", + tpm_state->tpm_stclear_data.auditDigest); + TPM_PrintAll(" TPM_AuditDigest_ExtendOut: TPM_AUDIT_EVENT_OUT", eventOut_buffer, eventOut_length); + rc = TPM_SHA1(tpm_state->tpm_stclear_data.auditDigest, + TPM_DIGEST_SIZE, tpm_state->tpm_stclear_data.auditDigest, + eventOut_length, eventOut_buffer, + 0, NULL); + TPM_PrintFour(" TPM_AuditDigest_ExtendOut: Current digest (out)", + tpm_state->tpm_stclear_data.auditDigest); + } + TPM_AuditEventOut_Delete(&tpm_audit_event_out); /* @1 */ + TPM_Sbuffer_Delete(&eventOut_sbuffer); /* @2 */ + return rc; +} + +/* + Processing Functions +*/ + +/* The TPM generates an audit event in response to the TPM executing a command that has the audit + flag set to TRUE for that command. + + The TPM maintains an extended value for all audited operations. +*/ + +/* 8.3 TPM_GetAuditDigest rev 87 + + This returns the current audit digest. The external audit log has the responsibility to track the + parameters that constitute the audit digest. + + This value may be unique to an individual TPM. The value however will be changing at a rate set + by the TPM Owner. Those attempting to use this value may find it changing without their + knowledge. This value represents a very poor source of tracking uniqueness. +*/ + +TPM_RESULT TPM_Process_GetAuditDigest(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + uint32_t startOrdinal; /* The starting ordinal for the list of audited ordinals */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_DIGEST auditDigest; /* Log of all audited events */ + TPM_BOOL more; /* TRUE if the output does not contain a full list of + audited ordinals */ + TPM_SIZED_BUFFER ordList; /* List of ordinals that are audited. */ + + printf("TPM_Process_GetAuditDigest: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&ordList); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get startOrdinal parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&startOrdinal, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetAuditDigest: startOrdinal %08x\n", startOrdinal); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetAuditDigest: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + /* 1. The TPM sets auditDigest to TPM_STANY_DATA -> auditDigest */ + TPM_Digest_Copy(auditDigest, tpm_state->tpm_stclear_data.auditDigest); + /* 2. The TPM sets counterValue to TPM_PERMANENT_DATA -> auditMonotonicCounter */ + /* NOTE Since there is only one, use it directly on the output */ + printf("TPM_Process_GetAuditDigest: Counter value %08x\n", + tpm_state->tpm_permanent_data.auditMonotonicCounter.counter); + /* 3. The TPM creates an ordered list of audited ordinals. The list starts at startOrdinal + listing each ordinal that is audited. */ + /* a. If startOrdinal is 0 then the first ordinal that could be audited would be TPM_OIAP + (ordinal 0x0000000A) */ + /* b. The next ordinal would be TPM_OSAP (ordinal 0x0000000B) */ + returnCode = TPM_OrdinalAuditStatus_Store(&ordList, + &(tpm_state->tpm_permanent_data), + startOrdinal); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetAuditDigest: ordSize %u\n", ordList.size); + /* 4. If the ordered list does not fit in the output buffer the TPM sets more to TRUE */ + more = FALSE; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_GetAuditDigest: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + /* append counterValue */ + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append counterValue */ + returnCode = TPM_CounterValue_StorePublic + (response, + &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); + } + /* 5. Return TPM_STANY_DATA -> auditDigest as auditDigest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Store(response, auditDigest); + } + /* append more */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append(response, &more, sizeof(TPM_BOOL)); + } + /* append ordList */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Store(response, &ordList); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&ordList); /* @1 */ + return rcf; +} + +/* 8.4 TPM_GetAuditDigestSigned rev 101 + + The signing of the audit log returns the entire digest value and the list of currently audited + commands. + + The inclusion of the list of audited commands as an atomic operation is to tie the current digest + value with the list of commands that are being audited. + + Note to future architects + + When auditing functionality is active in a TPM, it may seem logical to remove this ordinal from + the active set of ordinals as the signing functionality of this command could be handled in a + signed transport session. While true this command has a secondary affect also, resetting the + audit log digest. As the reset requires TPM Owner authentication there must be some way in this + command to reflect the TPM Owner wishes. By requiring that a TPM Identity key be the only key + that can sign and reset the TPM Owners authentication is implicit in the execution of the command + (TPM Identity Keys are created and controlled by the TPM Owner only). Hence while one might want + to remove an ordinal this is not one that can be removed if auditing is functional. +*/ + +TPM_RESULT TPM_Process_GetAuditDigestSigned(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The handle of a loaded key that can perform digital + signatures. */ + TPM_BOOL closeAudit; /* Indication if audit session should be closed */ + TPM_NONCE antiReplay; /* A nonce to prevent replay attacks */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for key + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA keyAuth; /* Authorization. HMAC key: key.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ + TPM_SECRET *keyUsageAuth; + TPM_BOOL parentPCRStatus; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SIGN_INFO d1SignInfo; + TPM_SIZED_BUFFER d3SizedBuffer; /* List of ordinals that are audited. */ + TPM_STORE_BUFFER d2Sbuffer; /* data to be signed */ + TPM_DIGEST h1; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_DIGEST ordinalDigest; /* Digest of all audited ordinals */ + TPM_SIZED_BUFFER sig; /* The signature of the area */ + + printf("TPM_Process_GetAuditDigestSigned: Ordinal Entry\n"); + TPM_SignInfo_Init(&d1SignInfo); /* freed @1 */ + TPM_SizedBuffer_Init(&d3SizedBuffer); /* freed @2 */ + TPM_Sbuffer_Init(&d2Sbuffer); /* freed @3 */ + TPM_SizedBuffer_Init(&sig); /* freed @4 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get closeAudit parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetAuditDigestSigned: keyHandle %08x\n", keyHandle); + returnCode = TPM_LoadBool(&closeAudit, &command, ¶mSize); + } + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(antiReplay, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + keyAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetAuditDigestSigned: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the AuthData and parameters using keyAuth, return TPM_AUTHFAIL on error */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ + if (sigKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_GetAuditDigestSigned: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + sigKey, + keyUsageAuth, /* OIAP */ + sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* validate the authorization to use the key pointed to by keyHandle */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + keyAuth); /* Authorization digest for input */ + } + /* 2.Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, + if not return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->keyUsage != TPM_KEY_SIGNING) && + (sigKey->keyUsage != TPM_KEY_IDENTITY) && + (sigKey->keyUsage != TPM_KEY_LEGACY)) { + printf("TPM_Process_GetAuditDigestSigned: Error, keyUsage %04hx is invalid\n", + sigKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. The TPM validates that the key pointed to by keyHandle has a signature scheme of + TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO, return TPM_INVALID_KEYUSAGE on + error */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { + printf("TPM_Process_GetAuditDigestSigned: Error, invalid sigScheme %04hx\n", + sigKey->algorithmParms.sigScheme); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + if (returnCode == TPM_SUCCESS) { + /* 4. Create D1 a TPM_SIGN_INFO structure and set the structure defaults */ + /* NOTE Done by TPM_SignInfo_Init() */ + /* a. Set D1 -> fixed to "ADIG" */ + memcpy(d1SignInfo.fixed, "ADIG", TPM_SIGN_INFO_FIXED_SIZE); + /* b. Set D1 -> replay to antiReplay */ + TPM_Nonce_Copy(d1SignInfo.replay, antiReplay); + /* c. Create D3 a list of all audited ordinals as defined in the TPM_GetAuditDigest + uint32_t[] ordList outgoing parameter */ + returnCode = TPM_OrdinalAuditStatus_Store(&d3SizedBuffer, + &(tpm_state->tpm_permanent_data), + 0); + } + /* d. Create D4 (ordinalDigest outgoing parameter) the SHA-1 of D3 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1(ordinalDigest, + d3SizedBuffer.size, d3SizedBuffer.buffer, + 0, NULL); + } + if (returnCode == TPM_SUCCESS) { + /* e. Set auditDigest to TPM_STANY_DATA -> auditDigest */ + /* NOTE: Use it directly on the output */ + /* f. Set counterValue to TPM_PERMANENT_DATA -> auditMonotonicCounter */ + /* NOTE Since there is only one, use it directly on the output */ + /* g. Create D2 the concatenation of auditDigest || counterValue || D4 */ + returnCode = TPM_Sbuffer_Append(&d2Sbuffer, + tpm_state->tpm_stclear_data.auditDigest, TPM_DIGEST_SIZE); + } + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_CounterValue_StorePublic(&d2Sbuffer, + &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append(&d2Sbuffer, + ordinalDigest, TPM_DIGEST_SIZE); + } + /* h. Set D1 -> data to D2 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_SetFromStore(&(d1SignInfo.data), &d2Sbuffer); + } + /* i. Create a digital signature of the SHA-1 of D1 by using the signature scheme for keyHandle + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(h1, &d1SignInfo, + (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ + h1, /* message */ + TPM_DIGEST_SIZE, /* message size */ + sigKey); /* input, signing key */ + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_GetAuditDigestSigned: auditDigest", + tpm_state->tpm_stclear_data.auditDigest); + TPM_PrintFour("TPM_Process_GetAuditDigestSigned: ordinalDigest", + ordinalDigest); + } + /* j. Set ordinalDigest to D4 */ + /* NOTE Created directly in ordinalDigest */ + /* 5. If closeAudit == TRUE */ + if ((returnCode == TPM_SUCCESS) && closeAudit) { + /* a. If keyHandle->keyUsage is TPM_KEY_IDENTITY */ + if (sigKey->keyUsage == TPM_KEY_IDENTITY) { + /* i. TPM_STANY_DATA -> auditDigest MUST be set to all zeros. */ + TPM_Digest_Init(tpm_state->tpm_stclear_data.auditDigest); + } + /* b. Else */ + else { + /* i. Return TPM_INVALID_KEYUSAGE */ + printf("TPM_Process_GetAuditDigestSigned: Error, " + "cannot closeAudit with keyUsage %04hx\n", sigKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_GetAuditDigestSigned: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return counterValue */ + returnCode = TPM_CounterValue_StorePublic + (response, + &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); + } + /* return auditDigest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Store(response, tpm_state->tpm_stclear_data.auditDigest); + } + /* return ordinalDigest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Store(response, ordinalDigest); + } + /* return sig */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Store(response, &sig); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SignInfo_Delete(&d1SignInfo); /* @1 */ + TPM_SizedBuffer_Delete(&d3SizedBuffer); /* @2 */ + TPM_Sbuffer_Delete(&d2Sbuffer); /* @3 */ + TPM_SizedBuffer_Delete(&sig); /* @4 */ + return rcf; +} + +/* 8.5 TPM_SetOrdinalAuditStatus rev 109 + + Set the audit flag for a given ordinal. This command requires the authentication of the TPM + Owner. +*/ + +TPM_RESULT TPM_Process_SetOrdinalAuditStatus(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_COMMAND_CODE ordinalToAudit; /* The ordinal whose audit flag is to be set */ + TPM_BOOL auditState; /* Value for audit flag */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner + authentication. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL altered; /* status is changing */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SetOrdinalAuditStatus: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get ordinalToAudit parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&ordinalToAudit, &command, ¶mSize); + } + /* get auditState parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadBool(&auditState, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SetOrdinalAuditStatus: ordinalToAudit %08x auditState %02x\n", + ordinalToAudit, auditState); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SetOrdinalAuditStatus: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the AuthData to execute the command and the parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Validate that the ordinal points to a valid TPM ordinal, return TPM_BADINDEX on error */ + /* a. Valid TPM ordinal means an ordinal that the TPM implementation supports */ + /* Done by TPM_OrdinalAuditStatus_SetAuditState() */ + /* 3. Set the non-volatile flag associated with ordinalToAudit to the value in auditState */ + /* NOTE: On error, TPM_PERMANENT_DATA is not changed */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_OrdinalAuditStatus_SetAuditStatus(&altered, + &(tpm_state->tpm_permanent_data), + auditState, /* uninitialized */ + ordinalToAudit); + /* It's not really uninitialized, but beam doesn't understand that TPM_GetInParamDigest() + can't turn a FALSE into a TRUE */ + } + /* Store the permanent data back to NVRAM */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PermanentAll_NVStore(tpm_state, + altered, + returnCode); + } + /* Audit Generation 3.b. Corner Cases: TPM_SetOrdinalAuditStatus: In the case where the + ordinalToAudit is TPM_ORD_SetOrdinalAuditStatus, audit is based on the initial state, not the + final state. */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SetOrdinalAuditStatus: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + return rcf; +} diff --git a/src/tpm12/tpm_audit.h b/src/tpm12/tpm_audit.h new file mode 100644 index 0000000..4bb2e2e --- /dev/null +++ b/src/tpm12/tpm_audit.h @@ -0,0 +1,117 @@ +/********************************************************************************/ +/* */ +/* Audit Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_audit.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_AUDIT_H +#define TPM_AUDIT_H + +#include "tpm_global.h" +#include "tpm_store.h" +#include "tpm_structures.h" + +/* + TPM_AUDIT_EVENT_IN +*/ + +void TPM_AuditEventIn_Init(TPM_AUDIT_EVENT_IN *tpm_audit_event_in); +TPM_RESULT TPM_AuditEventIn_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_AUDIT_EVENT_IN *tpm_audit_event_in); +void TPM_AuditEventIn_Delete(TPM_AUDIT_EVENT_IN *tpm_audit_event_in); + +/* + TPM_AUDIT_EVENT_OUT +*/ + +void TPM_AuditEventOut_Init(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out); +TPM_RESULT TPM_AuditEventOut_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_AUDIT_EVENT_OUT *tpm_audit_event_out); +void TPM_AuditEventOut_Delete(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out); + +/* + ordinalAuditStatus Processing +*/ + +TPM_RESULT TPM_OrdinalAuditStatus_Init(TPM_PERMANENT_DATA *tpm_permanent_data); +TPM_RESULT TPM_OrdinalAuditStatus_Store(TPM_SIZED_BUFFER *ordinalList, + TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_COMMAND_CODE startOrdinal); +TPM_RESULT TPM_OrdinalAuditStatus_GetAuditStatus(TPM_BOOL *auditStatus, + TPM_COMMAND_CODE ordinal, + TPM_PERMANENT_DATA *tpm_permanent_data); +TPM_RESULT TPM_OrdinalAuditStatus_SetAuditStatus(TPM_BOOL *altered, + TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL auditStatus, + TPM_COMMAND_CODE ordinal); + +/* + Common Processing Functions +*/ + +TPM_RESULT TPM_AuditDigest_ExtendIn(tpm_state_t *tpm_state, + TPM_DIGEST inParamDigest); +TPM_RESULT TPM_AuditDigest_ExtendOut(tpm_state_t *tpm_state, + TPM_DIGEST outParamDigest); + +/* + Processing Functions +*/ + +TPM_RESULT TPM_Process_GetAuditDigest(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_GetAuditDigestSigned(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_SetOrdinalAuditStatus(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +#endif diff --git a/src/tpm12/tpm_auth.c b/src/tpm12/tpm_auth.c new file mode 100644 index 0000000..70888d7 --- /dev/null +++ b/src/tpm12/tpm_auth.c @@ -0,0 +1,2301 @@ +/********************************************************************************/ +/* */ +/* Authorization */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_auth.c 4438 2011-02-13 23:03:56Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_init.h" +#include "tpm_key.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_permanent.h" +#include "tpm_process.h" +#include "tpm_secret.h" +#include "tpm_storage.h" +#include "tpm_time.h" +#include "tpm_transport.h" + +#include "tpm_auth.h" + +/* Dictionary attack mitigation: + + TPM_Authdata_CheckState() - called at command entry + if past limit, + check authFailTime vs. current time + if command allowed + disableResetLock = FALSE + + TPM_Authdata_Check() - called during the command to validate authorization data + TPM_Authdata_Fail() - called on failure + authFailCount++ + if past limit, + authFailTime = current time + + TPM_ResetLockValue + TPM_Authdata_CheckState() + disableResetLock = FALSE if no lockout + if disableResetLock, return error + if authorization failure + disableResetLock = TRUE + authFailCount = 0 +*/ + +#if 0 +/* TPM_Authdata_Init() zeros the tpm_authdata + +*/ + +void TPM_Authdata_Init(TPM_AUTHDATA tpm_authdata) +{ + printf(" TPM_Authdata_Init:\n"); + memset(tpm_authdata, 0, TPM_AUTHDATA_SIZE); + return; +} +#endif + +/* TPM_Authdata_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes +*/ + +TPM_RESULT TPM_Authdata_Load(TPM_AUTHDATA tpm_authdata, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Authdata_Load:\n"); + + /* check stream_size */ + if (rc == 0) { + if (*stream_size < TPM_AUTHDATA_SIZE) { + printf("TPM_Authdata_Load: Error, stream_size %u less than %u\n", + *stream_size, TPM_DIGEST_SIZE); + rc = TPM_BAD_PARAM_SIZE; + } + } + if (rc == 0) { + memcpy(tpm_authdata, *stream, TPM_AUTHDATA_SIZE); + *stream += TPM_AUTHDATA_SIZE; + *stream_size -= TPM_AUTHDATA_SIZE; + } + return rc; +} + +/* TPM_Authdata_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + After use, call TPM_Sbuffer_Delete() to free memory +*/ + +TPM_RESULT TPM_Authdata_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_AUTHDATA tpm_authdata) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Authdata_Store:\n"); + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_authdata, TPM_AUTHDATA_SIZE); + } + return rc; +} + +/* TPM_AuthParams_Get() is common code to load a set of "below the double line" request parameters + from the input stream. + */ + +TPM_RESULT TPM_AuthParams_Get(TPM_AUTHHANDLE *authHandle, /* The authorization handle used for + this command */ + TPM_BOOL *authHandleValid, + TPM_NONCE nonceOdd, /* Nonce generated by system associated with + authHandle */ + TPM_BOOL *continueAuthSession, /* The continue use flag for the + authorization handle */ + TPM_AUTHDATA authData, /* Authorization digest for input params. */ + unsigned char **command, /* parameter stream */ + uint32_t *paramSize) /* bytes left in command */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_AuthParams_Get:\n"); + /* get authHandle parameter */ + if (rc == 0) { + rc = TPM_Load32(authHandle, command, paramSize); + } + /* get nonceOdd parameter */ + if (rc == 0) { + rc = TPM_Nonce_Load(nonceOdd, command, paramSize); + } + /* get continueAuthSession parameter */ + if (rc == 0) { + rc = TPM_LoadBool(continueAuthSession, command, paramSize); + } + /* get authData parameter */ + if (rc == 0) { + rc = TPM_Authdata_Load(authData, command, paramSize); + } + if (rc == 0) { + *authHandleValid = TRUE; /* so handle can be terminated */ + } + return rc; +} + + +/* TPM_SetAuthParams is common code to set a set of "below the double line" response parameters. + */ + +TPM_RESULT TPM_AuthParams_Set(TPM_STORE_BUFFER *response, + TPM_SECRET hmacKey, /* HMAC key */ + TPM_AUTH_SESSION_DATA *auth_session_data, /* session data for + authHandle */ + TPM_DIGEST outParamDigest, + TPM_NONCE nonceOdd, /* Nonce generated by system + associated with authHandle */ + TPM_BOOL continueAuthSession) /* session continue use flag */ +{ + TPM_RESULT rc = 0; + TPM_AUTHDATA resAuth; /* The authorization digest for the returned parameters */ + + printf(" TPM_AuthParams_Set:\n"); + /* generate new nonceEven */ + if (rc == 0) { + rc = TPM_Nonce_Generate(auth_session_data->nonceEven); + } + /* append nonceEven */ + if (rc == 0) { + rc = TPM_Nonce_Store(response, auth_session_data->nonceEven); + } + /* append continueAuthSession */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(response, &continueAuthSession, sizeof(TPM_BOOL)); + } + /* Calculate resAuth using the hmac key */ + if (rc == 0) { + rc = TPM_Authdata_Generate(resAuth, /* result */ + hmacKey, /* HMAC key */ + outParamDigest, /* params */ + auth_session_data->nonceEven, + nonceOdd, + continueAuthSession); + } + /* append resAuth */ + if (rc == 0) { + rc = TPM_Authdata_Store(response, resAuth); + } + return rc; +} + +TPM_RESULT TPM_Authdata_Generate(TPM_AUTHDATA resAuth, /* result */ + TPM_SECRET usageAuth, /* HMAC key */ + TPM_DIGEST outParamDigest, /* digest of outputs above double + line */ + TPM_NONCE nonceEven, + TPM_NONCE nonceOdd, + TPM_BOOL continueSession) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Authdata_Generate:\n"); + if (rc == 0) { + TPM_PrintFour(" TPM_Authdata_Generate: outParamDigest", outParamDigest); + TPM_PrintFour(" TPM_Authdata_Generate: usageAuth (key)", usageAuth); + TPM_PrintFour(" TPM_Authdata_Generate: nonceEven", nonceEven); + TPM_PrintFour(" TPM_Authdata_Generate: nonceOdd", nonceOdd); + printf (" TPM_Authdata_Generate: continueSession %02x\n", continueSession); + rc = TPM_HMAC_Generate(resAuth, + usageAuth, /* key */ + TPM_DIGEST_SIZE, outParamDigest, /* response digest */ + TPM_NONCE_SIZE, nonceEven, /* 2H */ + TPM_NONCE_SIZE, nonceOdd, /* 3H */ + sizeof(TPM_BOOL), &continueSession, /* 4H */ + 0, NULL); + TPM_PrintFour(" TPM_Authdata_Generate: resAuth", resAuth); + } + return rc; +} + +/* TPM_Authdata_Check() checks the authorization of a command. + + Handles the protection against dictionary attacks. + + Returns TPM_AUTHFAIL if the TPM_AUTHDATA does not match. +*/ + +TPM_RESULT TPM_Authdata_Check(tpm_state_t *tpm_state, + TPM_SECRET hmacKey, /* HMAC key */ + TPM_DIGEST inParamDigest, /* digest of inputs above line */ + TPM_AUTH_SESSION_DATA *tpm_auth_session_data, /* auth session */ + TPM_NONCE nonceOdd, /* Nonce generated by system + associated with authHandle */ + TPM_BOOL continueSession, + TPM_AUTHDATA usageAuth) /* Authorization digest for input */ +{ + TPM_RESULT rc = 0; + TPM_BOOL valid; + + printf(" TPM_Authdata_Check:\n"); + if (rc == 0) { + TPM_PrintFour(" TPM_Authdata_Check: inParamDigest", inParamDigest); + TPM_PrintFour(" TPM_Authdata_Check: usageAuth (key)", hmacKey); + TPM_PrintFour(" TPM_Authdata_Check: nonceEven", tpm_auth_session_data->nonceEven); + TPM_PrintFour(" TPM_Authdata_Check: nonceOdd", nonceOdd); + printf (" TPM_Authdata_Check: continueSession %02x\n", continueSession); + /* HMAC the inParamDigest, authLastNonceEven, nonceOdd, continue */ + /* authLastNonceEven is retrieved from internal authorization session storage */ + rc = TPM_HMAC_Check(&valid, + usageAuth, /* expected, from command */ + hmacKey, /* key */ + sizeof(TPM_DIGEST), inParamDigest, /* command digest */ + sizeof(TPM_NONCE), tpm_auth_session_data->nonceEven, /* 2H */ + sizeof(TPM_NONCE), nonceOdd, /* 3H */ + sizeof(TPM_BOOL), &continueSession, /* 4H */ + 0, NULL); + } + if (rc == 0) { + if (!valid) { + printf("TPM_Authdata_Check: Error, authorization failed\n"); + /* record the authorization failure */ + rc = TPM_Authdata_Fail(tpm_state); + /* TPM_Authdata_Fail() fatal TPM_FAIL error takes precedence, else TPM_AUTHFAIL */ + if (rc == 0) { + rc = TPM_AUTHFAIL; + } + } + } + return rc; +} + +/* TPM_Auth2data_Check() is a wrapper around TPM_Authdata_Check() that returns TPM_AUTH2FAIL + in place of TPM_AUTHFAIL. +*/ + +TPM_RESULT TPM_Auth2data_Check(tpm_state_t *tpm_state, + TPM_SECRET hmacKey, /* HMAC key */ + TPM_DIGEST inParamDigest, /* digest of inputs above line */ + TPM_AUTH_SESSION_DATA *tpm_auth_session_data, /* auth session */ + TPM_NONCE nonceOdd, /* Nonce generated by system + associated with authHandle */ + TPM_BOOL continueSession, + TPM_AUTHDATA usageAuth) /* Authorization digest for input */ +{ + TPM_RESULT rc = 0; + + rc = TPM_Authdata_Check(tpm_state, + hmacKey, + inParamDigest, + tpm_auth_session_data, + nonceOdd, + continueSession, + usageAuth); + if (rc == TPM_AUTHFAIL) { + rc = TPM_AUTH2FAIL; + } + return rc; +} + +/* TPM_Authdata_Fail() processes an authorization failure event, to mitigate dictionary attacks. + + Returns TPM_FAIL on error, so that the caller can shut down the TPM +*/ + +TPM_RESULT TPM_Authdata_Fail(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + uint32_t tv_usec; /* dummy, discard usec */ + + if (rc == 0) { + /* Each failure increments the counter. No need to check for overflow. Unless + TPM_LOCKOUT_THRESHOLD is absurdly large, the left shift overflows first. */ + tpm_state->tpm_stclear_data.authFailCount++; + printf(" TPM_Authdata_Fail: New authFailCount %u\n", + tpm_state->tpm_stclear_data.authFailCount); + /* Test if past the failure threshold. Each time authorization fails, this test is made. + Once in dictionary attack mitigation, there will be no authdata check until the + mitigation period is exceeded. After that, if there is another failure, the fail count + increases and mitigation begins again. + + Note that a successful authorization does NOT reset authFailCount, as this would allow a + dictionary attack by an attacker that knew ANY good authorization value. The count is + only reset by the owner using TPM_ResetLockValue. + */ + if (tpm_state->tpm_stclear_data.authFailCount > TPM_LOCKOUT_THRESHOLD) { + /* the current authorization failure time is the start time */ + rc = TPM_GetTimeOfDay(&(tpm_state->tpm_stclear_data.authFailTime), &tv_usec); + printf(" TPM_Authdata_Fail: Past limit, authFailTime %u\n", + tpm_state->tpm_stclear_data.authFailTime); + } + } + return rc; +} + +/* TPM_Authdata_GetState() gets the boolean dictionary attack mitigation state. + + */ + +TPM_RESULT TPM_Authdata_GetState(TPM_DA_STATE *state, + uint32_t *timeLeft, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + uint32_t currentTime; /* in seconds */ + uint32_t tv_usec; /* dummy, discarded */ + uint32_t threshold_diff; /* in failure counts */ + uint32_t waitTime; /* in seconds, timeout based on threshold_diff */ + uint32_t timeDiff; /* in seconds, how far along is timeout */ + + printf(" TPM_Authdata_GetState:\n"); + *state = TPM_DA_STATE_INACTIVE; /* default value */ + + /* if there is an attack in progress */ + if (tpm_state->tpm_stclear_data.authFailCount > TPM_LOCKOUT_THRESHOLD) { + printf(" TPM_Authdata_GetState: In timeout, authFailCount %u threshold %u\n", + tpm_state->tpm_stclear_data.authFailCount, TPM_LOCKOUT_THRESHOLD); + /* get the current time */ + if (rc == 0) { + /* throw away usec. This means that the time difference could be 1 sec off. But the + lockout mechanism is somewhat arbitrary anyway */ + rc = TPM_GetTimeOfDay(¤tTime, &tv_usec); + } + /* calculate how much time to wait */ + if (rc == 0) { + printf(" TPM_Authdata_GetState: currentTime %u authFailTime %u\n", + currentTime, tpm_state->tpm_stclear_data.authFailTime); + /* how many failures over the threshold. The -1 makes threshold_diff 0 based, so the + first waitTime is 1 sec. */ + threshold_diff = tpm_state->tpm_stclear_data.authFailCount - TPM_LOCKOUT_THRESHOLD - 1; + /* Wait time depends on how far over threshold, wait 1 sec and double each time. Ignore + shift overflow, since the previous timeout 0x80000000 sec is 68 years. */ + waitTime = 0x01 << threshold_diff; + /* how far along is timeout. */ + if (currentTime >= tpm_state->tpm_stclear_data.authFailTime) { + timeDiff = currentTime - tpm_state->tpm_stclear_data.authFailTime; + } + /* handle unlikely currentTime wrap around */ + else { + timeDiff = ((0xffffffff - tpm_state->tpm_stclear_data.authFailTime) + + currentTime) + 1; + } + /* if not past the timeout, return an error */ + printf(" TPM_Authdata_GetState: waitTime %u timeDiff %u\n", + waitTime, timeDiff); + if (waitTime > timeDiff) { + printf("TPM_Authdata_GetState: Error, timeout not complete\n"); + *state = TPM_DA_STATE_ACTIVE; + *timeLeft = waitTime - timeDiff; + } + } + } + return rc; +} + +/* TPM_Authdata_CheckState() checks the dictionary attack mitigation state. + + This function is typically called at the beginning of each command. + + If an attack is in progress, and the lockout timeout has not expired, an error is returned. +*/ + +TPM_RESULT TPM_Authdata_CheckState(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_DA_STATE state; + uint32_t timeLeft; + + printf(" TPM_Authdata_CheckState:\n"); + /* Get the dictionary attack mitigation state */ + if (rc == 0) { + rc = TPM_Authdata_GetState(&state, &timeLeft, tpm_state); + } + /* If not during the timeout period, allow the TPM_ResetLockValue ordinal */ + if (rc == 0) { + if (state == TPM_DA_STATE_INACTIVE) { + tpm_state->tpm_stclear_data.disableResetLock = FALSE; + } + else { /* TPM_DA_STATE_ACTIVE */ + rc = TPM_DEFEND_LOCK_RUNNING; + } + } + return rc; +} + +/* + TPM_CHANGEAUTH_VALIDATE +*/ + +/* TPM_ChangeauthValidate_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_ChangeauthValidate_Init(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate) +{ + printf(" TPM_ChangeauthValidate_Init:\n"); + TPM_Secret_Init(tpm_changeauth_validate->newAuthSecret); + TPM_Nonce_Init(tpm_changeauth_validate->n1); + return; +} + +/* TPM_ChangeauthValidate_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_ChangeauthValidate_Init() + After use, call TPM_ChangeauthValidate_Delete() to free memory +*/ + +TPM_RESULT TPM_ChangeauthValidate_Load(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ChangeauthValidate_Load:\n"); + /* load newAuthSecret */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_changeauth_validate->newAuthSecret, stream, stream_size); + } + /* load n1 */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_changeauth_validate->n1, stream, stream_size); + } + return rc; +} + +#if 0 +/* TPM_ChangeauthValidate_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_ChangeauthValidate_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ChangeauthValidate_Store:\n"); + /* store newAuthSecret */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_changeauth_validate->newAuthSecret); + } + /* store n1 */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_changeauth_validate->n1); + } + return rc; +} +#endif + +/* TPM_ChangeauthValidate_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_ChangeauthValidate_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_ChangeauthValidate_Delete(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate) +{ + printf(" TPM_ChangeauthValidate_Delete:\n"); + if (tpm_changeauth_validate != NULL) { + TPM_ChangeauthValidate_Init(tpm_changeauth_validate); + } + return; +} + +/* + TPM_DA_INFO +*/ + +/* TPM_DaInfo_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DaInfo_Init(TPM_DA_INFO *tpm_da_info) +{ + printf(" TPM_DaInfo_Init:\n"); +/* tpm_da_info->tag = TPM_TAG_DA_INFO; */ + tpm_da_info->state = TPM_DA_STATE_INACTIVE; + tpm_da_info->currentCount = 0; + tpm_da_info->thresholdCount = TPM_LOCKOUT_THRESHOLD; + /* TPM_DA_ACTION_TYPE is a trivial structure, in-line here */ + tpm_da_info->actionAtThreshold.tag = TPM_TAG_DA_ACTION_TYPE; + tpm_da_info->actionAtThreshold.actions = TPM_DA_ACTION_TIMEOUT; + tpm_da_info->actionDependValue = 0; + TPM_SizedBuffer_Init(&tpm_da_info->vendorData); + return; +} + +/* TPM_DaInfo_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DaInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DA_INFO *tpm_da_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DaInfo_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DA_INFO); + } + /* store state */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_da_info->state), sizeof(TPM_DA_STATE)); + } + /* store currentCount */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_da_info->currentCount); + } + /* store thresholdCount */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_da_info->thresholdCount); + } + /* store actionAtThreshold */ + /* TPM_DA_ACTION_TYPE is a trivial structure, in-line here */ + /* store TPM_DA_ACTION_TYPE tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DA_ACTION_TYPE); + } + /* store TPM_DA_ACTION_TYPE actions */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_da_info->actionAtThreshold.actions); + } + /* store actionDependValue */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_da_info->actionDependValue); + } + /* store vendorData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_da_info->vendorData)); + } + return rc; +} + +/* TPM_DaInfo_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DaInfo_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DaInfo_Delete(TPM_DA_INFO *tpm_da_info) +{ + printf(" TPM_DaInfo_Delete:\n"); + if (tpm_da_info != NULL) { + TPM_SizedBuffer_Delete(&(tpm_da_info->vendorData)); + TPM_DaInfo_Init(tpm_da_info); + } + return; +} + +/* TPM_DaInfoLimited_Set() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DaInfo_Set(TPM_DA_INFO *tpm_da_info, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DaInfo_Set:\n"); + /* state: Dynamic. The actual state of the dictionary attack mitigation logic. */ + /* actionDependValue: Dynamic. Action being taken when the dictionary attack mitigation logic + is active. E.g., when actionAtThreshold is TPM_DA_ACTION_TIMEOUT, this is the lockout time + remaining in seconds. */ + if (rc == 0) { + rc = TPM_Authdata_GetState(&(tpm_da_info->state), + &(tpm_da_info->actionDependValue), + tpm_state); + } + /* Dynamic. The actual count of the authorization failure counter for the selected entity + type */ + if (rc == 0) { + if (tpm_state->tpm_stclear_data.authFailCount <= 0xffff) { + tpm_da_info->currentCount = tpm_state->tpm_stclear_data.authFailCount; + } + /* with the doubling, this should never overflow. So overflow indicates a serious error */ + else { + printf("TPM_DaInfo_Set: Error (fatal), authFailCount overflow %08x\n", + tpm_state->tpm_stclear_data.authFailCount); + rc = TPM_FAIL; + } + } + return rc; +} + +/* + TPM_DA_INFO_LIMITED +*/ + +/* TPM_DaInfoLimited_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DaInfoLimited_Init(TPM_DA_INFO_LIMITED *tpm_da_info_limited) +{ + printf(" TPM_DaInfoLimited_Init:\n"); +/* tpm_da_info_limited->tag = TPM_TAG_DA_INFO_LIMITED; */ + tpm_da_info_limited->state = TPM_DA_STATE_INACTIVE; + /* TPM_DA_ACTION_TYPE is a trivial structure, in-line here */ + tpm_da_info_limited->actionAtThreshold.tag = TPM_TAG_DA_ACTION_TYPE; + tpm_da_info_limited->actionAtThreshold.actions = TPM_DA_ACTION_TIMEOUT; + TPM_SizedBuffer_Init(&tpm_da_info_limited->vendorData); + return; +} + +/* TPM_DaInfoLimited_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DaInfoLimited_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DA_INFO_LIMITED *tpm_da_info_limited) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DaInfoLimited_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DA_INFO_LIMITED); + } + /* store state */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_da_info_limited->state), sizeof (TPM_DA_STATE)); + } + /* store actionAtThreshold */ + /* TPM_DA_ACTION_TYPE is a trivial structure, in-line here */ + /* store TPM_DA_ACTION_TYPE tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DA_ACTION_TYPE); + } + /* store TPM_DA_ACTION_TYPE actions */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_da_info_limited->actionAtThreshold.actions); + } + /* store vendorData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_da_info_limited->vendorData)); + } + return rc; +} + +/* TPM_DaInfoLimited_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DaInfoLimited_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DaInfoLimited_Delete(TPM_DA_INFO_LIMITED *tpm_da_info_limited) +{ + printf(" TPM_DaInfoLimited_Delete:\n"); + if (tpm_da_info_limited != NULL) { + TPM_SizedBuffer_Delete(&(tpm_da_info_limited->vendorData)); + TPM_DaInfoLimited_Init(tpm_da_info_limited); + } + return; +} + +/* TPM_DaInfoLimited_Set() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DaInfoLimited_Set(TPM_DA_INFO_LIMITED *tpm_da_info_limited, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + uint32_t timeLeft; + + printf(" TPM_DaInfoLimited_Set:\n"); + /* Dynamic. The actual state of the dictionary attack mitigation logic. */ + if (rc == 0) { + rc = TPM_Authdata_GetState(&(tpm_da_info_limited->state), &timeLeft, tpm_state); + } + return rc; +} + +/* + Processing Functions +*/ + + +/* 17.1 TPM_ChangeAuth rev 107 + + The TPM_ChangeAuth command allows the owner of an entity to change the authorization data for the + entity. + + This command cannot invalidate the old entity. Therefore, the authorization change is only + effective if the application can guarantee that the old entity can be securely destroyed. If not, + two valid entities will exist, one with the old and one with the new authorization secret. + + If this command is delegated, the delegated party can expand its key use privileges. That party + can create a copy of the key with known authorization, and it can then use the key without any + ordinal restrictions. + + TPM_ChangeAuth requires the encryption of one parameter ("NewAuth"). For the sake of uniformity + with other commands that require the encryption of more than one parameter, the string used for + XOR encryption is generated by concatenating the evenNonce (created during the OSAP session) with + the session shared secret and then hashing the result. + + The parameter list to this command must always include two authorization sessions, regardless of + the state of authDataUsage for the respective keys. +*/ + +TPM_RESULT TPM_Process_ChangeAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* Handle of the parent key to the entity. */ + TPM_PROTOCOL_ID protocolID = 0; /* The protocol in use. */ + TPM_ENCAUTH newAuth; /* The encrypted new authorization data for the entity */ + TPM_ENTITY_TYPE entityType = 0; /* The type of entity to be modified */ + TPM_SIZED_BUFFER encData; /* The encrypted entity that is to be modified. */ + + TPM_AUTHHANDLE parentAuthHandle; /* The authorization handle used for the parent + key. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with + parentAuthHandle */ + TPM_BOOL continueAuthSession; /* Ignored, parentAuthHandle is always terminated. */ + TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and + parentHandle. HMAC key: parentKey.usageAuth. */ + + TPM_AUTHHANDLE entityAuthHandle; /* The authorization handle used for the encrypted + entity. The session type MUST be OIAP */ + TPM_NONCE entitynonceOdd; /* Nonce generated by system associated with + entityAuthHandle */ + TPM_BOOL continueEntitySession; /* Ignored, entityAuthHandle is always terminated. */ + TPM_AUTHDATA entityAuth; /* The authorization digest for the inputs and encrypted + entity. HMAC key: entity.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL parentAuthHandleValid = FALSE; + TPM_BOOL entityAuthHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *parent_auth_session_data = NULL; /* session data for + parentAuthHandle */ + TPM_AUTH_SESSION_DATA *entity_auth_session_data = NULL; /* session data for + entityAuthHandle */ + TPM_KEY *parentKey = NULL; + TPM_SECRET *parentHmacKey; + TPM_SECRET *entityHmacKey; + TPM_SECRET saveKey; /* copy of entity HMAC key for response */ + TPM_BOOL parentPCRStatus; + TPM_AUTHDATA decryptAuth; + unsigned char *b1DecryptData; + uint32_t b1DecryptDataLength = 0; /* actual valid data */ + unsigned char *stream; /* for deserializing decrypted encData */ + uint32_t stream_size; + TPM_STORE_ASYMKEY keyEntity; /* entity structure when it's a TPM_ET_KEY */ + TPM_SEALED_DATA sealEntity; /* entity structure when it's a TPM_ET_DATA */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER outData; /* The modified, encrypted entity. */ + + printf("TPM_Process_ChangeAuth: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&encData); /* freed @1 */ + TPM_SizedBuffer_Init(&outData); /* freed @2 */ + b1DecryptData = NULL; /* freed @3 */ + TPM_StoreAsymkey_Init(&keyEntity); /* freed @4 */ + TPM_SealedData_Init(&sealEntity); /* freed @5 */ + /* + get inputs + */ + /* get parentHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get protocolID parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuth: parentHandle %08x\n", parentHandle); + returnCode = TPM_Load16(&protocolID, &command, ¶mSize); + } + /* get newAuth parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuth: protocolID %04hx\n", protocolID); + returnCode = TPM_Authdata_Load(newAuth, &command, ¶mSize); + } + /* get entityType parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&entityType, &command, ¶mSize); + } + /* get encData parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&encData, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuth: encDataSize %u\n", encData.size); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag2(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&parentAuthHandle, + &parentAuthHandleValid, + nonceOdd, + &continueAuthSession, + parentAuth, + &command, ¶mSize); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuth: parentAuthHandle %08x\n", parentAuthHandle); + returnCode = TPM_AuthParams_Get(&entityAuthHandle, + &entityAuthHandleValid, + entitynonceOdd, + &continueEntitySession, + entityAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuth: entityAuthHandle %08x\n", entityAuthHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ChangeAuth: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + parentAuthHandleValid = FALSE; + entityAuthHandleValid = FALSE; + } + /* + Processing + */ + /* Description + 1. The parentAuthHandle session type MUST be TPM_PID_OSAP. + 2. In this capability, the SRK cannot be accessed as entityType TPM_ET_KEY, since the SRK is + not wrapped by a parent key. + */ + /* 1. Verify that entityType is one of TPM_ET_DATA, TPM_ET_KEY and return the error + TPM_WRONG_ENTITYTYPE if not. */ + if (returnCode == TPM_SUCCESS) { + if ((entityType != TPM_ET_DATA) && + (entityType != TPM_ET_KEY)) { + printf("TPM_Process_ChangeAuth: Error, bad entityType %04x\n", entityType); + returnCode = TPM_WRONG_ENTITYTYPE; + } + } + /* 2. Verify that parentAuthHandle session type is TPM_PID_OSAP return TPM_BAD_MODE on error */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* not r/o, using to authenticate */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get the OSAP session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&parent_auth_session_data, + &parentHmacKey, + tpm_state, + parentAuthHandle, + TPM_PID_OSAP, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + NULL, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* 3. Verify that entityAuthHandle session type is TPM_PID_OIAP return TPM_BAD_MODE on error */ + /* keyEntity and sealEntity are not valid yet, so pass in NULL and ignore the returned + entityHmacKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&entity_auth_session_data, + &entityHmacKey, + tpm_state, + entityAuthHandle, + TPM_PID_OIAP, + 0, /* OSAP entity type */ + ordinal, + NULL, + NULL, + NULL); + } + /* 4.If protocolID is not TPM_PID_ADCP, the TPM MUST return TPM_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if (protocolID != TPM_PID_ADCP) { + printf("TPM_Process_ChangeAuth: Error, bad protocolID\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 5. The encData field MUST be the encData field from either the TPM_STORED_DATA or TPM_KEY + structures. */ + /* NOTE Seems the same as Action 1. */ + /* 6. Create decryptAuth by decrypting newAuth according to the ADIP indicated by + parentHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_Decrypt(decryptAuth, + NULL, + newAuth, + parent_auth_session_data, + NULL, + NULL, + FALSE); /* odd and even */ + } + /* 7. The TPM MUST validate the command using the authorization data in the parentAuth parameter + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *parentHmacKey, /* HMAC key */ + inParamDigest, + parent_auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + parentAuth); /* Authorization digest for input */ + } + /* 8. Validate that parentHandle -> keyUsage is TPM_KEY_STORAGE, if not return + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_ChangeAuth: Error, keyUsage %04hx is invalid\n", + parentKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 9. After parameter validation the TPM creates b1 by decrypting encData using the key pointed + to by parentHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPrivateDecryptMalloc(&b1DecryptData, /* decrypted data */ + &b1DecryptDataLength, /* actual size of + decrypted data */ + encData.buffer,/* encrypted data */ + encData.size, /* encrypted data size */ + parentKey); + } + if ((returnCode == TPM_SUCCESS) && (entityType == TPM_ET_KEY)) { + printf("TPM_Process_ChangeAuth: entityType is TPM_ET_KEY\n"); + /* 10. The TPM MUST validate that b1 is a valid TPM structure, either a TPM_STORE_ASYMKEY or + a TPM_SEALED_DATA */ + if (returnCode == TPM_SUCCESS) { + stream = b1DecryptData; + stream_size = b1DecryptDataLength; + returnCode = TPM_StoreAsymkey_Load(&keyEntity, FALSE, + &stream, &stream_size, + NULL, /* TPM_KEY_PARMS */ + NULL); /* TPM_SIZED_BUFFER pubKey */ + } + /* a. Check the length and payload, return TPM_INVALID_STRUCTURE on any mismatch. */ + /* NOTE: Done by TPM_StoreAsymkey_Load() */ + if (returnCode == TPM_SUCCESS) { + /* save a copy of the HMAC key for the response before changing */ + TPM_Secret_Copy(saveKey, keyEntity.usageAuth); + /* a.The TPM must validate the command using the authorization data entityAuth + parameter. The HMAC key is TPM_STORE_ASYMKEY -> usageAuth or TPM_SEALED_DATA -> + authData. */ + returnCode = TPM_Auth2data_Check(tpm_state, + keyEntity.usageAuth, /* HMAC key */ + inParamDigest, + entity_auth_session_data, /* authorization session */ + entitynonceOdd, /* Nonce generated by system + associated with authHandle */ + continueEntitySession, + entityAuth); /* Authorization digest for input */ + } + /* 11. The TPM replaces the authorization data for b1 with decryptAuth created above. */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_ChangeAuth: usageAuth was", keyEntity.usageAuth); + TPM_PrintFour("TPM_Process_ChangeAuth: usageAuth now", decryptAuth); + TPM_Secret_Copy(keyEntity.usageAuth, decryptAuth); + } + /* 12. The TPM encrypts b1 using the appropriate mechanism for the type using the + parentKeyHandle to provide the key information. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_StoreAsymkey_GenerateEncData(&outData, &keyEntity, parentKey); + } + } + else if ((returnCode == TPM_SUCCESS) && (entityType == TPM_ET_DATA)) { + printf("TPM_Process_ChangeAuth: entityType is TPM_ET_DATA\n"); + /* 10. The TPM MUST validate that b1 is a valid TPM structure, either a TPM_STORE_ASYMKEY or + a TPM_SEALED_DATA */ + if (returnCode == TPM_SUCCESS) { + stream = b1DecryptData; + stream_size = b1DecryptDataLength; + returnCode = TPM_SealedData_Load(&sealEntity, &stream, &stream_size); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuth: Checking tpmProof\n"); + returnCode = TPM_Secret_Compare(sealEntity.tpmProof, + tpm_state->tpm_permanent_data.tpmProof); + } + /* a. Check the length and payload, return TPM_INVALID_STRUCTURE on any mismatch. */ + /* NOTE: Done by TPM_SealedData_Load() */ + if (returnCode == TPM_SUCCESS) { + /* save a copy of the HMAC key for the response before changing */ + TPM_Secret_Copy(saveKey, sealEntity.authData); + /* a.The TPM must validate the command using the authorization data entityAuth + parameter. The HMAC key is TPM_STORE_ASYMKEY -> usageAuth or TPM_SEALED_DATA -> + authData. */ + returnCode = TPM_Auth2data_Check(tpm_state, + sealEntity.authData, /* HMAC key */ + inParamDigest, + entity_auth_session_data, /* authorization session */ + entitynonceOdd, /* Nonce generated by system + associated with authHandle */ + continueEntitySession, + entityAuth); /* Authorization digest for input */ + } + /* 11. The TPM replaces the authorization data for b1 with decryptAuth created above. */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_ChangeAuth: authData was", sealEntity.authData); + TPM_PrintFour("TPM_Process_ChangeAuth: authData now", decryptAuth); + TPM_Secret_Copy(sealEntity.authData, decryptAuth); + } + /* 12. The TPM encrypts b1 using the appropriate mechanism for the type using the + parentKeyHandle to provide the key information. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SealedData_GenerateEncData(&outData, &sealEntity, parentKey); + } + } + /* 13. The TPM MUST enforce the destruction of both the parentAuthHandle and entityAuthHandle + sessions. */ + if (returnCode == TPM_SUCCESS) { + continueAuthSession = FALSE; + continueEntitySession = FALSE; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ChangeAuth: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 14. The new blob is returned in outData when appropriate. */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *parentHmacKey, /* HMAC key */ + parent_auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + saveKey, /* the original and not the new auth value */ + entity_auth_session_data, + outParamDigest, + entitynonceOdd, + continueEntitySession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* 15. The TPM MUST enforce the destruction of both the parentAuthHandle and entityAuthHandle + sessions. */ + if (parentAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, parentAuthHandle); + } + if (entityAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, entityAuthHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&encData); /* @1 */ + TPM_SizedBuffer_Delete(&outData); /* @2 */ + free(b1DecryptData); /* @3 */ + TPM_StoreAsymkey_Delete(&keyEntity); /* @4 */ + TPM_SealedData_Delete(&sealEntity); /* @5 */ + return rcf; +} + +/* 17.2 TPM_ChangeAuthOwner rev 98 + + The TPM_ChangeAuthOwner command allows the owner of an entity to change the authorization data + for the TPM Owner or the SRK. + + This command requires authorization from the current TPM Owner to execute. + + TPM's targeted for an environment (e.g. a server) with long lasting sessions should not + invalidate all sessions. +*/ + +TPM_RESULT TPM_Process_ChangeAuthOwner(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_PROTOCOL_ID protocolID; /* The protocol in use. */ + TPM_ENCAUTH newAuth; /* The encrypted new authorization data for the entity */ + TPM_ENTITY_TYPE entityType = 0; /* The type of entity to be modified */ + TPM_AUTHHANDLE ownerAuthHandle; /* The authorization handle used for the TPM + Owner. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with ownerAuthHandle + */ + TPM_BOOL continueAuthSession = TRUE; /* Continue use flag the TPM ignores this value */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and ownerHandle. HMAC + key: tpmOwnerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL ownerAuthHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *owner_auth_session_data = NULL; /* session data for ownerAuthHandle + */ + TPM_SECRET *hmacKey; + TPM_SECRET saveKey; /* copy of HMAC key, since sessions invalidated */ + TPM_AUTHDATA decryptAuth; + TPM_AUTHDATA *entityAuth; /* pointer to either owner or SRK auth */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ChangeAuthOwner: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get protocolID parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&protocolID, &command, ¶mSize); + } + /* get newAuth parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuthOwner: protocolID %04hx\n", protocolID); + returnCode = TPM_Authdata_Load(newAuth, &command, ¶mSize); + } + /* get entityType parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&entityType, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&ownerAuthHandle, + &ownerAuthHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ChangeAuthOwner: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + ownerAuthHandleValid = FALSE; + } + /* + Processing + */ + /* 1. The TPM MUST validate the command using the AuthData in the ownerAuth parameter */ + /* 2. The ownerAuthHandle session type MUST be TPM_PID_OSAP */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&owner_auth_session_data, + &hmacKey, + tpm_state, + ownerAuthHandle, + TPM_PID_OSAP, + TPM_ET_OWNER, + ordinal, + NULL, + NULL, + tpm_state->tpm_permanent_data.ownerAuth); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + owner_auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 3. If protocolID is not TPM_PID_ADCP, the TPM MUST return TPM_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if (protocolID != TPM_PID_ADCP) { + printf("TPM_Process_ChangeAuthOwner: Error, bad protocolID\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 4. Verify that entityType is either TPM_ET_OWNER or TPM_ET_SRK, and return the error + TPM_WRONG_ENTITYTYPE if not. */ + if (returnCode == TPM_SUCCESS) { + if (entityType == TPM_ET_OWNER) { + printf("TPM_Process_ChangeAuthOwner: entityType TPM_ET_OWNER\n"); + entityAuth = &(tpm_state->tpm_permanent_data.ownerAuth); + } + else if (entityType == TPM_ET_SRK) { + printf("TPM_Process_ChangeAuthOwner: entityType TPM_ET_SRK\n"); + entityAuth = &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->usageAuth); + } + else { + entityAuth = NULL; /* just to quiet the compiler */ + printf("TPM_Process_ChangeAuthOwner: Error, wrong entityType %04x\n", entityType); + returnCode = TPM_WRONG_ENTITYTYPE; + } + } + /* 5. Create decryptAuth by decrypting newAuth according to the ADIP indicated by + ownerAuthHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_Decrypt(decryptAuth, + NULL, + newAuth, + owner_auth_session_data, + NULL, + NULL, + FALSE); /* even and odd */ + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_ChangeAuthOwner: From entityAuth", *entityAuth); + TPM_PrintFour("TPM_Process_ChangeAuthOwner: To decryptAuth", decryptAuth); + /* 6. The TPM MUST enforce the destruction of the ownerAuthHandle session upon completion of + this command (successful or unsuccessful). This includes setting continueAuthSession to + FALSE */ + continueAuthSession = FALSE; + /* 7. Set the authorization data for the indicated entity to decryptAuth */ + TPM_Secret_Copy(*entityAuth, decryptAuth); + /* save a copy of the HMAC key for the response before invalidating */ + TPM_Secret_Copy(saveKey, *hmacKey); + /* 8. The TPM MUST invalidate all owner authorized OSAP and DSAP sessions, active or + saved. */ + TPM_AuthSessions_TerminateEntity(&continueAuthSession, + ownerAuthHandle, + tpm_state->tpm_stclear_data.authSessions, + TPM_ET_OWNER, /* TPM_ENTITY_TYPE */ + NULL); /* ignore entityDigest */ + /* 9. The TPM MAY invalidate all sessions, active or saved */ + /* Store the permanent data back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + TRUE, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ChangeAuthOwner: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + saveKey, /* HMAC key */ + owner_auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + ownerAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, ownerAuthHandle); + } + /* + cleanup + */ + return rcf; +} + + +/* 27.4.1 TPM_ChangeAuthAsymStart rev 87 + + The TPM_ChangeAuthAsymStart starts the process of changing AuthData for an entity. It sets up an + OIAP session that must be retained for use by its twin TPM_ChangeAuthAsymFinish command. + + TPM_ChangeAuthAsymStart creates a temporary asymmetric public key "tempkey" to provide + confidentiality for new AuthData to be sent to the TPM. TPM_ChangeAuthAsymStart certifies that + tempkey was generated by a genuine TPM, by generating a certifyInfo structure that is signed by a + TPM identity. The owner of that TPM identity must cooperate to produce this command, because + TPM_ChangeAuthAsymStart requires authorization to use that identity. + + It is envisaged that tempkey and certifyInfo are given to the owner of the entity whose + authorization is to be changed. That owner uses certifyInfo and a TPM_IDENTITY_CREDENTIAL to + verify that tempkey was generated by a genuine TPM. This is done by verifying the + TPM_IDENTITY_CREDENTIAL using the public key of a CA, verifying the signature on the certifyInfo + structure with the public key of the identity in TPM_IDENTITY_CREDENTIAL, and verifying tempkey + by comparing its digest with the value inside certifyInfo. The owner uses tempkey to encrypt the + desired new AuthData and inserts that encrypted data in a TPM_ChangeAuthAsymFinish command, in + the knowledge that only a TPM with a specific identity can interpret the new AuthData. +*/ + +TPM_RESULT TPM_Process_ChangeAuthAsymStart(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE idHandle; /* The keyHandle identifier of a loaded identity ID key */ + TPM_NONCE antiReplay; /* The nonce to be inserted into the certifyInfo structure + */ + TPM_KEY_PARMS tempKeyParms; /* Structure contains all parameters of ephemeral key. */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for idHandle + authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA idAuth; /* Authorization. HMAC key: idKey.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_KEY *idKey = NULL; + TPM_SECRET *idKeyUsageAuth; + TPM_BOOL idPCRStatus; + TPM_RSA_KEY_PARMS *temp_rsa_key_parms; /* tempKey is RSA */ + TPM_BOOL key_added = FALSE; /* added to key handle entries */ + TPM_DIGEST h1Digest; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_CERTIFY_INFO certifyInfo; /* The certifyInfo structure that is to be signed. */ + TPM_SIZED_BUFFER sig; /* The signature of the certifyInfo parameter. */ + TPM_KEY_HANDLE ephHandle; /* The keyHandle identifier to be used by + ChangeAuthAsymFinish for the ephemeral key */ + TPM_KEY *tempKey; /* Structure containing all parameters and public part of + ephemeral key. TPM_KEY.encSize is set to 0. NOTE + Actually tempKey and k1 are the same. The encData is + present but not returned in the response. */ + + printf("TPM_Process_ChangeAuthAsymStart: Ordinal Entry\n"); + TPM_KeyParms_Init(&tempKeyParms); /* freed @1 */ + TPM_CertifyInfo_Init(&certifyInfo); /* freed @2 */ + TPM_SizedBuffer_Init(&sig); /* freed @3 */ + tempKey = NULL; /* freed @4 */ + /* + get inputs + */ + /* get idHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&idHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuthAsymStart: idHandle %08x\n", idHandle); + /* get antiReplay parameter */ + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* get tempKey (actually tempKeyParms) parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_Load(&tempKeyParms, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + idAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ChangeAuthAsymStart: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. The TPM SHALL verify the AuthData to use the TPM identity key held in idHandle. The TPM + MUST verify that the key is a TPM identity key.*/ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&idKey, &idPCRStatus, tpm_state, idHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if (returnCode == TPM_SUCCESS) { + if (idKey->keyUsage != TPM_KEY_IDENTITY) { + printf("TPM_Process_ChangeAuthAsymStart: Error, keyUsage %04hx is invalid\n", + idKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ + if (idKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_ChangeAuthAsymStart: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get idHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&idKeyUsageAuth, idKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + idKey, + idKeyUsageAuth, /* OIAP */ + idKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + idAuth); /* Authorization digest for input */ + } + /* 2. The TPM SHALL validate the algorithm parameters for the key to create from the tempKey + parameter. */ + if (returnCode == TPM_SUCCESS) { + /* get the TPM_RSA_KEY_PARMS structure from the TPM_KEY_PARMS structure */ + /* 3. Recommended key type is RSA */ + returnCode = TPM_KeyParms_GetRSAKeyParms(&temp_rsa_key_parms, &tempKeyParms); + } + /* 4. Minimum RSA key size MUST is 512 bits, recommended RSA key size is 1024 */ + /* 5. For other key types the minimum key size strength MUST be comparable to RSA 512 */ + /* 6. If the TPM is not designed to create a key of the requested type, return the error code + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_CheckProperties(&tempKeyParms, + TPM_KEY_AUTHCHANGE, + 0, /* required key length in bits */ + tpm_state->tpm_permanent_flags.FIPS); + } + /* 7. The TPM SHALL create a new key (k1) in accordance with the algorithm parameter. The newly + created key is pointed to by ephHandle. */ + /* NOTE tempKey is used as k1 */ + /* Allocate space for k1. The key cannot be a local variable, since it persists in key storage + after the command completes. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc((unsigned char **)&tempKey, sizeof(TPM_KEY)); + } + /* + Field Descriptions for certifyInfo parameter + Type Name Description + TPM_VERSION Version TPM version structure; Part 2 TPM_VERSION + keyFlags Redirection This SHALL be set to FALSE + Migratable This SHALL be set to FALSE + Volatile This SHALL be set to TRUE + TPM_AUTH_DATA_USAGE authDataUsage This SHALL be set to TPM_AUTH_NEVER + TPM_KEY_USAGE KeyUsage This SHALL be set to TPM_KEY_AUTHCHANGE + uint32_t PCRInfoSize This SHALL be set to 0 + TPM_DIGEST pubDigest This SHALL be the hash of the public key + being certified. + TPM_NONCE Data This SHALL be set to antiReplay + TPM_KEY_PARMS info This specifies the type of key and its parameters. + TPM_BOOL parentPCRStatus This SHALL be set to FALSE. + */ + /* generate a TPM_KEY using TPM_KEY_PARMS. encData is stored as clear text since there is no + parent key for the ephemeral key */ + if (returnCode == TPM_SUCCESS) { + /* This must immediately follow the successful malloc, so the _Delete / free work */ + TPM_Key_Init(tempKey); + printf(" TPM_Process_ChangeAuthAsymStart: Creating ephemeral key\n"); + returnCode = TPM_Key_GenerateRSA(tempKey, + tpm_state, + NULL, /* encData cleartext */ + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + 1, /* TPM_KEY */ + TPM_KEY_AUTHCHANGE, /* keyUsage */ + TPM_ISVOLATILE, /* keyFlags */ + TPM_AUTH_NEVER, /* authDataUsage */ + &tempKeyParms, /* TPM_KEY_PARMS */ + NULL, /* TPM_PCR_INFO */ + NULL); /* TPM_PCR_INFO_LONG */ + } + if (returnCode == TPM_SUCCESS) { + ephHandle = 0; /* no preferred value */ + returnCode = TPM_KeyHandleEntries_AddKeyEntry(&ephHandle, /* output */ + tpm_state->tpm_key_handle_entries, /* input */ + tempKey, /* input */ + 0, /* parentPCRStatus not used */ + 0); /* keyControl not used */ + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuthAsymStart: Ephemeral key handle %08x\n", ephHandle); + /* remember that the handle has been added to handle list, so it can be deleted on error */ + key_added = TRUE; + } + /* 8. The TPM SHALL fill in all fields in tempKey using k1 for the information. The TPM_KEY -> + encSize MUST be 0. */ + /* NOTE Not required. k1 and tempKey are the same */ + /* 9. The TPM SHALL fill in certifyInfo using k1 for the information. The certifyInfo -> data + field is supplied by the antiReplay. */ + if (returnCode == TPM_SUCCESS) { + printf(" TPM_Process_ChangeAuthAsymStart: Creating certifyInfo\n"); + TPM_Nonce_Copy(certifyInfo.data, antiReplay); + returnCode = TPM_CertifyInfo_Set(&certifyInfo, tempKey); + } + /* 10. The TPM then signs the certifyInfo parameter using the key pointed to by idHandle. The + resulting signed blob is returned in sig parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(h1Digest, &certifyInfo, + (TPM_STORE_FUNCTION_T)TPM_CertifyInfo_Store); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuthAsymStart: Signing certifyInfo digest\n"); + returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ + h1Digest, /* message */ + TPM_DIGEST_SIZE, /* message size */ + idKey); /* input, signing key */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ChangeAuthAsymStart: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return certifyInfo */ + returnCode = TPM_CertifyInfo_Store(response, &certifyInfo); + } + /* return sig */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Store(response, &sig); + } + /* return ephHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append32(response, ephHandle); + } + /* return tempKey. TPM_Key_StorePubData() does not store any encData. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_StorePubData(response, FALSE, tempKey); + } + if (returnCode == TPM_SUCCESS) { + /* TPM_KEY.encSize is set to 0 */ + returnCode = TPM_Sbuffer_Append32(response, 0); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_KeyParms_Delete(&tempKeyParms); /* @1 */ + TPM_CertifyInfo_Delete(&certifyInfo); /* @2 */ + TPM_SizedBuffer_Delete(&sig); /* @3 */ + /* if there was a failure, delete inKey */ + if ((rcf != 0) || + (returnCode != TPM_SUCCESS)) { + TPM_Key_Delete(tempKey); /* @4 */ + free(tempKey); /* @4 */ + if (key_added) { + /* if there was a failure and tempKey was stored in the handle list, free the handle. + Ignore errors, since only one error code can be returned. */ + TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, ephHandle); + } + } + return rcf; +} + +/* 27.4.2 TPM_ChangeAuthAsymFinish rev 110 + + The TPM_ChangeAuthAsymFinish command allows the owner of an entity to change the AuthData for the + entity. + + The command requires the cooperation of the owner of the parent of the entity, since AuthData + must be provided to use that parent entity. The command requires knowledge of the existing + AuthData information and passes the new AuthData information. The newAuthLink parameter proves + knowledge of existing AuthData information and new AuthData information. The new AuthData + information "encNewAuth" is encrypted using the "tempKey" variable obtained via + TPM_ChangeAuthAsymStart. + + A parent therefore retains control over a change in the AuthData of a child, but is prevented + from knowing the new AuthData for that child. + + The changeProof parameter provides a proof that the new AuthData value was properly inserted into + the entity. The inclusion of a nonce from the TPM provides an entropy source in the case where + the AuthData value may be in itself be a low entropy value (hash of a password etc). +*/ + +TPM_RESULT TPM_Process_ChangeAuthAsymFinish(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* The keyHandle of the parent key for the input + data */ + TPM_KEY_HANDLE ephHandle; /* The keyHandle identifier for the ephemeral key */ + TPM_ENTITY_TYPE entityType = 0; /* The type of entity to be modified */ + TPM_HMAC newAuthLink; /* HMAC calculation that links the old and new + AuthData values together */ + TPM_SIZED_BUFFER encNewAuth; /* New AuthData encrypted with ephemeral key. */ + TPM_SIZED_BUFFER encData; /* The encrypted entity that is to be modified. */ + TPM_AUTHHANDLE authHandle; /* Authorization for parent key. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with + authHandle */ + TPM_BOOL continueAuthSession; /* The continue use flag for the + authorization session handle */ + TPM_AUTHDATA privAuth; /* The authorization session digest for inputs and + parentHandle. HMAC key: parentKey.usageAuth. */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_KEY *parentKey = NULL; + TPM_SECRET *parentKeyUsageAuth; + TPM_BOOL parentPCRStatus; + TPM_KEY *ephKey = NULL; + TPM_BOOL ephPCRStatus; + unsigned char *stream; /* for deserializing decrypted encData */ + uint32_t stream_size; + TPM_STORE_ASYMKEY keyEntity; /* entity structure when it's a TPM_ET_KEY */ + unsigned char *e1DecryptData; + uint32_t e1DecryptDataLength = 0; /* actual valid data */ + unsigned char *a1Auth; + uint32_t a1AuthLength = 0; /* actual valid data */ + TPM_CHANGEAUTH_VALIDATE changeauthValidate; + TPM_BOOL valid; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER outData; /* The modified, encrypted entity. */ + TPM_NONCE saltNonce; /* A nonce value from the TPM RNG to add entropy to the + changeProof value */ + TPM_DIGEST changeProof; /* Proof that AuthData has changed. */ + + printf("TPM_Process_ChangeAuthAsymFinish: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&encNewAuth); /* freed @1 */ + TPM_SizedBuffer_Init(&encData); /* freed @2 */ + TPM_SizedBuffer_Init(&outData); /* freed @3 */ + TPM_StoreAsymkey_Init(&keyEntity); /* freed @4 */ + e1DecryptData = NULL; /* freed @5 */ + a1Auth = NULL; /* freed @6 */ + TPM_ChangeauthValidate_Init(&changeauthValidate); /* freed @7 */ + /* + get inputs + */ + /* get parentHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* get ephHandle parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuthAsymFinish: parentHandle %08x\n", parentHandle); + returnCode = TPM_Load32(&ephHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuthAsymFinish: ephHandle %08x\n", ephHandle); + /* get entityType parameter */ + returnCode = TPM_Load16(&entityType, &command, ¶mSize); + } + /* get newAuthLink parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(newAuthLink, &command, ¶mSize); + } + /* get encNewAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&encNewAuth, &command, ¶mSize); + } + /* get encData parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&encData, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuthAsymFinish: encDataSize %u\n", encData.size); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ChangeAuthAsymFinish: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. The TPM SHALL validate that the authHandle parameter authorizes use of the key in + parentHandle.*/ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ + if (parentKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_ChangeAuthAsymFinish: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get idHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + if (parentHandle != TPM_KH_SRK) { + returnCode = TPM_Key_GetUsageAuth(&parentKeyUsageAuth, parentKey); + } + /* If the parentHandle points to the SRK then the HMAC key MUST be built using the TPM Owner + authorization. */ + else { + parentKeyUsageAuth = &(tpm_state->tpm_permanent_data.ownerAuth); + } + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + if (parentHandle != TPM_KH_SRK) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + parentKeyUsageAuth, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* If the parentHandle points to the SRK then the HMAC key MUST be built using the TPM Owner + authorization. */ + else { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + parentKey, + parentKeyUsageAuth, /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /*OSAP*/ + } + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + /* 2. The encData field MUST be the encData field from TPM_STORED_DATA or TPM_KEY. */ + if (returnCode == TPM_SUCCESS) { + /* FIXME currently only TPM_KEY supported */ + if (entityType != TPM_ET_KEY) { + printf("TPM_Process_ChangeAuthAsymFinish: Error, bad entityType %04x\n", entityType); + returnCode = TPM_WRONG_ENTITYTYPE; + } + } + /* Validate that parentHandle -> keyUsage is TPM_KEY_STORAGE, if not return the error code + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_ChangeAuthAsymFinish: Error, keyUsage %04hx is invalid\n", + parentKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. The TPM SHALL create e1 by decrypting the entity held in the encData parameter. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPrivateDecryptMalloc(&e1DecryptData, /* decrypted data */ + &e1DecryptDataLength, /* actual size of decrypted + data */ + encData.buffer,/* encrypted data */ + encData.size, /* encrypted data size */ + parentKey); + } + if (returnCode == TPM_SUCCESS) { + stream = e1DecryptData; + stream_size = e1DecryptDataLength; + returnCode = TPM_StoreAsymkey_Load(&keyEntity, FALSE, + &stream, &stream_size, + NULL, /* TPM_KEY_PARMS */ + NULL); /* TPM_SIZED_BUFFER pubKey */ + } + /* 4. The TPM SHALL create a1 by decrypting encNewAuth using the ephHandle -> + TPM_KEY_AUTHCHANGE private key. a1 is a structure of type TPM_CHANGEAUTH_VALIDATE. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&ephKey, &ephPCRStatus, tpm_state, ephHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if (returnCode == TPM_SUCCESS) { + if (ephKey->keyUsage != TPM_KEY_AUTHCHANGE) { + printf("TPM_Process_ChangeAuthAsymFinish: Error: " + "ephHandle does not point to TPM_KEY_AUTHCHANGE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPrivateDecryptMalloc(&a1Auth, /* decrypted data */ + &a1AuthLength, /* actual size of decrypted data */ + encNewAuth.buffer, /* encrypted data */ + encNewAuth.size, /* encrypted data size */ + ephKey); + } + if (returnCode == TPM_SUCCESS) { + stream = a1Auth; + stream_size = a1AuthLength; + returnCode = TPM_ChangeauthValidate_Load(&changeauthValidate, &stream, &stream_size); + } + /* 5. The TPM SHALL create b1 by performing the following HMAC calculation: b1 = HMAC (a1 -> + newAuthSecret). The secret for this calculation is encData -> currentAuth. This means that b1 + is a value built from the current AuthData value (encData -> currentAuth) and the new + AuthData value (a1 -> newAuthSecret). */ + /* 6. The TPM SHALL compare b1 with newAuthLink. The TPM SHALL indicate a failure if the values + do not match. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_HMAC_Check(&valid, + newAuthLink, /* expect */ + keyEntity.usageAuth, /* HMAC key is current auth */ + TPM_SECRET_SIZE, changeauthValidate.newAuthSecret, + 0, NULL); + } + if (returnCode == TPM_SUCCESS) { + if (!valid) { + printf("TPM_Process_ChangeAuthAsymFinish: Error, authenticating newAuthLink\n"); + returnCode = TPM_AUTHFAIL; + } + } + if (returnCode == TPM_SUCCESS) { + /* 7. The TPM SHALL replace e1 -> authData with a1 -> newAuthSecret */ + TPM_Secret_Copy(keyEntity.usageAuth, changeauthValidate.newAuthSecret); + /* 8. The TPM SHALL encrypt e1 using the appropriate functions for the entity type. The key + to encrypt with is parentHandle. */ + returnCode = TPM_StoreAsymkey_GenerateEncData(&outData, &keyEntity, parentKey); + } + /* 9. The TPM SHALL create salt-Nonce by taking the next 20 bytes from the TPM RNG. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Random(saltNonce, TPM_NONCE_SIZE); + } + /* 10. The TPM SHALL create changeProof a HMAC of (saltNonce concatenated with a1 -> n1) using + a1 -> newAuthSecret as the HMAC secret. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_HMAC_Generate(changeProof, /* hmac output */ + changeauthValidate.newAuthSecret, /* hmac key */ + TPM_NONCE_SIZE, saltNonce, + TPM_NONCE_SIZE, changeauthValidate.n1, + 0, NULL); + } + /* 11. The TPM MUST destroy the TPM_KEY_AUTHCHANGE key associated with the authorization + session. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ChangeAuthAsymFinish: Deleting ephemeral key\n"); + TPM_Key_Delete(ephKey); /* free the key resources */ + free(ephKey); /* free the key itself */ + /* remove entry from the key handle entries list */ + returnCode = TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, + ephHandle); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ChangeAuthAsymFinish: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + } + /* return saltNonce */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Store(response, saltNonce); + } + /* return changeProof */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Store(response, changeProof); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&encNewAuth); /* @1 */ + TPM_SizedBuffer_Delete(&encData); /* @2 */ + TPM_SizedBuffer_Delete(&outData); /* @3 */ + TPM_StoreAsymkey_Delete(&keyEntity); /* @4 */ + free(e1DecryptData); /* @5 */ + free(a1Auth); /* @6 */ + TPM_ChangeauthValidate_Delete(&changeauthValidate); /* @7 */ + return rcf; +} diff --git a/src/tpm12/tpm_auth.h b/src/tpm12/tpm_auth.h new file mode 100644 index 0000000..fba8e6d --- /dev/null +++ b/src/tpm12/tpm_auth.h @@ -0,0 +1,180 @@ +/********************************************************************************/ +/* */ +/* Authorization */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_auth.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_AUTH_H +#define TPM_AUTH_H + +#include "tpm_global.h" +#include "tpm_session.h" +#include "tpm_store.h" +#include "tpm_structures.h" +#include "tpm_types.h" + +/* + TPM_AUTHDATA +*/ + +#if 0 +void TPM_Authdata_Init(TPM_AUTHDATA tpm_authdata); +#endif +TPM_RESULT TPM_Authdata_Load(TPM_AUTHDATA tpm_authdata, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Authdata_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_AUTHDATA tpm_authdata); + +TPM_RESULT TPM_Authdata_Generate(TPM_AUTHDATA resAuth, + TPM_SECRET usageAuth, + TPM_DIGEST outParamDigest, + TPM_NONCE nonceEven, + TPM_NONCE nonceOdd, + TPM_BOOL continueSession); + +TPM_RESULT TPM_Authdata_Check(tpm_state_t *tpm_state, + TPM_SECRET hmacKey, + TPM_DIGEST inParamDigest, + TPM_AUTH_SESSION_DATA *tpm_auth_session_data, + TPM_NONCE nonceOdd, + TPM_BOOL continueSession, + TPM_AUTHDATA usageAuth); +TPM_RESULT TPM_Auth2data_Check(tpm_state_t *tpm_state, + TPM_SECRET hmacKey, + TPM_DIGEST inParamDigest, + TPM_AUTH_SESSION_DATA *tpm_auth_session_data, + TPM_NONCE nonceOdd, + TPM_BOOL continueSession, + TPM_AUTHDATA usageAuth); + +TPM_RESULT TPM_Authdata_Fail(tpm_state_t *tpm_state); +TPM_RESULT TPM_Authdata_GetState(TPM_DA_STATE *state, + uint32_t *timeLeft, + tpm_state_t *tpm_state); +TPM_RESULT TPM_Authdata_CheckState(tpm_state_t *tpm_state); + +/* + Utilities for command input and output parameter load and store +*/ + +TPM_RESULT TPM_AuthParams_Get(TPM_AUTHHANDLE *authHandle, + TPM_BOOL *authHandleValid, + TPM_NONCE nonceOdd, + TPM_BOOL *continueAuthSession, + TPM_AUTHDATA authData, + unsigned char **command, + uint32_t *paramSize); + +TPM_RESULT TPM_AuthParams_Set(TPM_STORE_BUFFER *response, + TPM_SECRET hmacKey, + TPM_AUTH_SESSION_DATA *auth_session_data, + TPM_DIGEST outParamDigest, + TPM_NONCE nonceOdd, + TPM_BOOL continueAuthSession); + +/* + TPM_CHANGEAUTH_VALIDATE +*/ + +void TPM_ChangeauthValidate_Init(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate); +TPM_RESULT TPM_ChangeauthValidate_Load(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate, + unsigned char **stream, + uint32_t *stream_size); +#if 0 +TPM_RESULT TPM_ChangeauthValidate_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate); +#endif +void TPM_ChangeauthValidate_Delete(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate); + +/* + TPM_DA_INFO +*/ + +void TPM_DaInfo_Init(TPM_DA_INFO *tpm_da_info); +TPM_RESULT TPM_DaInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DA_INFO *tpm_da_info); +void TPM_DaInfo_Delete(TPM_DA_INFO *tpm_da_info); + +TPM_RESULT TPM_DaInfo_Set(TPM_DA_INFO *tpm_da_info, + tpm_state_t *tpm_state); + +/* + TPM_DA_INFO_LIMITED +*/ + +void TPM_DaInfoLimited_Init(TPM_DA_INFO_LIMITED *tpm_da_info_limited); +TPM_RESULT TPM_DaInfoLimited_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DA_INFO_LIMITED *tpm_da_info_limited); +void TPM_DaInfoLimited_Delete(TPM_DA_INFO_LIMITED *tpm_da_info_limited); + +TPM_RESULT TPM_DaInfoLimited_Set(TPM_DA_INFO_LIMITED *tpm_da_info_limited, + tpm_state_t *tpm_state); + +/* + Processing functions +*/ + +TPM_RESULT TPM_Process_ChangeAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ChangeAuthOwner(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ChangeAuthAsymStart(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ChangeAuthAsymFinish(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +#endif diff --git a/src/tpm12/tpm_commands.h b/src/tpm12/tpm_commands.h new file mode 100644 index 0000000..a12c382 --- /dev/null +++ b/src/tpm12/tpm_commands.h @@ -0,0 +1,51 @@ +/********************************************************************************/ +/* */ +/* TPM Command Structure */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_commands.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_COMMANDS_H +#define TPM_COMMANDS_H + +#include "tpm_types.h" + +/* general structure for all commands */ + +#define TPM_TAG_OFFSET 0 +#define TPM_PARAMSIZE_OFFSET (sizeof(TPM_TAG) + TPM_TAG_OFFSET) +#define TPM_ORDINAL_OFFSET (sizeof(uint32_t) + TPM_PARAMSIZE_OFFSET) + +#endif diff --git a/src/tpm12/tpm_constants.h b/src/tpm12/tpm_constants.h new file mode 100644 index 0000000..9569e6d --- /dev/null +++ b/src/tpm12/tpm_constants.h @@ -0,0 +1,1652 @@ +/********************************************************************************/ +/* */ +/* TPM Constants */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_constants.h 4603 2011-08-16 20:40:26Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_CONSTANTS_H +#define TPM_CONSTANTS_H + +#include + +#include + +/* + NOTE implementation Specific +*/ + +/* + version, revision, specLevel, errataRev +*/ + +/* current for released specification revision 103 */ + +#define TPM_REVISION_MAX 9999 +#ifndef TPM_REVISION +#define TPM_REVISION TPM_REVISION_MAX +#endif + +#if (TPM_REVISION >= 116) + +#define TPM_SPEC_LEVEL 0x0002 /* uint16_t The level of ordinals supported */ +#define TPM_ERRATA_REV 0x03 /* specification errata level */ + +#elif (TPM_REVISION >= 103) + +#define TPM_SPEC_LEVEL 0x0002 /* uint16_t The level of ordinals supported */ +#define TPM_ERRATA_REV 0x02 /* specification errata level */ + +#elif (TPM_REVISION >= 94) + +#define TPM_SPEC_LEVEL 0x0002 /* uint16_t The level of ordinals supported */ +#define TPM_ERRATA_REV 0x01 /* specification errata level */ + +#elif (TPM_REVISION >= 85) + +#define TPM_SPEC_LEVEL 0x0002 /* uint16_t The level of ordinals supported */ +#define TPM_ERRATA_REV 0x00 /* specification errata level */ + +#else + +#define TPM_SPEC_LEVEL 0x0001 /* uint16_t The level of ordinals supported */ +#define TPM_ERRATA_REV 0x00 /* specification errata level */ + +#endif + +/* IBM specific */ + +#if 0 /* at one time vendorID was the PCI vendor ID, this is the IBM code */ +#define TPM_VENDOR_ID "\x00\x00\x10\x14" /* BYTE[4], the vendor ID, obtained from the TCG, + typically PCI vendor ID */ +#endif + + + +#define TPM_VENDOR_ID "IBM" /* 4 bytes, as of rev 99 vendorID and TPM_CAP_PROP_MANUFACTURER + return the same value */ +#define TPM_MANUFACTURER "IBM" /* 4 characters, assigned by TCG, typically stock ticker symbol */ + + +/* Timeouts in microseconds. These are for the platform specific interface (e.g. the LPC bus + registers in the PC Client TPM). They are most likely not applicable to a software TPM. */ +#define TPM_TIMEOUT_A 1000000 +#define TPM_TIMEOUT_B 1000000 +#define TPM_TIMEOUT_C 1000000 +#define TPM_TIMEOUT_D 1000000 + +/* dictionary attack mitigation */ + +#define TPM_LOCKOUT_THRESHOLD 5 /* successive failures to trigger lockout, must be greater + than 0 */ + +/* Denotes the duration value in microseconds of the duration of the three classes of commands: + Small, Medium and Long. The command types are in the Part 2 Ordinal Table. Essentially: + + Long - creating an RSA key pair + Medium - using an RSA key + Short - anything else +*/ + +#ifndef TPM_SMALL_DURATION +#define TPM_SMALL_DURATION 2000000 +#endif + +#ifndef TPM_MEDIUM_DURATION +#define TPM_MEDIUM_DURATION 5000000 +#endif + +#ifndef TPM_LONG_DURATION +#define TPM_LONG_DURATION 60000000 +#endif + +/* startup effects */ + +#define TPM_STARTUP_EFFECTS_VALUE \ +(TPM_STARTUP_EFFECTS_ST_ANY_RT_KEY | /* key resources init by TPM_Startup(ST_ANY) */ \ + TPM_STARTUP_EFFECTS_ST_STATE_RT_HASH | /* hash resources are init by TPM_Startup(ST_STATE) */ \ + TPM_STARTUP_EFFECTS_ST_CLEAR_AUDITDIGEST) /* auditDigest nulled on TPM_Startup(ST_CLEAR) */ + +/* + TPM buffer limits +*/ + +/* This is the increment by which the TPM_STORE_BUFFER grows. A larger number saves realloc's. A + smaller number saves memory. + + TPM_ALLOC_MAX must be a multiple of this value. +*/ + +#define TPM_STORE_BUFFER_INCREMENT (TPM_ALLOC_MAX / 64) + +/* This is the maximum value of the TPM input and output packet buffer. It should be large enough + to accommodate the largest TPM command or response, currently about 1200 bytes. It should be + small enough to accommodate whatever software is driving the TPM. + + NOTE: Some commands are somewhat open ended, and related to this parmater. E.g., The input size + for the TPM_SHA1Init. The output size for TPM_GetRandom. + + It is returned by TPM_GetCapability -> TPM_CAP_PROP_INPUT_BUFFER +*/ + +#ifndef TPM_BUFFER_MAX +#define TPM_BUFFER_MAX 0x1000 /* 4k bytes */ +#endif + +#ifndef TPM_BUFFER_MIN +#define TPM_BUFFER_MIN 0x0c00 /* 3k bytes */ +#endif + +/* Random number generator */ + +/* maximum bytes in one TPM_GetRandom() call + + Use maximum input buffer size minus tag, paramSize, returnCode, randomBytesSize. +*/ + +#define TPM_RANDOM_MAX (TPM12_GetBufferSize() \ + - sizeof(TPM_TAG) - sizeof(uint32_t) \ + - sizeof(TPM_RESULT) - sizeof(uint32_t)) + +/* Maximum number of bytes that can be sent to TPM_SHA1Update. Must be a multiple of 64 bytes. + + Use maximum input buffer size minus tag, paramSize, ordinal, numBytes. +*/ + +#define TPM_SHA1_MAXNUMBYTES (TPM12_GetBufferSize() - 64) + +/* extra audit status bits for TSC commands outside the normal ordinal range */ +#define TSC_PHYS_PRES_AUDIT 0x01 +#define TSC_RESET_ESTAB_AUDIT 0x02 + + +/* TPM_CAP_MFR capabilities */ +#define TPM_CAP_PROCESS_ID 0x00000020 + + +/* define a value for an illegal instance handle */ + +#define TPM_ILLEGAL_INSTANCE_HANDLE 0xffffffff + +/* + NOTE End Implementation Specific +*/ + +/* 3. Structure Tags rev 105 + + There have been some indications that knowing what structure is in use would be valuable + information in each structure. This new tag will be in each new structure that the TPM defines. + + The upper nibble of the value designates the purview of the structure tag. 0 is used for TPM + structures, 1 for platforms, and 2-F are reserved. +*/ + +/* 3.1 TPM_STRUCTURE_TAG */ + +/* Structure */ +#define TPM_TAG_CONTEXTBLOB 0x0001 /* TPM_CONTEXT_BLOB */ +#define TPM_TAG_CONTEXT_SENSITIVE 0x0002 /* TPM_CONTEXT_SENSITIVE */ +#define TPM_TAG_CONTEXTPOINTER 0x0003 /* TPM_CONTEXT_POINTER */ +#define TPM_TAG_CONTEXTLIST 0x0004 /* TPM_CONTEXT_LIST */ +#define TPM_TAG_SIGNINFO 0x0005 /* TPM_SIGN_INFO */ +#define TPM_TAG_PCR_INFO_LONG 0x0006 /* TPM_PCR_INFO_LONG */ +#define TPM_TAG_PERSISTENT_FLAGS 0x0007 /* TPM_PERSISTENT_FLAGS (deprecated 1.1 struct) */ +#define TPM_TAG_VOLATILE_FLAGS 0x0008 /* TPM_VOLATILE_FLAGS (deprecated 1.1 struct) */ +#define TPM_TAG_PERSISTENT_DATA 0x0009 /* TPM_PERSISTENT_DATA (deprecated 1.1 struct) */ +#define TPM_TAG_VOLATILE_DATA 0x000A /* TPM_VOLATILE_DATA (deprecated 1.1 struct) */ +#define TPM_TAG_SV_DATA 0x000B /* TPM_SV_DATA */ +#define TPM_TAG_EK_BLOB 0x000C /* TPM_EK_BLOB */ +#define TPM_TAG_EK_BLOB_AUTH 0x000D /* TPM_EK_BLOB_AUTH */ +#define TPM_TAG_COUNTER_VALUE 0x000E /* TPM_COUNTER_VALUE */ +#define TPM_TAG_TRANSPORT_INTERNAL 0x000F /* TPM_TRANSPORT_INTERNAL */ +#define TPM_TAG_TRANSPORT_LOG_IN 0x0010 /* TPM_TRANSPORT_LOG_IN */ +#define TPM_TAG_TRANSPORT_LOG_OUT 0x0011 /* TPM_TRANSPORT_LOG_OUT */ +#define TPM_TAG_AUDIT_EVENT_IN 0x0012 /* TPM_AUDIT_EVENT_IN */ +#define TPM_TAG_AUDIT_EVENT_OUT 0X0013 /* TPM_AUDIT_EVENT_OUT */ +#define TPM_TAG_CURRENT_TICKS 0x0014 /* TPM_CURRENT_TICKS */ +#define TPM_TAG_KEY 0x0015 /* TPM_KEY */ +#define TPM_TAG_STORED_DATA12 0x0016 /* TPM_STORED_DATA12 */ +#define TPM_TAG_NV_ATTRIBUTES 0x0017 /* TPM_NV_ATTRIBUTES */ +#define TPM_TAG_NV_DATA_PUBLIC 0x0018 /* TPM_NV_DATA_PUBLIC */ +#define TPM_TAG_NV_DATA_SENSITIVE 0x0019 /* TPM_NV_DATA_SENSITIVE */ +#define TPM_TAG_DELEGATIONS 0x001A /* TPM DELEGATIONS */ +#define TPM_TAG_DELEGATE_PUBLIC 0x001B /* TPM_DELEGATE_PUBLIC */ +#define TPM_TAG_DELEGATE_TABLE_ROW 0x001C /* TPM_DELEGATE_TABLE_ROW */ +#define TPM_TAG_TRANSPORT_AUTH 0x001D /* TPM_TRANSPORT_AUTH */ +#define TPM_TAG_TRANSPORT_PUBLIC 0X001E /* TPM_TRANSPORT_PUBLIC */ +#define TPM_TAG_PERMANENT_FLAGS 0X001F /* TPM_PERMANENT_FLAGS */ +#define TPM_TAG_STCLEAR_FLAGS 0X0020 /* TPM_STCLEAR_FLAGS */ +#define TPM_TAG_STANY_FLAGS 0X0021 /* TPM_STANY_FLAGS */ +#define TPM_TAG_PERMANENT_DATA 0X0022 /* TPM_PERMANENT_DATA */ +#define TPM_TAG_STCLEAR_DATA 0X0023 /* TPM_STCLEAR_DATA */ +#define TPM_TAG_STANY_DATA 0X0024 /* TPM_STANY_DATA */ +#define TPM_TAG_FAMILY_TABLE_ENTRY 0X0025 /* TPM_FAMILY_TABLE_ENTRY */ +#define TPM_TAG_DELEGATE_SENSITIVE 0X0026 /* TPM_DELEGATE_SENSITIVE */ +#define TPM_TAG_DELG_KEY_BLOB 0X0027 /* TPM_DELG_KEY_BLOB */ +#define TPM_TAG_KEY12 0x0028 /* TPM_KEY12 */ +#define TPM_TAG_CERTIFY_INFO2 0X0029 /* TPM_CERTIFY_INFO2 */ +#define TPM_TAG_DELEGATE_OWNER_BLOB 0X002A /* TPM_DELEGATE_OWNER_BLOB */ +#define TPM_TAG_EK_BLOB_ACTIVATE 0X002B /* TPM_EK_BLOB_ACTIVATE */ +#define TPM_TAG_DAA_BLOB 0X002C /* TPM_DAA_BLOB */ +#define TPM_TAG_DAA_CONTEXT 0X002D /* TPM_DAA_CONTEXT */ +#define TPM_TAG_DAA_ENFORCE 0X002E /* TPM_DAA_ENFORCE */ +#define TPM_TAG_DAA_ISSUER 0X002F /* TPM_DAA_ISSUER */ +#define TPM_TAG_CAP_VERSION_INFO 0X0030 /* TPM_CAP_VERSION_INFO */ +#define TPM_TAG_DAA_SENSITIVE 0X0031 /* TPM_DAA_SENSITIVE */ +#define TPM_TAG_DAA_TPM 0X0032 /* TPM_DAA_TPM */ +#define TPM_TAG_CMK_MIGAUTH 0X0033 /* TPM_CMK_MIGAUTH */ +#define TPM_TAG_CMK_SIGTICKET 0X0034 /* TPM_CMK_SIGTICKET */ +#define TPM_TAG_CMK_MA_APPROVAL 0X0035 /* TPM_CMK_MA_APPROVAL */ +#define TPM_TAG_QUOTE_INFO2 0X0036 /* TPM_QUOTE_INFO2 */ +#define TPM_TAG_DA_INFO 0x0037 /* TPM_DA_INFO */ +#define TPM_TAG_DA_INFO_LIMITED 0x0038 /* TPM_DA_INFO_LIMITED */ +#define TPM_TAG_DA_ACTION_TYPE 0x0039 /* TPM_DA_ACTION_TYPE */ + +/* + SW TPM Tags +*/ + +/* + These tags are used to describe the format of serialized TPM non-volatile state +*/ + +/* These describe the overall format */ + +/* V1 state is the sequence permanent data, permanent flags, owner evict keys, NV defined space */ + +#define TPM_TAG_NVSTATE_V1 0x0001 /* svn revision 4078 */ + +/* These tags describe the TPM_PERMANENT_DATA format */ + +/* For the first release, use the standard TPM_TAG_PERMANENT_DATA tag. Since this tag is never + visible outside the TPM, the tag value can be changed if the format changes. +*/ + +/* These tags describe the TPM_PERMANENT_FLAGS format */ + +/* The TPM_PERMANENT_FLAGS structure changed from rev 94 to 103. Unfortunately, the standard TPM + tag did not change. Define distinguishing values here. +*/ + +#define TPM_TAG_NVSTATE_PF94 0x0001 +#define TPM_TAG_NVSTATE_PF103 0x0002 + +/* This tag describes the owner evict key format */ + +#define TPM_TAG_NVSTATE_OE_V1 0x0001 + +/* This tag describes the NV defined space format */ + +#define TPM_TAG_NVSTATE_NV_V1 0x0001 + +/* V2 added the NV public optimization */ + +#define TPM_TAG_NVSTATE_NV_V2 0x0002 + +/* + These tags are used to describe the format of serialized TPM volatile state +*/ + +/* These describe the overall format */ + +/* V1 state is the sequence TPM Parameters, TPM_STCLEAR_FLAGS, TPM_STANY_FLAGS, TPM_STCLEAR_DATA, + TPM_STANY_DATA, TPM_KEY_HANDLE_ENTRY, SHA1 context(s), TPM_TRANSHANDLE, testState, NV volatile + flags */ + +#define TPM_TAG_VSTATE_V1 0x0001 + +/* This tag defines the TPM Parameters format */ + +#define TPM_TAG_TPM_PARAMETERS_V1 0x0001 + +/* This tag defines the TPM_STCLEAR_FLAGS format */ + +/* V1 is the TCG standard returned by the getcap. It's unlikely that this will change */ + +#define TPM_TAG_STCLEAR_FLAGS_V1 0x0001 + +/* These tags describe the TPM_STANY_FLAGS format */ + +/* For the first release, use the standard TPM_TAG_STANY_FLAGS tag. Since this tag is never visible + outside the TPM, the tag value can be changed if the format changes. +*/ + +/* This tag defines the TPM_STCLEAR_DATA format */ + +/* V2 deleted the ordinalResponse, responseCount */ + +#define TPM_TAG_STCLEAR_DATA_V2 0X0024 + +/* These tags describe the TPM_STANY_DATA format */ + +/* For the first release, use the standard TPM_TAG_STANY_DATA tag. Since this tag is never visible + outside the TPM, the tag value can be changed if the format changes. +*/ + +/* This tag defines the key handle entries format */ + +#define TPM_TAG_KEY_HANDLE_ENTRIES_V1 0x0001 + +/* This tag defines the SHA-1 context format */ + +#define TPM_TAG_SHA1CONTEXT_OSSL_V1 0x0001 /* for openssl */ + +#define TPM_TAG_SHA1CONTEXT_FREEBL_V1 0x0101 /* for freebl */ + +/* This tag defines the NV index entries volatile format */ + +#define TPM_TAG_NV_INDEX_ENTRIES_VOLATILE_V1 0x0001 + +/* 4. Types + */ + +/* 4.1 TPM_RESOURCE_TYPE rev 87 */ + +#define TPM_RT_KEY 0x00000001 /* The handle is a key handle and is the result of a LoadKey + type operation */ + +#define TPM_RT_AUTH 0x00000002 /* The handle is an authorization handle. Auth handles come from + TPM_OIAP, TPM_OSAP and TPM_DSAP */ + +#define TPM_RT_HASH 0X00000003 /* Reserved for hashes */ + +#define TPM_RT_TRANS 0x00000004 /* The handle is for a transport session. Transport handles come + from TPM_EstablishTransport */ + +#define TPM_RT_CONTEXT 0x00000005 /* Resource wrapped and held outside the TPM using the context + save/restore commands */ + +#define TPM_RT_COUNTER 0x00000006 /* Reserved for counters */ + +#define TPM_RT_DELEGATE 0x00000007 /* The handle is for a delegate row. These are the internal rows + held in NV storage by the TPM */ + +#define TPM_RT_DAA_TPM 0x00000008 /* The value is a DAA TPM specific blob */ + +#define TPM_RT_DAA_V0 0x00000009 /* The value is a DAA V0 parameter */ + +#define TPM_RT_DAA_V1 0x0000000A /* The value is a DAA V1 parameter */ + +/* 4.2 TPM_PAYLOAD_TYPE rev 87 + + This structure specifies the type of payload in various messages. +*/ + +#define TPM_PT_ASYM 0x01 /* The entity is an asymmetric key */ +#define TPM_PT_BIND 0x02 /* The entity is bound data */ +#define TPM_PT_MIGRATE 0x03 /* The entity is a migration blob */ +#define TPM_PT_MAINT 0x04 /* The entity is a maintenance blob */ +#define TPM_PT_SEAL 0x05 /* The entity is sealed data */ +#define TPM_PT_MIGRATE_RESTRICTED 0x06 /* The entity is a restricted-migration asymmetric key */ +#define TPM_PT_MIGRATE_EXTERNAL 0x07 /* The entity is a external migratable key */ +#define TPM_PT_CMK_MIGRATE 0x08 /* The entity is a CMK migratable blob */ +/* 0x09 - 0x7F Reserved for future use by TPM */ +/* 0x80 - 0xFF Vendor specific payloads */ + +/* 4.3 TPM_ENTITY_TYPE rev 100 + + This specifies the types of entity that are supported by the TPM. + + The LSB is used to indicate the entity type. The MSB is used to indicate the ADIP + encryption scheme when applicable. + + For compatibility with TPM 1.1, this mapping is maintained: + + 0x0001 specifies a keyHandle entity with XOR encryption + 0x0002 specifies an owner entity with XOR encryption + 0x0003 specifies some data entity with XOR encryption + 0x0004 specifies the SRK entity with XOR encryption + 0x0005 specifies a key entity with XOR encryption + + When the entity is not being used for ADIP encryption, the MSB MUST be 0x00. +*/ + +/* TPM_ENTITY_TYPE LSB Values (entity type) */ + +#define TPM_ET_KEYHANDLE 0x01 /* The entity is a keyHandle or key */ +#define TPM_ET_OWNER 0x02 /*0x40000001 The entity is the TPM Owner */ +#define TPM_ET_DATA 0x03 /* The entity is some data */ +#define TPM_ET_SRK 0x04 /*0x40000000 The entity is the SRK */ +#define TPM_ET_KEY 0x05 /* The entity is a key or keyHandle */ +#define TPM_ET_REVOKE 0x06 /*0x40000002 The entity is the RevokeTrust value */ +#define TPM_ET_DEL_OWNER_BLOB 0x07 /* The entity is a delegate owner blob */ +#define TPM_ET_DEL_ROW 0x08 /* The entity is a delegate row */ +#define TPM_ET_DEL_KEY_BLOB 0x09 /* The entity is a delegate key blob */ +#define TPM_ET_COUNTER 0x0A /* The entity is a counter */ +#define TPM_ET_NV 0x0B /* The entity is a NV index */ +#define TPM_ET_OPERATOR 0x0C /* The entity is the operator */ +#define TPM_ET_RESERVED_HANDLE 0x40 /* Reserved. This value avoids collisions with the handle + MSB setting.*/ + +/* TPM_ENTITY_TYPE MSB Values (ADIP encryption scheme) */ + +#define TPM_ET_XOR 0x00 /* XOR */ +#define TPM_ET_AES128_CTR 0x06 /* AES 128 bits in CTR mode */ + +/* 4.4 Handles rev 88 + + Handles provides pointers to TPM internal resources. Handles should provide the ability to locate + a value without collision. + + 1. The TPM MAY order and set a handle to any value the TPM determines is appropriate + + 2. The handle value SHALL provide assurance that collisions SHOULD not occur in 2^24 handles + + 4.4.1 Reserved Key Handles + + The reserved key handles. These values specify specific keys or specific actions for the TPM. +*/ + +/* 4.4.1 Reserved Key Handles rev 87 + + The reserved key handles. These values specify specific keys or specific actions for the TPM. + + TPM_KH_TRANSPORT indicates to TPM_EstablishTransport that there is no encryption key, and that + the "secret" wrapped parameters are actually passed unencrypted. +*/ + +#define TPM_KH_SRK 0x40000000 /* The handle points to the SRK */ +#define TPM_KH_OWNER 0x40000001 /* The handle points to the TPM Owner */ +#define TPM_KH_REVOKE 0x40000002 /* The handle points to the RevokeTrust value */ +#define TPM_KH_TRANSPORT 0x40000003 /* The handle points to the TPM_EstablishTransport static + authorization */ +#define TPM_KH_OPERATOR 0x40000004 /* The handle points to the Operator auth */ +#define TPM_KH_ADMIN 0x40000005 /* The handle points to the delegation administration + auth */ +#define TPM_KH_EK 0x40000006 /* The handle points to the PUBEK, only usable with + TPM_OwnerReadInternalPub */ + +/* 4.5 TPM_STARTUP_TYPE rev 87 + + To specify what type of startup is occurring. +*/ + +#define TPM_ST_CLEAR 0x0001 /* The TPM is starting up from a clean state */ +#define TPM_ST_STATE 0x0002 /* The TPM is starting up from a saved state */ +#define TPM_ST_DEACTIVATED 0x0003 /* The TPM is to startup and set the deactivated flag to + TRUE */ + +/* 4.6 TPM_STARTUP_EFFECTS rev 101 + + This structure lists for the various resources and sessions on a TPM the affect that TPM_Startup + has on the values. + + There are three ST_STATE options for keys (restore all, restore non-volatile, or restore none) + and two ST_CLEAR options (restore non-volatile or restore none). As bit 4 was insufficient to + describe the possibilities, it is deprecated. Software should use TPM_CAP_KEY_HANDLE to + determine which keys are loaded after TPM_Startup. + + 31-9 No information and MUST be FALSE + + 8 TPM_RT_DAA_TPM resources are initialized by TPM_Startup(ST_STATE) + 7 TPM_Startup has no effect on auditDigest + 6 auditDigest is set to all zeros on TPM_Startup(ST_CLEAR) but not on other types of TPM_Startup + 5 auditDigest is set to all zeros on TPM_Startup(any) + 4 TPM_RT_KEY Deprecated, as the meaning was subject to interpretation. (Was:TPM_RT_KEY resources + are initialized by TPM_Startup(ST_ANY)) + 3 TPM_RT_AUTH resources are initialized by TPM_Startup(ST_STATE) + 2 TPM_RT_HASH resources are initialized by TPM_Startup(ST_STATE) + 1 TPM_RT_TRANS resources are initialized by TPM_Startup(ST_STATE) + 0 TPM_RT_CONTEXT session (but not key) resources are initialized by TPM_Startup(ST_STATE) +*/ + + +#define TPM_STARTUP_EFFECTS_ST_STATE_RT_DAA 0x00000100 /* bit 8 */ +#define TPM_STARTUP_EFFECTS_STARTUP_NO_AUDITDIGEST 0x00000080 /* bit 7 */ +#define TPM_STARTUP_EFFECTS_ST_CLEAR_AUDITDIGEST 0x00000040 /* bit 6 */ +#define TPM_STARTUP_EFFECTS_STARTUP_AUDITDIGEST 0x00000020 /* bit 5 */ +#define TPM_STARTUP_EFFECTS_ST_ANY_RT_KEY 0x00000010 /* bit 4 */ +#define TPM_STARTUP_EFFECTS_ST_STATE_RT_AUTH 0x00000008 /* bit 3 */ +#define TPM_STARTUP_EFFECTS_ST_STATE_RT_HASH 0x00000004 /* bit 2 */ +#define TPM_STARTUP_EFFECTS_ST_STATE_RT_TRANS 0x00000002 /* bit 1 */ +#define TPM_STARTUP_EFFECTS_ST_STATE_RT_CONTEXT 0x00000001 /* bit 0 */ + +/* 4.7 TPM_PROTOCOL_ID rev 87 + + This value identifies the protocol in use. +*/ + +#define TPM_PID_NONE 0x0000 /* kgold - added */ +#define TPM_PID_OIAP 0x0001 /* The OIAP protocol. */ +#define TPM_PID_OSAP 0x0002 /* The OSAP protocol. */ +#define TPM_PID_ADIP 0x0003 /* The ADIP protocol. */ +#define TPM_PID_ADCP 0X0004 /* The ADCP protocol. */ +#define TPM_PID_OWNER 0X0005 /* The protocol for taking ownership of a TPM. */ +#define TPM_PID_DSAP 0x0006 /* The DSAP protocol */ +#define TPM_PID_TRANSPORT 0x0007 /*The transport protocol */ + +/* 4.8 TPM_ALGORITHM_ID rev 99 + + This table defines the types of algorithms that may be supported by the TPM. + + The TPM MUST support the algorithms TPM_ALG_RSA, TPM_ALG_SHA, TPM_ALG_HMAC, and TPM_ALG_MGF1 +*/ + +#define TPM_ALG_RSA 0x00000001 /* The RSA algorithm. */ +/* #define TPM_ALG_DES 0x00000002 (was the DES algorithm) */ +/* #define TPM_ALG_3DES 0X00000003 (was the 3DES algorithm in EDE mode) */ +#define TPM_ALG_SHA 0x00000004 /* The SHA1 algorithm */ +#define TPM_ALG_HMAC 0x00000005 /* The RFC 2104 HMAC algorithm */ +#define TPM_ALG_AES128 0x00000006 /* The AES algorithm, key size 128 */ +#define TPM_ALG_MGF1 0x00000007 /* The XOR algorithm using MGF1 to create a string the size + of the encrypted block */ +#define TPM_ALG_AES192 0x00000008 /* AES, key size 192 */ +#define TPM_ALG_AES256 0x00000009 /* AES, key size 256 */ +#define TPM_ALG_XOR 0x0000000A /* XOR using the rolling nonces */ + +/* 4.9 TPM_PHYSICAL_PRESENCE rev 87 + +*/ + +#define TPM_PHYSICAL_PRESENCE_HW_DISABLE 0x0200 /* Sets the physicalPresenceHWEnable to FALSE + */ +#define TPM_PHYSICAL_PRESENCE_CMD_DISABLE 0x0100 /* Sets the physicalPresenceCMDEnable to + FALSE */ +#define TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK 0x0080 /* Sets the physicalPresenceLifetimeLock to + TRUE */ +#define TPM_PHYSICAL_PRESENCE_HW_ENABLE 0x0040 /* Sets the physicalPresenceHWEnable to TRUE + */ +#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE 0x0020 /* Sets the physicalPresenceCMDEnable to TRUE + */ +#define TPM_PHYSICAL_PRESENCE_NOTPRESENT 0x0010 /* Sets PhysicalPresence = FALSE */ +#define TPM_PHYSICAL_PRESENCE_PRESENT 0x0008 /* Sets PhysicalPresence = TRUE */ +#define TPM_PHYSICAL_PRESENCE_LOCK 0x0004 /* Sets PhysicalPresenceLock = TRUE */ + +#define TPM_PHYSICAL_PRESENCE_MASK 0xfc03 /* ~ OR of all above bits */ + +/* 4.10 TPM_MIGRATE_SCHEME rev 103 + + The scheme indicates how the StartMigrate command should handle the migration of the encrypted + blob. +*/ + +#define TPM_MS_MIGRATE 0x0001 /* A public key that can be used with all TPM + migration commands other than 'ReWrap' mode. */ +#define TPM_MS_REWRAP 0x0002 /* A public key that can be used for the ReWrap mode + of TPM_CreateMigrationBlob. */ +#define TPM_MS_MAINT 0x0003 /* A public key that can be used for the Maintenance + commands */ +#define TPM_MS_RESTRICT_MIGRATE 0x0004 /* The key is to be migrated to a Migration + Authority. */ +#define TPM_MS_RESTRICT_APPROVE 0x0005 /* The key is to be migrated to an entity approved by + a Migration Authority using double wrapping */ + +/* 4.11 TPM_EK_TYPE rev 87 + + This structure indicates what type of information that the EK is dealing with. +*/ + +#define TPM_EK_TYPE_ACTIVATE 0x0001 /* The blob MUST be TPM_EK_BLOB_ACTIVATE */ +#define TPM_EK_TYPE_AUTH 0x0002 /* The blob MUST be TPM_EK_BLOB_AUTH */ + +/* 4.12 TPM_PLATFORM_SPECIFIC rev 87 + + This enumerated type indicates the platform specific spec that the information relates to. +*/ + +#define TPM_PS_PC_11 0x0001 /* PC Specific version 1.1 */ +#define TPM_PS_PC_12 0x0002 /* PC Specific version 1.2 */ +#define TPM_PS_PDA_12 0x0003 /* PDA Specific version 1.2 */ +#define TPM_PS_Server_12 0x0004 /* Server Specific version 1.2 */ +#define TPM_PS_Mobile_12 0x0005 /* Mobil Specific version 1.2 */ + +/* 5.8 TPM_KEY_USAGE rev 101 + + This table defines the types of keys that are possible. Each value defines for what operation + the key can be used. Most key usages can be CMKs. See 4.2, TPM_PAYLOAD_TYPE. + + Each key has a setting defining the encryption and signature scheme to use. The selection of a + key usage value limits the choices of encryption and signature schemes. +*/ + +#define TPM_KEY_UNINITIALIZED 0x0000 /* NOTE: Added. This seems like a good place to indicate + that a TPM_KEY structure has not been initialized */ + +#define TPM_KEY_SIGNING 0x0010 /* This SHALL indicate a signing key. The [private] key + SHALL be used for signing operations, only. This means + that it MUST be a leaf of the Protected Storage key + hierarchy. */ + +#define TPM_KEY_STORAGE 0x0011 /* This SHALL indicate a storage key. The key SHALL be used + to wrap and unwrap other keys in the Protected Storage + hierarchy */ + +#define TPM_KEY_IDENTITY 0x0012 /* This SHALL indicate an identity key. The key SHALL be + used for operations that require a TPM identity, only. */ + +#define TPM_KEY_AUTHCHANGE 0X0013 /* This SHALL indicate an ephemeral key that is in use + during the ChangeAuthAsym process, only. */ + +#define TPM_KEY_BIND 0x0014 /* This SHALL indicate a key that can be used for TPM_Bind + and TPM_Unbind operations only. */ + +#define TPM_KEY_LEGACY 0x0015 /* This SHALL indicate a key that can perform signing and + binding operations. The key MAY be used for both signing + and binding operations. The TPM_KEY_LEGACY key type is to + allow for use by applications where both signing and + encryption operations occur with the same key. */ + +#define TPM_KEY_MIGRATE 0x0016 /* This SHALL indicate a key in use for TPM_MigrateKey */ + +/* 5.8.1 TPM_ENC_SCHEME Mandatory Key Usage Schemes rev 99 + + The TPM MUST check that the encryption scheme defined for use with the key is a valid scheme for + the key type, as follows: +*/ + +#define TPM_ES_NONE 0x0001 +#define TPM_ES_RSAESPKCSv15 0x0002 +#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003 +#define TPM_ES_SYM_CTR 0x0004 +#define TPM_ES_SYM_OFB 0x0005 + +/* 5.8.1 TPM_SIG_SCHEME Mandatory Key Usage Schemes rev 99 + + The TPM MUST check that the signature scheme defined for use with the key is a valid scheme for + the key type, as follows: +*/ + +#define TPM_SS_NONE 0x0001 +#define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002 +#define TPM_SS_RSASSAPKCS1v15_DER 0x0003 +#define TPM_SS_RSASSAPKCS1v15_INFO 0x0004 + +/* 5.9 TPM_AUTH_DATA_USAGE rev 110 + + The indication to the TPM when authorization sessions for an entity are required. Future + versions may allow for more complex decisions regarding AuthData checking. +*/ + +#define TPM_AUTH_NEVER 0x00 /* This SHALL indicate that usage of the key without + authorization is permitted. */ + +#define TPM_AUTH_ALWAYS 0x01 /* This SHALL indicate that on each usage of the key the + authorization MUST be performed. */ + +#define TPM_NO_READ_PUBKEY_AUTH 0x03 /* This SHALL indicate that on commands that require the TPM to + use the the key, the authorization MUST be performed. For + commands that cause the TPM to read the public portion of the + key, but not to use the key (e.g. TPM_GetPubKey), the + authorization may be omitted. */ + +/* 5.10 TPM_KEY_FLAGS rev 110 + + This table defines the meanings of the bits in a TPM_KEY_FLAGS structure, used in + TPM_STORE_ASYMKEY and TPM_CERTIFY_INFO. + + The value of TPM_KEY_FLAGS MUST be decomposed into individual mask values. The presence of a mask + value SHALL have the effect described in the above table + + On input, all undefined bits MUST be zero. The TPM MUST return an error if any undefined bit is + set. On output, the TPM MUST set all undefined bits to zero. +*/ + +#ifdef TPM_V12 +#define TPM_KEY_FLAGS_MASK 0x0000001f +#else +#define TPM_KEY_FLAGS_MASK 0x00000007 +#endif + +#define TPM_REDIRECTION 0x00000001 /* This mask value SHALL indicate the use of redirected + output. */ + +#define TPM_MIGRATABLE 0x00000002 /* This mask value SHALL indicate that the key is + migratable. */ + +#define TPM_ISVOLATILE 0x00000004 /* This mask value SHALL indicate that the key MUST be + unloaded upon execution of the + TPM_Startup(ST_Clear). This does not indicate that a + non-volatile key will remain loaded across + TPM_Startup(ST_Clear) events. */ + +#define TPM_PCRIGNOREDONREAD 0x00000008 /* When TRUE the TPM MUST NOT check digestAtRelease or + localityAtRelease for commands that read the public + portion of the key (e.g., TPM_GetPubKey) and MAY NOT + check digestAtRelease or localityAtRelease for + commands that use the public portion of the key + (e.g. TPM_Seal) + + When FALSE the TPM MUST check digestAtRelease and + localityAtRelease for commands that read or use the + public portion of the key */ + +#define TPM_MIGRATEAUTHORITY 0x00000010 /* When set indicates that the key is under control of a + migration authority. The TPM MUST only allow the + creation of a key with this flag in + TPM_MA_CreateKey */ + +/* 5.17 TPM_CMK_DELEGATE values rev 89 + + The bits of TPM_CMK_DELEGATE are flags that determine how the TPM responds to delegated requests + to manipulate a certified-migration-key, a loaded key with payload type TPM_PT_MIGRATE_RESTRICTED + or TPM_PT_MIGRATE_EXTERNAL.. + + 26:0 reserved MUST be 0 + + The default value of TPM_CMK_Delegate is zero (0) +*/ + +#define TPM_CMK_DELEGATE_SIGNING 0x80000000 /* When set to 1, this bit SHALL indicate that a + delegated command may manipulate a CMK of + TPM_KEY_USAGE == TPM_KEY_SIGNING */ +#define TPM_CMK_DELEGATE_STORAGE 0x40000000 /* When set to 1, this bit SHALL indicate that a + delegated command may manipulate a CMK of + TPM_KEY_USAGE == TPM_KEY_STORAGE */ +#define TPM_CMK_DELEGATE_BIND 0x20000000 /* When set to 1, this bit SHALL indicate that a + delegated command may manipulate a CMK of + TPM_KEY_USAGE == TPM_KEY_BIND */ +#define TPM_CMK_DELEGATE_LEGACY 0x10000000 /* When set to 1, this bit SHALL indicate that a + delegated command may manipulate a CMK of + TPM_KEY_USAGE == TPM_KEY_LEGACY */ +#define TPM_CMK_DELEGATE_MIGRATE 0x08000000 /* When set to 1, this bit SHALL indicate that a + delegated command may manipulate a CMK of + TPM_KEY_USAGE == TPM_KEY_MIGRATE */ + +/* 6. TPM_TAG (Command and Response Tags) rev 100 + + These tags indicate to the TPM the construction of the command either as input or as output. The + AUTH indicates that there are one or more AuthData values that follow the command + parameters. +*/ + +#define TPM_TAG_RQU_COMMAND 0x00C1 /* A command with no authentication. */ +#define TPM_TAG_RQU_AUTH1_COMMAND 0x00C2 /* An authenticated command with one authentication + handle */ +#define TPM_TAG_RQU_AUTH2_COMMAND 0x00C3 /* An authenticated command with two authentication + handles */ +#define TPM_TAG_RSP_COMMAND 0x00C4 /* A response from a command with no authentication + */ +#define TPM_TAG_RSP_AUTH1_COMMAND 0x00C5 /* An authenticated response with one authentication + handle */ +#define TPM_TAG_RSP_AUTH2_COMMAND 0x00C6 /* An authenticated response with two authentication + handles */ + +/* TIS 7.2 PCR Attributes + +*/ + +#define TPM_DEBUG_PCR 16 +#define TPM_LOCALITY_4_PCR 17 +#define TPM_LOCALITY_3_PCR 18 +#define TPM_LOCALITY_2_PCR 19 +#define TPM_LOCALITY_1_PCR 20 + +/* 10.9 TPM_KEY_CONTROL rev 87 + + Attributes that can control various aspects of key usage and manipulation. + + Allows for controlling of the key when loaded and how to handle TPM_Startup issues. +*/ + +#define TPM_KEY_CONTROL_OWNER_EVICT 0x00000001 /* Owner controls when the key is evicted + from the TPM. When set the TPM MUST + preserve key the key across all TPM_Init + invocations. */ + +/* 13.1.1 TPM_TRANSPORT_ATTRIBUTES Definitions */ + +#define TPM_TRANSPORT_ENCRYPT 0x00000001 /* The session will provide encryption using + the internal encryption algorithm */ +#define TPM_TRANSPORT_LOG 0x00000002 /* The session will provide a log of all + operations that occur in the session */ +#define TPM_TRANSPORT_EXCLUSIVE 0X00000004 /* The transport session is exclusive and + any command executed outside the + transport session causes the invalidation + of the session */ + +/* 21.1 TPM_CAPABILITY_AREA rev 115 + + To identify a capability to be queried. +*/ + +#define TPM_CAP_ORD 0x00000001 /* Boolean value. TRUE indicates that the TPM supports + the ordinal. FALSE indicates that the TPM does not + support the ordinal. Unimplemented optional ordinals + and unused (unassigned) ordinals return FALSE. */ +#define TPM_CAP_ALG 0x00000002 /* Boolean value. TRUE means that the TPM supports the + asymmetric algorithm for TPM_Sign, TPM_Seal, + TPM_UnSeal and TPM_UnBind and related commands. FALSE + indicates that the asymmetric algorithm is not + supported for these types of commands. The TPM MAY + return TRUE or FALSE for other than asymmetric + algorithms that it supports. Unassigned and + unsupported algorithm IDs return FALSE.*/ + +#define TPM_CAP_PID 0x00000003 /* Boolean value. TRUE indicates that the TPM supports + the protocol, FALSE indicates that the TPM does not + support the protocol. */ +#define TPM_CAP_FLAG 0x00000004 /* Return the TPM_PERMANENT_FLAGS structure or Return the + TPM_STCLEAR_FLAGS structure */ +#define TPM_CAP_PROPERTY 0x00000005 /* See following table for the subcaps */ +#define TPM_CAP_VERSION 0x00000006 /* TPM_STRUCT_VER structure. The Major and Minor must + indicate 1.1. The firmware revision MUST indicate + 0.0 */ +#define TPM_CAP_KEY_HANDLE 0x00000007 /* A TPM_KEY_HANDLE_LIST structure that enumerates all + key handles loaded on the TPM. */ +#define TPM_CAP_CHECK_LOADED 0x00000008 /* A Boolean value. TRUE indicates that the TPM has + enough memory available to load a key of the type + specified by TPM_KEY_PARMS. FALSE indicates that the + TPM does not have enough memory. */ +#define TPM_CAP_SYM_MODE 0x00000009 /* Subcap TPM_SYM_MODE + A Boolean value. TRUE indicates that the TPM supports + the TPM_SYM_MODE, FALSE indicates the TPM does not + support the mode. */ +#define TPM_CAP_KEY_STATUS 0x0000000C /* Boolean value of ownerEvict. The handle MUST point to + a valid key handle.*/ +#define TPM_CAP_NV_LIST 0x0000000D /* A list of TPM_NV_INDEX values that are currently + allocated NV storage through TPM_NV_DefineSpace. */ +#define TPM_CAP_MFR 0x00000010 /* Manufacturer specific. The manufacturer may provide + any additional information regarding the TPM and the + TPM state but MUST not expose any sensitive + information. */ +#define TPM_CAP_NV_INDEX 0x00000011 /* A TPM_NV_DATA_PUBLIC structure that indicates the + values for the TPM_NV_INDEX. Returns TPM_BADINDEX if + the index is not in the TPM_CAP_NV_LIST list. */ +#define TPM_CAP_TRANS_ALG 0x00000012 /* Boolean value. TRUE means that the TPM supports the + algorithm for TPM_EstablishTransport, + TPM_ExecuteTransport and + TPM_ReleaseTransportSigned. FALSE indicates that for + these three commands the algorithm is not supported." + */ +#define TPM_CAP_HANDLE 0x00000014 /* A TPM_KEY_HANDLE_LIST structure that enumerates all + handles currently loaded in the TPM for the given + resource type. */ +#define TPM_CAP_TRANS_ES 0x00000015 /* Boolean value. TRUE means the TPM supports the + encryption scheme in a transport session for at least + one algorithm.. */ +#define TPM_CAP_AUTH_ENCRYPT 0x00000017 /* Boolean value. TRUE indicates that the TPM supports + the encryption algorithm in OSAP encryption of + AuthData values */ +#define TPM_CAP_SELECT_SIZE 0x00000018 /* Boolean value. TRUE indicates that the TPM supports + the size for the given version. For instance a request + could ask for version 1.1 size 2 and the TPM would + indicate TRUE. For 1.1 size 3 the TPM would indicate + FALSE. For 1.2 size 3 the TPM would indicate TRUE. */ +#define TPM_CAP_DA_LOGIC 0x00000019 /* (OPTIONAL) + A TPM_DA_INFO or TPM_DA_INFO_LIMITED structure that + returns data according to the selected entity type + (e.g., TPM_ET_KEYHANDLE, TPM_ET_OWNER, TPM_ET_SRK, + TPM_ET_COUNTER, TPM_ET_OPERATOR, etc.). If the + implemented dictionary attack logic does not support + different secret types, the entity type can be + ignored. */ +#define TPM_CAP_VERSION_VAL 0x0000001A /* TPM_CAP_VERSION_INFO structure. The TPM fills in the + structure and returns the information indicating what + the TPM currently supports. */ + +#define TPM_CAP_FLAG_PERMANENT 0x00000108 /* Return the TPM_PERMANENT_FLAGS structure */ +#define TPM_CAP_FLAG_VOLATILE 0x00000109 /* Return the TPM_STCLEAR_FLAGS structure */ + +/* 21.2 CAP_PROPERTY Subcap values for CAP_PROPERTY rev 105 + + The TPM_CAP_PROPERTY capability has numerous subcap values. The definition for all subcap values + occurs in this table. + + TPM_CAP_PROP_MANUFACTURER returns a vendor ID unique to each manufacturer. The same value is + returned as the TPM_CAP_VERSION_INFO -> tpmVendorID. A company abbreviation such as a null + terminated stock ticker is a typical choice. However, there is no requirement that the value + contain printable characters. The document "TCG Vendor Naming" lists the vendor ID values. + + TPM_CAP_PROP_MAX_xxxSESS is a constant. At TPM_Startup(ST_CLEAR) TPM_CAP_PROP_xxxSESS == + TPM_CAP_PROP_MAX_xxxSESS. As sessions are created on the TPM, TPM_CAP_PROP_xxxSESS decreases + toward zero. As sessions are terminated, TPM_CAP_PROP_xxxSESS increases toward + TPM_CAP_PROP_MAX_xxxSESS. + + There is a similar relationship between the constants TPM_CAP_PROP_MAX_COUNTERS and + TPM_CAP_PROP_MAX_CONTEXT and the varying TPM_CAP_PROP_COUNTERS and TPM_CAP_PROP_CONTEXT. + + In one typical implementation where authorization and transport sessions reside in separate + pools, TPM_CAP_PROP_SESSIONS will be the sum of TPM_CAP_PROP_AUTHSESS and TPM_CAP_PROP_TRANSESS. + In another typical implementation where authorization and transport sessions share the same pool, + TPM_CAP_PROP_SESSIONS, TPM_CAP_PROP_AUTHSESS, and TPM_CAP_PROP_TRANSESS will all be equal. +*/ + +#define TPM_CAP_PROP_PCR 0x00000101 /* uint32_t value. Returns the number of PCR + registers supported by the TPM */ +#define TPM_CAP_PROP_DIR 0x00000102 /* uint32_t. Deprecated. Returns the number of + DIR, which is now fixed at 1 */ +#define TPM_CAP_PROP_MANUFACTURER 0x00000103 /* uint32_t value. Returns the vendor ID + unique to each TPM manufacturer. */ +#define TPM_CAP_PROP_KEYS 0x00000104 /* uint32_t value. Returns the number of 2048- + bit RSA keys that can be loaded. This may + vary with time and circumstances. */ +#define TPM_CAP_PROP_MIN_COUNTER 0x00000107 /* uint32_t. The minimum amount of time in + 10ths of a second that must pass between + invocations of incrementing the monotonic + counter. */ +#define TPM_CAP_PROP_AUTHSESS 0x0000010A /* uint32_t. The number of available + authorization sessions. This may vary with + time and circumstances. */ +#define TPM_CAP_PROP_TRANSESS 0x0000010B /* uint32_t. The number of available transport + sessions. This may vary with time and + circumstances. */ +#define TPM_CAP_PROP_COUNTERS 0x0000010C /* uint32_t. The number of available monotonic + counters. This may vary with time and + circumstances. */ +#define TPM_CAP_PROP_MAX_AUTHSESS 0x0000010D /* uint32_t. The maximum number of loaded + authorization sessions the TPM supports */ +#define TPM_CAP_PROP_MAX_TRANSESS 0x0000010E /* uint32_t. The maximum number of loaded + transport sessions the TPM supports. */ +#define TPM_CAP_PROP_MAX_COUNTERS 0x0000010F /* uint32_t. The maximum number of monotonic + counters under control of TPM_CreateCounter + */ +#define TPM_CAP_PROP_MAX_KEYS 0x00000110 /* uint32_t. The maximum number of 2048 RSA + keys that the TPM can support. The number + does not include the EK or SRK. */ +#define TPM_CAP_PROP_OWNER 0x00000111 /* BOOL. A value of TRUE indicates that the + TPM has successfully installed an owner. */ +#define TPM_CAP_PROP_CONTEXT 0x00000112 /* uint32_t. The number of available saved + session slots. This may vary with time and + circumstances. */ +#define TPM_CAP_PROP_MAX_CONTEXT 0x00000113 /* uint32_t. The maximum number of saved + session slots. */ +#define TPM_CAP_PROP_FAMILYROWS 0x00000114 /* uint32_t. The maximum number of rows in the + family table */ +#define TPM_CAP_PROP_TIS_TIMEOUT 0x00000115 /* A 4 element array of uint32_t values each + denoting the timeout value in microseconds + for the following in this order: + + TIMEOUT_A, TIMEOUT_B, TIMEOUT_C, TIMEOUT_D + + Where these timeouts are to be used is + determined by the platform specific TPM + Interface Specification. */ +#define TPM_CAP_PROP_STARTUP_EFFECT 0x00000116 /* The TPM_STARTUP_EFFECTS structure */ +#define TPM_CAP_PROP_DELEGATE_ROW 0x00000117 /* uint32_t. The maximum size of the delegate + table in rows. */ +#define TPM_CAP_PROP_MAX_DAASESS 0x00000119 /* uint32_t. The maximum number of loaded DAA + sessions (join or sign) that the TPM + supports */ +#define TPM_CAP_PROP_DAASESS 0x0000011A /* uint32_t. The number of available DAA + sessions. This may vary with time and + circumstances */ +#define TPM_CAP_PROP_CONTEXT_DIST 0x0000011B /* uint32_t. The maximum distance between + context count values. This MUST be at least + 2^16-1. */ +#define TPM_CAP_PROP_DAA_INTERRUPT 0x0000011C /* BOOL. A value of TRUE indicates that the + TPM will accept ANY command while executing + a DAA Join or Sign. + + A value of FALSE indicates that the TPM + will invalidate the DAA Join or Sign upon + the receipt of any command other than the + next join/sign in the session or a + TPM_SaveContext */ +#define TPM_CAP_PROP_SESSIONS 0X0000011D /* uint32_t. The number of available sessions + from the pool. This MAY vary with time and + circumstances. Pool sessions include + authorization and transport sessions. */ +#define TPM_CAP_PROP_MAX_SESSIONS 0x0000011E /* uint32_t. The maximum number of sessions + the TPM supports. */ +#define TPM_CAP_PROP_CMK_RESTRICTION 0x0000011F /* uint32_t TPM_Permanent_Data -> + restrictDelegate + */ +#define TPM_CAP_PROP_DURATION 0x00000120 /* A 3 element array of uint32_t values each + denoting the duration value in microseconds + of the duration of the three classes of + commands: Small, Medium and Long in the + following in this order: SMALL_DURATION, + MEDIUM_DURATION, LONG_DURATION */ +#define TPM_CAP_PROP_ACTIVE_COUNTER 0x00000122 /* TPM_COUNT_ID. The id of the current + counter. 0xff..ff if no counter is active + */ +#define TPM_CAP_PROP_MAX_NV_AVAILABLE 0x00000123 /*uint32_t. Deprecated. The maximum number + of NV space that can be allocated, MAY + vary with time and circumstances. This + capability was not implemented + consistently, and is replaced by + TPM_NV_INDEX_TRIAL. */ +#define TPM_CAP_PROP_INPUT_BUFFER 0x00000124 /* uint32_t. The maximum size of the TPM + input buffer or output buffer in + bytes. */ + +/* 21.4 Set_Capability Values rev 107 + */ + +#define TPM_SET_PERM_FLAGS 0x00000001 /* The ability to set a value is field specific and + a review of the structure will disclose the + ability and requirements to set a value */ +#define TPM_SET_PERM_DATA 0x00000002 /* The ability to set a value is field specific and + a review of the structure will disclose the + ability and requirements to set a value */ +#define TPM_SET_STCLEAR_FLAGS 0x00000003 /* The ability to set a value is field specific and + a review of the structure will disclose the + ability and requirements to set a value */ +#define TPM_SET_STCLEAR_DATA 0x00000004 /* The ability to set a value is field specific and + a review of the structure will disclose the + ability and requirements to set a value */ +#define TPM_SET_STANY_FLAGS 0x00000005 /* The ability to set a value is field specific and + a review of the structure will disclose the + ability and requirements to set a value */ +#define TPM_SET_STANY_DATA 0x00000006 /* The ability to set a value is field specific and + a review of the structure will disclose the + ability and requirements to set a value */ +#define TPM_SET_VENDOR 0x00000007 /* This area allows the vendor to set specific areas + in the TPM according to the normal shielded + location requirements */ + +/* Set Capability sub caps */ + +/* TPM_PERMANENT_FLAGS */ + +#define TPM_PF_DISABLE 1 +#define TPM_PF_OWNERSHIP 2 +#define TPM_PF_DEACTIVATED 3 +#define TPM_PF_READPUBEK 4 +#define TPM_PF_DISABLEOWNERCLEAR 5 +#define TPM_PF_ALLOWMAINTENANCE 6 +#define TPM_PF_PHYSICALPRESENCELIFETIMELOCK 7 +#define TPM_PF_PHYSICALPRESENCEHWENABLE 8 +#define TPM_PF_PHYSICALPRESENCECMDENABLE 9 +#define TPM_PF_CEKPUSED 10 +#define TPM_PF_TPMPOST 11 +#define TPM_PF_TPMPOSTLOCK 12 +#define TPM_PF_FIPS 13 +#define TPM_PF_OPERATOR 14 +#define TPM_PF_ENABLEREVOKEEK 15 +#define TPM_PF_NV_LOCKED 16 +#define TPM_PF_READSRKPUB 17 +#define TPM_PF_TPMESTABLISHED 18 +#define TPM_PF_MAINTENANCEDONE 19 +#define TPM_PF_DISABLEFULLDALOGICINFO 20 + +/* TPM_STCLEAR_FLAGS */ + +#define TPM_SF_DEACTIVATED 1 +#define TPM_SF_DISABLEFORCECLEAR 2 +#define TPM_SF_PHYSICALPRESENCE 3 +#define TPM_SF_PHYSICALPRESENCELOCK 4 +#define TPM_SF_BGLOBALLOCK 5 + +/* TPM_STANY_FLAGS */ + +#define TPM_AF_POSTINITIALISE 1 +#define TPM_AF_LOCALITYMODIFIER 2 +#define TPM_AF_TRANSPORTEXCLUSIVE 3 +#define TPM_AF_TOSPRESENT 4 + +/* TPM_PERMANENT_DATA */ + +#define TPM_PD_REVMAJOR 1 +#define TPM_PD_REVMINOR 2 +#define TPM_PD_TPMPROOF 3 +#define TPM_PD_OWNERAUTH 4 +#define TPM_PD_OPERATORAUTH 5 +#define TPM_PD_MANUMAINTPUB 6 +#define TPM_PD_ENDORSEMENTKEY 7 +#define TPM_PD_SRK 8 +#define TPM_PD_DELEGATEKEY 9 +#define TPM_PD_CONTEXTKEY 10 +#define TPM_PD_AUDITMONOTONICCOUNTER 11 +#define TPM_PD_MONOTONICCOUNTER 12 +#define TPM_PD_PCRATTRIB 13 +#define TPM_PD_ORDINALAUDITSTATUS 14 +#define TPM_PD_AUTHDIR 15 +#define TPM_PD_RNGSTATE 16 +#define TPM_PD_FAMILYTABLE 17 +#define TPM_DELEGATETABLE 18 +#define TPM_PD_EKRESET 19 +#define TPM_PD_LASTFAMILYID 21 +#define TPM_PD_NOOWNERNVWRITE 22 +#define TPM_PD_RESTRICTDELEGATE 23 +#define TPM_PD_TPMDAASEED 24 +#define TPM_PD_DAAPROOF 25 + +/* TPM_STCLEAR_DATA */ + +#define TPM_SD_CONTEXTNONCEKEY 1 +#define TPM_SD_COUNTID 2 +#define TPM_SD_OWNERREFERENCE 3 +#define TPM_SD_DISABLERESETLOCK 4 +#define TPM_SD_PCR 5 +#define TPM_SD_DEFERREDPHYSICALPRESENCE 6 + +/* TPM_STCLEAR_DATA -> deferredPhysicalPresence bits */ + +#define TPM_DPP_UNOWNED_FIELD_UPGRADE 0x00000001 /* bit 0 TPM_FieldUpgrade */ + +/* TPM_STANY_DATA */ + +#define TPM_AD_CONTEXTNONCESESSION 1 +#define TPM_AD_AUDITDIGEST 2 +#define TPM_AD_CURRENTTICKS 3 +#define TPM_AD_CONTEXTCOUNT 4 +#define TPM_AD_CONTEXTLIST 5 +#define TPM_AD_SESSIONS 6 + +/* 17. Ordinals rev 110 + + Ordinals are 32 bit values of type TPM_COMMAND_CODE. The upper byte contains values that serve + as flag indicators, the next byte contains values indicating what committee designated the + ordinal, and the final two bytes contain the Command Ordinal Index. + + 3 2 1 + 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |P|C|V| Reserved| Purview | Command Ordinal Index | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Where: + + P is Protected/Unprotected command. When 0 the command is a Protected command, when 1 the + command is an Unprotected command. + + C is Non-Connection/Connection related command. When 0 this command passes through to either the + protected (TPM) or unprotected (TSS) components. + + V is TPM/Vendor command. When 0 the command is TPM defined, when 1 the command is vendor + defined. + + All reserved area bits are set to 0. +*/ + +/* The following masks are created to allow for the quick definition of the commands */ + +#define TPM_PROTECTED_COMMAND 0x00000000 /* TPM protected command, specified in main specification + */ +#define TPM_UNPROTECTED_COMMAND 0x80000000 /* TSS command, specified in the TSS specification */ +#define TPM_CONNECTION_COMMAND 0x40000000 /* TSC command, protected connection commands are + specified in the main specification Unprotected + connection commands are specified in the TSS */ +#define TPM_VENDOR_COMMAND 0x20000000 /* Command that is vendor specific for a given TPM or + TSS. */ + + +/* The following Purviews have been defined: */ + +#define TPM_MAIN 0x00 /* Command is from the main specification */ +#define TPM_PC 0x01 /* Command is specific to the PC */ +#define TPM_PDA 0x02 /* Command is specific to a PDA */ +#define TPM_CELL_PHONE 0x03 /* Command is specific to a cell phone */ +#define TPM_SERVER 0x04 /* Command is specific to servers */ +#define TPM_PERIPHERAL 0x05 /* Command is specific to peripherals */ +#define TPM_TSS 0x06 /* Command is specific to TSS */ + +/* Combinations for the main specification would be: */ + +#define TPM_PROTECTED_ORDINAL (TPM_PROTECTED_COMMAND | TPM_MAIN) +#define TPM_UNPROTECTED_ORDINAL (TPM_UNPROTECTED_COMMAND | TPM_MAIN) +#define TPM_CONNECTION_ORDINAL (TPM_CONNECTION_COMMAND | TPM_MAIN) + +/* Command ordinals */ + +#define TPM_ORD_ActivateIdentity 0x0000007A +#define TPM_ORD_AuthorizeMigrationKey 0x0000002B +#define TPM_ORD_CertifyKey 0x00000032 +#define TPM_ORD_CertifyKey2 0x00000033 +#define TPM_ORD_CertifySelfTest 0x00000052 +#define TPM_ORD_ChangeAuth 0x0000000C +#define TPM_ORD_ChangeAuthAsymFinish 0x0000000F +#define TPM_ORD_ChangeAuthAsymStart 0x0000000E +#define TPM_ORD_ChangeAuthOwner 0x00000010 +#define TPM_ORD_CMK_ApproveMA 0x0000001D +#define TPM_ORD_CMK_ConvertMigration 0x00000024 +#define TPM_ORD_CMK_CreateBlob 0x0000001B +#define TPM_ORD_CMK_CreateKey 0x00000013 +#define TPM_ORD_CMK_CreateTicket 0x00000012 +#define TPM_ORD_CMK_SetRestrictions 0x0000001C +#define TPM_ORD_ContinueSelfTest 0x00000053 +#define TPM_ORD_ConvertMigrationBlob 0x0000002A +#define TPM_ORD_CreateCounter 0x000000DC +#define TPM_ORD_CreateEndorsementKeyPair 0x00000078 +#define TPM_ORD_CreateMaintenanceArchive 0x0000002C +#define TPM_ORD_CreateMigrationBlob 0x00000028 +#define TPM_ORD_CreateRevocableEK 0x0000007F +#define TPM_ORD_CreateWrapKey 0x0000001F +#define TPM_ORD_DAA_Join 0x00000029 +#define TPM_ORD_DAA_Sign 0x00000031 +#define TPM_ORD_Delegate_CreateKeyDelegation 0x000000D4 +#define TPM_ORD_Delegate_CreateOwnerDelegation 0x000000D5 +#define TPM_ORD_Delegate_LoadOwnerDelegation 0x000000D8 +#define TPM_ORD_Delegate_Manage 0x000000D2 +#define TPM_ORD_Delegate_ReadTable 0x000000DB +#define TPM_ORD_Delegate_UpdateVerification 0x000000D1 +#define TPM_ORD_Delegate_VerifyDelegation 0x000000D6 +#define TPM_ORD_DirRead 0x0000001A +#define TPM_ORD_DirWriteAuth 0x00000019 +#define TPM_ORD_DisableForceClear 0x0000005E +#define TPM_ORD_DisableOwnerClear 0x0000005C +#define TPM_ORD_DisablePubekRead 0x0000007E +#define TPM_ORD_DSAP 0x00000011 +#define TPM_ORD_EstablishTransport 0x000000E6 +#define TPM_ORD_EvictKey 0x00000022 +#define TPM_ORD_ExecuteTransport 0x000000E7 +#define TPM_ORD_Extend 0x00000014 +#define TPM_ORD_FieldUpgrade 0x000000AA +#define TPM_ORD_FlushSpecific 0x000000BA +#define TPM_ORD_ForceClear 0x0000005D +#define TPM_ORD_GetAuditDigest 0x00000085 +#define TPM_ORD_GetAuditDigestSigned 0x00000086 +#define TPM_ORD_GetAuditEvent 0x00000082 +#define TPM_ORD_GetAuditEventSigned 0x00000083 +#define TPM_ORD_GetCapability 0x00000065 +#define TPM_ORD_GetCapabilityOwner 0x00000066 +#define TPM_ORD_GetCapabilitySigned 0x00000064 +#define TPM_ORD_GetOrdinalAuditStatus 0x0000008C +#define TPM_ORD_GetPubKey 0x00000021 +#define TPM_ORD_GetRandom 0x00000046 +#define TPM_ORD_GetTestResult 0x00000054 +#define TPM_ORD_GetTicks 0x000000F1 +#define TPM_ORD_IncrementCounter 0x000000DD +#define TPM_ORD_Init 0x00000097 +#define TPM_ORD_KeyControlOwner 0x00000023 +#define TPM_ORD_KillMaintenanceFeature 0x0000002E +#define TPM_ORD_LoadAuthContext 0x000000B7 +#define TPM_ORD_LoadContext 0x000000B9 +#define TPM_ORD_LoadKey 0x00000020 +#define TPM_ORD_LoadKey2 0x00000041 +#define TPM_ORD_LoadKeyContext 0x000000B5 +#define TPM_ORD_LoadMaintenanceArchive 0x0000002D +#define TPM_ORD_LoadManuMaintPub 0x0000002F +#define TPM_ORD_MakeIdentity 0x00000079 +#define TPM_ORD_MigrateKey 0x00000025 +#define TPM_ORD_NV_DefineSpace 0x000000CC +#define TPM_ORD_NV_ReadValue 0x000000CF +#define TPM_ORD_NV_ReadValueAuth 0x000000D0 +#define TPM_ORD_NV_WriteValue 0x000000CD +#define TPM_ORD_NV_WriteValueAuth 0x000000CE +#define TPM_ORD_OIAP 0x0000000A +#define TPM_ORD_OSAP 0x0000000B +#define TPM_ORD_OwnerClear 0x0000005B +#define TPM_ORD_OwnerReadInternalPub 0x00000081 +#define TPM_ORD_OwnerReadPubek 0x0000007D +#define TPM_ORD_OwnerSetDisable 0x0000006E +#define TPM_ORD_PCR_Reset 0x000000C8 +#define TPM_ORD_PcrRead 0x00000015 +#define TPM_ORD_PhysicalDisable 0x00000070 +#define TPM_ORD_PhysicalEnable 0x0000006F +#define TPM_ORD_PhysicalSetDeactivated 0x00000072 +#define TPM_ORD_Quote 0x00000016 +#define TPM_ORD_Quote2 0x0000003E +#define TPM_ORD_ReadCounter 0x000000DE +#define TPM_ORD_ReadManuMaintPub 0x00000030 +#define TPM_ORD_ReadPubek 0x0000007C +#define TPM_ORD_ReleaseCounter 0x000000DF +#define TPM_ORD_ReleaseCounterOwner 0x000000E0 +#define TPM_ORD_ReleaseTransportSigned 0x000000E8 +#define TPM_ORD_Reset 0x0000005A +#define TPM_ORD_ResetLockValue 0x00000040 +#define TPM_ORD_RevokeTrust 0x00000080 +#define TPM_ORD_SaveAuthContext 0x000000B6 +#define TPM_ORD_SaveContext 0x000000B8 +#define TPM_ORD_SaveKeyContext 0x000000B4 +#define TPM_ORD_SaveState 0x00000098 +#define TPM_ORD_Seal 0x00000017 +#define TPM_ORD_Sealx 0x0000003D +#define TPM_ORD_SelfTestFull 0x00000050 +#define TPM_ORD_SetCapability 0x0000003F +#define TPM_ORD_SetOperatorAuth 0x00000074 +#define TPM_ORD_SetOrdinalAuditStatus 0x0000008D +#define TPM_ORD_SetOwnerInstall 0x00000071 +#define TPM_ORD_SetOwnerPointer 0x00000075 +#define TPM_ORD_SetRedirection 0x0000009A +#define TPM_ORD_SetTempDeactivated 0x00000073 +#define TPM_ORD_SHA1Complete 0x000000A2 +#define TPM_ORD_SHA1CompleteExtend 0x000000A3 +#define TPM_ORD_SHA1Start 0x000000A0 +#define TPM_ORD_SHA1Update 0x000000A1 +#define TPM_ORD_Sign 0x0000003C +#define TPM_ORD_Startup 0x00000099 +#define TPM_ORD_StirRandom 0x00000047 +#define TPM_ORD_TakeOwnership 0x0000000D +#define TPM_ORD_Terminate_Handle 0x00000096 +#define TPM_ORD_TickStampBlob 0x000000F2 +#define TPM_ORD_UnBind 0x0000001E +#define TPM_ORD_Unseal 0x00000018 + +#define TSC_ORD_PhysicalPresence 0x4000000A +#define TSC_ORD_ResetEstablishmentBit 0x4000000B + +/* 19. NV storage structures */ + +/* 19.1 TPM_NV_INDEX rev 110 + + The index provides the handle to identify the area of storage. The reserved bits allow for a + segregation of the index name space to avoid name collisions. + + The TPM may check the resvd bits for zero. Thus, applications should set the bits to zero. + + The TCG defines the space where the high order bits (T, P, U) are 0. The other spaces are + controlled by the indicated entity. + + T is the TPM manufacturer reserved bit. 0 indicates a TCG defined value. 1 indicates a TPM + manufacturer specific value. + + P is the platform manufacturer reserved bit. 0 indicates a TCG defined value. 1 indicates that + the index is controlled by the platform manufacturer. + + U is for the platform user. 0 indicates a TCG defined value. 1 indicates that the index is + controlled by the platform user. + + The TPM_NV_INDEX is a 32-bit value. + 3 2 1 + 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |T|P|U|D| resvd | Purview | Index | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Where: + + 1. The TPM MAY return an error if the reserved area bits are not set to 0. + + 2. The TPM MUST accept all values for T, P, and U + + 3. D indicates defined. 1 indicates that the index is permanently defined and that any + TPM_NV_DefineSpace operation will fail after nvLocked is set TRUE. + + a. TCG reserved areas MAY have D set to 0 or 1 + + 4. Purview is the value used to indicate the platform specific area. This value is the + same as used for command ordinals. + + a. The TPM MUST reject purview values that the TPM cannot support. This means that an + index value for a PDA MUST be rejected by a TPM designed to work only on the PC Client. +*/ + +#define TPM_NV_INDEX_T_BIT 0x80000000 +#define TPM_NV_INDEX_P_BIT 0x40000000 +#define TPM_NV_INDEX_U_BIT 0x20000000 +#define TPM_NV_INDEX_D_BIT 0x10000000 +/* added kgold */ +#define TPM_NV_INDEX_RESVD 0x0f000000 +#define TPM_NV_INDEX_PURVIEW_BIT 16 +#define TPM_NV_INDEX_PURVIEW_MASK 0x00ff0000 + +/* 19.1.1 Required TPM_NV_INDEX values rev 97 + + The required index values must be found on each TPM regardless of platform. These areas are + always present and do not require a TPM_DefineSpace command to allocate. + + A platform specific specification may add additional required index values for the platform. + + The TPM MUST reserve the space as indicated for the required index values +*/ + +#define TPM_NV_INDEX_LOCK 0xFFFFFFFF /* This value turns on the NV authorization + protections. Once executed all NV areas use the + protections as defined. This value never resets. + + Attempting to execute TPM_NV_DefineSpace on this value + with non-zero size MAY result in a TPM_BADINDEX + response. + */ + +#define TPM_NV_INDEX0 0x00000000 /* This value allows for the setting of the bGlobalLock + flag, which is only reset on TPM_Startup(ST_Clear) + + Attempting to execute TPM_NV_WriteValue with a size other + than zero MAY result in the TPM_BADINDEX error code. + */ + +#define TPM_NV_INDEX_DIR 0x10000001 /* Size MUST be 20. This index points to the deprecated DIR + command area from 1.1. The TPM MUST map this reserved + space to be the area operated on by the 1.1 DIR commands. + */ + +/* 19.1.2 Reserved Index values rev 116 + + The reserved values are defined to avoid index collisions. These values are not in each and every + TPM. + + 1. The reserved index values are to avoid index value collisions. + 2. These index values require a TPM_DefineSpace to have the area for the index allocated + 3. A platform specific specification MAY indicate that reserved values are required. + 4. The reserved index values MAY have their D bit set by the TPM vendor to permanently +*/ + +#define TPM_NV_INDEX_TPM 0x0000Fxxx /* Reserved for TPM use */ +#define TPM_NV_INDEX_EKCert 0x0000F000 /* The Endorsement credential */ + +#define TPM_NV_INDEX_TPM_CC 0x0000F001 /* The TPM Conformance credential */ +#define TPM_NV_INDEX_PlatformCert 0x0000F002 /* The platform credential */ +#define TPM_NV_INDEX_Platform_CC 0x0000F003 /* The Platform conformance credential */ +#define TPM_NV_INDEX_TRIAL 0x0000F004 /* To try TPM_NV_DefineSpace without + actually allocating NV space */ + +#if 0 +#define TPM_NV_INDEX_PC 0x0001xxxx /* Reserved for PC Client use */ +#define TPM_NV_INDEX_GPIO_xx 0x000116xx /* Reserved for GPIO pins */ +#define TPM_NV_INDEX_PDA 0x0002xxxx /* Reserved for PDA use */ +#define TPM_NV_INDEX_MOBILE 0x0003xxxx /* Reserved for mobile use */ +#define TPM_NV_INDEX_SERVER 0x0004xxxx /* Reserved for Server use */ +#define TPM_NV_INDEX_PERIPHERAL 0x0005xxxx /* Reserved for peripheral use */ +#define TPM_NV_INDEX_TSS 0x0006xxxx /* Reserved for TSS use */ +#define TPM_NV_INDEX_GROUP_RESV 0x00xxxxxx /* Reserved for TCG WG use */ +#endif + +#define TPM_NV_INDEX_GPIO_00 0x00011600 /* GPIO-Express-00 */ + +#define TPM_NV_INDEX_GPIO_START 0x00011600 /* Reserved for GPIO pins */ +#define TPM_NV_INDEX_GPIO_END 0x000116ff /* Reserved for GPIO pins */ + +/* 19.2 TPM_NV_ATTRIBUTES rev 99 + + The attributes TPM_NV_PER_AUTHREAD and TPM_NV_PER_OWNERREAD cannot both be set to TRUE. + Similarly, the attributes TPM_NV_PER_AUTHWRITE and TPM_NV_PER_OWNERWRITE cannot both be set to + TRUE. +*/ + +#define TPM_NV_PER_READ_STCLEAR 0x80000000 /* 31: The value can be read until locked by a + read with a data size of 0. It can only be + unlocked by TPM_Startup(ST_Clear) or a + successful write. Lock held for each area in + bReadSTClear. */ +/* #define 30:19 Reserved */ +#define TPM_NV_PER_AUTHREAD 0x00040000 /* 18: The value requires authorization to read + */ +#define TPM_NV_PER_OWNERREAD 0x00020000 /* 17: The value requires TPM Owner authorization + to read. */ +#define TPM_NV_PER_PPREAD 0x00010000 /* 16: The value requires physical presence to + read */ +#define TPM_NV_PER_GLOBALLOCK 0x00008000 /* 15: The value is writable until a write to + index 0 is successful. The lock of this + attribute is reset by + TPM_Startup(ST_CLEAR). Lock held by SF -> + bGlobalLock */ +#define TPM_NV_PER_WRITE_STCLEAR 0x00004000 /* 14: The value is writable until a write to + the specified index with a datasize of 0 is + successful. The lock of this attribute is + reset by TPM_Startup(ST_CLEAR). Lock held for + each area in bWriteSTClear. */ +#define TPM_NV_PER_WRITEDEFINE 0x00002000 /* 13: Lock set by writing to the index with a + datasize of 0. Lock held for each area in + bWriteDefine. This is a persistent lock. */ +#define TPM_NV_PER_WRITEALL 0x00001000 /* 12: The value must be written in a single + operation */ +/* #define 11:3 Reserved for write additions */ +#define TPM_NV_PER_AUTHWRITE 0x00000004 /* 2: The value requires authorization to write + */ +#define TPM_NV_PER_OWNERWRITE 0x00000002 /* 1: The value requires TPM Owner authorization + to write */ +#define TPM_NV_PER_PPWRITE 0x00000001 /* 0: The value requires physical presence to + write */ + +/* 20.2.1 Owner Permission Settings rev 87 */ + +/* Per1 bits */ + +#define TPM_DELEGATE_PER1_MASK 0xffffffff /* mask of legal bits */ +#define TPM_DELEGATE_KeyControlOwner 31 +#define TPM_DELEGATE_SetOrdinalAuditStatus 30 +#define TPM_DELEGATE_DirWriteAuth 29 +#define TPM_DELEGATE_CMK_ApproveMA 28 +#define TPM_DELEGATE_NV_WriteValue 27 +#define TPM_DELEGATE_CMK_CreateTicket 26 +#define TPM_DELEGATE_NV_ReadValue 25 +#define TPM_DELEGATE_Delegate_LoadOwnerDelegation 24 +#define TPM_DELEGATE_DAA_Join 23 +#define TPM_DELEGATE_AuthorizeMigrationKey 22 +#define TPM_DELEGATE_CreateMaintenanceArchive 21 +#define TPM_DELEGATE_LoadMaintenanceArchive 20 +#define TPM_DELEGATE_KillMaintenanceFeature 19 +#define TPM_DELEGATE_OwnerReadInternalPub 18 +#define TPM_DELEGATE_ResetLockValue 17 +#define TPM_DELEGATE_OwnerClear 16 +#define TPM_DELEGATE_DisableOwnerClear 15 +#define TPM_DELEGATE_NV_DefineSpace 14 +#define TPM_DELEGATE_OwnerSetDisable 13 +#define TPM_DELEGATE_SetCapability 12 +#define TPM_DELEGATE_MakeIdentity 11 +#define TPM_DELEGATE_ActivateIdentity 10 +#define TPM_DELEGATE_OwnerReadPubek 9 +#define TPM_DELEGATE_DisablePubekRead 8 +#define TPM_DELEGATE_SetRedirection 7 +#define TPM_DELEGATE_FieldUpgrade 6 +#define TPM_DELEGATE_Delegate_UpdateVerification 5 +#define TPM_DELEGATE_CreateCounter 4 +#define TPM_DELEGATE_ReleaseCounterOwner 3 +#define TPM_DELEGATE_Delegate_Manage 2 +#define TPM_DELEGATE_Delegate_CreateOwnerDelegation 1 +#define TPM_DELEGATE_DAA_Sign 0 + +/* Per2 bits */ +#define TPM_DELEGATE_PER2_MASK 0x00000000 /* mask of legal bits */ +/* All reserved */ + +/* 20.2.3 Key Permission settings rev 85 */ + +/* Per1 bits */ + +#define TPM_KEY_DELEGATE_PER1_MASK 0x1fffffff /* mask of legal bits */ +#define TPM_KEY_DELEGATE_CMK_ConvertMigration 28 +#define TPM_KEY_DELEGATE_TickStampBlob 27 +#define TPM_KEY_DELEGATE_ChangeAuthAsymStart 26 +#define TPM_KEY_DELEGATE_ChangeAuthAsymFinish 25 +#define TPM_KEY_DELEGATE_CMK_CreateKey 24 +#define TPM_KEY_DELEGATE_MigrateKey 23 +#define TPM_KEY_DELEGATE_LoadKey2 22 +#define TPM_KEY_DELEGATE_EstablishTransport 21 +#define TPM_KEY_DELEGATE_ReleaseTransportSigned 20 +#define TPM_KEY_DELEGATE_Quote2 19 +#define TPM_KEY_DELEGATE_Sealx 18 +#define TPM_KEY_DELEGATE_MakeIdentity 17 +#define TPM_KEY_DELEGATE_ActivateIdentity 16 +#define TPM_KEY_DELEGATE_GetAuditDigestSigned 15 +#define TPM_KEY_DELEGATE_Sign 14 +#define TPM_KEY_DELEGATE_CertifyKey2 13 +#define TPM_KEY_DELEGATE_CertifyKey 12 +#define TPM_KEY_DELEGATE_CreateWrapKey 11 +#define TPM_KEY_DELEGATE_CMK_CreateBlob 10 +#define TPM_KEY_DELEGATE_CreateMigrationBlob 9 +#define TPM_KEY_DELEGATE_ConvertMigrationBlob 8 +#define TPM_KEY_DELEGATE_Delegate_CreateKeyDelegation 7 +#define TPM_KEY_DELEGATE_ChangeAuth 6 +#define TPM_KEY_DELEGATE_GetPubKey 5 +#define TPM_KEY_DELEGATE_UnBind 4 +#define TPM_KEY_DELEGATE_Quote 3 +#define TPM_KEY_DELEGATE_Unseal 2 +#define TPM_KEY_DELEGATE_Seal 1 +#define TPM_KEY_DELEGATE_LoadKey 0 + +/* Per2 bits */ +#define TPM_KEY_DELEGATE_PER2_MASK 0x00000000 /* mask of legal bits */ +/* All reserved */ + +/* 20.3 TPM_FAMILY_FLAGS rev 87 + + These flags indicate the operational state of the delegation and family table. These flags + are additions to TPM_PERMANENT_FLAGS and are not stand alone values. +*/ + +#define TPM_DELEGATE_ADMIN_LOCK 0x00000002 /* TRUE: Some TPM_Delegate_XXX commands are locked and + return TPM_DELEGATE_LOCK + + FALSE: TPM_Delegate_XXX commands are available + + Default is FALSE */ +#define TPM_FAMFLAG_ENABLED 0x00000001 /* When TRUE the table is enabled. The default value is + FALSE. */ + +/* 20.14 TPM_FAMILY_OPERATION Values rev 87 + + These are the opFlag values used by TPM_Delegate_Manage. +*/ + +#define TPM_FAMILY_CREATE 0x00000001 /* Create a new family */ +#define TPM_FAMILY_ENABLE 0x00000002 /* Set or reset the enable flag for this family. */ +#define TPM_FAMILY_ADMIN 0x00000003 /* Prevent administration of this family. */ +#define TPM_FAMILY_INVALIDATE 0x00000004 /* Invalidate a specific family row. */ + +/* 21.9 TPM_DA_STATE rev 100 + + TPM_DA_STATE enumerates the possible states of the dictionary attack mitigation logic. +*/ + +#define TPM_DA_STATE_INACTIVE 0x00 /* The dictionary attack mitigation logic is currently + inactive */ +#define TPM_DA_STATE_ACTIVE 0x01 /* The dictionary attack mitigation logic is + active. TPM_DA_ACTION_TYPE (21.10) is in progress. */ + +/* 21.10 TPM_DA_ACTION_TYPE rev 100 + */ + +/* 31-4 Reserved No information and MUST be FALSE */ + +#define TPM_DA_ACTION_FAILURE_MODE 0x00000008 /* bit 3: The TPM is in failure mode. */ +#define TPM_DA_ACTION_DEACTIVATE 0x00000004 /* bit 2: The TPM is in the deactivated state. */ +#define TPM_DA_ACTION_DISABLE 0x00000002 /* bit 1: The TPM is in the disabled state. */ +#define TPM_DA_ACTION_TIMEOUT 0x00000001 /* bit 0: The TPM will be in a locked state for + TPM_DA_INFO -> actionDependValue seconds. This + value is dynamic, depending on the time the + lock has been active. */ + +/* 22. DAA Structures rev 91 + + All byte and bit areas are byte arrays treated as large integers +*/ + +#define DAA_SIZE_r0 43 +#define DAA_SIZE_r1 43 +#define DAA_SIZE_r2 128 +#define DAA_SIZE_r3 168 +#define DAA_SIZE_r4 219 +#define DAA_SIZE_NT 20 +#define DAA_SIZE_v0 128 +#define DAA_SIZE_v1 192 +#define DAA_SIZE_NE 256 +#define DAA_SIZE_w 256 +#define DAA_SIZE_issuerModulus 256 + +/* check that DAA_SIZE_issuerModulus will fit in DAA_scratch */ +#if (DAA_SIZE_issuerModulus != 256) +#error "DAA_SIZE_issuerModulus must be 256" +#endif + +/* 22.2 Constant definitions rev 91 */ + +#define DAA_power0 104 +#define DAA_power1 1024 + +#endif diff --git a/src/tpm12/tpm_counter.c b/src/tpm12/tpm_counter.c new file mode 100644 index 0000000..65a2db2 --- /dev/null +++ b/src/tpm12/tpm_counter.c @@ -0,0 +1,1565 @@ +/********************************************************************************/ +/* */ +/* Counter Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_counter.c 4539 2011-04-04 21:44:22Z kgoldman $ */ +/* */ +//* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_auth.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_permanent.h" +#include "tpm_process.h" +#include "tpm_secret.h" + +#include "tpm_counter.h" + +/* + Monotonic Counter Resource Handling +*/ + +/* TPM_Counters_Init() initializes the monotonic counters + */ + +void TPM_Counters_Init(TPM_COUNTER_VALUE *monotonicCounters) +{ + uint32_t i; + + for (i = 0 ; i < TPM_MIN_COUNTERS ; i++) { + TPM_CounterValue_Init(&(monotonicCounters[i])); + } + return; +} + +/* TPM_Counters_Load() loads the monotonic counters + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes +*/ + +TPM_RESULT TPM_Counters_Load(TPM_COUNTER_VALUE *monotonicCounters, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t i; + + /* load the counters */ + for (i = 0 ; (rc == 0) && (i < TPM_MIN_COUNTERS) ; i++) { + rc = TPM_CounterValue_Load(&(monotonicCounters[i]), stream, stream_size); + } + return rc; +} + +TPM_RESULT TPM_Counters_Store(TPM_STORE_BUFFER *sbuffer, + TPM_COUNTER_VALUE *monotonicCounters) +{ + TPM_RESULT rc = 0; + uint32_t i; + + /* store the counters */ + for (i = 0 ; (rc == 0) && (i < TPM_MIN_COUNTERS) ; i++) { + rc = TPM_CounterValue_Store(sbuffer, &(monotonicCounters[i])); + } + return rc; +} + +/* TPM_Counters_StoreHandles() stores a count of the created counters and a list of created counter + handles. +*/ + +TPM_RESULT TPM_Counters_StoreHandles(TPM_STORE_BUFFER *sbuffer, + TPM_COUNTER_VALUE *monotonicCounters) +{ + TPM_RESULT rc = 0; + uint16_t loaded; + uint32_t i; + + printf(" TPM_Counters_StoreHandles:\n"); + if (rc == 0) { + loaded = 0; + /* count the number of loaded counters */ + for (i = 0 ; i < TPM_MIN_COUNTERS ; i++) { + if ((monotonicCounters[i]).valid) { + loaded++; + } + } + /* store created handle count */ + rc = TPM_Sbuffer_Append16(sbuffer, loaded); + } + for (i = 0 ; (rc == 0) && (i < TPM_MIN_COUNTERS) ; i++) { + if ((monotonicCounters[i]).valid) { + /* the handle is just the index */ + rc = TPM_Sbuffer_Append32(sbuffer, i); /* store it */ + } + } + return rc; +} + +/* TPM_Counters_GetSpace() returns the number of unused monotonicCounters. + */ + +void TPM_Counters_GetSpace(uint32_t *space, + TPM_COUNTER_VALUE *monotonicCounters) +{ + uint32_t i; + + printf(" TPM_Counters_GetSpace:\n"); + for (*space = 0 , i = 0 ; i < TPM_MIN_COUNTERS ; i++) { + if (!(monotonicCounters[i]).valid) { + (*space)++; + } + } + return; +} + + +/* TPM_Counters_GetNewHandle() checks for space in the monotonicCounters table. + + If there is space, it returns a TPM_COUNTER_VALUE entry in 'tpm_counter_value' and its + handle in 'countID'. The entry is marked 'valid'. + + Returns TPM_RESOURCES if there is no space in the sessions table. monotonicCounters is not + altered on error. +*/ + +TPM_RESULT TPM_Counters_GetNewHandle(TPM_COUNTER_VALUE **tpm_counter_value, + TPM_COUNT_ID *countID, + TPM_COUNTER_VALUE *monotonicCounters) +{ + TPM_RESULT rc = 0; + TPM_BOOL is_space; + + printf(" TPM_Counters_GetNewHandle:\n"); + for (*countID = 0, is_space = FALSE ; + *countID < TPM_MIN_COUNTERS ; + (*countID)++) { + + if (!(monotonicCounters[*countID]).valid) { + is_space = TRUE; + break; + } + } + /* NOTE: According to TPMWG email, TPM_COUNT_ID can be an index */ + if (is_space) { + printf(" TPM_Counters_GetNewHandle: Assigned handle %u\n", *countID); + *tpm_counter_value = &(monotonicCounters[*countID]); + (*tpm_counter_value)->valid = TRUE; /* mark it occupied */ + } + else { + printf("TPM_Counters_GetNewHandle: Error, no space in monotonicCounters table\n"); + rc = TPM_RESOURCES; + } + return rc; +} + +/* TPM_Counters_GetNextCount() searches the monotonicCounters for the maximum count, and returns + nextCount equal to the incremented maximum count. + + The counter does not have to be valid (created). It can be invalid (released). +*/ + +void TPM_Counters_GetNextCount(TPM_ACTUAL_COUNT *nextCount, + TPM_COUNTER_VALUE *monotonicCounters) +{ + TPM_COUNT_ID countID; + TPM_ACTUAL_COUNT maxCount = 0; + + printf(" TPM_Counters_GetNextCount:\n"); + for (countID = 0 ; countID < TPM_MIN_COUNTERS ; countID++) { + if (monotonicCounters[countID].counter > maxCount) { + maxCount = monotonicCounters[countID].counter; + } + } + *nextCount = maxCount + 1; + printf(" TPM_Counters_GetNextCount: Next count %u\n", *nextCount); + return; +} + +/* TPM_Counters_IsValidId() verifies that countID is in range and a created counter + */ + +TPM_RESULT TPM_Counters_IsValidId(TPM_COUNTER_VALUE *monotonicCounters, + TPM_COUNT_ID countID) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Counters_IsValidId: countID %u\n", countID); + /* range check */ + if (rc == 0) { + if (countID >= TPM_MIN_COUNTERS) { + printf("TPM_Counters_IsValidId: Error countID %u out of range\n", countID); + rc = TPM_BAD_COUNTER ; + } + } + /* validity (creation) check */ + if (rc == 0) { + if (!(monotonicCounters[countID].valid)) { + printf("TPM_Counters_IsValidId: Error countID %u invalid\n", countID); + rc = TPM_BAD_COUNTER ; + } + } + return rc; +} + + +/* TPM_Counters_GetCounterValue() gets the TPM_COUNTER_VALUE associated with the countID. + + */ + +TPM_RESULT TPM_Counters_GetCounterValue(TPM_COUNTER_VALUE **tpm_counter_value, + TPM_COUNTER_VALUE *monotonicCounters, + TPM_COUNT_ID countID) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Counters_GetCounterValue: countID %u\n", countID); + /* valid counter check */ + if (rc == 0) { + rc = TPM_Counters_IsValidId(monotonicCounters, countID); + } + if (rc == 0) { + *tpm_counter_value = &(monotonicCounters[countID]); + } + return rc; +} + +/* TPM_Counters_Release() iterates through all monotonicCounter's, and releases those that are + created. + + The resource is set invalid, and the authorization data and digest are cleared. + + a. This includes invalidating all currently allocated counters. The result will be no + currently allocated counters and the new owner will need to allocate counters. The actual + count value will continue to increase. +*/ + +TPM_RESULT TPM_Counters_Release(TPM_COUNTER_VALUE *monotonicCounters) +{ + TPM_RESULT rc = 0; + TPM_COUNT_ID i; + + printf(" TPM_Counters_Release:\n"); + for (i = 0 ; i < TPM_MIN_COUNTERS ; i++) { + if (monotonicCounters[i].valid) { + /* the actual count value does not reset to zero */ + printf(" TPM_Counters_Release: Releasing %u\n", i); + TPM_Secret_Init(monotonicCounters[i].authData); + TPM_Digest_Init(monotonicCounters[i].digest); + monotonicCounters[i].valid = FALSE; + } + } + return rc; +} + +/* TPM_Counters_GetActiveCounter() gets the active counter based on the value in TPM_STCLEAR_DATA -> + countID */ + +void TPM_Counters_GetActiveCounter(TPM_COUNT_ID *activeCounter, + TPM_COUNT_ID countID) +{ + if (countID < TPM_MIN_COUNTERS) { + *activeCounter = countID; + } + else { + *activeCounter = TPM_COUNT_ID_NULL; + } +} + +/* + TPM_COUNTER_VALUE +*/ + +/* TPM_CounterValue_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_CounterValue_Init(TPM_COUNTER_VALUE *tpm_counter_value) +{ + printf(" TPM_CounterValue_Init:\n"); + memset(tpm_counter_value->label, 0, TPM_COUNTER_LABEL_SIZE); + tpm_counter_value->counter = 0; + TPM_Secret_Init(tpm_counter_value->authData); + tpm_counter_value->valid = FALSE; + return; +} + +/* TPM_CounterValue_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes +*/ + +TPM_RESULT TPM_CounterValue_Load(TPM_COUNTER_VALUE *tpm_counter_value, /* result */ + unsigned char **stream, /* pointer to next + parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_CounterValue_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_COUNTER_VALUE, stream, stream_size); + } + /* load label */ + if (rc == 0) { + rc = TPM_Loadn(tpm_counter_value->label, TPM_COUNTER_LABEL_SIZE, stream, stream_size); + } + /* load counter */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_counter_value->counter), stream, stream_size); + } + /* load authData */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_counter_value->authData, stream, stream_size); + } + /* load valid */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_counter_value->valid), stream, stream_size); + } + return rc; +} + +/* TPM_CounterValue_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + It is typically used to store the structure in the permanent data file. +*/ + +TPM_RESULT TPM_CounterValue_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_COUNTER_VALUE *tpm_counter_value) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CounterValue_Store:\n"); + /* store tag, label, counter */ + if (rc == 0) { + rc = TPM_CounterValue_StorePublic(sbuffer, tpm_counter_value); + } + /* store authData */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_counter_value->authData); + } + /* store valid */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_counter_value->valid), sizeof(TPM_BOOL)); + } + return rc; +} + +/* TPM_CounterValue_StorePublic() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + This version only stores the public, externally visible fields: tag, label, counter. It is + typically used to return outgoing parameters. +*/ + +TPM_RESULT TPM_CounterValue_StorePublic(TPM_STORE_BUFFER *sbuffer, + const TPM_COUNTER_VALUE *tpm_counter_value) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CounterValue_StorePublic:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_COUNTER_VALUE); + } + /* store label */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_counter_value->label, TPM_COUNTER_LABEL_SIZE); + } + /* store counter */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_counter_value->counter); + } + return rc; +} + +/* TPM_CounterValue_CopyPublic() copies the public, externally visible fields: tag, label, counter. + */ + +void TPM_CounterValue_CopyPublic(TPM_COUNTER_VALUE *dst_tpm_counter_value, + TPM_COUNTER_VALUE *src_tpm_counter_value) +{ + memcpy(dst_tpm_counter_value->label, src_tpm_counter_value->label, TPM_COUNTER_LABEL_SIZE); + dst_tpm_counter_value->counter = src_tpm_counter_value->counter; + return; +} + +/* TPM_CounterValue_Set() + + Sets the label, counter, and authData members from input parameters, and sets the digest from + members. +*/ + +TPM_RESULT TPM_CounterValue_Set(TPM_COUNTER_VALUE *tpm_counter_value, + TPM_COUNT_ID countID, + BYTE *label, + TPM_ACTUAL_COUNT counter, + TPM_SECRET authData) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CounterValue_Set:\n"); + tpm_counter_value->counter = counter; + memcpy(tpm_counter_value->label, label, TPM_COUNTER_LABEL_SIZE); + TPM_Secret_Copy(tpm_counter_value->authData, authData); + /* create a hopefully unique digest of the object for the OSAP setup. The cast is OK here since + the actual value of the digest is never verified. */ + rc = TPM_SHA1(tpm_counter_value->digest, + sizeof(TPM_COUNT_ID), (unsigned char *)&countID, + TPM_COUNTER_LABEL_SIZE, label, + TPM_SECRET_SIZE, authData, + 0, NULL); + return rc; + +} + +/* TPM_CounterValue_Release() releases a counter. + + The resource is set invalid, and the authorization data and digest are cleared. +*/ + +TPM_RESULT TPM_CounterValue_Release(TPM_COUNTER_VALUE *tpm_counter_value, + TPM_COUNT_ID countID) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CounterValue_Release: countID %u\n", countID); + /* sanity check */ + if (rc == 0) { + if (!tpm_counter_value->valid) { + printf("TPM_CounterValue_Release: Error (fatal), countID %u not valid\n", countID); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + TPM_Secret_Init(tpm_counter_value->authData); + TPM_Digest_Init(tpm_counter_value->digest); + tpm_counter_value->valid = FALSE; + } + return rc; +} + +/* + Processing Functions +*/ + +/* 25.1 TPM_CreateCounter rev 98 + + This command creates the counter but does not select the counter. Counter creation assigns an + AuthData value to the counter and sets the counters original start value. The original start value + is the current internal base value plus one. Setting the new counter to the internal base avoids + attacks on the system that are attempting to use old counter values. + + This command creates a new monotonic counter. The TPM MUST support a minimum of 4 concurrent + counters. +*/ + +TPM_RESULT TPM_Process_CreateCounter(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_ENCAUTH encAuth; /* The encrypted auth data for the new counter */ + BYTE label[TPM_COUNTER_LABEL_SIZE]; /* Label to associate with counter */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA ownerAuth; /* Authorization ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey = NULL; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET a1Auth; + TPM_ACTUAL_COUNT nextCount; + TPM_BOOL writeAllNV= FALSE; /* flag to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_COUNT_ID countID = 0; /* The handle for the counter */ + TPM_COUNTER_VALUE *counterValue = NULL; /* The starting counter value */ + + printf("TPM_Process_CreateCounter: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get authData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Load(encAuth, &command, ¶mSize); + } + /* get label */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Loadn(label, TPM_COUNTER_LABEL_SIZE, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_CreateCounter: label", label); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CreateCounter: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Using the authHandle field, validate the owner's AuthData to execute the command and all + of the incoming parameters. The authorization session MUST be OSAP or DSAP. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_OWNER, + ordinal, + NULL, + NULL, + tpm_state->tpm_permanent_data.ownerAuth); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Ignore continueAuthSession on input and set continueAuthSession to FALSE on output */ + if (returnCode == TPM_SUCCESS) { + continueAuthSession = FALSE; + } + /* 3. Create a1 by decrypting encAuth according to the ADIP indicated by authHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_Decrypt(a1Auth, + NULL, + encAuth, + auth_session_data, + NULL, + NULL, + FALSE); /* even and odd */ + } + /* 4. Validate that there is sufficient internal space in the TPM to create a new counter. If + there is insufficient space the command returns an error. */ + /* a. The TPM MUST provide storage for a1, TPM_COUNTER_VALUE, countID, and any other internal + data the TPM needs to associate with the counter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Counters_GetNewHandle(&counterValue, /* structure */ + &countID, /* index */ + tpm_state->tpm_permanent_data.monotonicCounter); + } + if (returnCode == TPM_SUCCESS) { + writeAllNV = TRUE; + /* 5. Increment the max counter value */ + TPM_Counters_GetNextCount(&nextCount, + tpm_state->tpm_permanent_data.monotonicCounter); + /* 6. Set the counter to the max counter value */ + /* 7. Set the counter label to label */ + returnCode = TPM_CounterValue_Set(counterValue, + countID, + label, + nextCount, + a1Auth); + /* 8. Create a countID */ + /* NOTE Done in TPM_Counters_GetNewHandle() */ + } + /* save the permanent data structure in NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CreateCounter: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the countID */ + returnCode = TPM_Sbuffer_Append32(response, countID); + } + if (returnCode == TPM_SUCCESS) { + /* Return the TPM_COUNTER_VALUE publicly visible members */ + returnCode = TPM_CounterValue_StorePublic(response, counterValue); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 25.2 TPM_IncrementCounter rev 87 + + This authorized command increments the indicated counter by one. Once a counter has been + incremented then all subsequent increments must be for the same handle until a successful + TPM_Startup(ST_CLEAR) is executed. + + The order for checking validation of the command parameters when no counter is active, keeps an + attacker from creating a denial-of-service attack. + + This function increments the counter by 1. + The TPM MAY implement increment throttling to avoid burn problems +*/ + +TPM_RESULT TPM_Process_IncrementCounter(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_COUNT_ID countID; /* The handle of a valid counter */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for counter + authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA counterAuth; /* The authorization session digest that authorizes the use + of countID. HMAC key: countID -> authData */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_COUNTER_VALUE *counterValue = NULL; /* The counter value */ + + printf("TPM_Process_IncrementCounter: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get countID */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&countID, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_IncrementCounter: countID %u\n", countID); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + counterAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_IncrementCounter: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* The first check is that either there is no active counter and the countID has been created + or that the countID is the active counter */ + if (returnCode == TPM_SUCCESS) { + /* 1. If TPM_STCLEAR_DATA -> countID is NULL */ + if (tpm_state->tpm_stclear_data.countID == TPM_COUNT_ID_NULL) { + /* a. Validate that countID is a valid counter, return TPM_BAD_COUNTER on mismatch */ + returnCode = TPM_Counters_IsValidId(tpm_state->tpm_permanent_data.monotonicCounter, + countID); + } + /* 2. else (TPM_STCLEAR_DATA -> countID is not NULL */ + else { + /* a. If TPM_STCLEAR_DATA -> countID does not equal countID */ + if (tpm_state->tpm_stclear_data.countID != countID) { + if (tpm_state->tpm_stclear_data.countID == TPM_COUNT_ID_ILLEGAL) { + printf("TPM_Process_IncrementCounter: Error, counter has been released\n"); + } + else { + printf("TPM_Process_IncrementCounter: Error, %u is already active\n", + tpm_state->tpm_stclear_data.countID); + } + /* i. Return TPM_BAD_COUNTER */ + returnCode = TPM_BAD_COUNTER; + } + } + } + /* b. Validate the command parameters using counterAuth */ + /* Get the TPM_COUNTER_VALUE associated with the countID */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Counters_GetCounterValue(&counterValue, + tpm_state->tpm_permanent_data.monotonicCounter, + countID); + } + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_COUNTER, + ordinal, + NULL, + &(counterValue->authData), /* OIAP */ + counterValue->digest); /* OSAP */ + } + /* Validate the authorization to use the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + counterAuth); /* Authorization digest for input */ + } + if (returnCode == TPM_SUCCESS) { + /* 1. If TPM_STCLEAR_DATA -> countID is NULL */ + if (tpm_state->tpm_stclear_data.countID == TPM_COUNT_ID_NULL) { + /* c. Set TPM_STCLEAR_DATA -> countID to countID */ + tpm_state->tpm_stclear_data.countID = countID; + printf("TPM_Process_IncrementCounter: Setting %u as active counter\n", countID); + } + } + if (returnCode == TPM_SUCCESS) { + /* 3. Increments the counter by 1 */ + counterValue->counter++; /* in TPM_PERMANENT_DATA */ + /* save the permanent data structure in NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + TRUE, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_IncrementCounter: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 4. Return new count value in count */ + returnCode = TPM_CounterValue_StorePublic(response, counterValue); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 25.3 TPM_ReadCounter rev 87 + + Reading the counter provides the caller with the current number in the sequence. + + This returns the current value for the counter indicated. The counter MAY be any valid counter. +*/ + +TPM_RESULT TPM_Process_ReadCounter(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_COUNT_ID countID; /* ID value of the counter */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ReadCounter: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get countID */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&countID, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ReadCounter: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Validate that countID points to a valid counter. Return TPM_BAD_COUNTER on error. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ReadCounter: countID %u\n", countID); + returnCode = TPM_Counters_IsValidId(tpm_state->tpm_permanent_data.monotonicCounter, + countID); + } + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ReadCounter: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 2. Return count (directly from TPM_PERMANENT_DATA) */ + returnCode = TPM_CounterValue_StorePublic + (response, &(tpm_state->tpm_permanent_data.monotonicCounter[countID])); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + return rcf; +} + +/* 25.4 TPM_ReleaseCounter rev 87 + + This command releases a counter such that no reads or increments of the indicated counter will + succeed. + + The TPM uses countID to locate a valid counter. +*/ + +TPM_RESULT TPM_Process_ReleaseCounter(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_COUNT_ID countID; /* ID value of the counter */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for countID + authorization */ + TPM_NONCE nonceOdd; /* Nonce associated with countID */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA counterAuth; /* The authorization session digest that authorizes the use + of countID. HMAC key: countID -> authData */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_COUNTER_VALUE *counterValue; /* associated with countID */ + TPM_SECRET savedAuth; /* saved copy for response */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV*/ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ReleaseCounter: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get countID */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&countID, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ReleaseCounter: countID %u\n", countID); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + counterAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ReleaseCounter: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Authenticate the command and the parameters using the AuthData pointed to by + countID. Return TPM_AUTHFAIL on error */ + /* Get the TPM_COUNTER_VALUE associated with the countID */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Counters_GetCounterValue(&counterValue, + tpm_state->tpm_permanent_data.monotonicCounter, + countID); + } + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_COUNTER, + ordinal, + NULL, + &(counterValue->authData), /* OIAP */ + counterValue->digest); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + /* make a copy of the HMAC key for the response, since it gets invalidated */ + TPM_Secret_Copy(savedAuth, *hmacKey); + /* Validate the authorization to use the key pointed to by countID */ + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + counterAuth); /* Authorization digest for input */ + } + /* 3. The TPM invalidates sessions */ + /* a. MUST invalidate all OSAP sessions associated with the counter */ + /* b. MAY invalidate any other session */ + /* NOTE: Actions reversed because the sessions can't be found after the digest is initialized */ + if (returnCode == TPM_SUCCESS) { + TPM_AuthSessions_TerminateEntity(&continueAuthSession, + authHandle, + tpm_state->tpm_stclear_data.authSessions, + TPM_ET_COUNTER, /* TPM_ENTITY_TYPE */ + &(counterValue->digest)); /* entityDigest */ + } + /* 2. The TPM invalidates all internal information regarding the counter. This includes + releasing countID such that any subsequent attempts to use countID will fail. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ReleaseCounter: Releasing counter %u\n", countID); + returnCode = TPM_CounterValue_Release(counterValue, countID); + } + if (returnCode == TPM_SUCCESS) { + writeAllNV= TRUE; + /* 4. If TPM_STCLEAR_DATA -> countID equals countID, */ + if (tpm_state->tpm_stclear_data.countID == countID ) { + printf("TPM_Process_ReleaseCounter: Deactivating counter %u\n", countID); + /* a. Set TPM_STCLEAR_DATA -> countID to an illegal value (not the NULL value) */ + tpm_state->tpm_stclear_data.countID = TPM_COUNT_ID_ILLEGAL; + } + } + /* save the permanent data structure in NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ReleaseCounter: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + savedAuth, /* saved countID HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 25.5 TPM_ReleaseCounterOwner rev 101 + + This command releases a counter such that no reads or increments of the indicated counter will + succeed. + + This invalidates all information regarding a counter. +*/ + +TPM_RESULT TPM_Process_ReleaseCounterOwner(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + TPM_COUNT_ID countID; /* ID value of the counter */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = FALSE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest that authorizes the + inputs. HMAC key: ownerAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = TRUE; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey = NULL; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_COUNTER_VALUE *counterValue; /* associated with countID */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ReleaseCounterOwner: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get countID */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&countID, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ReleaseCounterOwner: countID %u\n", countID); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ReleaseCounterOwner: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate that ownerAuth properly authorizes the command and parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. The TPM uses countID to locate a valid counter. Return TPM_BAD_COUNTER if not found. */ + /* Get the TPM_COUNTER_VALUE associated with the countID */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Counters_GetCounterValue(&counterValue, + tpm_state->tpm_permanent_data.monotonicCounter, + countID); + } + /* NOTE: Actions reversed because the sessions can't be found after the digest is initialized */ + if (returnCode == TPM_SUCCESS) { + TPM_AuthSessions_TerminateEntity(&continueAuthSession, + authHandle, + tpm_state->tpm_stclear_data.authSessions, + TPM_ET_COUNTER, /* TPM_ENTITY_TYPE */ + &(counterValue->digest)); /* entityDigest */ + } + /* 3. The TPM invalidates all internal information regarding the counter. This includes + releasing countID such that any subsequent attempts to use countID will fail. */ + /* NOTE: This function can only return a TPM_FAIL error, so that the failure to store + TPM_PERMANENT_DATA will already be reported as fatal. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CounterValue_Release(counterValue, countID); + } + /* 4. The TPM invalidates sessions */ + /* a. MUST invalidate all OSAP sessions associated with the counter */ + /* b. MAY invalidate any other session */ + if (returnCode == TPM_SUCCESS) { + writeAllNV = TRUE; + /* 5. If TPM_STCLEAR_DATA -> countID equals countID, */ + if (tpm_state->tpm_stclear_data.countID == countID ) { + printf("TPM_Process_ReleaseCounterOwner: Deactivating counter %u\n", countID); + /* a. Set TPM_STCLEAR_DATA -> countID to an illegal value (not the zero value) */ + tpm_state->tpm_stclear_data.countID = TPM_COUNT_ID_ILLEGAL; + } + } + /* save the permanent data structure in NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ReleaseCounterOwner: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} diff --git a/src/tpm12/tpm_counter.h b/src/tpm12/tpm_counter.h new file mode 100644 index 0000000..18709d2 --- /dev/null +++ b/src/tpm12/tpm_counter.h @@ -0,0 +1,140 @@ +/********************************************************************************/ +/* */ +/* Counter Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_counter.h 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_COUNTER_H +#define TPM_COUNTER_H + +#include "tpm_global.h" +#include "tpm_store.h" +#include "tpm_structures.h" + +/* + Counter Resource Handling +*/ + +void TPM_Counters_Init(TPM_COUNTER_VALUE *monotonicCounters); +TPM_RESULT TPM_Counters_Load(TPM_COUNTER_VALUE *monotonicCountersa, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Counters_Store(TPM_STORE_BUFFER *sbuffer, + TPM_COUNTER_VALUE *monotonicCounters); + +TPM_RESULT TPM_Counters_StoreHandles(TPM_STORE_BUFFER *sbuffer, + TPM_COUNTER_VALUE *monotonicCounters); +TPM_RESULT TPM_Counters_GetNewHandle(TPM_COUNTER_VALUE **tpm_counter_value, + TPM_COUNT_ID *countID, + TPM_COUNTER_VALUE *monotonicCounters); +void TPM_Counters_GetSpace(uint32_t *space, + TPM_COUNTER_VALUE *monotonicCounters); +void TPM_Counters_GetNextCount(TPM_ACTUAL_COUNT *nextCount, + TPM_COUNTER_VALUE *monotonicCounters); +TPM_RESULT TPM_Counters_IsValidId(TPM_COUNTER_VALUE *monotonicCounters, + TPM_COUNT_ID countID); +TPM_RESULT TPM_Counters_GetCounterValue(TPM_COUNTER_VALUE **tpm_counter_value, + TPM_COUNTER_VALUE *monotonicCounters, + TPM_COUNT_ID countID); +TPM_RESULT TPM_Counters_Release(TPM_COUNTER_VALUE *monotonicCounters); +void TPM_Counters_GetActiveCounter(TPM_COUNT_ID *activeCounter, + TPM_COUNT_ID countID); + + +/* + TPM_COUNTER_VALUE +*/ + +void TPM_CounterValue_Init(TPM_COUNTER_VALUE *tpm_counter_value); +TPM_RESULT TPM_CounterValue_Load(TPM_COUNTER_VALUE *tpm_counter_value, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_CounterValue_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_COUNTER_VALUE *tpm_counter_value); + +TPM_RESULT TPM_CounterValue_StorePublic(TPM_STORE_BUFFER *sbuffer, + const TPM_COUNTER_VALUE *tpm_counter_value); +void TPM_CounterValue_CopyPublic(TPM_COUNTER_VALUE *dst_tpm_counter_value, + TPM_COUNTER_VALUE *src_tpm_counter_value); +TPM_RESULT TPM_CounterValue_Set(TPM_COUNTER_VALUE *tpm_counter_value, + TPM_COUNT_ID countID, + BYTE *label, + TPM_ACTUAL_COUNT counter, + TPM_SECRET authData); +TPM_RESULT TPM_CounterValue_Release(TPM_COUNTER_VALUE *tpm_counter_value, + TPM_COUNT_ID countID); +/* + Processing Functions +*/ + +TPM_RESULT TPM_Process_CreateCounter(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_IncrementCounter(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ReadCounter(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ReleaseCounter(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ReleaseCounterOwner(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +#endif diff --git a/src/tpm12/tpm_crypto.c b/src/tpm12/tpm_crypto.c new file mode 100644 index 0000000..9fb4fce --- /dev/null +++ b/src/tpm12/tpm_crypto.c @@ -0,0 +1,3088 @@ +/********************************************************************************/ +/* */ +/* Platform Dependent Crypto */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_crypto.c 4767 2017-07-27 23:06:32Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* This is the openSSL implementation */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_key.h" +#include "tpm_io.h" +#include "tpm_load.h" +#include "tpm_memory.h" +#include "tpm_process.h" +#include "tpm_types.h" + +#include "tpm_crypto.h" + +#include "tpm_openssl_helpers.h" // libtpms added + +/* The TPM OAEP encoding parameter */ +static const unsigned char tpm_oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; + + +/* local prototypes */ + +static void TPM_OpenSSL_PrintError(void); + +static TPM_RESULT TPM_RSAGeneratePublicToken(RSA **rsa_pub_key, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes); +static TPM_RESULT TPM_RSAGeneratePrivateToken(RSA **rsa_pri_key, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes, + unsigned char *darr, + uint32_t dbytes); +static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, + unsigned int *signature_length, + const unsigned char *message, + size_t message_size, + RSA *rsa_pri_key); +static TPM_RESULT TPM_RSASignDER(unsigned char *signature, + unsigned int *signature_length, + const unsigned char *message, + size_t message_size, + RSA *rsa_pri_key); + +static TPM_RESULT TPM_BN_CTX_new(BN_CTX **ctx); + + + +/* TPM_SYMMETRIC_KEY_DATA is a crypto library platform dependent symmetric key structure + */ +#ifdef TPM_DES + +/* local prototype and structure for DES */ + +#include + +/* DES requires data lengths that are a multiple of the block size */ +#define TPM_DES_BLOCK_SIZE 8 + +typedef struct tdTPM_SYMMETRIC_KEY_DATA { + TPM_TAG tag; + TPM_BOOL valid; + BYTE fill; + DES_cblock des_cblock1; + DES_cblock des_cblock2; + DES_cblock des_cblock3; +} TPM_SYMMETRIC_KEY_DATA; + +static TPM_RESULT TPM_SymmetricKeyData_Crypt(unsigned char *data_out, + const unsigned char *data_in, + uint32_t length, + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, + int enc, + TPM_RESULT error); + +#endif + +#ifdef TPM_AES + +/* local prototype and structure for AES */ + +#include + +#if defined(__OpenBSD__) + # define OPENSSL_OLD_API +#else + #if OPENSSL_VERSION_NUMBER < 0x10100000 + #define OPENSSL_OLD_API + #endif +#endif + +/* AES requires data lengths that are a multiple of the block size */ +#define TPM_AES_BITS 128 +/* The AES block size is always 16 bytes */ +#define TPM_AES_BLOCK_SIZE 16 + +/* Since the AES key is often derived by truncating the session shared secret, test that it's not + too large +*/ + +#if (TPM_AES_BLOCK_SIZE > TPM_SECRET_SIZE) +#error TPM_AES_BLOCK_SIZE larger than TPM_SECRET_SIZE +#endif + +/* The AES initial CTR value is derived from a nonce. */ + +#if (TPM_AES_BLOCK_SIZE > TPM_NONCE_SIZE) +#error TPM_AES_BLOCK_SIZE larger than TPM_NONCE_SIZE +#endif + +typedef struct tdTPM_SYMMETRIC_KEY_DATA { + TPM_TAG tag; + TPM_BOOL valid; + TPM_BOOL fill; + unsigned char userKey[TPM_AES_BLOCK_SIZE]; + /* For performance, generate these once from userKey */ + AES_KEY aes_enc_key; + AES_KEY aes_dec_key; +} TPM_SYMMETRIC_KEY_DATA; + +static TPM_RESULT TPM_SymmetricKeyData_SetKeys(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data); +static TPM_RESULT TPM_SymmetricKeyData_SetKey(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, + const unsigned char *key_data, + uint32_t key_data_size); +static TPM_RESULT TPM_AES_ctr128_encrypt(unsigned char *data_out, + const unsigned char *data_in, + uint32_t data_size, + const AES_KEY *aes_enc_key, + unsigned char ctr[TPM_AES_BLOCK_SIZE]); + +#endif + +/* + Initialization function +*/ + +TPM_RESULT TPM_Crypto_Init() +{ + TPM_RESULT rc = 0; + + printf("TPM_Crypto_Init: OpenSSL library %08lx\n", (unsigned long)OPENSSL_VERSION_NUMBER); + /* sanity check that the SHA1 context handling remains portable */ + if (rc == 0) { + if ((sizeof(SHA_LONG) != sizeof(uint32_t)) || + (sizeof(unsigned int) != sizeof(uint32_t)) || + (sizeof(SHA_CTX) != (sizeof(uint32_t) * (8 + SHA_LBLOCK)))) { + printf("TPM_Crypto_Init: Error(fatal), SHA_CTX has unexpected structure\n"); + rc = TPM_FAIL; + } + } + return rc; +} + +/* TPM_Crypto_TestSpecific() performs any library specific tests + + For OpenSSL + */ + +TPM_RESULT TPM_Crypto_TestSpecific() +{ + TPM_RESULT rc = 0; + + /* Saving the SHA-1 context is fragile code, so test at startup */ + void *context1; + void *context2; + unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C, + 0x3B,0xD2,0x6E,0xBA,0xAE, + 0x4A,0xA1,0xF9,0x51,0x29, + 0xE5,0xE5,0x46,0x70,0xF1}; + TPM_DIGEST actual; + int not_equal; + TPM_STORE_BUFFER sbuffer; + const unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_Crypto_TestSpecific: Test 1 - SHA1 two parts\n"); + context1 = NULL; /* freed @1 */ + context2 = NULL; /* freed @2 */ + TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ + + if (rc== 0) { + rc = TPM_Malloc((unsigned char **)&context1, sizeof(SHA_CTX)); /* freed @1 */ + } + /* digest the first part of the array */ + if (rc== 0) { + SHA1_Init(context1); + SHA1_Update(context1, buffer1, 16); + } + /* store the SHA1 context */ + if (rc== 0) { + rc = TPM_Sha1Context_Store(&sbuffer, context1); + } + /* load the SHA1 context */ + if (rc== 0) { + TPM_Sbuffer_Get(&sbuffer, &stream, &stream_size); + rc = TPM_Sha1Context_Load + (&context2, (unsigned char **)&stream, &stream_size); /* freed @2 */ + } + /* digest the rest of the array */ + if (rc== 0) { + SHA1_Update(context2, buffer1 + 16, sizeof(buffer1) - 17); + SHA1_Final(actual, context2); + } + if (rc == 0) { + not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); + if (not_equal) { + printf("TPM_Crypto_TestSpecific: Error in test 1\n"); + TPM_PrintFour("\texpect", expect1); + TPM_PrintFour("\tactual", actual); + rc = TPM_FAILEDSELFTEST; + } + } + free(context1); /* @1 */ + free(context2); /* @2 */ + TPM_Sbuffer_Delete(&sbuffer); /* @3 */ + return rc; +} + + + +/* + Random Number Functions +*/ + +/* TPM_Random() fills 'buffer' with 'bytes' bytes. + */ + +TPM_RESULT TPM_Random(BYTE *buffer, size_t bytes) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Random: Requesting %lu bytes\n", (unsigned long)bytes); + + if (rc == 0) { + /* openSSL call */ + rc = RAND_bytes(buffer, bytes); + if (rc == 1) { /* OSSL success */ + rc = 0; + } + else { /* OSSL failure */ + printf("TPM_Random: Error (fatal) calling RAND_bytes()\n"); + rc = TPM_FAIL; + } + } + return rc; +} + +TPM_RESULT TPM_StirRandomCmd(TPM_SIZED_BUFFER *inData) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StirRandomCmd:\n"); + if (rc == 0) { + /* NOTE: The TPM command does not give an entropy estimate. This assumes the best case */ + /* openSSL call */ + RAND_add(inData->buffer, /* buf mixed into PRNG state*/ + inData->size, /* number of bytes */ + inData->size); /* entropy, the lower bound of an estimate of how much randomness is + contained in buf */ + } + return rc; +} + +/* + RSA Functions +*/ + +/* Generate an RSA key pair. + + 'n', 'p', 'q', 'd' must be freed by the caller +*/ + +TPM_RESULT TPM_RSAGenerateKeyPair(unsigned char **n, /* public key - modulus */ + unsigned char **p, /* private key prime */ + unsigned char **q, /* private key prime */ + unsigned char **d, /* private key (private exponent) */ + int num_bits, /* key size in bits */ + const unsigned char *earr, /* public exponent as an array */ + uint32_t e_size) +{ + TPM_RESULT rc = 0; + RSA *rsa = NULL; + const BIGNUM *bnn = NULL; + BIGNUM *bne = NULL; + const BIGNUM *bnp = NULL; + const BIGNUM *bnq = NULL; + const BIGNUM *bnd = NULL; + uint32_t nbytes; + uint32_t pbytes; + uint32_t qbytes; + uint32_t dbytes; + + unsigned long e; + + /* initialize in case of error */ + printf(" TPM_RSAGenerateKeyPair:\n"); + *n = NULL; + *p = NULL; + *q = NULL; + *d = NULL; + + /* check that num_bits is a multiple of 16. If not, the primes p and q will not be a multiple of + 8 and will not fit well in a byte */ + if (rc == 0) { + if ((num_bits % 16) != 0) { + printf("TPM_RSAGenerateKeyPair: Error, num_bits %d is not a multiple of 16\n", + num_bits); + rc = TPM_BAD_KEY_PROPERTY; + } + } + /* convert the e array to an unsigned long */ + if (rc == 0) { + rc = TPM_LoadLong(&e, earr, e_size); + } + /* validate the public exponent against a list of legal values. Some values (e.g. even numbers) + will hang the key generator. */ + if (rc == 0) { + rc = TPM_RSA_exponent_verify(e); + } + if (rc == 0) { + rsa = RSA_new(); /* freed @1 */ + if (rsa == NULL) { + printf("TPM_RSAGenerateKeyPair: Error in RSA_new()\n"); + rc = TPM_SIZE; + } + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&bne, earr, e_size); /* freed @2 */ + } + if (rc == 0) { + printf(" TPM_RSAGenerateKeyPair: num_bits %d exponent %08lx\n", num_bits, e); + int irc = RSA_generate_key_ex(rsa, num_bits, bne, NULL); + if (irc != 1) { + printf("TPM_RSAGenerateKeyPair: Error calling RSA_generate_key_ex()\n"); + rc = TPM_BAD_KEY_PROPERTY; + } + } + if (rc == 0) { +#if defined OPENSSL_OLD_API + bnn = rsa->n; + bnp = rsa->p; + bnq = rsa->q; + bnd = rsa->d; +#else + /* currently, this function accepts NULL inputs, but it's not guaranteed by the + documentation */ + const BIGNUM *bnetmp = NULL; /* not needed */ + RSA_get0_key(rsa, &bnn, &bnetmp, &bnd); + RSA_get0_factors(rsa, &bnp, &bnq); +#endif + } + /* load n */ + if (rc == 0) { + rc = TPM_bn2binMalloc(n, &nbytes, (TPM_BIGNUM)bnn, num_bits/8); /* freed by caller */ + } + /* load p */ + if (rc == 0) { + rc = TPM_bn2binMalloc(p, &pbytes, (TPM_BIGNUM)bnp, num_bits/16); /* freed by caller */ + } + /* load q */ + if (rc == 0) { + rc = TPM_bn2binMalloc(q, &qbytes, (TPM_BIGNUM)bnq, num_bits/16); /* freed by caller */ + } + /* load d */ + if (rc == 0) { + rc = TPM_bn2binMalloc(d, &dbytes, (TPM_BIGNUM)bnd, num_bits/8); /* freed by caller */ + } + if (rc == 0) { + printf(" TPM_RSAGenerateKeyPair: length of n,p,q,d = %d / %d / %d / %d\n", + nbytes, pbytes, qbytes, dbytes); + } + if (rc != 0) { + free(*n); + free(*p); + free(*q); + free(*d); + *n = NULL; + *p = NULL; + *q = NULL; + *d = NULL; + } + if (rsa != NULL) { + RSA_free(rsa); /* @1 */ + } + if (bne != NULL) { + BN_free(bne); /* @2 */ + } + return rc; +} + +/* TPM_RSAGeneratePublicToken() generates an RSA key token from n and e + */ + +static TPM_RESULT TPM_RSAGeneratePublicToken(RSA **rsa_pub_key, /* freed by caller */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + BIGNUM * n = NULL; + BIGNUM * e = NULL; + + /* sanity check for the free */ + if (rc == 0) { + if (*rsa_pub_key != NULL) { + printf("TPM_RSAGeneratePublicToken: Error (fatal), token %p should be NULL\n", + *rsa_pub_key ); + rc = TPM_FAIL; + + } + } + /* construct the OpenSSL private key object */ + if (rc == 0) { + *rsa_pub_key = RSA_new(); /* freed by caller */ + if (*rsa_pub_key == NULL) { + printf("TPM_RSAGeneratePublicToken: Error in RSA_new()\n"); + rc = TPM_SIZE; + } + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ + } + if (rc == 0) { +#if defined OPENSSL_OLD_API + (*rsa_pub_key)->n = n; + (*rsa_pub_key)->e = e; + (*rsa_pub_key)->d = NULL; +#else + int irc = RSA_set0_key(*rsa_pub_key, n, e, NULL); + if (irc != 1) { + printf("TPM_RSAGeneratePublicToken: Error in RSA_set0_key()\n"); + rc = TPM_SIZE; + } +#endif + } + return rc; +} + +/* TPM_RSAGeneratePrivateToken() generates an RSA key token from n,e,d + */ + +static TPM_RESULT TPM_RSAGeneratePrivateToken(RSA **rsa_pri_key, /* freed by caller */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + BIGNUM * n = NULL; + BIGNUM * e = NULL; + BIGNUM * d = NULL; + + /* sanity check for the free */ + if (rc == 0) { + if (*rsa_pri_key != NULL) { + printf("TPM_RSAGeneratePrivateToken: Error (fatal), token %p should be NULL\n", + *rsa_pri_key ); + rc = TPM_FAIL; + + } + } + /* construct the OpenSSL private key object */ + if (rc == 0) { + *rsa_pri_key = RSA_new(); /* freed by caller */ + if (*rsa_pri_key == NULL) { + printf("TPM_RSAGeneratePrivateToken: Error in RSA_new()\n"); + rc = TPM_SIZE; + } + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&d, darr, dbytes); /* freed by caller */ + } + if (rc == 0) { +#if defined OPENSSL_OLD_API + (*rsa_pri_key)->n = n; + (*rsa_pri_key)->e = e; + (*rsa_pri_key)->d = d; + BN_set_flags(d, BN_FLG_CONSTTIME); // d is private +#else + int irc = RSA_set0_key(*rsa_pri_key, n, e, d); + if (irc != 1) { + printf("TPM_RSAGeneratePrivateToken: Error in RSA_set0_key()\n"); + rc = TPM_SIZE; + } +#endif + } + return rc; +} + +#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added +/* TPM_RSAPrivateDecrypt() decrypts 'encrypt_data' using the private key 'n, e, d'. The OAEP + padding is removed and 'decrypt_data_length' bytes are moved to 'decrypt_data'. + + 'decrypt_data_length' is at most 'decrypt_data_size'. +*/ + +TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ + uint32_t *decrypt_data_length, /* length of data put into + decrypt_data */ + size_t decrypt_data_size, /* size of decrypt_data buffer */ + TPM_ENC_SCHEME encScheme, /* encryption scheme */ + unsigned char *encrypt_data, /* encrypted data */ + uint32_t encrypt_data_size, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + int irc; + RSA * rsa_pri_key = NULL; /* freed @1 */ + + unsigned char *padded_data = NULL; + int padded_data_size = 0; + + printf(" TPM_RSAPrivateDecrypt:\n"); + /* construct the OpenSSL private key object */ + if (rc == 0) { + rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + darr, /* private exponent */ + dbytes); + } + /* intermediate buffer for the decrypted but still padded data */ + if (rc == 0) { + /* the size of the decrypted data is guaranteed to be less than this */ + padded_data_size = RSA_size(rsa_pri_key); + rc = TPM_Malloc(&padded_data, padded_data_size); + } + if (rc == 0) { + /* decrypt with private key. Must decrypt first and then remove padding because the decrypt + call cannot specify an encoding parameter */ + /* returns the size of the encrypted data. On error, -1 is returned */ + irc = RSA_private_decrypt(encrypt_data_size, /* length */ + encrypt_data, /* from - the encrypted data */ + padded_data, /* to - the decrypted but padded data */ + rsa_pri_key, /* key */ + RSA_NO_PADDING); /* padding */ + if (irc < 0) { + printf("TPM_RSAPrivateDecrypt: Error in RSA_private_decrypt()\n"); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + printf(" TPM_RSAPrivateDecrypt: RSA_private_decrypt() success\n"); + printf(" TPM_RSAPrivateDecrypt: Padded data size %u\n", padded_data_size); + TPM_PrintFour(" TPM_RSAPrivateDecrypt: Decrypt padded data", padded_data); + if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { + /* openSSL expects the padded data to skip the first 0x00 byte, since it expects the + padded data to come from a bignum via bn2bin. */ + irc = RSA_padding_check_PKCS1_OAEP(decrypt_data, /* to */ + decrypt_data_size, /* to length */ + padded_data + 1, /* from */ + padded_data_size - 1, /* from length */ + encrypt_data_size, /* rsa_len */ + tpm_oaep_pad_str, /* encoding parameter */ + sizeof(tpm_oaep_pad_str) /* encoding parameter length + */ + ); + if (irc < 0) { + printf("TPM_RSAPrivateDecrypt: Error in RSA_padding_check_PKCS1_OAEP()\n"); + rc = TPM_DECRYPT_ERROR; + } + } + else if (encScheme == TPM_ES_RSAESPKCSv15) { + irc = RSA_padding_check_PKCS1_type_2(decrypt_data, /* to */ + decrypt_data_size, /* to length */ + padded_data + 1, /* from */ + padded_data_size - 1, /* from length */ + encrypt_data_size /* rsa_len */ + ); + if (irc < 0) { + printf("TPM_RSAPrivateDecrypt: Error in RSA_padding_check_PKCS1_type_2()\n"); + rc = TPM_DECRYPT_ERROR; + } + } + else { + printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); + rc = TPM_INAPPROPRIATE_ENC; + } + } + if (rc == 0) { + *decrypt_data_length = irc; + printf(" TPM_RSAPrivateDecrypt: RSA_padding_check_PKCS1_OAEP() recovered %d bytes\n", irc); + TPM_PrintFourLimit(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data, *decrypt_data_length); + } + if (rsa_pri_key != NULL) { + RSA_free(rsa_pri_key); /* @1 */ + } + free(padded_data); /* @2 */ + return rc; +} + +#else // libtpms added begin + +TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ + uint32_t *decrypt_data_length, /* length of data put into + decrypt_data */ + size_t decrypt_data_size, /* size of decrypt_data buffer */ + TPM_ENC_SCHEME encScheme, /* encryption scheme */ + unsigned char *encrypt_data, /* encrypted data */ + uint32_t encrypt_data_size, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md = NULL; + unsigned char *label = NULL; + size_t outlen; + unsigned char buffer[(TPM_RSA_KEY_LENGTH_MAX + 7) / 8]; + + printf(" TPM_RSAPrivateDecrypt:\n"); + /* construct the OpenSSL private key object */ + if (rc == 0) { + rc = TPM_RSAGenerateEVP_PKEY(&pkey, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + darr, /* private exponent */ + dbytes); + } + + if (rc == 0) { + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == 0) { + printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_CTX_new()\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + if (EVP_PKEY_decrypt_init(ctx) <= 0) { + printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_decrypt_init()\n"); + rc = TPM_FAIL; + } + } + + if (rc == 0) { + switch (encScheme) { + case TPM_ES_RSAESOAEP_SHA1_MGF1: + if (rc == 0) { + md = EVP_get_digestbyname("sha1"); + if (md == NULL || + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) { + printf("TPM_RSAPrivateDecrypt: Error in setting up decrypt context for TPM_ES_RSAESOAEP_SHA1_MGF\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + rc = TPM_Malloc(&label, sizeof(tpm_oaep_pad_str)); + if (rc) { + printf("TPM_RSAPrivateDecrypt: TPM_Malloc failed\n"); + } + } + if (rc == 0) { + memcpy(label, tpm_oaep_pad_str, sizeof(tpm_oaep_pad_str)); + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sizeof(tpm_oaep_pad_str)) <= 0) { + printf("TPM_RSAPrivateDecrypt: EVP_PKEY_CTX_set0_rsa_oaep_label() failed\n"); + rc = TPM_FAIL; + } + if (rc == 0) { + label = NULL; + } + } + break; + case TPM_ES_RSAESPKCSv15: + if (rc == 0) { + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { + printf("TPM_RSAPrivateDecrypt: Error in setting up decrypt context for TPM_ES_RSAESPKCSv15\n"); + rc = TPM_FAIL; + } + } + break; + default: + if (rc == 0) { + printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); + rc = TPM_INAPPROPRIATE_ENC; + } + } + } + + if (rc == 0) { + outlen = sizeof(buffer); + if (EVP_PKEY_decrypt(ctx, buffer, &outlen, + encrypt_data, encrypt_data_size) <= 0) { + printf("TPM_RSAPrivateDecrypt: EVP_PKEY_decrypt failed\n"); + rc = TPM_DECRYPT_ERROR; + } + if (rc == 0) { + if (outlen > decrypt_data_size) { + printf("TPM_RSAPrivateDecrypt: Error, decrypt_data_size %u too small for message size %u\n", + decrypt_data_size, outlen); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + *decrypt_data_length = (uint32_t)outlen; + memcpy(decrypt_data, buffer, outlen); + TPM_PrintFourLimit(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data, *decrypt_data_length); + } + } + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + TPM_Free(label); + + return rc; +} + +#endif // libtpms added end + +/* TPM_RSAPublicEncrypt() pads 'decrypt_data' to 'encrypt_data_size' and encrypts using the public + key 'n, e'. +*/ + +#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added + +TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, /* encrypted data */ + size_t encrypt_data_size, /* size of encrypted data buffer */ + TPM_ENC_SCHEME encScheme, + const unsigned char *decrypt_data, /* decrypted data */ + size_t decrypt_data_size, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + int irc; + RSA *rsa_pub_key = NULL; + unsigned char *padded_data = NULL; + + printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); + /* intermediate buffer for the decrypted but still padded data */ + if (rc == 0) { + rc = TPM_Malloc(&padded_data, encrypt_data_size); /* freed @2 */ + } + /* construct the OpenSSL public key object */ + if (rc == 0) { + rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + if (rc == 0) { + if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { + irc = RSA_padding_add_PKCS1_OAEP(padded_data, /* to */ + encrypt_data_size, /* to length */ + decrypt_data, /* from */ + decrypt_data_size, /* from length */ + tpm_oaep_pad_str, /* encoding parameter */ + sizeof(tpm_oaep_pad_str) /* encoding parameter length + */ + ); + if (irc != 1) { + printf("TPM_RSAPublicEncrypt: Error in RSA_padding_add_PKCS1_OAEP()\n"); + rc = TPM_ENCRYPT_ERROR; + } + else { + printf(" TPM_RSAPublicEncrypt: RSA_padding_add_PKCS1_OAEP() success\n"); + } + } + else if (encScheme == TPM_ES_RSAESPKCSv15) { + irc = RSA_padding_add_PKCS1_type_2(padded_data, /* to */ + encrypt_data_size, /* to length */ + decrypt_data, /* from */ + decrypt_data_size); /* from length */ + if (irc != 1) { + printf("TPM_RSAPublicEncrypt: Error in RSA_padding_add_PKCS1_type_2()\n"); + rc = TPM_ENCRYPT_ERROR; + } + else { + printf(" TPM_RSAPublicEncrypt: RSA_padding_add_PKCS1_type_2() success\n"); + } + } + else { + printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); + rc = TPM_INAPPROPRIATE_ENC; + } + } + if (rc == 0) { + printf(" TPM_RSAPublicEncrypt: Padded data size %lu\n", (unsigned long)encrypt_data_size); + TPM_PrintFour(" TPM_RSAPublicEncrypt: Padded data", padded_data); + /* encrypt with public key. Must pad first and then encrypt because the encrypt + call cannot specify an encoding parameter */ + /* returns the size of the encrypted data. On error, -1 is returned */ + irc = RSA_public_encrypt(encrypt_data_size, /* from length */ + padded_data, /* from - the clear text data */ + encrypt_data, /* the padded and encrypted data */ + rsa_pub_key, /* key */ + RSA_NO_PADDING); /* padding */ + if (irc < 0) { + printf("TPM_RSAPublicEncrypt: Error in RSA_public_encrypt()\n"); + rc = TPM_ENCRYPT_ERROR; + } + } + if (rc == 0) { + printf(" TPM_RSAPublicEncrypt: RSA_public_encrypt() success\n"); + } + if (rsa_pub_key != NULL) { + RSA_free(rsa_pub_key); /* @1 */ + } + free(padded_data); /* @2 */ + return rc; +} + +#else // libtpms added begin + +TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, /* encrypted data */ + size_t encrypt_data_size, /* size of encrypted data buffer */ + TPM_ENC_SCHEME encScheme, + const unsigned char *decrypt_data, /* decrypted data */ + size_t decrypt_data_size, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md = NULL; + unsigned char *label = NULL; + size_t outlen; + + printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); + + /* construct the OpenSSL private key object */ + if (rc == 0) { + rc = TPM_RSAGenerateEVP_PKEY(&pkey, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + NULL, /* private exponent */ + 0); + } + + if (rc == 0) { + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == 0) { + printf("TPM_RSAqPrivateDecrypt: Error in EVP_PKEY_CTX_new()\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + if (EVP_PKEY_encrypt_init(ctx) <= 0) { + printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_decrypt_init()\n"); + rc = TPM_FAIL; + } + } + + if (rc == 0) { + switch (encScheme) { + case TPM_ES_RSAESOAEP_SHA1_MGF1: + if (rc == 0) { + md = EVP_get_digestbyname("sha1"); + if (md == NULL || + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) { + printf("TPM_RSAPublicEncrypt: Error in setting up encrypt context for TPM_ES_RSAESOAEP_SHA1_MGF\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + rc = TPM_Malloc(&label, sizeof(tpm_oaep_pad_str)); + if (rc) { + printf("TPM_RSAPublicEncrypt: TPM_Malloc failed\n"); + } + } + if (rc == 0) { + memcpy(label, tpm_oaep_pad_str, sizeof(tpm_oaep_pad_str)); + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sizeof(tpm_oaep_pad_str)) <= 0) { + printf("TPM_RSAPublicEncrypt: EVP_PKEY_CTX_set0_rsa_oaep_label() failed\n"); + rc = TPM_FAIL; + } + if (rc == 0) { + label = NULL; + } + } + break; + case TPM_ES_RSAESPKCSv15: + if (rc == 0) { + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { + printf("TPM_RSAPublicEncrypt: Error in setting up encrypt context for TPM_ES_RSAESPKCSv15\n"); + rc = TPM_FAIL; + } + } + break; + default: + if (rc == 0) { + printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); + rc = TPM_INAPPROPRIATE_ENC; + } + } + } + + if (rc == 0) { + outlen = encrypt_data_size; + if (EVP_PKEY_encrypt(ctx, encrypt_data, &outlen, + decrypt_data, decrypt_data_size) <= 0) { + printf("TPM_RSAPublicEncrypt: EVP_PKEY_encrypt failed\n"); + rc = TPM_ENCRYPT_ERROR; + } + } + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + TPM_Free(label); + + return rc; +} + +#endif // libtpms added end + +#if USE_FREEBL_CRYPTO_LIBRARY +/* TPM_RSAPublicEncryptRaw() does a raw public key operation without any padding. + +*/ + +TPM_RESULT TPM_RSAPublicEncryptRaw(unsigned char *encrypt_data, /* output */ + uint32_t encrypt_data_size, /* input, size of message buffer */ + unsigned char *decrypt_data, /* input */ + uint32_t decrypt_data_size, /* input, size of sig buffer */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + int irc; + RSA *rsa_pub_key = NULL; + + printf(" TPM_RSAPublicEncryptRaw:\n"); + /* the input data size must equal the public key size */ + if (rc == 0) { + if (decrypt_data_size != nbytes) { + printf("TPM_RSAPublicEncryptRaw: Error, decrypt data size is %u not %u\n", + decrypt_data_size, nbytes); + rc = TPM_ENCRYPT_ERROR; + } + } + /* the output data size must equal the public key size */ + if (rc == 0) { + if (encrypt_data_size != nbytes) { + printf("TPM_RSAPublicEncryptRaw: Error, Encrypted data size is %u not %u\n", + encrypt_data_size, nbytes); + rc = TPM_ENCRYPT_ERROR; + } + } + /* construct the OpenSSL public key object */ + if (rc == 0) { + rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Public modulus", narr); + TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Public exponent", earr, ebytes); + TPM_PrintFourLimit(" TPM_RSAPublicEncryptRaw: Decrypt data", decrypt_data, decrypt_data_size); + /* encrypt the decrypt_data */ + irc = RSA_public_encrypt(decrypt_data_size, /* from length */ + decrypt_data, /* from - the clear text data */ + encrypt_data, /* to - the padded and encrypted data */ + rsa_pub_key, /* key */ + RSA_NO_PADDING); /* padding */ + if (irc < 0) { + printf("TPM_RSAPublicEncryptRaw: Error in RSA_public_encrypt()\n"); + rc = TPM_ENCRYPT_ERROR; + } + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Encrypt data", encrypt_data); +#if 0 /* NOTE: Uncomment as a debug aid for signature verification */ + TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Padded signed data", + encrypt_data, encrypt_data_size); +#endif + } + if (rsa_pub_key != NULL) { + RSA_free(rsa_pub_key); /* @1 */ + } + return rc; +} +#endif + +/* TPM_RSASign() signs 'message' of size 'message_size' using the private key n,e,d and the + signature scheme 'sigScheme' as specified in PKCS #1 v2.0. + + 'signature_length' bytes are moved to 'signature'. 'signature_length' is at most + 'signature_size'. signature must point to RSA_size(rsa) bytes of memory. +*/ +/* Note regarding conversion to EVP_PKEY_sign for the purpose of constant-timeness: + + - TPM_SS_RSASSAPKCS1v15_SHA1: + EVP_PKEY_sign() will call pkey_rsa_sign() which in turn will call RSA_sign() for + RSA_PKCS1_PADDING. This is the same as we do here. + - TPM_SS_RSASSAPKCS1v15_DER: + EVP_PKEY_sign() must not have a message digest since none of the padding choices calls + RSA_padding_add_PKCS1_type_1(), so we would have to do the padding again ourselves. +*/ + +TPM_RESULT TPM_RSASign(unsigned char *signature, /* output */ + unsigned int *signature_length, /* output, size of signature */ + unsigned int signature_size, /* input, size of signature buffer */ + TPM_SIG_SCHEME sigScheme, /* input, type of signature */ + const unsigned char *message, /* input */ + size_t message_size, /* input */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + RSA * rsa_pri_key = NULL; /* freed @1 */ + unsigned int key_size; + + printf(" TPM_RSASign:\n"); + /* construct the OpenSSL private key object */ + if (rc == 0) { + rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + darr, /* private exponent */ + dbytes); + } + /* check the size of the output signature buffer */ + if (rc == 0) { + key_size = (unsigned int)RSA_size(rsa_pri_key); /* openSSL returns an int, but never + negative */ + if (signature_size < key_size) { + printf("TPM_RSASign: Error (fatal), buffer %u too small for signature %u\n", + signature_size, key_size); + rc = TPM_FAIL; /* internal error, should never occur */ + } + } + /* determine the signature scheme for the key */ + if (rc == 0) { + switch(sigScheme) { + case TPM_SS_NONE: + printf("TPM_RSASign: Error, sigScheme TPM_SS_NONE\n"); + rc = TPM_INVALID_KEYUSAGE; + break; + case TPM_SS_RSASSAPKCS1v15_SHA1: + case TPM_SS_RSASSAPKCS1v15_INFO: + rc = TPM_RSASignSHA1(signature, + signature_length, + message, + message_size, + rsa_pri_key); + break; + case TPM_SS_RSASSAPKCS1v15_DER: + rc = TPM_RSASignDER(signature, + signature_length, + message, + message_size, + rsa_pri_key); + break; + default: + printf("TPM_RSASign: Error, sigScheme %04hx unknown\n", sigScheme); + rc = TPM_INVALID_KEYUSAGE; + break; + } + } + if (rsa_pri_key != NULL) { + RSA_free(rsa_pri_key); /* @1 */ + } + return rc; +} + +/* TPM_RSASignSHA1() performs the following: + prepend a DER encoded algorithm ID + prepend a type 1 pad + encrypt with the private key +*/ + +static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, /* output */ + unsigned int *signature_length, /* output, size of signature */ + const unsigned char *message, /* input */ + size_t message_size, /* input */ + RSA *rsa_pri_key) /* signing private key */ +{ + TPM_RESULT rc = 0; + int irc; + + printf(" TPM_RSASignSHA1:\n"); + /* sanity check, SHA1 messages must be 20 bytes */ + if (rc == 0) { + if (message_size != TPM_DIGEST_SIZE) { + printf("TPM_RSASignSHA1: Error, message size %lu not TPM_DIGEST_SIZE\n", + (unsigned long)message_size ); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + /* type NID_sha1, adds the algorithm identifier and type 1 pad */ + irc = RSA_sign(NID_sha1, /* type */ + message, message_size, + signature, signature_length, + rsa_pri_key); + /* RSA_sign() returns 1 on success, 0 otherwise. */ + if (irc != 1) { + printf("TPM_RSASignSHA1: Error in RSA_sign()\n"); + rc = TPM_DECRYPT_ERROR; + } + } + return rc; +} + +/* TPM_RSASignDER() performs the following: + + prepend a type 1 pad + encrypt with the private key + + The caller must check that the signature buffer is >= the key size. +*/ + +static TPM_RESULT TPM_RSASignDER(unsigned char *signature, /* output */ + unsigned int *signature_length, /* output, size of signature */ + const unsigned char *message, /* input */ + size_t message_size, /* input */ + RSA *rsa_pri_key) /* signing private key */ +{ + TPM_RESULT rc = 0; + int irc; + int key_size; + unsigned char *message_pad; + int int_sig_len; /* openSSL overloads RSA_private_decrypt return code */ + + printf(" TPM_RSASignDER:\n"); + message_pad = NULL; /* freed @1 */ + /* the padded message size is the same as the key size */ + if (rc == 0) { + key_size = RSA_size(rsa_pri_key); + if (key_size < 0) { + printf(" TPM_RSASignDER: Error (fatal), negative key size %d\n", key_size); + rc = TPM_FAIL; /* should never occur */ + } + } + /* allocate memory for the padded message */ + if (rc == 0) { + printf(" TPM_RSASignDER: key size %d\n", key_size); + rc = TPM_Malloc(&message_pad, key_size); /* freed @1 */ + } + /* PKCS1 type 1 pad the message */ + if (rc == 0) { + printf(" TPM_RSASignDER: Applying PKCS1 type 1 padding, size from %lu to %u\n", + (unsigned long)message_size, key_size); + TPM_PrintFourLimit(" TPM_RSASignDER: Input message", message, message_size); + /* This call checks that the message will fit with the padding */ + irc = RSA_padding_add_PKCS1_type_1(message_pad, /* to */ + key_size, + message, /* from */ + message_size); + if (irc != 1) { + printf("TPM_RSASignDER: Error padding message, size %lu key size %u\n", + (unsigned long)message_size, key_size); + rc = TPM_DECRYPT_ERROR; + } + } + /* raw sign with private key */ + if (rc == 0) { + printf(" TPM_RSASignDER: Encrypting with private key, message size %d\n", key_size); + TPM_PrintFour(" TPM_RSASignDER: Padded message", message_pad); + /* returns the size of the encrypted data. On error, -1 is returned */ + int_sig_len = RSA_private_encrypt(key_size, /* int flen */ + message_pad, /* unsigned char *from, */ + signature, /* unsigned char *to, */ + rsa_pri_key, /* RSA *rsa, */ + RSA_NO_PADDING); /* int padding); */ + if (int_sig_len >= 0) { + *signature_length = (unsigned int)int_sig_len; + } + else { + printf("TPM_RSASignDER: Error in RSA_private_encrypt()\n"); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSASignDER: signature", signature); + } + free(message_pad); /* @1 */ + return rc; +} + +/* TPM_RSAVerifySHA1() performs the following: + decrypt the signature + verify and remove type 1 pad + verify and remove DER encoded algorithm ID + verify the signature on the message +*/ + +TPM_RESULT TPM_RSAVerifySHA1(unsigned char *signature, /* input */ + unsigned int signature_size, /* input, size of signature + buffer */ + const unsigned char *message, /* input */ + uint32_t message_size, /* input */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + TPM_BOOL valid; + RSA * rsa_pub_key = NULL; + + printf(" TPM_RSAVerifySHA1:\n"); + /* construct the openSSL public key object from n and e */ + if (rc == 0) { + rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + if (rc == 0) { + /* RSA_verify() returns 1 on successful verification, 0 otherwise. */ + valid = RSA_verify(NID_sha1, + message, message_size, + signature, signature_size, rsa_pub_key); + if (valid != 1) { + printf("TPM_RSAVerifySHA1: Error, bad signature\n"); + rc = TPM_BAD_SIGNATURE; + } + } + if (rsa_pub_key != NULL) { + RSA_free(rsa_pub_key); /* @1 */ + } + return rc; +} + +/* TPM_RSAGetPrivateKey recalculates q (2nd prime factor) and d (private key) from n (public key), e + (public exponent), and p (1st prime factor) + + The private key is validated by dividing the RSA product n by the RSA prime p and verifying that + the remainder is 0. + + 'qarr', darr' must be freed by the caller. +*/ + +TPM_RESULT TPM_RSAGetPrivateKey(uint32_t *qbytes, unsigned char **qarr, + uint32_t *dbytes, unsigned char **darr, + uint32_t nbytes, unsigned char *narr, + uint32_t ebytes, unsigned char *earr, + uint32_t pbytes, unsigned char *parr) +{ + TPM_RESULT rc = 0; /* TPM return code */ + int irc; /* openSSL return code */ + BIGNUM *brc; /* BIGNUM return code */ + + BIGNUM *n = NULL; /* public modulus */ + BIGNUM *e = NULL; /* public exponent */ + BIGNUM *d = NULL; /* private exponent */ + BIGNUM *p = NULL; /* secret prime factor */ + BIGNUM *q = NULL; /* secret prime factor */ + /* temporary variables */ + BN_CTX *ctx = NULL; /* freed @5, @6 */ + BIGNUM *r0 = NULL; /* n/p remainder */ + BIGNUM *r1 = NULL; + BIGNUM *r2 = NULL; + + /* set to NULL so caller can free after failure */ + printf(" TPM_RSAGetPrivateKey:\n"); + *qarr = NULL; + *darr = NULL; + /* check input parameters */ + if (rc == 0) { + if ((narr == NULL) || (nbytes == 0)) { + printf("TPM_RSAGetPrivateKey: Error, missing n\n"); + rc = TPM_BAD_PARAMETER; + } + } + /* check input parameters */ + if (rc == 0) { + if ((earr == NULL) || (ebytes == 0)) { + printf("TPM_RSAGetPrivateKey: Error, missing e\n"); + rc = TPM_BAD_PARAMETER; + } + } + /* check input parameters */ + if (rc == 0) { + if ((parr == NULL) || (pbytes == 0)) { + printf("TPM_RSAGetPrivateKey: Error, missing p\n"); + rc = TPM_BAD_PARAMETER; + } + } + /* get some temporary BIGNUM's for use in the calculations */ + if (rc == 0) { + rc = TPM_BN_CTX_new(&ctx); + } + if (rc == 0) { + BN_CTX_start(ctx); /* no return code */ + r0 = BN_CTX_get(ctx); /* sufficient to test return of last 'get' call */ + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + if (r2 == 0) { + printf("TPM_RSAGetPrivateKey: Error in BN_CTX_get()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_SIZE; + } + } + /* allocate BIGNUM's for q, d */ + if (rc == 0) { + rc = TPM_BN_new((TPM_BIGNUM *)&q); + } + if (rc == 0) { + rc = TPM_BN_new((TPM_BIGNUM *)&d); + } + /* convert n, e, p to BIGNUM's */ + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed @1 */ + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed @2 */ + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&p, parr, pbytes); /* freed @3 */ + if (p) + BN_set_flags(p, BN_FLG_CONSTTIME); // p is private + } + /* calculate q = n/p */ + if (rc == 0) { + irc = BN_div(q, r0, n, p, ctx); /* q = n/p freed @4 */ + if (irc != 1) { /* 1 is success */ + printf("TPM_RSAGetPrivateKey: Error in BN_div()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_BAD_PARAMETER; + } else + BN_set_flags(q, BN_FLG_CONSTTIME); // q is private + } + /* remainder should be zero */ + if (rc == 0) { + irc = BN_is_zero(r0); + if (irc != 1) { /* 1 is success */ + printf("TPM_RSAGetPrivateKey: Error in BN_is_zero()\n"); + rc = TPM_BAD_PARAMETER; + } + } + /* calculate r0 = p-1 */ + if (rc == 0) { + irc = BN_sub(r0, p, BN_value_one()); /* r0 = p-1 freed @6 */ + if (irc != 1) { /* 1 is success */ + printf("TPM_RSAGetPrivateKey: Error in BN_sub()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_BAD_PARAMETER; + } + } + /* calculate r1 = q-1 */ + if (rc == 0) { + irc = BN_sub(r1, q, BN_value_one()); /* freed @6 */ + if (irc != 1) { /* 1 is success */ + printf("TPM_RSAGetPrivateKey: Error in BN_sub()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_BAD_PARAMETER; + } + } + /* calculate r2 = (p-1)(q-1) */ + if (rc == 0) { + irc = BN_mul(r2, r0, r1, ctx); /* freed @6 */ + if (irc != 1) { /* 1 is success */ + printf("TPM_RSAGetPrivateKey: Error in BN_mul()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_BAD_PARAMETER; + } else + BN_set_flags(r2, BN_FLG_CONSTTIME); // r2 is private + } + /* calculate d = multiplicative inverse e mod r0 */ + if (rc == 0) { + brc = BN_mod_inverse(d, e, r2, ctx); /* feed @5 */ + if (brc == NULL) { + printf("TPM_RSAGetPrivateKey: Error in BN_mod_inverse()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_BAD_PARAMETER; + } + } + /* get q as an array */ + if (rc == 0) { + rc = TPM_bn2binMalloc(qarr, qbytes, (TPM_BIGNUM)q, pbytes); /* freed by caller */ + } + /* get d as an array */ + if (rc == 0) { + TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated q", *qarr); + rc = TPM_bn2binMalloc(darr, dbytes, (TPM_BIGNUM)d, nbytes); /* freed by caller */ + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated d", *darr); + printf(" TPM_RSAGetPrivateKey: length of n,p,q,d = %u / %u / %u / %u\n", + nbytes, pbytes, *qbytes, *dbytes); + } + BN_free(n); /* @1 */ + BN_free(e); /* @2 */ + BN_free(p); /* @3 */ + BN_free(q); /* @4 */ + BN_free(d); /* @3 */ + BN_CTX_end(ctx); /* @5 */ + BN_CTX_free(ctx); /* @6 */ + return rc; +} + +/* + openSSL wrappers do error logging and transformation of openSSL errors to TPM type errors +*/ + +/* TPM_OpenSSL_PrintError() prints a detailed openSSL error trace. + +*/ + +static void TPM_OpenSSL_PrintError() +{ + /* openssl error printing */ + unsigned long error; + const char *file; + int line; + const char *data; + int flags; + + error = ERR_get_error_line_data(&file, &line, &data, &flags); + printf("\terror %08lx file %s line %d data %s flags %08x\n", + error, file, line, data, flags); + return; +} + +/* TPM_BN_num_bytes() wraps the openSSL function in a TPM error handler + + Returns number of bytes in the input +*/ + +TPM_RESULT TPM_BN_num_bytes(unsigned int *numBytes, TPM_BIGNUM bn_in) +{ + TPM_RESULT rc = 0; + int i; + BIGNUM *bn = (BIGNUM *)bn_in; + + i = BN_num_bytes(bn); + if (i >= 0) { + *numBytes = (unsigned int)i; + } + else { + printf("TPM_BN_num_bytes: Error (fatal), bytes in BIGNUM is negative\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_FAIL; + } + return rc; +} + +/* TPM_BN_is_one() wraps the openSSL function in a TPM error handler + + Returns success if input is 1 + */ + +TPM_RESULT TPM_BN_is_one(TPM_BIGNUM bn_in) +{ + TPM_RESULT rc = 0; + int irc; + BIGNUM *bn = (BIGNUM *)bn_in; + + /* int BN_is_one(BIGNUM *a); + BN_is_one() tests if a equals 0, 1, + BN_is_one() returns 1 if the condition is true, 0 otherwise. */ + irc = BN_is_one(bn); + if (irc != 1) { + printf("TPM_BN_is_one: Error, result is not 1\n"); + rc = TPM_DAA_WRONG_W; + } + return rc; +} + +/* TPM_BN_mod() wraps the openSSL function in a TPM error handler + + r = a mod m + */ + +TPM_RESULT TPM_BN_mod(TPM_BIGNUM rem_in, + const TPM_BIGNUM a_in, + const TPM_BIGNUM m_in) +{ + TPM_RESULT rc = 0; + int irc; + BIGNUM *rem = (BIGNUM *)rem_in; + BIGNUM *a = (BIGNUM *)a_in; + BIGNUM *m = (BIGNUM *)m_in; + BN_CTX *ctx = NULL; /* freed @1 */ + + if (rc == 0) { + rc = TPM_BN_CTX_new(&ctx); /* freed @1 */ + } + /*int BN_mod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); + BN_mod() corresponds to BN_div() with dv set to NULL. + + int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d, BN_CTX *ctx); + + BN_div() divides a by d and places the result in dv and the remainder in rem (dv=a/d, + rem=a%d). Either of dv and rem may be NULL, in which case the respective value is not + returned. The result is rounded towards zero; thus if a is negative, the remainder will be + zero or negative. For division by powers of 2, use BN_rshift(3). + + For all functions, 1 is returned for success, 0 on error. The return value should always be + checked + */ + irc = BN_mod(rem, a, m, ctx); + if (irc != 1) { + printf("TPM_BN_mod: Error performing BN_mod()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + BN_CTX_free(ctx); /* @1 */ + return rc; +} + +/* TPM_BN_mask_bits() wraps the openSSL function in a TPM error handler + + erase all but the lowest n bits of bn + bn = bn mod 2^^n +*/ + +TPM_RESULT TPM_BN_mask_bits(TPM_BIGNUM bn_in, unsigned int n) +{ + TPM_RESULT rc = 0; + int irc; + unsigned int numBytes; + BIGNUM *bn = (BIGNUM *)bn_in; + + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, bn_in); + } + /* if the BIGNUM is already the correct number of bytes, no need to mask, and BN_mask_bits() + will fail. */ + if (rc == 0) { + if (numBytes > (n / 8)) { + /* BN_mask_bits() truncates a to an n bit number (a&=~((~0)>>;n)). An error occurs if a + already is shorter than n bits. + + int BN_mask_bits(BIGNUM *a, int n); + return 1 for success, 0 on error. + */ + irc = BN_mask_bits(bn, n); + if (irc != 1) { + printf("TPM_BN_mask_bits: Error performing BN_mask_bits()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + } + } + return rc; +} + +/* TPM_BN_rshift() wraps the openSSL function in a TPM error handler + + Shift a right by n bits (discard the lowest n bits) and label the result r +*/ + +TPM_RESULT TPM_BN_rshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ + TPM_BIGNUM aBignum_in, + int n) +{ + TPM_RESULT rc = 0; + int irc; + BIGNUM **rBignum = (BIGNUM **)rBignum_in; + BIGNUM *aBignum = (BIGNUM *)aBignum_in; + + printf(" TPM_BN_rshift: n %d\n", n); + if (rc == 0) { + rc = TPM_BN_new(rBignum_in); + } + if (rc == 0) { + /* BN_rshift() shifts a right by n bits and places the result in r (r=a/2^n). + int BN_rshift(BIGNUM *r, BIGNUM *a, int n); + return 1 for success, 0 on error. + */ + irc = BN_rshift(*rBignum, aBignum, n); + if (irc != 1) { + printf("TPM_BN_rshift: Error performing BN_rshift()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + } + return rc; +} + +/* TPM_BN_lshift() wraps the openSSL function in a TPM error handler + + Shift a left by n bits and label the result r +*/ + +TPM_RESULT TPM_BN_lshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ + TPM_BIGNUM aBignum_in, + int n) +{ + TPM_RESULT rc = 0; + int irc; + BIGNUM **rBignum = (BIGNUM **)rBignum_in; + BIGNUM *aBignum = (BIGNUM *)aBignum_in; + + printf(" TPM_BN_lshift: n %d\n", n); + if (rc == 0) { + rc = TPM_BN_new(rBignum_in); + } + if (rc == 0) { + /* BN_lshift() shifts a left by n bits and places the result in r (r=a*2^n). + int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); + return 1 for success, 0 on error. + */ + irc = BN_lshift(*rBignum, aBignum, n); + if (irc != 1) { + printf("TPM_lshift: Error performing BN_lshift()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + } + return rc; +} + +/* TPM_BN_add() wraps the openSSL function in a TPM error handler + + Performs R = A + B + + R may be the same as A or B +*/ + +TPM_RESULT TPM_BN_add(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in) +{ + TPM_RESULT rc = 0; + int irc; + BIGNUM *rBignum = (BIGNUM *)rBignum_in; + BIGNUM *aBignum = (BIGNUM *)aBignum_in; + BIGNUM *bBignum = (BIGNUM *)bBignum_in; + + printf(" TPM_BN_add:\n"); + /* int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + BN_add() adds a and b and places the result in r (r=a+b). r may be the same BIGNUM as a or b. + 1 is returned for success, 0 on error. + */ + irc = BN_add(rBignum, aBignum, bBignum); + if (irc != 1) { + printf("TPM_BN_add: Error performing BN_add()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + return rc; +} + +/* TPM_BN_mul() wraps the openSSL function in a TPM error handler + + r = a * b +*/ + +TPM_RESULT TPM_BN_mul(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in) +{ + TPM_RESULT rc = 0; + int irc; + BN_CTX *ctx; + BIGNUM *rBignum = (BIGNUM *)rBignum_in; + BIGNUM *aBignum = (BIGNUM *)aBignum_in; + BIGNUM *bBignum = (BIGNUM *)bBignum_in; + + printf(" TPM_BN_mul:\n"); + ctx = NULL; /* freed @1 */ + if (rc == 0) { + rc = TPM_BN_CTX_new(&ctx); /* freed @1 */ + } + /* int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); + BN_mul() multiplies a and b and places the result in r (r=a*b). r may be the same BIGNUM as a + or b. + 1 is returned for success, 0 on error. + */ + if (rc == 0) { + irc = BN_mul(rBignum, aBignum, bBignum, ctx); + if (irc != 1) { + printf("TPM_BN_add: Error performing BN_mul()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + } + BN_CTX_free(ctx); /* @1 */ + return rc; +} + +/* TPM_BN_mod_exp() wraps the openSSL function in a TPM error handler + + computes a to the p-th power modulo m (r=a^p % n) +*/ + +TPM_RESULT TPM_BN_mod_exp(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM pBignum_in, + TPM_BIGNUM nBignum_in) +{ + TPM_RESULT rc = 0; + int irc; + BN_CTX *ctx; + BIGNUM *rBignum = (BIGNUM *)rBignum_in; + BIGNUM *aBignum = (BIGNUM *)aBignum_in; + BIGNUM *pBignum = (BIGNUM *)pBignum_in; + BIGNUM *nBignum = (BIGNUM *)nBignum_in; + + printf(" TPM_BN_mod_exp:\n"); + ctx = NULL; /* freed @1 */ + if (rc == 0) { + rc = TPM_BN_CTX_new(&ctx); + } + /* BIGNUM calculation */ + /* int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx); + + BN_mod_exp() computes a to the p-th power modulo m (r=a^p % m). This function uses less time + and space than BN_exp(). + + 1 is returned for success, 0 on error. + */ + if (rc == 0) { + printf(" TPM_BN_mod_exp: Calculate mod_exp\n"); + BN_set_flags(pBignum, BN_FLG_CONSTTIME); // p may be private + irc = BN_mod_exp(rBignum, aBignum, pBignum, nBignum, ctx); + if (irc != 1) { + printf("TPM_BN_mod_exp: Error performing BN_mod_exp()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + } + BN_CTX_free(ctx); /* @1 */ + return rc; +} + +/* TPM_BN_Mod_add() wraps the openSSL function in a TPM error handler + + adds a to b modulo m +*/ + +TPM_RESULT TPM_BN_mod_add(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in, + TPM_BIGNUM mBignum_in) +{ + TPM_RESULT rc = 0; + int irc; + BN_CTX *ctx; + BIGNUM *rBignum = (BIGNUM *)rBignum_in; + BIGNUM *aBignum = (BIGNUM *)aBignum_in; + BIGNUM *bBignum = (BIGNUM *)bBignum_in; + BIGNUM *mBignum = (BIGNUM *)mBignum_in; + + printf(" TPM_BN_mod_add:\n"); + ctx = NULL; /* freed @1 */ + if (rc == 0) { + rc = TPM_BN_CTX_new(&ctx); + } + /* int BN_mod_add(BIGNUM *r, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); + BN_mod_add() adds a to b modulo m and places the non-negative result in r. + 1 is returned for success, 0 on error. + */ + if (rc == 0) { + irc = BN_mod_add(rBignum, aBignum, bBignum, mBignum, ctx); + if (irc != 1) { + printf("TPM_BN_mod_add: Error performing BN_mod_add()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + } + + BN_CTX_free(ctx); /* @1 */ + return rc; +} + +/* TPM_BN_mod_mul() wraps the openSSL function in a TPM error handler + + r = (a * b) mod m + */ + +TPM_RESULT TPM_BN_mod_mul(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in, + TPM_BIGNUM mBignum_in) +{ + TPM_RESULT rc = 0; + int irc; + BN_CTX *ctx; + BIGNUM *rBignum = (BIGNUM *)rBignum_in; + BIGNUM *aBignum = (BIGNUM *)aBignum_in; + BIGNUM *bBignum = (BIGNUM *)bBignum_in; + BIGNUM *mBignum = (BIGNUM *)mBignum_in; + + printf(" TPM_BN_mod_mul:\n"); + ctx = NULL; /* freed @1 */ + if (rc == 0) { + rc = TPM_BN_CTX_new(&ctx); + } + /* int BN_mod_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); + BN_mod_mul() multiplies a by b and finds the non-negative remainder respective to modulus m + (r=(a*b) mod m). r may be the same BIGNUM as a or b. + 1 is returned for success, 0 on error. + */ + if (rc == 0) { + irc = BN_mod_mul(rBignum, aBignum, bBignum, mBignum, ctx); + if (irc != 1) { + printf("TPM_BN_mod_mul: Error performing BN_mod_mul()\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_DAA_WRONG_W; + } + } + BN_CTX_free(ctx); /* @1 */ + return rc; +} + +/* TPM_BN_CTX_new() wraps the openSSL function in a TPM error handler */ + +static TPM_RESULT TPM_BN_CTX_new(BN_CTX **ctx) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + if (*ctx != NULL) { + printf("TPM_BN_CTX_new: Error (fatal), *ctx %p should be NULL before BN_CTX_new \n", + *ctx); + rc = TPM_FAIL; + } + } + if (rc == 0) { + *ctx = BN_CTX_new(); + if (*ctx == NULL) { + printf("TPM_BN_CTX_new: Error, context is NULL\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_SIZE; + + } + } + return rc; +} + +/* TPM_BN_new() wraps the openSSL function in a TPM error handler + + Allocates a new bignum +*/ + +TPM_RESULT TPM_BN_new(TPM_BIGNUM *bn_in) +{ + TPM_RESULT rc = 0; + BIGNUM **bn = (BIGNUM **)bn_in; + + *bn = BN_new(); + if (*bn == NULL) { + printf("TPM_BN_new: Error, bn is NULL\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_SIZE; + } + return rc; +} + +/* TPM_BN_free() wraps the openSSL function + + Frees the bignum +*/ + +void TPM_BN_free(TPM_BIGNUM bn_in) +{ + BIGNUM *bn = (BIGNUM *)bn_in; + + BN_free(bn); + return; +} + +/* TPM_bn2bin wraps the openSSL function in a TPM error handler. + + Converts a bignum to char array + + 'bin' must already be checked for sufficient size. + + int BN_bn2bin(const BIGNUM *a, unsigned char *to); + BN_bn2bin() returns the length of the big-endian number placed at to +*/ + +TPM_RESULT TPM_bn2bin(unsigned char *bin, + TPM_BIGNUM bn_in) +{ + TPM_RESULT rc = 0; + BN_bn2bin((BIGNUM *)bn_in, bin); + return rc; +} + + +/* TPM_bin2bn() wraps the openSSL function in a TPM error handler + + Converts a char array to bignum + + bn must be freed by the caller. +*/ + +TPM_RESULT TPM_bin2bn(TPM_BIGNUM *bn_in, const unsigned char *bin, unsigned int bytes) +{ + TPM_RESULT rc = 0; + BIGNUM **bn = (BIGNUM **)bn_in; + + /* BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); + + BN_bin2bn() converts the positive integer in big-endian form of length len at s into a BIGNUM + and places it in ret. If ret is NULL, a new BIGNUM is created. + + BN_bin2bn() returns the BIGNUM, NULL on error. + */ + if (rc == 0) { + *bn = BN_bin2bn(bin, bytes, *bn); + if (*bn == NULL) { + printf("TPM_bin2bn: Error in BN_bin2bn\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_SIZE; + } + } + return rc; +} + +/* + Hash Functions +*/ + +/* for the openSSL version, TPM_SHA1Context is a SHA_CTX structure */ + +/* TPM_SHA1InitCmd() initializes a platform dependent TPM_SHA1Context structure. + + The structure must be freed using TPM_SHA1Delete() +*/ + +TPM_RESULT TPM_SHA1InitCmd(void **context) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SHA1InitCmd:\n"); + if (rc== 0) { + rc = TPM_Malloc((unsigned char **)context, sizeof(SHA_CTX)); + } + if (rc== 0) { + SHA1_Init(*context); + } + return rc; +} + +/* TPM_SHA1UpdateCmd() adds 'data' of 'length' to the SHA-1 context + */ + +TPM_RESULT TPM_SHA1UpdateCmd(void *context, const unsigned char *data, uint32_t length) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SHA1Update: length %u\n", length); + if (context != NULL) { + SHA1_Update(context, data, length); + } + else { + printf("TPM_SHA1Update: Error, no existing SHA1 thread\n"); + rc = TPM_SHA_THREAD; + } + return rc; +} + +/* TPM_SHA1FinalCmd() extracts the SHA-1 digest 'md' from the context + */ + +TPM_RESULT TPM_SHA1FinalCmd(unsigned char *md, void *context) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SHA1FinalCmd:\n"); + if (context != NULL) { + SHA1_Final(md, context); + } + else { + printf("TPM_SHA1FinalCmd: Error, no existing SHA1 thread\n"); + rc = TPM_SHA_THREAD; + } + return rc; +} + +/* TPM_SHA1Delete() zeros and frees the SHA1 context */ + +void TPM_SHA1Delete(void **context) +{ + if (*context != NULL) { + printf(" TPM_SHA1Delete:\n"); + /* zero because the SHA1 context might have data left from an HMAC */ + memset(*context, 0, sizeof(SHA_CTX)); + free(*context); + *context = NULL; + } + return; +} + +/* TPM_Sha1Context_Load() is non-portable code to deserialize the OpenSSL SHA1 context. + + If the contextPresent prepended by TPM_Sha1Context_Store() is FALSE, context remains NULL. If + TRUE, context is allocated and loaded. +*/ + +TPM_RESULT TPM_Sha1Context_Load(void **context, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + SHA_CTX *sha_ctx = NULL; /* initialize to silence hopefully bogus gcc 4.4.4 + warning */ + TPM_BOOL contextPresent; /* is there a context to be loaded */ + + printf(" TPM_Sha1Context_Load: OpenSSL\n"); + /* TPM_Sha1Context_Store() stored a flag to indicate whether a context should be stored */ + if (rc== 0) { + rc = TPM_LoadBool(&contextPresent, stream, stream_size); + printf(" TPM_Sha1Context_Load: contextPresent %u\n", contextPresent); + } + /* check format tag */ + /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' + on the tag */ + if ((rc== 0) && contextPresent) { + rc = TPM_CheckTag(TPM_TAG_SHA1CONTEXT_OSSL_V1, stream, stream_size); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Malloc((unsigned char **)context, sizeof(SHA_CTX)); + sha_ctx = (SHA_CTX *)*context; + } + /* load h0 */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&(sha_ctx->h0), stream, stream_size); + } + /* load h1 */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&(sha_ctx->h1), stream, stream_size); + } + /* load h2 */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&(sha_ctx->h2), stream, stream_size); + } + /* load h3 */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&(sha_ctx->h3), stream, stream_size); + } + /* load h4 */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&(sha_ctx->h4), stream, stream_size); + } + /* load Nl */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&(sha_ctx->Nl), stream, stream_size); + } + /* load Nh */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&(sha_ctx->Nh), stream, stream_size); + } + /* load data */ + for (i = 0 ; (rc == 0) && contextPresent && (i < SHA_LBLOCK) ; i++) { + rc = TPM_Load32(&(sha_ctx->data[i]), stream, stream_size); + } + /* load num */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&(sha_ctx->num), stream, stream_size); + } + return rc; +} + +/* TPM_Sha1Context_Store() is non-portable code to serialize the OpenSSL SHA1 context. context is + not altered. + + It prepends a contextPresent flag to the stream, FALSE if context is NULL, TRUE if not. +*/ + +TPM_RESULT TPM_Sha1Context_Store(TPM_STORE_BUFFER *sbuffer, + void *context) +{ + TPM_RESULT rc = 0; + size_t i; + SHA_CTX *sha_ctx = (SHA_CTX *)context; + TPM_BOOL contextPresent; /* is there a context to be stored */ + + printf(" TPM_Sha1Context_Store: OpenSSL\n"); + /* store contextPresent */ + if (rc == 0) { + if (sha_ctx != NULL) { + printf(" TPM_Sha1Context_Store: Storing context\n"); + contextPresent = TRUE; + } + else { + printf(" TPM_Sha1Context_Store: No context to store\n"); + contextPresent = FALSE; + } + rc = TPM_Sbuffer_Append(sbuffer, &contextPresent, sizeof(TPM_BOOL)); + } + /* overall format tag */ + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SHA1CONTEXT_OSSL_V1); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h0); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h1); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h2); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h3); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h4); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->Nl); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->Nh); + } + for (i = 0 ; (rc == 0) && contextPresent && (i < SHA_LBLOCK) ; i++) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->data[i]); + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->num); + } + return rc; +} + +/* + TPM_SYMMETRIC_KEY_DATA +*/ + +/* TPM_SymmetricKeyData_New() allocates memory for and initializes a TPM_SYMMETRIC_KEY_DATA token. + */ + +TPM_RESULT TPM_SymmetricKeyData_New(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SymmetricKeyData_New:\n"); + if (rc == 0) { + rc = TPM_Malloc(tpm_symmetric_key_data, sizeof(TPM_SYMMETRIC_KEY_DATA)); + } + if (rc == 0) { + TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); + } + return rc; +} + +/* TPM_SymmetricKeyData_Free() initializes the key token to wipe secrets. It then frees the + TPM_SYMMETRIC_KEY_DATA token and sets it to NULL. +*/ + +void TPM_SymmetricKeyData_Free(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) +{ + printf(" TPM_SymmetricKeyData_Free:\n"); + if (*tpm_symmetric_key_data != NULL) { + TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); + free(*tpm_symmetric_key_data); + *tpm_symmetric_key_data = NULL; + } + return; +} + +#ifdef TPM_DES + +/* TPM_SymmetricKeyData_Init() is DES non-portable code to initialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Init:\n"); + tpm_symmetric_key_data->tag = TPM_TAG_KEY; + tpm_symmetric_key_data->valid = FALSE; + tpm_symmetric_key_data->fill = 0; + memset(tpm_symmetric_key_data->des_cblock1, 0, sizeof(DES_cblock)); + memset(tpm_symmetric_key_data->des_cblock2, 0, sizeof(DES_cblock)); + memset(tpm_symmetric_key_data->des_cblock3, 0, sizeof(DES_cblock)); + return; +} + +/* TPM_SymmetricKeyData_Load() is DES non-portable code to deserialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_KEY, stream, stream_size); + } + /* load valid */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_symmetric_key_data->valid), stream, stream_size); + } + /* load fill */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_symmetric_key_data->fill), stream, stream_size); + } + /* this assumes that DES_cblock is a consistently packed structure. It is in fact an array of 8 + bytes for openSSL. */ + if (rc == 0) { + rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock1, sizeof(DES_cblock), + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock2, sizeof(DES_cblock), + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock3, sizeof(DES_cblock), + stream, stream_size); + } + if (rc == 0) { + TPM_PrintFour(" TPM_SymmetricKeyData_Load: des1", tpm_symmetric_key_data->des_cblock1); + TPM_PrintFour(" TPM_SymmetricKeyData_Load: des2", tpm_symmetric_key_data->des_cblock2); + TPM_PrintFour(" TPM_SymmetricKeyData_Load: des3", tpm_symmetric_key_data->des_cblock3); + } + return rc; +} + +/* TPM_SymmetricKeyData_Store() DES is non-portable code to serialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Store:\n"); + if (rc == 0) { + TPM_PrintFour(" TPM_SymmetricKeyData_Store: des1", tpm_symmetric_key_data->des_cblock1); + TPM_PrintFour(" TPM_SymmetricKeyData_Store: des2", tpm_symmetric_key_data->des_cblock2); + TPM_PrintFour(" TPM_SymmetricKeyData_Store: des3", tpm_symmetric_key_data->des_cblock3); + } + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key_data->tag); + } + /* store valid */s + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->valid), sizeof(TPM_BOOL)); + } + /* store fill */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->fill), sizeof(TPM_BOOL)); + } + /* store DES key */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock1, sizeof(DES_cblock)); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock2, sizeof(DES_cblock)); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock3, sizeof(DES_cblock)); + } + return rc; +} + +/* TPM_SymmetricKeyData_GenerateKey() is DES non-portable code to generate a symmetric key + + vsymmetric_key must be freed by the caller +*/ + +TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_GenerateKey:\n"); + /* generate a random key */ + if (rc == 0) { + DES_random_key(&(tpm_symmetric_key_data->des_cblock1)); + DES_random_key(&(tpm_symmetric_key_data->des_cblock2)); + DES_random_key(&(tpm_symmetric_key_data->des_cblock3)); + /* sets the parity of the passed key to odd. */ + DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock1)); + DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock2)); + DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock3)); + TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des1", + tpm_symmetric_key_data->des_cblock1); + TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des2", + tpm_symmetric_key_data->des_cblock2); + TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des3", + tpm_symmetric_key_data->des_cblock3); + tpm_symmetric_key_data->valid = TRUE; + } + return rc; +} + +/* TPM_SymmetricKeyData_Encrypt() is DES non-portable code to encrypt 'decrypt_data' to + 'encrypt_data' + + The stream is padded as per PKCS#7 / RFC2630 + + 'encrypt_data' must be free by the caller +*/ + +TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ + uint32_t *encrypt_length, /* output */ + const unsigned char *decrypt_data, /* input */ + uint32_t decrypt_length, /* input */ + const TPM_SYMMETRIC_KEY_TOKEN + tpm_symmetric_key_token) /* input */ +{ + TPM_RESULT rc = 0; + uint32_t pad_length; + unsigned char *decrypt_data_pad; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); + decrypt_data_pad = NULL; /* freed @1 */ + if (rc == 0) { + /* calculate the pad length and padded data length */ + pad_length = TPM_DES_BLOCK_SIZE - (decrypt_length % TPM_DES_BLOCK_SIZE); + *encrypt_length = decrypt_length + pad_length; + printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", + *encrypt_length, pad_length); + /* allocate memory for the encrypted response */ + rc = TPM_Malloc(encrypt_data, *encrypt_length); + } + /* allocate memory for the padded decrypted data */ + if (rc == 0) { + rc = TPM_Malloc(&decrypt_data_pad, *encrypt_length); + } + /* pad the decrypted clear text data */ + if (rc == 0) { + /* unpadded original data */ + memcpy(decrypt_data_pad, decrypt_data, decrypt_length); + /* last gets pad = pad length */ + memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); + /* encrypt the padded input to the output */ + rc = TPM_SymmetricKeyData_Crypt(*encrypt_data, + decrypt_data_pad, + *encrypt_length, + tpm_symmetric_key_data, + DES_ENCRYPT, + TPM_ENCRYPT_ERROR); + } + free(decrypt_data_pad); /* @1 */ + return rc; +} + +/* TPM_SymmetricKeyData_Decrypt() is DES non-portable code to decrypt 'encrypt_data' to + 'decrypt_data' + + The stream must be padded as per PKCS#7 / RFC2630 + + decrypt_data must be free by the caller +*/ + +TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ + uint32_t *decrypt_length, /* output */ + const unsigned char *encrypt_data, /* input */ + uint32_t encrypt_length, /* input */ + const TPM_SYMMETRIC_KEY_TOKEN + tpm_symmetric_key_data) /* input */ +{ + TPM_RESULT rc = 0; + uint32_t pad_length; + uint32_t i; + unsigned char *pad_data; + + printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); + /* sanity check encrypted length */ + if (rc == 0) { + if (encrypt_length < TPM_DES_BLOCK_SIZE) { + printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); + rc = TPM_DECRYPT_ERROR; + } + } + /* allocate memory for the padded decrypted data */ + if (rc == 0) { + rc = TPM_Malloc(decrypt_data, encrypt_length); + } + /* decrypt the input to the padded output */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_Crypt(*decrypt_data, + encrypt_data, + encrypt_length, + tpm_symmetric_key_data, + DES_DECRYPT, + TPM_DECRYPT_ERROR); + } + /* get the pad length */ + if (rc == 0) { + /* get the pad length from the last byte */ + pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); + /* sanity check the pad length */ + printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); + if ((pad_length == 0) || + (pad_length > TPM_DES_BLOCK_SIZE)) { + printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + /* get the unpadded length */ + *decrypt_length = encrypt_length - pad_length; + /* pad starting point */ + pad_data = *decrypt_data + *decrypt_length; + /* sanity check the pad */ + for (i = 0 ; i < pad_length ; i++, pad_data++) { + if (*pad_data != pad_length) { + printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", + *pad_data, i); + rc = TPM_DECRYPT_ERROR; + } + } + } + return rc; +} + +/* TPM_SymmetricKeyData_Crypt() is DES common code for openSSL, since encrypt and decrypt use the + same function with an 'enc' flag. + + 'data_in' and 'data_out' must be preallocated arrays of 'length' bytes. 'length' must be a + multiple of TPM_DES_BLOCK_SIZE. + + Returns 'error' on error. +*/ + +/* openSSL prototype + + void DES_ede3_cbc_encrypt(const unsigned char *input, + unsigned char *output, long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, DES_cblock *ivec, + int enc); +*/ + +static TPM_RESULT TPM_SymmetricKeyData_Crypt(unsigned char *data_out, /* output */ + const unsigned char *data_in, /* input */ + uint32_t length, /* input */ + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, /*in*/ + int enc, /* input */ + TPM_RESULT error) /* input */ +{ + TPM_RESULT rc = 0; + int irc; + DES_key_schedule des_key_schedule1; + DES_key_schedule des_key_schedule2; + DES_key_schedule des_key_schedule3; + DES_cblock ivec; /* initial chaining vector */ + + if (rc == 0) { + if ((length % TPM_DES_BLOCK_SIZE) != 0) { + printf("TPM_SymmetricKeyData_Crypt: Error, illegal length %u\n", length); + rc = error; /* should never occur */ + } + } + if (rc == 0) { + TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des1", tpm_symmetric_key_data->des_cblock1); + TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des2", tpm_symmetric_key_data->des_cblock2); + TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des3", tpm_symmetric_key_data->des_cblock3); + } + /* Before a DES key can be used, it must be converted into the architecture dependent + DES_key_schedule via the DES_set_key_checked() or DES_set_key_unchecked() function. */ + if (rc == 0) { + irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock1), &des_key_schedule1); + if (irc != 0) { + printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); + rc = error; + } + } + if (rc == 0) { + irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock2), &des_key_schedule2); + if (irc != 0) { + printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); + rc = error; + } + } + if (rc == 0) { + irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock3), &des_key_schedule3); + if (irc != 0) { + printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); + rc = error; + } + } + /* initialize initial chaining vector */ + if (rc == 0) { + TPM_PrintFourLimit(" TPM_SymmetricKeyData_Crypt: Input", data_in, length); + /* encrypt operation */ + memset(&ivec, 0, sizeof(DES_cblock)); + DES_ede3_cbc_encrypt(data_in, + data_out, + length, + &des_key_schedule1, + &des_key_schedule2, + &des_key_schedule3, + &ivec, + enc); + TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: Output", data_out); + } + return rc; +} + +#endif + +#ifdef TPM_AES + +/* TPM_SymmetricKeyData_Init() is AES non-portable code to initialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Init:\n"); + tpm_symmetric_key_data->tag = TPM_TAG_KEY; + tpm_symmetric_key_data->valid = FALSE; + tpm_symmetric_key_data->fill = 0; + memset(tpm_symmetric_key_data->userKey, 0, sizeof(tpm_symmetric_key_data->userKey)); + memset(&(tpm_symmetric_key_data->aes_enc_key), 0, sizeof(tpm_symmetric_key_data->aes_enc_key)); + memset(&(tpm_symmetric_key_data->aes_dec_key), 0, sizeof(tpm_symmetric_key_data->aes_dec_key)); + return; +} + +/* TPM_SymmetricKeyData_Load() is AES non-portable code to deserialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_KEY, stream, stream_size); + } + /* load valid */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_symmetric_key_data->valid), stream, stream_size); + } + /* load fill */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_symmetric_key_data->fill), stream, stream_size); + } + /* The AES key is a simple array. */ + if (rc == 0) { + rc = TPM_Loadn(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey), + stream, stream_size); + } + /* reconstruct the internal AES keys */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); + } + return rc; +} + +/* TPM_SymmetricKeyData_Store() is AES non-portable code to serialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key_data->tag); + } + /* store valid */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->valid), sizeof(TPM_BOOL)); + } + /* store fill */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->fill), sizeof(TPM_BOOL)); + } + /* store AES key */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + tpm_symmetric_key_data->userKey, + sizeof(tpm_symmetric_key_data->userKey)); + } + /* No need to store the internal AES keys. They are reconstructed on load */ + return rc; +} + +/* TPM_SymmetricKeyData_GenerateKey() is AES non-portable code to generate a random symmetric key + + tpm_symmetric_key_data should be initialized before and after use +*/ + +TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_GenerateKey:\n"); + /* generate a random key */ + if (rc == 0) { + rc = TPM_Random(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey)); + } + /* construct the internal AES keys */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); + } + if (rc == 0) { + tpm_symmetric_key_data->valid = TRUE; + } + return rc; +} + +/* TPM_SymmetricKeyData_SetKey() is AES non-portable code to set a symmetric key from input data + + tpm_symmetric_key_data should be initialized before and after use +*/ + +TPM_RESULT TPM_SymmetricKeyData_SetKey(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, + const unsigned char *key_data, + uint32_t key_data_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SymmetricKeyData_SetKey:\n"); + /* check the input data size, it can be truncated, but cannot be smaller than the AES key */ + if (rc == 0) { + if (sizeof(tpm_symmetric_key_data->userKey) > key_data_size) { + printf("TPM_SymmetricKeyData_SetKey: Error (fatal), need %lu bytes, received %u\n", + (unsigned long)sizeof(tpm_symmetric_key_data->userKey), key_data_size); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + /* copy the input data into the AES key structure */ + memcpy(tpm_symmetric_key_data->userKey, key_data, sizeof(tpm_symmetric_key_data->userKey)); + /* construct the internal AES keys */ + rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); + } + if (rc == 0) { + tpm_symmetric_key_data->valid = TRUE; + } + return rc; +} + +/* TPM_SymmetricKeyData_SetKeys() is AES non-portable code to construct the internal AES keys from + the userKey + + tpm_symmetric_key_data should be initialized before and after use +*/ + +static TPM_RESULT TPM_SymmetricKeyData_SetKeys(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data) +{ + TPM_RESULT rc = 0; + int irc; + + printf(" TPM_SymmetricKeyData_SetKeys:\n"); + if (rc == 0) { + TPM_PrintFour(" TPM_SymmetricKeyData_SetKeys: userKey", tpm_symmetric_key_data->userKey); + irc = AES_set_encrypt_key(tpm_symmetric_key_data->userKey, + TPM_AES_BITS, + &(tpm_symmetric_key_data->aes_enc_key)); + if (irc != 0) { + printf("TPM_SymmetricKeyData_SetKeys: Error (fatal) generating enc key\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_FAIL; /* should never occur, null pointers or bad bit size */ + } + } + if (rc == 0) { + irc = AES_set_decrypt_key(tpm_symmetric_key_data->userKey, + TPM_AES_BITS, + &(tpm_symmetric_key_data->aes_dec_key)); + if (irc != 0) { + printf("TPM_SymmetricKeyData_SetKeys: Error (fatal) generating dec key\n"); + TPM_OpenSSL_PrintError(); + rc = TPM_FAIL; /* should never occur, null pointers or bad bit size */ + } + } + return rc; +} + +/* TPM_SymmetricKeyData_Encrypt() is AES non-portable code to encrypt 'decrypt_data' to + 'encrypt_data' + + The stream is padded as per PKCS#7 / RFC2630 + + 'encrypt_data' must be free by the caller +*/ + +TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ + uint32_t *encrypt_length, /* output */ + const unsigned char *decrypt_data, /* input */ + uint32_t decrypt_length, /* input */ + const TPM_SYMMETRIC_KEY_TOKEN + tpm_symmetric_key_token) /* input */ +{ + TPM_RESULT rc = 0; + uint32_t pad_length; + unsigned char *decrypt_data_pad; + unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); + decrypt_data_pad = NULL; /* freed @1 */ + if (rc == 0) { + /* calculate the pad length and padded data length */ + pad_length = TPM_AES_BLOCK_SIZE - (decrypt_length % TPM_AES_BLOCK_SIZE); + *encrypt_length = decrypt_length + pad_length; + printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", + *encrypt_length, pad_length); + /* allocate memory for the encrypted response */ + rc = TPM_Malloc(encrypt_data, *encrypt_length); + } + /* allocate memory for the padded decrypted data */ + if (rc == 0) { + rc = TPM_Malloc(&decrypt_data_pad, *encrypt_length); + } + /* pad the decrypted clear text data */ + if (rc == 0) { + /* unpadded original data */ + memcpy(decrypt_data_pad, decrypt_data, decrypt_length); + /* last gets pad = pad length */ + memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); + /* set the IV */ + memset(ivec, 0, sizeof(ivec)); + /* encrypt the padded input to the output */ + TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Input", decrypt_data_pad); + AES_cbc_encrypt(decrypt_data_pad, + *encrypt_data, + *encrypt_length, + &(tpm_symmetric_key_data->aes_enc_key), + ivec, + AES_ENCRYPT); + TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Output", *encrypt_data); + } + free(decrypt_data_pad); /* @1 */ + return rc; +} + +/* TPM_SymmetricKeyData_Decrypt() is AES non-portable code to decrypt 'encrypt_data' to + 'decrypt_data' + + The stream must be padded as per PKCS#7 / RFC2630 + + decrypt_data must be free by the caller +*/ + +TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ + uint32_t *decrypt_length, /* output */ + const unsigned char *encrypt_data, /* input */ + uint32_t encrypt_length, /* input */ + const TPM_SYMMETRIC_KEY_TOKEN + tpm_symmetric_key_token) /* input */ +{ + TPM_RESULT rc = 0; + uint32_t pad_length; + uint32_t i; + unsigned char *pad_data; + unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); + /* sanity check encrypted length */ + if (rc == 0) { + if (encrypt_length < TPM_AES_BLOCK_SIZE) { + printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); + rc = TPM_DECRYPT_ERROR; + } + } + /* allocate memory for the padded decrypted data */ + if (rc == 0) { + rc = TPM_Malloc(decrypt_data, encrypt_length); + } + /* decrypt the input to the padded output */ + if (rc == 0) { + /* set the IV */ + memset(ivec, 0, sizeof(ivec)); + /* decrypt the padded input to the output */ + TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Input", encrypt_data); + AES_cbc_encrypt(encrypt_data, + *decrypt_data, + encrypt_length, + &(tpm_symmetric_key_data->aes_dec_key), + ivec, + AES_DECRYPT); + TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Output", *decrypt_data); + } + /* get the pad length */ + if (rc == 0) { + /* get the pad length from the last byte */ + pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); + /* sanity check the pad length */ + printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); + if ((pad_length == 0) || + (pad_length > TPM_AES_BLOCK_SIZE)) { + printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + /* get the unpadded length */ + *decrypt_length = encrypt_length - pad_length; + /* pad starting point */ + pad_data = *decrypt_data + *decrypt_length; + /* sanity check the pad */ + for (i = 0 ; i < pad_length ; i++, pad_data++) { + if (*pad_data != pad_length) { + printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", + *pad_data, i); + rc = TPM_DECRYPT_ERROR; + } + } + } + return rc; +} + +/* TPM_SymmetricKeyData_CtrCrypt() does an encrypt or decrypt (they are the same XOR operation with + a CTR mode pad) of 'data_in' to 'data_out'. + + NOTE: This function looks general, but is currently hard coded to AES128. + + 'symmetric key' is the raw key, not converted to a non-portable form + 'ctr_in' is the initial CTR value before possible truncation +*/ + +TPM_RESULT TPM_SymmetricKeyData_CtrCrypt(unsigned char *data_out, /* output */ + const unsigned char *data_in, /* input */ + uint32_t data_size, /* input */ + const unsigned char *symmetric_key, /* input */ + uint32_t symmetric_key_size, /* input */ + const unsigned char *ctr_in, /* input */ + uint32_t ctr_in_size) /* input */ +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = NULL; /* freed @1 */ + unsigned char ctr[TPM_AES_BLOCK_SIZE]; + + printf(" TPM_SymmetricKeyData_CtrCrypt: data_size %u\n", data_size); + /* allocate memory for the key token. The token is opaque in the API, but at this low level, + the code understands the TPM_SYMMETRIC_KEY_DATA structure */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_New((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); + } + /* convert the raw key to the AES key, truncating as required */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_SetKey(tpm_symmetric_key_data, + symmetric_key, + symmetric_key_size); + } + /* check the input CTR size, it can be truncated, but cannot be smaller than the AES key */ + if (rc == 0) { + if (ctr_in_size < sizeof(ctr)) { + printf(" TPM_SymmetricKeyData_CtrCrypt: Error (fatal)" + ", CTR size %u too small for AES key\n", ctr_in_size); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + /* make a truncated copy of CTR, since AES_ctr128_encrypt alters the value */ + memcpy(ctr, ctr_in, sizeof(ctr)); + printf(" TPM_SymmetricKeyData_CtrCrypt: Calling AES in CTR mode\n"); + TPM_PrintFour(" TPM_SymmetricKeyData_CtrCrypt: CTR", ctr); + rc = TPM_AES_ctr128_encrypt(data_out, + data_in, + data_size, + &(tpm_symmetric_key_data->aes_enc_key), + ctr); + } + TPM_SymmetricKeyData_Free((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); /* @1 */ + return rc; +} + +/* TPM_AES_ctr128_encrypt() is a TPM variant of the openSSL AES_ctr128_encrypt() function that + increments only the low 4 bytes of the counter. + + openSSL increments the entire CTR array. The TPM does not follow that convention. +*/ + +static TPM_RESULT TPM_AES_ctr128_encrypt(unsigned char *data_out, + const unsigned char *data_in, + uint32_t data_size, + const AES_KEY *aes_enc_key, + unsigned char ctr[TPM_AES_BLOCK_SIZE]) +{ + TPM_RESULT rc = 0; + uint32_t cint; + unsigned char pad_buffer[TPM_AES_BLOCK_SIZE]; /* the XOR pad */ + + printf(" TPM_AES_Ctr128_encrypt:\n"); + while (data_size != 0) { + printf(" TPM_AES_Ctr128_encrypt: data_size %lu\n", (unsigned long)data_size); + /* get an XOR pad array by encrypting the CTR with the AES key */ + AES_encrypt(ctr, pad_buffer, aes_enc_key); + /* partial or full last data block */ + if (data_size <= TPM_AES_BLOCK_SIZE) { + TPM_XOR(data_out, data_in, pad_buffer, data_size); + data_size = 0; + } + /* full block, not the last block */ + else { + TPM_XOR(data_out, data_in, pad_buffer, TPM_AES_BLOCK_SIZE); + data_in += TPM_AES_BLOCK_SIZE; + data_out += TPM_AES_BLOCK_SIZE; + data_size -= TPM_AES_BLOCK_SIZE; + } + /* if not the last block, increment CTR, only the low 4 bytes */ + if (data_size != 0) { + /* CTR is a big endian array, so the low 4 bytes are 12-15 */ + cint = LOAD32(ctr, 12); /* byte array to uint32_t */ + cint++; /* increment */ + STORE32(ctr, 12, cint); /* uint32_t to byte array */ + } + } + return rc; +} + +/* TPM_SymmetricKeyData_OfbCrypt() does an encrypt or decrypt (they are the same XOR operation with + a OFB mode pad) of 'data_in' to 'data_out' + + NOTE: This function looks general, but is currently hard coded to AES128. + + 'symmetric key' is the raw key, not converted to a non-portable form + 'ivec_in' is the initial IV value before possible truncation +*/ + +/* openSSL prototype + + void AES_ofb128_encrypt(const unsigned char *in, + unsigned char *out, + const unsigned long length, + const AES_KEY *key, + unsigned char *ivec, + int *num); +*/ + +TPM_RESULT TPM_SymmetricKeyData_OfbCrypt(unsigned char *data_out, /* output */ + const unsigned char *data_in, /* input */ + uint32_t data_size, /* input */ + const unsigned char *symmetric_key, /* in */ + uint32_t symmetric_key_size, /* in */ + unsigned char *ivec_in, /* input */ + uint32_t ivec_in_size) /* input */ +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = NULL; /* freed @1 */ + unsigned char ivec[TPM_AES_BLOCK_SIZE]; + int num; + + printf(" TPM_SymmetricKeyData_OfbCrypt: data_size %u\n", data_size); + /* allocate memory for the key token. The token is opaque in the API, but at this low level, + the code understands the TPM_SYMMETRIC_KEY_DATA structure */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_New((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); + } + /* convert the raw key to the AES key, truncating as required */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_SetKey(tpm_symmetric_key_data, + symmetric_key, + symmetric_key_size); + } + /* check the input OFB size, it can be truncated, but cannot be smaller than the AES key */ + if (rc == 0) { + if (ivec_in_size < sizeof(ivec)) { + printf(" TPM_SymmetricKeyData_OfbCrypt: Error (fatal)," + "IV size %u too small for AES key\n", ivec_in_size); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + /* make a truncated copy of IV, since AES_ofb128_encrypt alters the value */ + memcpy(ivec, ivec_in, sizeof(ivec)); + num = 0; + printf(" TPM_SymmetricKeyData_OfbCrypt: Calling AES in OFB mode\n"); + TPM_PrintFour(" TPM_SymmetricKeyData_OfbCrypt: IV", ivec); + AES_ofb128_encrypt(data_in, + data_out, + data_size, + &(tpm_symmetric_key_data->aes_enc_key), + ivec, + &num); + } + TPM_SymmetricKeyData_Free((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); + return rc; +} + +#endif /* TPM_AES */ diff --git a/src/tpm12/tpm_crypto.h b/src/tpm12/tpm_crypto.h new file mode 100644 index 0000000..f2d0701 --- /dev/null +++ b/src/tpm12/tpm_crypto.h @@ -0,0 +1,223 @@ +/********************************************************************************/ +/* */ +/* Platform Dependent Crypto */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_crypto.h 4406 2011-02-08 22:11:37Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_CRYPTO_H +#define TPM_CRYPTO_H + +#include "config.h" /* libtpms added */ + +#include "tpm_secret.h" +#include "tpm_types.h" + +/* self test */ + +TPM_RESULT TPM_Crypto_Init(void); +TPM_RESULT TPM_Crypto_TestSpecific(void); + +/* random number */ + +TPM_RESULT TPM_Random(BYTE *buffer, size_t bytes); +TPM_RESULT TPM_StirRandomCmd(TPM_SIZED_BUFFER *inData); + +/* + bignum +*/ + +TPM_RESULT TPM_BN_num_bytes(unsigned int *numBytes, TPM_BIGNUM bn_in); +TPM_RESULT TPM_BN_is_one(TPM_BIGNUM bn_in); +TPM_RESULT TPM_BN_mod(TPM_BIGNUM rem_in, + const TPM_BIGNUM a_in, + const TPM_BIGNUM m_in); +TPM_RESULT TPM_BN_mask_bits(TPM_BIGNUM bn_in, unsigned int n); +TPM_RESULT TPM_BN_rshift(TPM_BIGNUM *rBignum_in, + TPM_BIGNUM aBignum_in, + int n); +TPM_RESULT TPM_BN_lshift(TPM_BIGNUM *rBignum_in, + TPM_BIGNUM aBignum_in, + int n); +TPM_RESULT TPM_BN_add(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in); +TPM_RESULT TPM_BN_mul(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in); +TPM_RESULT TPM_BN_mod_exp(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM pBignum_in, + TPM_BIGNUM nBignum_in); +TPM_RESULT TPM_BN_mod_mul(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in, + TPM_BIGNUM mBignum_in); +TPM_RESULT TPM_BN_mod_add(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in, + TPM_BIGNUM mBignum_in); + +TPM_RESULT TPM_bin2bn(TPM_BIGNUM *bn_in, + const unsigned char *bin, + unsigned int bytes); +TPM_RESULT TPM_bn2bin(unsigned char *bin, + TPM_BIGNUM bn_in); + +TPM_RESULT TPM_BN_new(TPM_BIGNUM *bn_in); +void TPM_BN_free(TPM_BIGNUM bn_in); + +/* RSA */ + +TPM_RESULT TPM_RSAGenerateKeyPair(unsigned char **n, + unsigned char **p, + unsigned char **q, + unsigned char **d, + int num_bit, + const unsigned char *earr, + uint32_t e_size); + +TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, + uint32_t *decrypt_data_length, + size_t decrypt_data_size, + TPM_ENC_SCHEME encScheme, + unsigned char* encrypt_data, + uint32_t encrypt_data_size, + unsigned char *n, + uint32_t nbytes, + unsigned char *e, + uint32_t ebytes, + unsigned char *d, + uint32_t dbytes); + +TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, + size_t encrypt_data_size, + TPM_ENC_SCHEME encScheme, + const unsigned char *decrypt_data, + size_t decrypt_data_size, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes); +#if USE_FREEBL_CRYPTO_LIBRARY +TPM_RESULT TPM_RSAPublicEncryptRaw(unsigned char *encrypt_data, + uint32_t encrypt_data_size, + unsigned char *decrypt_data, + uint32_t decrypt_data_size, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes); +#endif + +TPM_RESULT TPM_RSAGetPrivateKey(uint32_t *qbytes, unsigned char **qarr, + uint32_t *dbytes, unsigned char **darr, + uint32_t nbytes, unsigned char *narr, + uint32_t ebytes, unsigned char *earr, + uint32_t pbytes, unsigned char *parr); +TPM_RESULT TPM_RSASign(unsigned char *signature, + unsigned int *signature_length, + unsigned int signature_size, + TPM_SIG_SCHEME sigScheme, + const unsigned char *message, + size_t message_size, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes, + unsigned char *darr, + uint32_t dbytes); +TPM_RESULT TPM_RSAVerifySHA1(unsigned char *signature, + unsigned int signature_size, + const unsigned char *message, + uint32_t message_size, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes); + +/* SHA-1 */ + +TPM_RESULT TPM_SHA1InitCmd(void **context); +TPM_RESULT TPM_SHA1UpdateCmd(void *context, const unsigned char *data, uint32_t length); +TPM_RESULT TPM_SHA1FinalCmd(unsigned char *md, void *context); +void TPM_SHA1Delete(void **context); + +/* SHA-1 Context */ + +TPM_RESULT TPM_Sha1Context_Load(void **context, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Sha1Context_Store(TPM_STORE_BUFFER *sbuffer, + void *context); + +/* + TPM_SYMMETRIC_KEY_DATA +*/ + +TPM_RESULT TPM_SymmetricKeyData_New(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data); +void TPM_SymmetricKeyData_Free(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data); +void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); +TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); +TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); +TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, + uint32_t *encrypt_length, + const unsigned char *decrypt_data, + uint32_t decrypt_length, + const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); +TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, + uint32_t *decrypt_length, + const unsigned char *encrypt_data, + uint32_t encrypt_length, + const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); +TPM_RESULT TPM_SymmetricKeyData_CtrCrypt(unsigned char *data_out, + const unsigned char *data_in, + uint32_t data_size, + const unsigned char *symmetric_key, + uint32_t symmetric_key_size, + const unsigned char *ctr_in, + uint32_t ctr_in_size); +TPM_RESULT TPM_SymmetricKeyData_OfbCrypt(unsigned char *data_out, + const unsigned char *data_in, + uint32_t data_size, + const unsigned char *symmetric_key, + uint32_t symmetric_key_size, + unsigned char *ivec_in, + uint32_t ivec_in_size); +#endif diff --git a/src/tpm12/tpm_crypto_freebl.c b/src/tpm12/tpm_crypto_freebl.c new file mode 100644 index 0000000..272c264 --- /dev/null +++ b/src/tpm12/tpm_crypto_freebl.c @@ -0,0 +1,2652 @@ +/********************************************************************************/ +/* */ +/* Platform Dependent Crypto */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_crypto_freebl.c 4655 2011-12-21 21:03:15Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* This is the FreeBL implementation + + setenv CVSROOT :pserver:anonymous@cvsmirror.mozilla.org:/cvsroot + cvs co mosilla/nsprpub + gmake nss_build_all +*/ + +#include +#include +#include +#include + +#include "blapi.h" +#include + +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_key.h" +#include "tpm_io.h" +#include "tpm_load.h" +#include "tpm_memory.h" +#include "tpm_process.h" +#include "tpm_types.h" + +#include "tpm_crypto.h" + +/* The TPM OAEP encoding parameter */ +static const unsigned char tpm_oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; + +/* pre-calculate hash of the constant tpm_oaep_pad_str, used often in the OAEP padding + calculations */ +static const unsigned char pHashConst[TPM_DIGEST_SIZE]; + +/* ASN.1 industry standard SHA1 with RSA object identifier */ +static unsigned char sha1Oid[] = { + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, + 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0x04, 0x14}; + + +/* + local prototypes +*/ + +static void TPM_RSAPrivateKeyInit(RSAPrivateKey *rsa_pri_key); +static TPM_RESULT TPM_RSAGeneratePublicToken(RSAPublicKey *rsa_pub_key, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes); +static TPM_RESULT TPM_RSAGeneratePrivateToken(RSAPrivateKey *rsa_pri_key, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes, + unsigned char *darr, + uint32_t dbytes); +static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, + unsigned int *signature_length, + const unsigned char *message, + size_t message_size, + RSAPrivateKey *rsa_pri_key); +static TPM_RESULT TPM_RSASignDER(unsigned char *signature, + unsigned int *signature_length, + const unsigned char *message, + size_t message_size, + RSAPrivateKey *rsa_pri_key); + +static TPM_RESULT TPM_RandomNonZero(BYTE *buffer, size_t bytes); + +static TPM_RESULT TPM_PKCS1_PaddingType1Add(unsigned char *output, + uint32_t outputLength, + const unsigned char *input, + uint32_t inputLength); +static TPM_RESULT TPM_PKCS1_PaddingType1Check(uint32_t *padLength, + unsigned char *input, + uint32_t inputLength); +static TPM_RESULT TPM_PKCS1_PaddingType2Add(unsigned char *encodedMessage, + uint32_t encodedMessageLength, + const unsigned char *message, + uint32_t messageLength); +static TPM_RESULT TPM_PKCS1_PaddingType2Check(unsigned char *outputData, + uint32_t *outputDataLength, + uint32_t outputDataSize, + unsigned char *inputData, + uint32_t inputDataLength); + +static TPM_RESULT TPM_memcpyPad(unsigned char **bin_out, + unsigned char *bin_in, + uint32_t bin_in_length, + uint32_t padBytes); + + +/* TPM_SYMMETRIC_KEY_DATA is a crypto library platform dependent symmetric key structure + */ + +#ifdef TPM_AES + +/* local prototype and structure for AES */ + +/* AES requires data lengths that are a multiple of the block size */ +#define TPM_AES_BITS 128 +/* The AES block size is always 16 bytes */ +#define TPM_AES_BLOCK_SIZE 16 + +/* Since the AES key is often derived by truncating the session shared secret, test that it's not + too large +*/ + +#if (TPM_AES_BLOCK_SIZE > TPM_SECRET_SIZE) +#error TPM_AES_BLOCK_SIZE larger than TPM_SECRET_SIZE +#endif + +/* The AES initial CTR value is derived from a nonce. */ + +#if (TPM_AES_BLOCK_SIZE > TPM_NONCE_SIZE) +#error TPM_AES_BLOCK_SIZE larger than TPM_NONCE_SIZE +#endif + +typedef struct tdTPM_SYMMETRIC_KEY_DATA { + TPM_TAG tag; + TPM_BOOL valid; + TPM_BOOL fill; + unsigned char userKey[TPM_AES_BLOCK_SIZE]; +} TPM_SYMMETRIC_KEY_DATA; + +#endif /* TPM_AES */ + +/* + Crypto library Initialization function +*/ + +TPM_RESULT TPM_Crypto_Init() +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + + printf("TPM_Crypto_Init: FreeBL library\n"); + /* initialize the random number generator */ + if (rc == 0) { + printf(" TPM_Crypto_Init: Initializing RNG\n"); + rv = RNG_RNGInit(); + if (rv != SECSuccess) { + printf("TPM_Crypto_Init: Error (fatal), RNG_RNGInit rv %d\n", rv); + rc = TPM_FAIL; + } + } + /* add additional seed entropy to the random number generator */ + if (rc == 0) { + printf(" TPM_Crypto_Init: Seeding RNG\n"); + RNG_SystemInfoForRNG(); + } + if (rc == 0) { + rv = BL_Init(); + if (rv != SECSuccess) { + printf("TPM_Crypto_Init: Error (fatal), BL_Init rv %d\n", rv); + rc =TPM_FAIL ; + } + } + /* pre-calculate hash of the constant tpm_oaep_pad_str, used often in the OAEP padding + calculations */ + if (rc == 0) { + rc = TPM_SHA1((unsigned char *)pHashConst, /* cast once to precalculate the constant */ + sizeof(tpm_oaep_pad_str), tpm_oaep_pad_str, + 0, NULL); + TPM_PrintFour("TPM_Crypto_Init: pHashConst", pHashConst); + } + return rc; +} + +/* TPM_Crypto_TestSpecific() performs any library specific tests + + For FreeBL +*/ + +TPM_RESULT TPM_Crypto_TestSpecific() +{ + TPM_RESULT rc = 0; + + /* Saving the SHA-1 context is fragile code, so test at startup */ + void *context1; + void *context2; + unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C, + 0x3B,0xD2,0x6E,0xBA,0xAE, + 0x4A,0xA1,0xF9,0x51,0x29, + 0xE5,0xE5,0x46,0x70,0xF1}; + TPM_DIGEST actual; + int not_equal; + TPM_STORE_BUFFER sbuffer; + const unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_Crypto_TestSpecific: Test 1 - SHA1 two parts\n"); + context1 = NULL; /* freed @1 */ + context2 = NULL; /* freed @2 */ + TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ + + if (rc== 0) { + rc = TPM_SHA1InitCmd(&context1); /* freed @1 */ + } + /* digest the first part of the array */ + if (rc== 0) { + rc = TPM_SHA1UpdateCmd(context1, buffer1, 16); + } + /* store the SHA1 context */ + if (rc== 0) { + rc = TPM_Sha1Context_Store(&sbuffer, context1); + } + /* load the SHA1 context */ + if (rc== 0) { + TPM_Sbuffer_Get(&sbuffer, &stream, &stream_size); + rc = TPM_Sha1Context_Load + (&context2, (unsigned char **)&stream, &stream_size); /* freed @2 */ + } + /* digest the rest of the array */ + if (rc== 0) { + rc = TPM_SHA1UpdateCmd(context2, buffer1 + 16, sizeof(buffer1) - 17); + } + /* get the digest result */ + if (rc== 0) { + rc = TPM_SHA1FinalCmd(actual, context2); + } + /* check the result */ + if (rc == 0) { + not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); + if (not_equal) { + printf("TPM_Crypto_TestSpecific: Error in test 1\n"); + TPM_PrintFour("\texpect", expect1); + TPM_PrintFour("\tactual", actual); + rc = TPM_FAILEDSELFTEST; + } + } + TPM_SHA1Delete(&context1); /* @1 */ + TPM_SHA1Delete(&context2); /* @2 */ + TPM_Sbuffer_Delete(&sbuffer); /* @3 */ + return rc; +} + +/* + Random Number Functions +*/ + +/* TPM_Random() fills 'buffer' with 'bytes' bytes. + */ + +TPM_RESULT TPM_Random(BYTE *buffer, size_t bytes) +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + + printf(" TPM_Random: Requesting %lu bytes\n", (unsigned long)bytes); + /* generate the random bytes */ + if (rc == 0) { + rv = RNG_GenerateGlobalRandomBytes(buffer, bytes); + if (rv != SECSuccess) { + printf("TPM_Random: Error (fatal) in RNG_GenerateGlobalRandomBytes rv %d\n", rv); + rc = TPM_FAIL; + } + } + return rc; +} + +/* TPM_Random() fills 'buffer' with 'bytes' non-zero bytes + + This is used for PKCS padding. +*/ + +static TPM_RESULT TPM_RandomNonZero(BYTE *buffer, size_t bytes) +{ + TPM_RESULT rc = 0; + size_t i; + SECStatus rv = SECSuccess; + + printf(" TPM_RandomNonZero: Requesting %lu bytes\n", (unsigned long)bytes); + for (i = 0 ; (rc == 0) && (i < bytes) ; ) { + rv = RNG_GenerateGlobalRandomBytes(buffer, 1); + if (rv != SECSuccess) { + printf("TPM_Random: Error (fatal) in RNG_GenerateGlobalRandomBytes rv %d\n", rv); + rc = TPM_FAIL; + } + else { + if (*buffer != 0x00) { + buffer++; + i++; + } + } + } + return rc; +} + +/* TPM_StirRandomCmd() adds the supplied entropy to the random number generator + */ + +TPM_RESULT TPM_StirRandomCmd(TPM_SIZED_BUFFER *inData) +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + + printf(" TPM_StirRandomCmd:\n"); + if (rc == 0) { + /* add the seeding material */ + rv = RNG_RandomUpdate(inData->buffer, inData->size); + if (rv != SECSuccess) { + printf("TPM_StirRandom: Error (fatal) in RNG_RandomUpdate rv %d\n", rv); + rc = TPM_FAIL; + } + } + return rc; +} + +/* + RSA Functions +*/ + +/* TPM_RSAPrivateKeyInit() NULLs all the structure members in preparation for constructing an RSA + key token from byte arrays using RSA_PopulatePrivateKey() +*/ + +static void TPM_RSAPrivateKeyInit(RSAPrivateKey *rsa_pri_key) +{ + rsa_pri_key->arena = NULL; + rsa_pri_key->publicExponent.type = siBuffer; + rsa_pri_key->publicExponent.data = NULL; + rsa_pri_key->publicExponent.len = 0; + rsa_pri_key->modulus.type = siBuffer; + rsa_pri_key->modulus.data = NULL; + rsa_pri_key->modulus.len = 0; + rsa_pri_key->privateExponent.type = siBuffer; + rsa_pri_key->privateExponent.data = NULL; + rsa_pri_key->privateExponent.len = 0; + rsa_pri_key->prime1.type = siBuffer; + rsa_pri_key->prime1.data = NULL; + rsa_pri_key->prime1.len = 0; + rsa_pri_key->prime2.type = siBuffer; + rsa_pri_key->prime2.data = NULL; + rsa_pri_key->prime2.len = 0; + rsa_pri_key->exponent1.type = siBuffer; + rsa_pri_key->exponent1.data = NULL; + rsa_pri_key->exponent1.len = 0; + rsa_pri_key->exponent2.type = siBuffer; + rsa_pri_key->exponent2.data = NULL; + rsa_pri_key->exponent2.len = 0; + rsa_pri_key->coefficient.type = siBuffer; + rsa_pri_key->coefficient.data = NULL; + rsa_pri_key->coefficient.len = 0; + return; +} + +/* Generate an RSA key pair of size 'num_bits' using public exponent 'earr' + + 'n', 'p', 'q', 'd' must be freed by the caller +*/ + +TPM_RESULT TPM_RSAGenerateKeyPair(unsigned char **n, /* public key - modulus */ + unsigned char **p, /* private key prime */ + unsigned char **q, /* private key prime */ + unsigned char **d, /* private key (private exponent) */ + int num_bits, /* key size in bits */ + const unsigned char *earr, /* public exponent as an array */ + uint32_t e_size) +{ + TPM_RESULT rc = 0; + SECItem publicExponent = { 0, 0, 0}; + RSAPrivateKey *rsaPrivateKey = NULL; /* freed @1 */ + unsigned long e; /* public exponent */ + + printf(" TPM_RSAGenerateKeyPair:\n"); + /* initialize in case of error */ + *n = NULL; + *p = NULL; + *q = NULL; + *d = NULL; + /* check that num_bits is a multiple of 16. If not, the primes p and q will not be a multiple + of 8 and will not fit well in a byte */ + if (rc == 0) { + if ((num_bits % 16) != 0) { + printf("TPM_RSAGenerateKeyPair: Error, num_bits %d is not a multiple of 16\n", + num_bits); + rc = TPM_BAD_KEY_PROPERTY; + } + } + /* convert the e array to an unsigned long */ + if (rc == 0) { + rc = TPM_LoadLong(&e, earr, e_size); + } + /* validate the public exponent against a list of legal values. Some values (e.g. even numbers) + can hang the key generator. */ + if (rc == 0) { + rc = TPM_RSA_exponent_verify(e); + } + /* generate the key pair */ + if (rc == 0) { + printf(" TPM_RSAGenerateKeyPair: num_bits %d exponent %08lx\n", num_bits, e); + publicExponent.type = siBuffer; + publicExponent.data = (unsigned char *)earr; + publicExponent.len = e_size; + /* Generate and return a new RSA public and private key token */ + rsaPrivateKey = RSA_NewKey(num_bits, &publicExponent); /* freed @1 */ + if (rsaPrivateKey == NULL) { + printf("TPM_RSAGenerateKeyPair: Error (fatal) calling RSA_NewKey()\n"); + rc = TPM_FAIL; + } + } + /* Key parts can some times have leading zeros, and some crypto libraries truncate. However, + the TPM expects fixed lengths. These calls restore any removed padding */ + /* load n */ + if (rc == 0) { + rc = TPM_memcpyPad(n, /* freed by caller */ + rsaPrivateKey->modulus.data, + rsaPrivateKey->modulus.len, + num_bits/8); /* required length */ + } + /* load p */ + if (rc == 0) { + rc = TPM_memcpyPad(p, /* freed by caller */ + rsaPrivateKey->prime1.data, + rsaPrivateKey->prime1.len, + num_bits/16); /* required length */ + } + /* load q */ + if (rc == 0) { + rc = TPM_memcpyPad(q, /* freed by caller */ + rsaPrivateKey->prime2.data, + rsaPrivateKey->prime2.len, + num_bits/16); /* required length */ + } + /* load d */ + if (rc == 0) { + rc = TPM_memcpyPad(d, /* freed by caller */ + rsaPrivateKey->privateExponent.data, + rsaPrivateKey->privateExponent.len, + num_bits/8); /* required length */ + } + /* on error, free the components and set back to NULL so subsequent free is safe */ + if (rc != 0) { + free(*n); + free(*p); + free(*q); + free(*d); + *n = NULL; + *p = NULL; + *q = NULL; + *d = NULL; + } + if (rsaPrivateKey != NULL) { + PORT_FreeArena(rsaPrivateKey->arena, PR_TRUE); /* @1 */ + } + return rc; +} + +/* TPM_RSAGeneratePublicToken() generates an RSA key token from n and e + */ + +static TPM_RESULT TPM_RSAGeneratePublicToken(RSAPublicKey *rsaPublicKey, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + + /* simply assign the arrays to the key token */ + if (rc == 0) { + printf(" TPM_RSAGeneratePublicToken: nbytes %u ebytes %u\n", nbytes, ebytes); + rsaPublicKey->arena = NULL; + /* public modulus */ + rsaPublicKey->modulus.type = siBuffer; + rsaPublicKey->modulus.data = narr; + rsaPublicKey->modulus.len = nbytes; + /* public exponent */ + rsaPublicKey->publicExponent.type = siBuffer; + rsaPublicKey->publicExponent.data = earr; + rsaPublicKey->publicExponent.len = ebytes; + } + return rc; +} + +/* TPM_RSAGeneratePrivateToken() generates an RSA key token from n, e, d + */ + +static TPM_RESULT TPM_RSAGeneratePrivateToken(RSAPrivateKey *rsa_pri_key, /* freed by caller */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + + printf(" TPM_RSAGeneratePrivateToken:\n"); + if (rc == 0) { + rsa_pri_key->arena = NULL; + /* public exponent */ + rsa_pri_key->publicExponent.type = siBuffer; + rsa_pri_key->publicExponent.data = earr; + rsa_pri_key->publicExponent.len = ebytes; + /* public modulus */ + rsa_pri_key->modulus.type = siBuffer; + rsa_pri_key->modulus.data = narr; + rsa_pri_key->modulus.len = nbytes; + /* private exponent */ + rsa_pri_key->privateExponent.type = siBuffer; + rsa_pri_key->privateExponent.data = darr; + rsa_pri_key->privateExponent.len = dbytes; + /* given these key parameters (n,e,d), fill in the rest of the parameters */ + rv = RSA_PopulatePrivateKey(rsa_pri_key); /* freed by caller */ + if (rv != SECSuccess) { + printf("TPM_RSAGeneratePrivateToken: Error, RSA_PopulatePrivateKey rv %d\n", rv); + rc = TPM_BAD_PARAMETER; + } + } + return rc; +} + +/* TPM_RSAPrivateDecrypt() decrypts 'encrypt_data' using the private key 'n, e, d'. The OAEP + padding is removed and 'decrypt_data_length' bytes are moved to 'decrypt_data'. + + 'decrypt_data_length' is at most 'decrypt_data_size'. +*/ + +TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ + uint32_t *decrypt_data_length, /* length of data put into + decrypt_data */ + size_t decrypt_data_size, /* size of decrypt_data buffer */ + TPM_ENC_SCHEME encScheme, /* encryption scheme */ + unsigned char* encrypt_data, /* encrypted data */ + uint32_t encrypt_data_size, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + RSAPrivateKey rsa_pri_key; + unsigned char *padded_data = NULL; /* freed @2 */ + int padded_data_size = 0; + + printf(" TPM_RSAPrivateDecrypt: Input data size %u\n", encrypt_data_size); + TPM_RSAPrivateKeyInit(&rsa_pri_key); /* freed @1 */ + /* the encrypted data size must equal the public key size */ + if (rc == 0) { + if (encrypt_data_size != nbytes) { + printf("TPM_RSAPrivateDecrypt: Error, Encrypted data size is %u not %u\n", + encrypt_data_size, nbytes); + rc = TPM_DECRYPT_ERROR; + } + } + /* construct the freebl private key object from n,e,d */ + if (rc == 0) { + rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + darr, /* private exponent */ + dbytes); + } + /* allocate intermediate buffer for the decrypted but still padded data */ + if (rc == 0) { + /* the size of the decrypted data is guaranteed to be less than this */ + padded_data_size = rsa_pri_key.modulus.len; + rc = TPM_Malloc(&padded_data, padded_data_size); /* freed @2 */ + } + if (rc == 0) { + /* decrypt with private key. Must decrypt first and then remove padding because the decrypt + call cannot specify an encoding parameter */ + rv = RSA_PrivateKeyOp(&rsa_pri_key, /* private key token */ + padded_data, /* to - the decrypted but padded data */ + encrypt_data); /* from - the encrypted data */ + if (rv != SECSuccess) { + printf("TPM_RSAPrivateDecrypt: Error in RSA_PrivateKeyOp(), rv %d\n", rv); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + printf(" TPM_RSAPrivateDecrypt: RSA_PrivateKeyOp() success\n"); + printf(" TPM_RSAPrivateDecrypt: Padded data size %u\n", padded_data_size); + TPM_PrintFour(" TPM_RSAPrivateDecrypt: Decrypt padded data", padded_data); + /* check and remove the padding based on the TPM encryption scheme */ + if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { + /* recovered seed and pHash are not returned */ + unsigned char seed[TPM_DIGEST_SIZE]; + unsigned char pHash[TPM_DIGEST_SIZE]; + if (rc == 0) { + /* the padded data skips the first 0x00 byte, since it expects the + padded data to come from a truncated bignum */ + rc = TPM_RSA_padding_check_PKCS1_OAEP(decrypt_data, /* to */ + decrypt_data_length, /* to length */ + decrypt_data_size, /* to buffer size */ + padded_data + 1, /* from */ + padded_data_size - 1, /* from length */ + pHash, /* 20 bytes */ + seed); /* 20 bytes */ + } + } + else if (encScheme == TPM_ES_RSAESPKCSv15) { + rc = TPM_PKCS1_PaddingType2Check(decrypt_data, /* to */ + decrypt_data_length, /* to length */ + decrypt_data_size, /* to buffer size*/ + padded_data, /* from */ + padded_data_size); /* from length */ + } + else { + printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); + rc = TPM_INAPPROPRIATE_ENC; + } + } + if (rc == 0) { + printf(" TPM_RSAPrivateDecrypt: RSA_padding_check_PKCS1 recovered %d bytes\n", + *decrypt_data_length); + TPM_PrintFourLimit(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data, decrypt_data_size); + } + PORT_FreeArena(rsa_pri_key.arena, PR_TRUE); /* @1 */ + free(padded_data); /* @2 */ + return rc; +} + +/* TPM_RSAPublicEncrypt() PKCS1 pads 'decrypt_data' to 'encrypt_data_size' and encrypts using the + public key 'n, e'. +*/ + +TPM_RESULT TPM_RSAPublicEncrypt(unsigned char *encrypt_data, /* encrypted data */ + size_t encrypt_data_size, /* size of encrypted data buffer */ + TPM_ENC_SCHEME encScheme, /* padding type */ + const unsigned char *decrypt_data, /* decrypted data */ + size_t decrypt_data_size, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + unsigned char *padded_data = NULL; /* freed @1 */ + + printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); + /* intermediate buffer for the padded decrypted data */ + if (rc == 0) { + rc = TPM_Malloc(&padded_data, encrypt_data_size); /* freed @1 */ + } + /* pad the decrypted data */ + if (rc == 0) { + /* based on the TPM encryption scheme */ + if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { + unsigned char seed[TPM_DIGEST_SIZE]; + if (rc == 0) { + rc = TPM_Random(seed, TPM_DIGEST_SIZE); + } + if (rc == 0) { + padded_data[0] = 0x00; + rc = TPM_RSA_padding_add_PKCS1_OAEP(padded_data +1, /* to */ + encrypt_data_size -1, /* to length */ + decrypt_data, /* from */ + decrypt_data_size, /* from length */ + pHashConst, /* 20 bytes */ + seed); /* 20 bytes */ + } + } + else if (encScheme == TPM_ES_RSAESPKCSv15) { + rc = TPM_PKCS1_PaddingType2Add(padded_data, /* to */ + encrypt_data_size, /* to length */ + decrypt_data, /* from */ + decrypt_data_size); /* from length */ + } + else { + printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); + rc = TPM_INAPPROPRIATE_ENC; + } + } + /* raw public key operation on the already padded input data */ + if (rc == 0) { + rc = TPM_RSAPublicEncryptRaw(encrypt_data, /* output */ + encrypt_data_size, /* input, size of enc buffer */ + padded_data, /* input */ + encrypt_data_size, /* input, size of dec buffer */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + free(padded_data); /* @1 */ + return rc; +} + +/* TPM_RSAPublicEncryptRaw() does a raw public key operation without any padding. + +*/ + +TPM_RESULT TPM_RSAPublicEncryptRaw(unsigned char *encrypt_data, /* output */ + uint32_t encrypt_data_size, /* input, size of enc buffer */ + unsigned char *decrypt_data, /* input */ + uint32_t decrypt_data_size, /* input, size of dec buffer */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + RSAPublicKey rsa_pub_key; + + printf(" TPM_RSAPublicEncryptRaw:\n"); + /* the input data size must equal the public key size (already padded) */ + if (rc == 0) { + if (decrypt_data_size != nbytes) { + printf("TPM_RSAPublicEncryptRaw: Error, decrypt data size is %u not %u\n", + decrypt_data_size, nbytes); + rc = TPM_ENCRYPT_ERROR; + } + } + /* the output data size must equal the public key size */ + if (rc == 0) { + if (encrypt_data_size != nbytes) { + printf("TPM_RSAPublicEncryptRaw: Error, Output data size is %u not %u\n", + encrypt_data_size, nbytes); + rc = TPM_ENCRYPT_ERROR; + } + } + /* construct the freebl public key object */ + if (rc == 0) { + rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freebl public key token */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Public modulus", narr); + TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Public exponent", earr, ebytes); + TPM_PrintFourLimit(" TPM_RSAPublicEncryptRaw: Decrypt data", decrypt_data, decrypt_data_size); + /* raw public key operation, encrypt the decrypt_data */ + rv = RSA_PublicKeyOp(&rsa_pub_key, /* freebl public key token */ + encrypt_data, /* output - the encrypted data */ + decrypt_data); /* input - the clear text data */ + if (rv != SECSuccess) { + printf("TPM_RSAPublicEncrypt: Error in RSA_PublicKeyOp, rv %d\n", rv); + rc = TPM_ENCRYPT_ERROR; + } + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Encrypt data", encrypt_data); +#if 0 /* NOTE: Uncomment as a debug aid for signature verification */ + TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Encrypt data", + encrypt_data, encrypt_data_size); +#endif + } + return rc; +} + +/* TPM_RSASign() signs 'message' of size 'message_size' using the private key n,e,d and the + signature scheme 'sigScheme' as specified in PKCS #1 v2.0. + + 'signature_length' bytes are moved to 'signature'. 'signature_length' is at most + 'signature_size'. signature must point to bytes of memory equal to the public modulus size. +*/ + +TPM_RESULT TPM_RSASign(unsigned char *signature, /* output */ + unsigned int *signature_length, /* output, size of signature */ + unsigned int signature_size, /* input, size of signature buffer */ + TPM_SIG_SCHEME sigScheme, /* input, type of signature */ + const unsigned char *message, /* input */ + size_t message_size, /* input */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + RSAPrivateKey rsa_pri_key; + + printf(" TPM_RSASign:\n"); + TPM_RSAPrivateKeyInit(&rsa_pri_key); /* freed @1 */ + /* construct the free private key object from n,e,d */ + if (rc == 0) { + rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + darr, /* private exponent */ + dbytes); + } + /* sanity check the size of the output signature buffer */ + if (rc == 0) { + if (signature_size < nbytes) { + printf("TPM_RSASign: Error (fatal), buffer %u too small for signature %u\n", + signature_size, nbytes); + rc = TPM_FAIL; /* internal error, should never occur */ + } + } + /* determine the signature scheme for the key */ + if (rc == 0) { + switch(sigScheme) { + case TPM_SS_NONE: + printf("TPM_RSASign: Error, sigScheme TPM_SS_NONE\n"); + rc = TPM_INVALID_KEYUSAGE; + break; + case TPM_SS_RSASSAPKCS1v15_SHA1: + case TPM_SS_RSASSAPKCS1v15_INFO: + rc = TPM_RSASignSHA1(signature, + signature_length, + message, + message_size, + &rsa_pri_key); + break; + case TPM_SS_RSASSAPKCS1v15_DER: + rc = TPM_RSASignDER(signature, + signature_length, + message, + message_size, + &rsa_pri_key); + break; + default: + printf("TPM_RSASign: Error, sigScheme %04hx unknown\n", sigScheme); + rc = TPM_INVALID_KEYUSAGE; + break; + } + } + PORT_FreeArena(rsa_pri_key.arena, PR_TRUE); /* @1 */ + return rc; +} + +/* TPM_RSASignSHA1() performs the following: + prepend a DER encoded algorithm ID (SHA1 and RSA) + prepend a type 1 pad + encrypt with the private key +*/ + +static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, /* output */ + unsigned int *signature_length, /* output, size of signature */ + const unsigned char *message, /* input */ + size_t message_size, /* input */ + RSAPrivateKey *rsa_pri_key) /* signing private key */ +{ + TPM_RESULT rc = 0; + unsigned char *message_der; /* DER padded message, freed @1 */ + + printf(" TPM_RSASignSHA1: key size %d\n", rsa_pri_key->modulus.len); + message_der = NULL; /* freed @1 */ + /* sanity check, SHA1 messages must be 20 bytes */ + if (rc == 0) { + if (message_size != TPM_DIGEST_SIZE) { + printf("TPM_RSASignSHA1: Error, message size %lu not TPM_DIGEST_SIZE\n", + (unsigned long)message_size ); + rc = TPM_DECRYPT_ERROR; + } + } + /* allocate memory for the DER padded message */ + if (rc == 0) { + rc = TPM_Malloc(&message_der, sizeof(sha1Oid) + message_size); /* freed @1 */ + } + if (rc == 0) { + /* copy the OID */ + memcpy(message_der, sha1Oid, sizeof(sha1Oid)); + /* copy the message */ + memcpy(message_der + sizeof(sha1Oid), message, message_size); + /* sign the DER padded message */ + rc = TPM_RSASignDER(signature, /* output */ + signature_length, /* output, size of signature */ + message_der, /* input */ + sizeof(sha1Oid) + message_size, /* input */ + rsa_pri_key); /* signing private key */ + } + free(message_der); /* @1 */ + return rc; +} + +/* TPM_RSASignDER() performs the following: + + prepend a PKCS1 type 1 pad + encrypt with the private key + + The caller must ensure that the signature buffer is >= the key size. +*/ + +static TPM_RESULT TPM_RSASignDER(unsigned char *signature, /* output */ + unsigned int *signature_length, /* output, size of signature */ + const unsigned char *message, /* input */ + size_t message_size, /* input */ + RSAPrivateKey *rsa_pri_key) /* signing private key */ +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + unsigned char *message_pad; /* PKCS1 type 1 padded message, freed @1 */ + + printf(" TPM_RSASignDER: key size %d\n", rsa_pri_key->modulus.len); + message_pad = NULL; /* freed @1 */ + /* the padded message size is the same as the key size */ + /* allocate memory for the padded message */ + if (rc == 0) { + rc = TPM_Malloc(&message_pad, rsa_pri_key->modulus.len); /* freed @1 */ + } + /* PKCS1 type 1 pad the message */ + if (rc == 0) { + printf(" TPM_RSASignDER: Applying PKCS1 type 1 padding, size from %lu to %u\n", + (unsigned long)message_size, rsa_pri_key->modulus.len); + TPM_PrintFourLimit(" TPM_RSASignDER: Input message", message, message_size); + /* This call checks that the message will fit with the padding */ + rc = TPM_PKCS1_PaddingType1Add(message_pad, /* to */ + rsa_pri_key->modulus.len, /* to length */ + message, /* from */ + message_size); /* from length */ + } + /* raw sign with private key */ + if (rc == 0) { + printf(" TPM_RSASignDER: Encrypting with private key, message size %d\n", + rsa_pri_key->modulus.len); + TPM_PrintFour(" TPM_RSASignDER: Padded message", message_pad); + /* sign with private key */ + rv = RSA_PrivateKeyOp(rsa_pri_key, /* freebl key token */ + signature, /* to - the decrypted but padded data */ + message_pad); /* from - the encrypted data */ + if (rv != SECSuccess) { + printf("TPM_RSASignDER: Error in RSA_PrivateKeyOp(), rv %d\n", rv); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSASignDER: signature", signature); + *signature_length = rsa_pri_key->modulus.len; + } + free(message_pad); /* @1 */ + return rc; +} + +/* TPM_RSAVerifySHA1() performs the following: + decrypt the signature + verify and remove type 1 pad + verify and remove DER encoded algorithm ID + verify the signature on the message +*/ + +TPM_RESULT TPM_RSAVerifySHA1(unsigned char *signature, /* input */ + unsigned int signature_size, /* input, size of signature + buffer */ + const unsigned char *message, /* input */ + uint32_t message_size, /* input */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + unsigned char *padded_data = NULL; /* decrypted signature, freed @1 */ + uint32_t padLength; + int irc; + + printf(" TPM_RSAVerifySHA1:\n"); + /* allocate memory for the padded result of the public key operation */ + if (rc == 0) { + rc = TPM_Malloc(&padded_data, nbytes); /* freed @1 */ + } + /* do a raw encrypt of the signature */ + if (rc == 0) { + rc = TPM_RSAPublicEncryptRaw(padded_data, /* output */ + nbytes, /* input, size of message buffer */ + signature, /* input */ + signature_size, /* input, size of signature buffer */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + /* check PKCS1 padding and OID */ + if (rc == 0) { + rc = TPM_PKCS1_PaddingType1Check(&padLength, /* length of the PKCS1 padd and OID */ + padded_data, /* input data */ + nbytes); /* input data length */ + } + /* check message length */ + if (rc == 0) { + if (message_size != (nbytes - padLength)) { + printf("TPM_RSAVerifySHA1: Error, " + "message size %u not equal to size %u after padding removed\n", + message_size, nbytes - padLength); + rc = TPM_BAD_SIGNATURE; + } + } + /* check message */ + if (rc == 0) { + irc = memcmp(message, padded_data + padLength, message_size); + if (irc != 0) { + printf("TPM_RSAVerifySHA1: Error, message mismatch\n"); + TPM_PrintFourLimit(" TPM_RSAVerifySHA1: message", message, message_size); + TPM_PrintFourLimit(" TPM_RSAVerifySHA1: message from signature", padded_data + padLength, message_size); + rc = TPM_BAD_SIGNATURE; + } + } + /* public encrypt is general, here we're doing a signature check, so adjust the error message */ + else { + rc = TPM_BAD_SIGNATURE; + } + free(padded_data); /* @1 */ + return rc; +} + +/* TPM_RSAGetPrivateKey calculates q (2nd prime factor) and d (private key) from n (public key), e + (public exponent), and p (1st prime factor) + + 'qarr', darr' must be freed by the caller. +*/ + +TPM_RESULT TPM_RSAGetPrivateKey(uint32_t *qbytes, unsigned char **qarr, + uint32_t *dbytes, unsigned char **darr, + uint32_t nbytes, unsigned char *narr, + uint32_t ebytes, unsigned char *earr, + uint32_t pbytes, unsigned char *parr) +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + RSAPrivateKey rsa_pri_key; + + /* set to NULL so caller can free after failure */ + printf(" TPM_RSAGetPrivateKey:\n"); + TPM_RSAPrivateKeyInit(&rsa_pri_key); /* freed @1 */ + *qarr = NULL; + *darr = NULL; + /* check input parameters */ + if (rc == 0) { + if ((narr == NULL) || (nbytes == 0)) { + printf("TPM_RSAGetPrivateKey: Error, missing n\n"); + rc = TPM_BAD_PARAMETER; + } + } + /* check input parameters */ + if (rc == 0) { + if ((earr == NULL) || (ebytes == 0)) { + printf("TPM_RSAGetPrivateKey: Error, missing e\n"); + rc = TPM_BAD_PARAMETER; + } + } + /* check input parameters */ + if (rc == 0) { + if ((parr == NULL) || (pbytes == 0)) { + printf("TPM_RSAGetPrivateKey: Error, missing p\n"); + rc = TPM_BAD_PARAMETER; + } + } + /* populate the private key token with n, e, p */ + if (rc == 0) { + rsa_pri_key.publicExponent.type = siBuffer; + rsa_pri_key.publicExponent.data = earr; + rsa_pri_key.publicExponent.len = ebytes; + rsa_pri_key.modulus.type = siBuffer; + rsa_pri_key.modulus.data = narr; + rsa_pri_key.modulus.len = nbytes; + rsa_pri_key.prime1.type = siBuffer; + rsa_pri_key.prime1.data = parr; + rsa_pri_key.prime1.len = pbytes; + /* fill in the rest of the freebl key token parameters. */ + rv = RSA_PopulatePrivateKey(&rsa_pri_key); /* freed @1 */ + if (rv != SECSuccess) { + printf("TPM_RSAGetPrivateKey: Error in RSA_PopulatePrivateKey rv %d\n", rv); + rc = TPM_BAD_PARAMETER; + } + } + /* extract and pad q */ + if (rc == 0) { + rc = TPM_memcpyPad(qarr, /* freed by caller */ + rsa_pri_key.prime2.data, rsa_pri_key.prime2.len, + pbytes); /* pad to p prime */ + *qbytes = pbytes; + } + /* extract and pad d */ + if (rc == 0) { + rc = TPM_memcpyPad(darr, /* freed by caller */ + rsa_pri_key.privateExponent.data, rsa_pri_key.privateExponent.len, + nbytes); /* pad to public modulus */ + *dbytes = nbytes; + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated q", *qarr); + TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated d", *darr); + printf(" TPM_RSAGetPrivateKey: length of n,p,q,d = %u / %u / %u / %u\n", + nbytes, pbytes, *qbytes, *dbytes); + } + PORT_FreeArena(rsa_pri_key.arena, PR_TRUE); /* @1 */ + return rc; +} + +/* + PKCS1 Padding Functions +*/ + +/* TPM_PKCS1_PaddingType1Add() adds PKCS1 type 1 padding. + + The output buffer is preallocated. +*/ + +static TPM_RESULT TPM_PKCS1_PaddingType1Add(unsigned char *output, /* to */ + uint32_t outputLength, + const unsigned char *input, /* from */ + uint32_t inputLength) +{ + TPM_RESULT rc = 0; + uint32_t psLength; + uint32_t index; + + /* sanity check the length, this should never fail */ + printf(" TPM_PKCS1_PaddingType1Add:\n"); + if (rc == 0) { + if ((inputLength + 11) > outputLength) { + printf("TPM_PKCS1_PaddingType1Add: Error, input %u too big for output %u\n", + inputLength, outputLength); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + index = 0; + /* psLength is the number of 0xff bytes, subtract 3 for the leading 00,01 and trailing 00 */ + psLength = outputLength - inputLength - 3; + + /* add the PKCS1 pad 01 || PS || 00 || T where PS is at least 8 0xff bytes */ + /* PKCS1 pads to k-1 bytes, implies a leading 0 */ + output[index] = 0x00; + index++; + + output[index] = 0x01; + index++; + + memset(output + index, 0xff, psLength); + index += psLength; + + output[index] = 0x00; + index++; + + /* add the input data */ + memcpy(output + index, input, inputLength); + index += inputLength; + } + return rc; +} + +/* TPM_PKCS1_PaddingType1Check() checks PKCS1 type 1 padding and the SHA1withRSA OID + and returns their length + + Type 1 is: 00 01 FF's 00 OID message +*/ + +static TPM_RESULT TPM_PKCS1_PaddingType1Check(uint32_t *padLength, + unsigned char *input, + uint32_t inputLength) +{ + TPM_RESULT rc = 0; + int irc; + + printf(" TPM_PKCS1_PaddingType1Check:\n"); + /* sanity check the length */ + if (rc == 0) { + if ((sizeof(sha1Oid) + 11) > inputLength) { + printf("TPM_PKCS1_PaddingType1Check: Error, " + "sizeof(sha1Oid) %lu + 11 > inputLength %u\n", + (unsigned long)sizeof(sha1Oid), inputLength); + rc = TPM_ENCRYPT_ERROR; + } + } + /* check byte 0 */ + if (rc == 0) { + *padLength = 0; + if (input[*padLength] != 0x00) { + printf("TPM_PKCS1_PaddingType1Check: Error, byte %u %02x not 0x00\n", + *padLength, input[*padLength]); + rc = TPM_ENCRYPT_ERROR; + } + (*padLength)++; + } + /* check byte 1 */ + if (rc == 0) { + if (input[*padLength] != 0x01) { + printf("TPM_PKCS1_PaddingType1Check: Error, byte %u %02x not 0x01\n", + *padLength, input[*padLength]); + rc = TPM_ENCRYPT_ERROR; + } + (*padLength)++; + } + /* check for at least 8 0xff bytes */ + for ( ; (rc == 0) && (*padLength < 10) ; (*padLength)++) { + if (input[*padLength] != 0xff) { + printf("TPM_PKCS1_PaddingType1Check: Error, byte %u %02x not 0xff\n", + *padLength, input[*padLength]); + rc = TPM_ENCRYPT_ERROR; + } + } + /* check for more 0xff bytes */ + for ( ; (rc == 0) && (*padLength < inputLength) ; (*padLength)++) { + if (input[*padLength] != 0xff) { + break; + } + } + /* check for 0x00 byte */ + if (rc == 0) { + if (input[*padLength] != 0x00) { + printf("TPM_PKCS1_PaddingType1Check: Error, byte %u %02x not 0x00\n", + *padLength, input[*padLength]); + rc = TPM_ENCRYPT_ERROR; + } + (*padLength)++; + } + /* check length for OID */ + if (rc == 0) { + if (*padLength + sizeof(sha1Oid) > inputLength) { + printf("TPM_PKCS1_PaddingType1Check: Error, " + "padLength %u + sizeof(sha1Oid) %lu > inputLength %u\n", + *padLength, (unsigned long)sizeof(sha1Oid), inputLength); + rc = TPM_ENCRYPT_ERROR; + } + } + /* check OID */ + if (rc == 0) { + irc = memcmp(input + *padLength, sha1Oid, sizeof(sha1Oid)); + if (irc != 0) { + printf("TPM_PKCS1_PaddingType1Check: Error, OID mismatch\n"); + TPM_PrintAll(" TPM_PKCS1_PaddingType1Check: OID", + input + *padLength, sizeof(sha1Oid)); + rc = TPM_ENCRYPT_ERROR; + } + *padLength += sizeof(sha1Oid); + } + return rc; +} + +/* TPM_PKCS1_PaddingType2Add() adds the PKCS1 type 2 padding + + The output buffer is preallocated. + + See PKCS1 9.1.2.1 Encoding operation + + This method cheats a bit by adding a leading 00 as well, which is needed for the RSA operation. + + M message to be encoded, an octet string of length at most emLen-10 + emLen intended length in octets of the encoded message + + Output: + EM encoded message, an octet string of length emLen; or "message too long" +*/ + +static TPM_RESULT TPM_PKCS1_PaddingType2Add(unsigned char *encodedMessage, /* to */ + uint32_t encodedMessageLength, /* to length */ + const unsigned char *message, /* from */ + uint32_t messageLength) /* from length */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_PKCS1_PaddingType2Add: Message length %u padded length %u\n", + messageLength, encodedMessageLength); + /* 1. If the length of the message M is greater than emLen - 10 octets, output "message too + long" and stop. */ + if (rc == 0) { + if ((messageLength + 11) > encodedMessageLength) { + printf("TPM_PKCS1_PaddingType2Add: Error, message length too big for padded length\n"); + rc = TPM_ENCRYPT_ERROR; + } + } + /* 2. Generate an octet string PS of length emLen-||M||-2 consisting of pseudorandomly generated + nonzero octets. The length of PS will be at least 8 octets. */ + if (rc == 0) { + rc = TPM_RandomNonZero(encodedMessage + 2, encodedMessageLength - messageLength - 3); + } + /* 3. Concatenate PS, the message M, and other padding to form the encoded message EM as: */ + /* EM = 02 || PS || 00 || M */ + if (rc == 0) { + encodedMessage[0] = 0x00; + encodedMessage[1] = 0x02; + encodedMessage[encodedMessageLength - messageLength - 1] = 0x00; + memcpy(encodedMessage + encodedMessageLength - messageLength, message, messageLength); + } + return rc; +} + +/* TPM_PKCS1_Type2PaddingCheck checks the PKCS1 type 2 padding and recovers the message + + The output buffer is preallocated. +*/ + +static +TPM_RESULT TPM_PKCS1_PaddingType2Check(unsigned char *outputData, /* to */ + uint32_t *outputDataLength, /* to length */ + uint32_t outputDataSize, /* pre-allocated to length */ + unsigned char *inputData, /* from - padded data */ + uint32_t inputDataLength) /* from length */ +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_PKCS1_PaddingType2Check:\n"); + /* check the leading bytes for 0x00, 0x02 */ + if (rc == 0) { + if ((inputData[0] != 0x00) || + (inputData[1] != 0x02)) { + printf("TPM_PKCS1_PaddingType2Check: Error, bad leading bytes %02x %02x\n", + inputData[0], inputData[1]); + rc = TPM_DECRYPT_ERROR; + } + } + /* skip the non-zero random PS */ + for (i = 2 ; (rc == 0) && (i < inputDataLength) ; i++) { + if (inputData[i] == 0x00) { + break; + } + } + /* check for the trailing 0x00 */ + if (rc == 0) { + if (i == inputDataLength) { + printf("TPM_PKCS1_PaddingType2Check: Error, missing trailing 0x00\n"); + rc = TPM_DECRYPT_ERROR; + } + } + /* check that PS was at least 8 bytes */ + if (rc == 0) { + if (i < 10) { + printf("TPM_PKCS1_PaddingType2Check: Error, bad PS length %lu\n", (unsigned long)i-2); + rc = TPM_DECRYPT_ERROR; + } + } + /* check that the output can accommodate the message */ + if (rc == 0) { + i++; /* index past the trailing 0x00 */ + *outputDataLength = inputDataLength - i; + if (*outputDataLength > outputDataSize) { + printf("TPM_PKCS1_PaddingType2Check: Error, " + "message %u greater than output data size %u\n", + *outputDataLength, outputDataSize); + rc = TPM_DECRYPT_ERROR; + } + } + /* copy the message */ + if (rc == 0) { + memcpy(outputData, inputData + inputDataLength - *outputDataLength, *outputDataLength); + } + return rc; +} + +/* + GNU MP wrappers do error logging and transformation of errors to TPM type errors +*/ + +/* TPM_BN_num_bytes() wraps the gnump function in a TPM error handler + + Returns number of bytes in the input +*/ + +TPM_RESULT TPM_BN_num_bytes(unsigned int *numBytes, TPM_BIGNUM bn_in) +{ + TPM_RESULT rc = 0; + mpz_t *bn = (mpz_t *)bn_in; + + /* is the bignum zero */ + int result = mpz_cmp_ui(*bn, 0); + /* mpz_sizeinbase() always returns at least one. If the value is zero, there should really be 0 + bytes */ + if (result == 0) { + *numBytes = 0; + } + /* take the base 2 number and round up to the next byte */ + else { + *numBytes = (mpz_sizeinbase (*bn, 2) +7) / 8; + } + return rc; +} + +/* TPM_BN_is_one() wraps the gnump function in a TPM error handler + + Returns success if input is 1 +*/ + +TPM_RESULT TPM_BN_is_one(TPM_BIGNUM bn_in) +{ + TPM_RESULT rc = 0; + mpz_t *bn = (mpz_t *)bn_in; + int irc; + + irc = mpz_cmp_ui(*bn, 1); + if (irc != 0) { + printf("TPM_BN_is_one: Error, result is not 1\n"); + rc = TPM_DAA_WRONG_W; + } + return rc; +} + + +/* TPM_BN_mod() wraps the gnump function in a TPM error handler + + r = a mod m +*/ + +TPM_RESULT TPM_BN_mod(TPM_BIGNUM rem_in, + const TPM_BIGNUM a_in, + const TPM_BIGNUM m_in) +{ + TPM_RESULT rc = 0; + mpz_t *rBignum = (mpz_t *)rem_in; + mpz_t *aBignum = (mpz_t *)a_in; + mpz_t *mBignum = (mpz_t *)m_in; + + /* set r to a mod m */ + mpz_mod(*rBignum, *aBignum, *mBignum); + return rc; +} + +/* TPM_BN_mask_bits() wraps the gnump function in a TPM error handler + + erase all but the lowest n bits of bn + bn = bn mod 2^^n +*/ + +TPM_RESULT TPM_BN_mask_bits(TPM_BIGNUM bn_in, unsigned int n) +{ + TPM_RESULT rc = 0; + unsigned int numBytes; + mpz_t *bn = (mpz_t *)bn_in; + + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, bn_in); + } + if (rc == 0) { + /* if the BIGNUM is already fewer bits, no need to mask */ + if (numBytes > (n / 8)) { + /* divide and return remainder, divisor is 2^^n */ + mpz_fdiv_r_2exp(*bn, *bn, n); + } + } + return rc; +} + +/* TPM_BN_rshift() wraps the gnump function in a TPM error handler + + Shift a right by n bits (discard the lowest n bits) and label the result r +*/ + +TPM_RESULT TPM_BN_rshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ + TPM_BIGNUM aBignum_in, + int n) +{ + TPM_RESULT rc = 0; + mpz_t **rBignum = (mpz_t **)rBignum_in; + mpz_t *aBignum = (mpz_t *)aBignum_in; + + printf(" TPM_BN_rshift: n %d\n", n); + if (rc == 0) { + rc = TPM_BN_new(rBignum_in); + } + if (rc == 0) { + /* divide and return quotient, rounded down (floor) */ + mpz_fdiv_q_2exp(**rBignum, *aBignum, n); + } + return rc; +} + +/* TPM_BN_lshift() wraps the gnump function in a TPM error handler + + Shift a left by n bits and label the result r +*/ + +TPM_RESULT TPM_BN_lshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ + TPM_BIGNUM aBignum_in, + int n) +{ + TPM_RESULT rc = 0; + mpz_t **rBignum = (mpz_t **)rBignum_in; + mpz_t *aBignum = (mpz_t *)aBignum_in; + + printf(" TPM_BN_lshift: n %d\n", n); + if (rc == 0) { + rc = TPM_BN_new(rBignum_in); + } + if (rc == 0) { + /* multiply by 2^^n is is a left shift by n */ + mpz_mul_2exp(**rBignum, *aBignum, n); + } + return rc; +} + +/* TPM_BN_add() wraps the gnump function in a TPM error handler + + r = a + b +*/ + +TPM_RESULT TPM_BN_add(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in) +{ + TPM_RESULT rc = 0; + mpz_t *rBignum = (mpz_t *)rBignum_in; + mpz_t *aBignum = (mpz_t *)aBignum_in; + mpz_t *bBignum = (mpz_t *)bBignum_in; + + printf(" TPM_BN_add:\n"); + /* result = a + b */ + mpz_add(*rBignum, *aBignum, *bBignum); + return rc; +} + +/* TPM_BN_mul() wraps the gnump function in a TPM error handler + + r = a * b +*/ + +TPM_RESULT TPM_BN_mul(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in) +{ + TPM_RESULT rc = 0; + mpz_t *rBignum = (mpz_t *)rBignum_in; + mpz_t *aBignum = (mpz_t *)aBignum_in; + mpz_t *bBignum = (mpz_t *)bBignum_in; + + printf(" TPM_BN_mul:\n"); + /* r = a * b */ + mpz_mul(*rBignum, *aBignum, *bBignum); + return rc; +} + +/* TPM_BN_mod_exp() wraps the gnump function in a TPM error handler + + computes a to the p-th power modulo m (r=a^p % n) +*/ + +TPM_RESULT TPM_BN_mod_exp(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM pBignum_in, + TPM_BIGNUM nBignum_in) +{ + TPM_RESULT rc = 0; + mpz_t *rBignum = (mpz_t *)rBignum_in; + mpz_t *aBignum = (mpz_t *)aBignum_in; + mpz_t *pBignum = (mpz_t *)pBignum_in; + mpz_t *nBignum = (mpz_t *)nBignum_in; + + printf(" TPM_BN_mod_exp:\n"); + mpz_powm(*rBignum, *aBignum, *pBignum, *nBignum); + return rc; +} + +/* TPM_BN_Mod_add() wraps the gnump function in a TPM error handler + + adds a to b modulo m +*/ + +TPM_RESULT TPM_BN_mod_add(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in, + TPM_BIGNUM mBignum_in) +{ + TPM_RESULT rc = 0; + mpz_t *rBignum = (mpz_t *)rBignum_in; + mpz_t *aBignum = (mpz_t *)aBignum_in; + mpz_t *bBignum = (mpz_t *)bBignum_in; + mpz_t *mBignum = (mpz_t *)mBignum_in; + + printf(" TPM_BN_mod_add:\n"); + /* r = a + b */ + mpz_add(*rBignum, *aBignum, *bBignum); + /* set r to r mod m */ + mpz_mod(*rBignum, *rBignum, *mBignum); + return rc; +} + +/* TPM_BN_mod_mul() wraps the gnump function in a TPM error handler + + r = (a * b) mod m +*/ + +TPM_RESULT TPM_BN_mod_mul(TPM_BIGNUM rBignum_in, + TPM_BIGNUM aBignum_in, + TPM_BIGNUM bBignum_in, + TPM_BIGNUM mBignum_in) +{ + TPM_RESULT rc = 0; + mpz_t *rBignum = (mpz_t *)rBignum_in; + mpz_t *aBignum = (mpz_t *)aBignum_in; + mpz_t *bBignum = (mpz_t *)bBignum_in; + mpz_t *mBignum = (mpz_t *)mBignum_in; + + printf(" TPM_BN_mod_mul:\n"); + /* r = a * b */ + mpz_mul(*rBignum, *aBignum, *bBignum); + /* set r to r mod m */ + mpz_mod(*rBignum, *rBignum, *mBignum); + return rc; +} + +/* TPM_BN_new() wraps the gnump function in a TPM error handler + + Allocates a new bignum +*/ + +TPM_RESULT TPM_BN_new(TPM_BIGNUM *bn_in) /* freed by caller */ +{ + TPM_RESULT rc = 0; + mpz_t *bn; + + if (rc== 0) { + rc = TPM_Malloc(bn_in, sizeof(mpz_t)); /* freed by caller */ + } + if (rc== 0) { + bn = (mpz_t *)*bn_in; + mpz_init(*bn); + } + return rc; +} + +/* TPM_BN_free() wraps the gnump function + + Frees the bignum +*/ + +void TPM_BN_free(TPM_BIGNUM bn_in) +{ + mpz_t *bn = (mpz_t *)bn_in; + if (bn != NULL) { + mpz_clear(*bn); + free(bn_in); + } + return; +} + +/* TPM_bn2bin wraps the function in gnump a TPM error handler. + + Converts a bignum to char array + + 'bin' must already be checked for sufficient size. +*/ + +TPM_RESULT TPM_bn2bin(unsigned char *bin, + TPM_BIGNUM bn_in) +{ + TPM_RESULT rc = 0; + mpz_t *bn = (mpz_t *)bn_in; + + mpz_export(bin, /* output */ + NULL, /* countp */ + 1, /* order, MSB first */ + 1, /* size, char */ + 0, /* endian, native (unused) */ + 0, /* nails, don't discard */ + *bn); /* input */ + return rc; +} + +/* TPM_memcpyPad allocates a buffer 'bin_out' and loads it from 'bin_in'. + + If padBytes is non-zero, 'bin_out' is padded with leading zeros if necessary, so that 'bytes' + will equal 'padBytes'. This is used when TPM data structures expect a fixed length while + the crypto library truncates leading zeros. + + '*bin_out' must be freed by the caller +*/ + +static TPM_RESULT TPM_memcpyPad(unsigned char **bin_out, + unsigned char *bin_in, + uint32_t bin_in_length, + uint32_t padBytes) +{ + TPM_RESULT rc = 0; + + printf(" TPM_memcpyPad: padBytes %u\n", padBytes); + if (rc == 0) { + /* padBytes 0 says that no padding is required */ + if (padBytes == 0) { + padBytes = bin_in_length; /* setting equal yields no padding */ + } + /* The required output should never be less than the supplied input. Sanity check and + return a fatal error. */ + if (padBytes < bin_in_length) { + printf("TPM_memcpyPad: Error (fatal), " + "padBytes %u less than %u\n", padBytes, bin_in_length); + rc = TPM_FAIL; + } + if (padBytes != bin_in_length) { + printf(" TPM_memcpyPad: padBytes %u bytes %u\n", padBytes, bin_in_length); + } + } + /* allocate memory for the padded output */ + if (rc == 0) { + rc = TPM_Malloc(bin_out, padBytes); + } + if (rc == 0) { + memset(*bin_out, 0, padBytes - bin_in_length); /* leading 0 padding */ + memcpy((*bin_out) + padBytes - bin_in_length, /* start copy after padding */ + bin_in, bin_in_length); + } + return rc; +} + +/* TPM_bin2bn() wraps the gnump function in a TPM error handler + + Converts a char array to bignum + + bn must be freed by the caller. +*/ + +TPM_RESULT TPM_bin2bn(TPM_BIGNUM *bn_in, const unsigned char *bin, unsigned int bytes) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + rc = TPM_BN_new(bn_in); + } + if (rc == 0) { + mpz_t *bn = (mpz_t *)*bn_in; + mpz_import(*bn, /* output */ + bytes, /* count */ + 1, /* order, MSB first */ + 1, /* size, char */ + 0, /* endian, native (unused) */ + 0, /* nail, don't discard */ + bin); /* input */ + } + return rc; +} + +/* + Hash Functions +*/ + +/* TPM_SHA1InitCmd() initializes a platform dependent TPM_SHA1Context structure. + + The structure must be freed using TPM_SHA1FinalCmd() +*/ + +TPM_RESULT TPM_SHA1InitCmd(void **context) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SHA1InitCmd:\n"); + if (rc == 0) { + /* create a new freebl SHA1 context */ + *context = SHA1_NewContext(); + if (*context == NULL) { + printf("TPM_SHA1InitCmd: Error allocating a new context\n"); + rc = TPM_SIZE; + } + } + /* reset the SHA-1 context, preparing it for a fresh round of hashing */ + if (rc== 0) { + SHA1_Begin(*context); + } + return rc; +} + +/* TPM_SHA1UpdateCmd() adds 'data' of 'length' to the SHA-1 context + */ + +TPM_RESULT TPM_SHA1UpdateCmd(void *context, const unsigned char *data, uint32_t length) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SHA1Update: length %u\n", length); + if (context != NULL) { + SHA1_Update(context, data, length); + } + else { + printf("TPM_SHA1Update: Error, no existing SHA1 thread\n"); + rc = TPM_SHA_THREAD; + } + return rc; +} + +/* TPM_SHA1FinalCmd() extracts the SHA-1 digest 'md' from the context + */ + +TPM_RESULT TPM_SHA1FinalCmd(unsigned char *md, void *context) +{ + TPM_RESULT rc = 0; + unsigned int digestLen; + + printf(" TPM_SHA1FinalCmd:\n"); + if (rc== 0) { + if (context == NULL) { + printf("TPM_SHA1FinalCmd: Error, no existing SHA1 thread\n"); + rc = TPM_SHA_THREAD; + } + } + if (rc== 0) { + SHA1_End(context, md, &digestLen, TPM_DIGEST_SIZE); + /* Sanity check. For SHA1 it should always be 20 bytes. */ + if (digestLen != TPM_DIGEST_SIZE) { + printf("TPM_SHA1Final: Error (fatal), SHA1_End returned %u bytes\n", digestLen); + rc = TPM_FAIL; + } + } + return rc; +} + +/* TPM_SHA1Delete() zeros and frees the SHA1 context */ + +void TPM_SHA1Delete(void **context) +{ + if (*context != NULL) { + printf(" TPM_SHA1Delete:\n"); + /* zero because the SHA1 context might have data left from an HMAC */ + SHA1_DestroyContext(*context, PR_TRUE); + *context = NULL; + } + return; +} + +#if defined (__x86_64__) || \ + defined(__amd64__) || \ + defined(__ia64__) || \ + defined(__powerpc64__) || \ + defined(__s390x__) || \ + (defined(__sparc__) && defined(__arch64__)) || \ + defined(__aarch64__) + +#define IS_64 +typedef PRUint64 SHA_HW_t; + +#elif defined (__i386__) || \ + defined (__powerpc__) || \ + defined (__s390__) || \ + defined(__sparc__) || \ + defined(__arm__) + +typedef PRUint32 SHA_HW_t; +#undef IS_64 + +#else +#error "Cannot determine 32 or 64 bit platform" +#endif + +/* The structure returned by the SHA1_Flatten() command and passed to SHA1_Resurrect() + */ + +typedef struct SHA1SaveContextStrtd { + union { + PRUint32 w[16]; /* input buffer */ + PRUint8 b[64]; + } u; + PRUint64 size; /* count of hashed bytes. */ + SHA_HW_t H[22]; /* 5 state variables, 16 tmp values, 1 + extra */ +} SHA1SaveContextStr; + + +/* TPM_Sha1Context_Load() is non-portable code to deserialize the FreeBL SHA1 context. + + If the contextPresent prepended by TPM_Sha1Context_Store() is FALSE, context remains NULL. If + TRUE, context is allocated and loaded. +*/ + +TPM_RESULT TPM_Sha1Context_Load(void **context, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + TPM_BOOL contextPresent; /* is there a context to be loaded */ + uint32_t flattenSize; /* from the freebl library */ + SHA1Context *tmpContext = NULL; /* temp to get flatten size, freed @1 */ + uint32_t tmp32; /* temp to recreate 64-bit size */ + SHA1SaveContextStr restoreContext; + size_t i; + + printf(" TPM_Sha1Context_Load: FreeBL\n"); + /* TPM_Sha1Context_Store() stored a flag to indicate whether a context was stored */ + if (rc== 0) { + rc = TPM_LoadBool(&contextPresent, stream, stream_size); + printf(" TPM_Sha1Context_Load: contextPresent %u\n", contextPresent); + } + /* check format tag */ + /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' + on the tag */ + if ((rc== 0) && contextPresent) { + rc = TPM_CheckTag(TPM_TAG_SHA1CONTEXT_FREEBL_V1, stream, stream_size); + } + /* check that context is NULL to detect memory leak */ + if ((rc== 0) && contextPresent) { + if (*context != NULL) { + printf("TPM_Sha1Context_Load: Error (fatal), *context %p should be NULL\n", *context ); + rc = TPM_FAIL; + } + } + /* create a temporary context just to get the freebl library size */ + if ((rc== 0) && contextPresent) { + rc = TPM_SHA1InitCmd((void **)&tmpContext); /* freed @1 */ + } + /* get the size of the FreeBL library SHA1 context */ + if ((rc== 0) && contextPresent) { + flattenSize = SHA1_FlattenSize(tmpContext); + /* sanity check that the freebl library and TPM structure here are in sync */ + if (flattenSize != sizeof(SHA1SaveContextStr)) { + printf("TPM_Sha1Context_Load: Error, " + "SHA1 context size %u from SHA1_FlattenSize not equal %lu from structure\n", + flattenSize, (unsigned long)sizeof(SHA1SaveContextStr)); + rc = TPM_BAD_PARAM_SIZE; + } + } + /* + deserialization code to fill in restoreContext + */ + /* b[0..63] <- u.b[0..63] (bytes only, no bytswapping) */ + if ((rc== 0) && contextPresent) { + rc = TPM_Loadn(restoreContext.u.b, 64, stream, stream_size); + } + /* count <- size (this is 64 bits on all platforms) */ + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&tmp32, stream, stream_size); + restoreContext.size = (uint64_t)tmp32 << 32; /* big endian */ + } + if ((rc== 0) && contextPresent) { + rc = TPM_Load32(&tmp32, stream, stream_size); + restoreContext.size += (uint64_t)tmp32 & 0xffffffff; /* big endian */ + } + for (i = 0 ; (rc == 0) && contextPresent && (i < 5) ; i++) { + rc = TPM_Load32(&tmp32, stream, stream_size); + restoreContext.H[i] = tmp32; /* H can be 32 or 64 bits */ + } + /* load the context */ + if ((rc== 0) && contextPresent) { + /* the size test above ensures that the cast here is safe */ + *context = SHA1_Resurrect((unsigned char *)&restoreContext, NULL); + if (*context == NULL) { + printf("TPM_Sha1Context_Load: Error, could not SHA1_Resurrect\n"); + rc = TPM_SIZE; + } + } + TPM_SHA1Delete((void *)&tmpContext); /* @1 */ + return rc; +} + +/* TPM_Sha1Context_Store() is non-portable code to serialize the FreeBL SHA1 context. context is + not altered. + + It prepends a contextPresent flag to the stream, FALSE if context is NULL, TRUE if not. +*/ + +TPM_RESULT TPM_Sha1Context_Store(TPM_STORE_BUFFER *sbuffer, + void *context) +{ + TPM_RESULT rc = 0; + SECStatus rv = SECSuccess; + size_t i; + unsigned int flattenSize; + SHA1SaveContextStr saveContext; + TPM_BOOL contextPresent; /* is there a context to be stored */ + + printf(" TPM_Sha1Context_Store: FreeBL\n"); + /* store contextPresent */ + if (rc == 0) { + if (context != NULL) { + printf(" TPM_Sha1Context_Store: Storing context\n"); + contextPresent = TRUE; + } + else { + printf(" TPM_Sha1Context_Store: No context to store\n"); + contextPresent = FALSE; + } + printf(" TPM_Sha1Context_Store: contextPresent %u \n", contextPresent); + rc = TPM_Sbuffer_Append(sbuffer, &contextPresent, sizeof(TPM_BOOL)); + } + /* overall format tag */ + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SHA1CONTEXT_FREEBL_V1); + } + if ((rc== 0) && contextPresent) { + /* get the size of the FreeBL SHA1 context */ + flattenSize = SHA1_FlattenSize(context); /* it will not be NULL here */ + /* sanity check that the freebl library and TPM structure here are in sync */ + if (flattenSize != sizeof(SHA1SaveContextStr)) { + printf("TPM_Sha1Context_Store: Error (fatal), " + "SHA1 context size %u from SHA1_FlattenSize not equal %lu from structure\n", + flattenSize, (unsigned long)sizeof(SHA1SaveContextStr)); + rc = TPM_FAIL; + } + } + /* store into the structure from the library */ + if ((rc== 0) && contextPresent) { + /* the size test above ensures that the cast here is safe */ + rv = SHA1_Flatten(context, (unsigned char *)&saveContext); + if (rv != SECSuccess) { + printf("TPM_Sha1Context_Store: Error (fatal), SHA1_Flatten rv %d\n", rv); + rc = TPM_FAIL; + } + } + /* + append the FreeBL SHA1 context to the stream + */ + /* b[0..63] <- u.b[0..63] (bytes only, no byte swapping) */ + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append(sbuffer, saveContext.u.b, 64); + } + /* count <- size (this is 64 bits on all platforms) */ + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, saveContext.size >> 32); /* big endian */ + } + if ((rc== 0) && contextPresent) { + rc = TPM_Sbuffer_Append32(sbuffer, saveContext.size & 0xffffffff); + } + /* SHA_HW_t - NSS uses 64 bits on 64 bit platforms for performance reasons only. The lower 32 + bits are critical, so you can always serialize/deserialize just the lower 32 bits. */ + /* The remainder of the H array is scratch memory and does not need to be preserved or + transmitted. */ + for (i = 0 ; (rc == 0) && contextPresent && (i < 5) ; i++) { + rc = TPM_Sbuffer_Append32(sbuffer, saveContext.H[i] & 0xffffffff); + } + return rc; +} + +/* + TPM_SYMMETRIC_KEY_DATA +*/ + +#ifdef TPM_AES + +/* TPM_SymmetricKeyData_New() allocates memory for and initializes a TPM_SYMMETRIC_KEY_DATA token. + */ + +TPM_RESULT TPM_SymmetricKeyData_New(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SymmetricKeyData_New:\n"); + if (rc == 0) { + rc = TPM_Malloc(tpm_symmetric_key_data, sizeof(TPM_SYMMETRIC_KEY_DATA)); + } + if (rc == 0) { + TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); + } + return rc; +} + +/* TPM_SymmetricKeyData_Free() initializes the key token to wipe secrets. It then frees the + TPM_SYMMETRIC_KEY_DATA token and sets it to NULL. +*/ + +void TPM_SymmetricKeyData_Free(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) +{ + printf(" TPM_SymmetricKeyData_Free:\n"); + if (*tpm_symmetric_key_data != NULL) { + TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); + free(*tpm_symmetric_key_data); + *tpm_symmetric_key_data = NULL; + } + return; +} + +/* TPM_SymmetricKeyData_Init() is AES non-portable code to initialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Init:\n"); + tpm_symmetric_key_data->tag = TPM_TAG_KEY; + tpm_symmetric_key_data->valid = FALSE; + tpm_symmetric_key_data->fill = 0; + /* zero to wipe secrets */ + memset(tpm_symmetric_key_data->userKey, 0, sizeof(tpm_symmetric_key_data->userKey)); + return; +} + +/* TPM_SymmetricKeyData_Load() is AES non-portable code to deserialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_KEY, stream, stream_size); + } + /* load valid */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_symmetric_key_data->valid), stream, stream_size); + } + /* load fill */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_symmetric_key_data->fill), stream, stream_size); + } + /* The AES key is a simple array. */ + if (rc == 0) { + rc = TPM_Loadn(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey), + stream, stream_size); + } + return rc; +} + +/* TPM_SymmetricKeyData_Store() is AES non-portable code to serialize the TPM_SYMMETRIC_KEY_DATA + + It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. +*/ + +TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key_data->tag); + } + /* store valid */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->valid), sizeof(TPM_BOOL)); + } + /* store fill */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->fill), sizeof(TPM_BOOL)); + } + /* store AES key */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + tpm_symmetric_key_data->userKey, + sizeof(tpm_symmetric_key_data->userKey)); + } + return rc; +} + +/* TPM_SymmetricKeyData_GenerateKey() is AES non-portable code to generate a random symmetric key + + tpm_symmetric_key_data should be initialized before and after use +*/ + +TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) +{ + TPM_RESULT rc = 0; + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_GenerateKey:\n"); + /* generate a random key */ + if (rc == 0) { + rc = TPM_Random(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey)); + } + if (rc == 0) { + tpm_symmetric_key_data->valid = TRUE; + } + return rc; +} + +/* TPM_SymmetricKeyData_Encrypt() is AES non-portable code to CBC encrypt 'decrypt_data' to + 'encrypt_data' + + The stream is padded as per PKCS#7 / RFC2630 + + 'encrypt_data' must be free by the caller +*/ + +TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ + uint32_t *encrypt_length, /* output */ + const unsigned char *decrypt_data, /* input */ + uint32_t decrypt_length, /* input */ + const TPM_SYMMETRIC_KEY_TOKEN + tpm_symmetric_key_token) /* input */ +{ + TPM_RESULT rc = 0; + SECStatus rv; + AESContext *cx; + uint32_t pad_length; + uint32_t output_length; /* dummy */ + unsigned char *decrypt_data_pad; + unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); + decrypt_data_pad = NULL; /* freed @1 */ + cx = NULL; /* freed @2 */ + + /* sanity check that the AES key has previously been generated */ + if (rc == 0) { + if (!tpm_symmetric_key_data->valid) { + printf("TPM_SymmetricKeyData_Encrypt: Error (fatal), AES key not valid\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + /* calculate the PKCS#7 / RFC2630 pad length and padded data length */ + pad_length = TPM_AES_BLOCK_SIZE - (decrypt_length % TPM_AES_BLOCK_SIZE); + *encrypt_length = decrypt_length + pad_length; + printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", + *encrypt_length, pad_length); + /* allocate memory for the encrypted response */ + rc = TPM_Malloc(encrypt_data, *encrypt_length); + } + /* allocate memory for the padded decrypted data */ + if (rc == 0) { + rc = TPM_Malloc(&decrypt_data_pad, *encrypt_length); + } + if (rc == 0) { + /* set the IV */ + memset(ivec, 0, sizeof(ivec)); + /* create a new AES context */ + cx = AES_CreateContext(tpm_symmetric_key_data->userKey, + ivec, /* CBC initialization vector */ + NSS_AES_CBC, /* CBC mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE, /* key length */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + if (cx == NULL) { + printf("TPM_SymmetricKeyData_Encrypt: Error creating AES context\n"); + rc = TPM_SIZE; + } + } + /* pad the decrypted clear text data */ + if (rc == 0) { + /* unpadded original data */ + memcpy(decrypt_data_pad, decrypt_data, decrypt_length); + /* last gets pad = pad length */ + memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); + /* encrypt the padded input to the output */ + TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Input", decrypt_data_pad); + /* perform the AES encryption */ + rv = AES_Encrypt(cx, + *encrypt_data, &output_length, *encrypt_length, /* output */ + decrypt_data_pad, *encrypt_length); /* input */ + + if (rv != SECSuccess) { + printf("TPM_SymmetricKeyData_Encrypt: Error, rv %d\n", rv); + rc = TPM_ENCRYPT_ERROR; + } + } + if (rc == 0) { + TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Output", *encrypt_data); + } + free(decrypt_data_pad); /* @1 */ + if (cx != NULL) { + /* due to a FreeBL bug, must zero the context before destroying it */ + unsigned char dummy_key[TPM_AES_BLOCK_SIZE]; + unsigned char dummy_ivec[TPM_AES_BLOCK_SIZE]; + memset(dummy_key, 0x00, TPM_AES_BLOCK_SIZE); + memset(dummy_ivec, 0x00, TPM_AES_BLOCK_SIZE); + rv = AES_InitContext(cx, /* AES context */ + dummy_key, /* AES key */ + TPM_AES_BLOCK_SIZE, /* key length */ + dummy_ivec, /* ivec */ + NSS_AES_CBC, /* CBC mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + AES_DestroyContext(cx, PR_TRUE); /* @2 */ + } + return rc; +} + +/* TPM_SymmetricKeyData_Decrypt() is AES non-portable code to CBC decrypt 'encrypt_data' to + 'decrypt_data' + + The stream must be padded as per PKCS#7 / RFC2630 + + decrypt_data must be free by the caller +*/ + +TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ + uint32_t *decrypt_length, /* output */ + const unsigned char *encrypt_data, /* input */ + uint32_t encrypt_length, /* input */ + const TPM_SYMMETRIC_KEY_TOKEN + tpm_symmetric_key_token) /* input */ +{ + TPM_RESULT rc = 0; + SECStatus rv; + AESContext *cx; + uint32_t pad_length; + uint32_t output_length; /* dummy */ + uint32_t i; + unsigned char *pad_data; + unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ + TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = + (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; + + printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); + cx = NULL; /* freed @1 */ + + /* sanity check encrypted length */ + if (rc == 0) { + if (encrypt_length < TPM_AES_BLOCK_SIZE) { + printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); + rc = TPM_DECRYPT_ERROR; + } + } + /* sanity check that the AES key has previously been generated */ + if (rc == 0) { + if (!tpm_symmetric_key_data->valid) { + printf("TPM_SymmetricKeyData_Decrypt: Error (fatal), AES key not valid\n"); + rc = TPM_FAIL; + } + } + /* allocate memory for the PKCS#7 / RFC2630 padded decrypted data */ + if (rc == 0) { + rc = TPM_Malloc(decrypt_data, encrypt_length); + } + if (rc == 0) { + /* set the IV */ + memset(ivec, 0, sizeof(ivec)); + /* create a new AES context */ + cx = AES_CreateContext(tpm_symmetric_key_data->userKey, + ivec, /* CBC initialization vector */ + NSS_AES_CBC, /* CBC mode */ + FALSE, /* decrypt */ + TPM_AES_BLOCK_SIZE, /* key length */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + if (cx == NULL) { + printf("TPM_SymmetricKeyData_Decrypt: Error creating AES context\n"); + rc = TPM_SIZE; + } + } + /* decrypt the input to the PKCS#7 / RFC2630 padded output */ + if (rc == 0) { + TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Input", encrypt_data); + /* perform the AES decryption */ + rv = AES_Decrypt(cx, + *decrypt_data, &output_length, encrypt_length, /* output */ + encrypt_data, encrypt_length); /* input */ + if (rv != SECSuccess) { + printf("TPM_SymmetricKeyData_Decrypt: Error, rv %d\n", rv); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Output", *decrypt_data); + } + /* get the pad length */ + if (rc == 0) { + /* get the pad length from the last byte */ + pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); + /* sanity check the pad length */ + printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); + if ((pad_length == 0) || + (pad_length > TPM_AES_BLOCK_SIZE)) { + printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + /* get the unpadded length */ + *decrypt_length = encrypt_length - pad_length; + /* pad starting point */ + pad_data = *decrypt_data + *decrypt_length; + /* sanity check the pad */ + for (i = 0 ; i < pad_length ; i++, pad_data++) { + if (*pad_data != pad_length) { + printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", + *pad_data, i); + rc = TPM_DECRYPT_ERROR; + } + } + } + if (cx != NULL) { + /* due to a FreeBL bug, must zero the context before destroying it */ + unsigned char dummy_key[TPM_AES_BLOCK_SIZE]; + unsigned char dummy_ivec[TPM_AES_BLOCK_SIZE]; + memset(dummy_key, 0x00, TPM_AES_BLOCK_SIZE); + memset(dummy_ivec, 0x00, TPM_AES_BLOCK_SIZE); + rv = AES_InitContext(cx, /* AES context */ + dummy_key, /* AES key */ + TPM_AES_BLOCK_SIZE, /* key length */ + dummy_ivec, /* ivec */ + NSS_AES_CBC, /* CBC mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + AES_DestroyContext(cx, PR_TRUE); /* @1 */ + } + return rc; +} + +/* TPM_SymmetricKeyData_CtrCrypt() does an encrypt or decrypt (they are the same XOR operation with + a CTR mode pad) of 'data_in' to 'data_out'. + + TPM_SymmetricKeyData_CtrCrypt() is a TPM variant of the standard CTR encrypt function that + increments only the low 4 bytes of the counter. + + NOTE: This function looks general, but is currently hard coded to AES128. + + 'symmetric key' is the raw key, not converted to a non-portable form + 'ctr_in' is the initial CTR value before possible truncation +*/ + +TPM_RESULT TPM_SymmetricKeyData_CtrCrypt(unsigned char *data_out, /* output */ + const unsigned char *data_in, /* input */ + uint32_t data_size, /* input */ + const unsigned char *symmetric_key, /* input */ + uint32_t symmetric_key_size, /* input */ + const unsigned char *ctr_in, /* input */ + uint32_t ctr_in_size) /* input */ +{ + TPM_RESULT rc = 0; + SECStatus rv; + AESContext *cx = NULL; + unsigned char ctr[TPM_AES_BLOCK_SIZE]; + unsigned char pad_buffer[TPM_AES_BLOCK_SIZE]; /* the XOR pad */ + uint32_t output_length; /* dummy */ + uint32_t cint; /* counter as a 32-bit integer */ + + printf(" TPM_SymmetricKeyData_CtrCrypt: data_size %u\n", data_size); + symmetric_key_size = symmetric_key_size; + /* check the input CTR size, it can be truncated, but cannot be smaller than the AES key */ + if (rc == 0) { + if (ctr_in_size < sizeof(ctr)) { + printf(" TPM_SymmetricKeyData_CtrCrypt: Error (fatal)" + ", CTR size %u too small for AES key\n", ctr_in_size); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + /* make a truncated copy of CTR, since this function alters the value */ + memcpy(ctr, ctr_in, sizeof(ctr)); + TPM_PrintFour(" TPM_SymmetricKeyData_CtrCrypt: CTR", ctr); + } + /* create a new AES context */ + if (rc == 0) { + cx = AES_CreateContext(symmetric_key, /* AES key */ + NULL, /* ivec not used in NSS_AES */ + NSS_AES, /* mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE, /* key length */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + if (cx == NULL) { + printf("TPM_SymmetricKeyData_CtrCrypt: Error creating AES context\n"); + rc = TPM_SIZE; + } + } + while (data_size != 0) { + printf(" TPM_SymmetricKeyData_CtrCrypt : data_size remaining %u\n", data_size); + /* initialize the context each time through the loop */ + if (rc == 0) { + rv = AES_InitContext(cx, /* AES context */ + symmetric_key, /* AES key */ + TPM_AES_BLOCK_SIZE, /* key length */ + NULL, /* ivec not used in NSS_AES */ + NSS_AES, /* mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + if (rv != SECSuccess) { + printf("TPM_SymmetricKeyData_CtrCrypt: Error, rv %d\n", rv); + rc = TPM_ENCRYPT_ERROR; + } + } + /* get an XOR pad array by encrypting the CTR with the AES key */ + if (rc == 0) { + rv = AES_Encrypt(cx, + pad_buffer, &output_length, TPM_AES_BLOCK_SIZE, /* output */ + ctr, TPM_AES_BLOCK_SIZE); /* input */ + + if (rv != SECSuccess) { + printf("TPM_SymmetricKeyData_CtrCrypt: Error, rv %d\n", rv); + rc = TPM_ENCRYPT_ERROR; + } + } + if (rc == 0) { + /* partial or full last data block */ + if (data_size <= TPM_AES_BLOCK_SIZE) { + TPM_XOR(data_out, data_in, pad_buffer, data_size); + data_size = 0; + } + /* full block, not the last block */ + else { + TPM_XOR(data_out, data_in, pad_buffer, TPM_AES_BLOCK_SIZE); + data_in += TPM_AES_BLOCK_SIZE; + data_out += TPM_AES_BLOCK_SIZE; + data_size -= TPM_AES_BLOCK_SIZE; + } + /* if not the last block, increment CTR, only the low 4 bytes */ + if (data_size != 0) { + /* CTR is a big endian array, so the low 4 bytes are used */ + cint = LOAD32(ctr, TPM_AES_BLOCK_SIZE-4); /* byte array to uint32_t */ + cint++; /* increment */ + STORE32(ctr, TPM_AES_BLOCK_SIZE-4, cint); /* uint32_t to byte array */ + } + } + } + if (cx != NULL) { + /* due to a FreeBL bug, must zero the context before destroying it */ + unsigned char dummy_key[TPM_AES_BLOCK_SIZE]; + memset(dummy_key, 0x00, TPM_AES_BLOCK_SIZE); + rv = AES_InitContext(cx, /* AES context */ + dummy_key, /* AES key */ + TPM_AES_BLOCK_SIZE, /* key length */ + NULL, /* ivec not used in NSS_AES */ + NSS_AES, /* mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + AES_DestroyContext(cx, PR_TRUE); /* @2 */ + } + return rc; +} + +/* TPM_SymmetricKeyData_OfbCrypt() does an encrypt or decrypt (they are the same XOR operation with + a OFB mode pad) of 'data_in' to 'data_out' + + NOTE: This function looks general, but is currently hard coded to AES128. + + 'symmetric key' is the raw key, not converted to a non-portable form + 'ivec_in' is the initial IV value before possible truncation +*/ + +TPM_RESULT TPM_SymmetricKeyData_OfbCrypt(unsigned char *data_out, /* output */ + const unsigned char *data_in, /* input */ + uint32_t data_size, /* input */ + const unsigned char *symmetric_key, /* in */ + uint32_t symmetric_key_size, /* in */ + unsigned char *ivec_in, /* input */ + uint32_t ivec_in_size) /* input */ +{ + TPM_RESULT rc = 0; + SECStatus rv; + AESContext *cx = NULL; + unsigned char ivec_loop[TPM_AES_BLOCK_SIZE]; /* ivec input to loop */ + unsigned char pad_buffer[TPM_AES_BLOCK_SIZE]; /* the XOR pad */ + uint32_t output_length; /* dummy */ + + printf(" TPM_SymmetricKeyData_OfbCrypt: data_size %u\n", data_size); + symmetric_key_size = symmetric_key_size; + /* check the input OFB size, it can be truncated, but cannot be smaller than the AES key */ + if (rc == 0) { + if (ivec_in_size < TPM_AES_BLOCK_SIZE) { + printf(" TPM_SymmetricKeyData_OfbCrypt: Error (fatal)," + "IV size %u too small for AES key\n", ivec_in_size); + rc = TPM_FAIL; /* should never occur */ + } + } + /* first time through, the ivec_loop will be the input ivec */ + if (rc == 0) { + memcpy(ivec_loop, ivec_in, sizeof(ivec_loop)); + TPM_PrintFour(" TPM_SymmetricKeyData_OfbCrypt: IV", ivec_loop); + } + /* create a new AES context */ + if (rc == 0) { + cx = AES_CreateContext(symmetric_key, + NULL, /* ivec not used in NSS_AES */ + NSS_AES, /* mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE, /* key length */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + if (cx == NULL) { + printf("TPM_SymmetricKeyData_OfbCrypt: Error creating AES context\n"); + rc = TPM_SIZE; + } + } + while (data_size != 0) { + printf(" TPM_SymmetricKeyData_OfbCrypt: data_size remaining %u\n", data_size); + /* initialize the context each time through the loop */ + if (rc == 0) { + rv = AES_InitContext(cx, /* AES context */ + symmetric_key, /* AES key */ + TPM_AES_BLOCK_SIZE, /* key length */ + NULL, /* ivec not used in NSS_AES */ + NSS_AES, /* mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + if (rv != SECSuccess) { + printf("TPM_SymmetricKeyData_OfbCrypt: Error, rv %d\n", rv); + rc = TPM_ENCRYPT_ERROR; + } + } + /* get an XOR pad array by encrypting the IV with the AES key */ + if (rc == 0) { + TPM_PrintFour(" TPM_SymmetricKeyData_OfbCrypt: IV", ivec_loop); + rv = AES_Encrypt(cx, + pad_buffer, &output_length, TPM_AES_BLOCK_SIZE, /* output */ + ivec_loop, TPM_AES_BLOCK_SIZE); /* input */ + + if (rv != SECSuccess) { + printf("TPM_SymmetricKeyData_OfbCrypt: Error, rv %d\n", rv); + rc = TPM_ENCRYPT_ERROR; + } + } + if (rc == 0) { + /* partial or full last data block */ + if (data_size <= TPM_AES_BLOCK_SIZE) { + TPM_XOR(data_out, data_in, pad_buffer, data_size); + data_size = 0; + } + /* full block, not the last block */ + else { + TPM_XOR(data_out, data_in, pad_buffer, TPM_AES_BLOCK_SIZE); + data_in += TPM_AES_BLOCK_SIZE; + data_out += TPM_AES_BLOCK_SIZE; + data_size -= TPM_AES_BLOCK_SIZE; + } + /* if not the last block, wrap the pad_buffer back to ivec_loop (output feed back) */ + memcpy(ivec_loop, pad_buffer, TPM_AES_BLOCK_SIZE); + } + } + if (cx != NULL) { + /* due to a FreeBL bug, must zero the context before destroying it */ + unsigned char dummy_key[TPM_AES_BLOCK_SIZE]; + memset(dummy_key, 0x00, TPM_AES_BLOCK_SIZE); + rv = AES_InitContext(cx, /* AES context */ + dummy_key, /* AES key */ + TPM_AES_BLOCK_SIZE, /* key length */ + NULL, /* ivec not used in NSS_AES */ + NSS_AES, /* mode */ + TRUE, /* encrypt */ + TPM_AES_BLOCK_SIZE); /* AES block length */ + AES_DestroyContext(cx, PR_TRUE); /* @2 */ + } + return rc; +} + +#endif /* TPM_AES */ diff --git a/src/tpm12/tpm_cryptoh.c b/src/tpm12/tpm_cryptoh.c new file mode 100644 index 0000000..36df6aa --- /dev/null +++ b/src/tpm12/tpm_cryptoh.c @@ -0,0 +1,5427 @@ +/********************************************************************************/ +/* */ +/* High Level Platform Independent Cryptography */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_cryptoh.c 4540 2011-04-07 18:51:34Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include +#include + +#include "tpm_admin.h" +#include "tpm_auth.h" +#include "tpm_crypto.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_memory.h" +#include "tpm_migration.h" +#include "tpm_nonce.h" +#include "tpm_key.h" +#include "tpm_pcr.h" +#include "tpm_process.h" +#include "tpm_store.h" +#include "tpm_ver.h" + +#include "tpm_cryptoh.h" + +/* local prototypes */ + +static TPM_RESULT TPM_SHA1_valist(TPM_DIGEST md, + uint32_t length0, unsigned char *buffer0, + va_list ap); +static TPM_RESULT TPM_HMAC_Generatevalist(TPM_HMAC hmac, + const TPM_SECRET key, + va_list ap); + +static TPM_RESULT TPM_SHA1CompleteCommon(TPM_DIGEST hashValue, + void **sha1_context, + TPM_SIZED_BUFFER *hashData); + +/* + TPM_SIGN_INFO +*/ + +/* TPM_SignInfo_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_SignInfo_Init(TPM_SIGN_INFO *tpm_sign_info) +{ + printf(" TPM_SignInfo_Init:\n"); + memset(tpm_sign_info->fixed, 0, TPM_SIGN_INFO_FIXED_SIZE); + TPM_Nonce_Init(tpm_sign_info->replay); + TPM_SizedBuffer_Init(&(tpm_sign_info->data)); + return; +} + +/* TPM_SignInfo_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_SignInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SIGN_INFO *tpm_sign_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SignInfo_Store:\n"); + /* store the tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SIGNINFO); + } + /* store the fixed */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_sign_info->fixed, TPM_SIGN_INFO_FIXED_SIZE); + } + /* store the replay */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_sign_info->replay); + } + /* store the dataLen and data */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_sign_info->data)); + } + if (rc == 0) { + const unsigned char *buffer; + uint32_t length; + TPM_Sbuffer_Get(sbuffer, &buffer, &length); + TPM_PrintAll(" TPM_SignInfo_Store: Buffer", buffer, length); + } + return rc; +} + +/* TPM_SignInfo_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the sign_info + sets pointers to NULL + calls TPM_SignInfo_Init to set members back to default values + The sign_info itself is not freed +*/ + +void TPM_SignInfo_Delete(TPM_SIGN_INFO *tpm_sign_info) +{ + printf(" TPM_SignInfo_Delete:\n"); + if (tpm_sign_info != NULL) { + TPM_SizedBuffer_Delete(&(tpm_sign_info->data)); + TPM_SignInfo_Init(tpm_sign_info); + } + return; +} + +/* + TPM_CERTIFY_INFO +*/ + +/* TPM_CertifyInfo_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_CertifyInfo_Init(TPM_CERTIFY_INFO *tpm_certify_info) +{ + printf(" TPM_CertifyInfo_Init:\n"); + TPM_StructVer_Init(&(tpm_certify_info->version)); + tpm_certify_info->keyUsage = TPM_KEY_UNINITIALIZED; + tpm_certify_info->keyFlags = 0; + tpm_certify_info->authDataUsage = TPM_AUTH_ALWAYS; + TPM_KeyParms_Init(&(tpm_certify_info->algorithmParms)); + TPM_Digest_Init(tpm_certify_info->pubkeyDigest); + TPM_Nonce_Init(tpm_certify_info->data); + tpm_certify_info->parentPCRStatus = TRUE; + TPM_SizedBuffer_Init(&(tpm_certify_info->pcrInfo)); + tpm_certify_info->tpm_pcr_info = NULL; + return; +} + +#if 0 +/* TPM_CertifyInfo_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_CertifyInfo_Init() + After use, call TPM_CertifyInfo_Delete() to free memory + + NOTE: Never called. +*/ + +TPM_RESULT TPM_CertifyInfo_Load(TPM_CERTIFY_INFO *tpm_certify_info, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CertifyInfo_Load:\n"); + /* load version */ + if (rc == 0) { + rc = TPM_StructVer_Load(&(tpm_certify_info->version), stream, stream_size); + } + /* check ver immediately to ease debugging */ + if (rc == 0) { + rc = TPM_StructVer_CheckVer(&(tpm_certify_info->version)); + } + /* load keyUsage */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_certify_info->keyUsage), stream, stream_size); + } + /* load keyFlags */ + if (rc == 0) { + rc = TPM_KeyFlags_Load(&(tpm_certify_info->keyFlags), stream, stream_size); + } + /* load authDataUsage */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_certify_info->authDataUsage), stream, stream_size); + } + /* load algorithmParms */ + if (rc == 0) { + rc = TPM_KeyParms_Load(&(tpm_certify_info->algorithmParms), stream, stream_size); + } + /* load pubkeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_certify_info->pubkeyDigest, stream, stream_size); + } + /* load data */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_certify_info->data, stream, stream_size); + } + /* load parentPCRStatus */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_certify_info->parentPCRStatus), stream, stream_size); + } + /* load pcrInfo */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_certify_info->pcrInfo), stream, stream_size); + } + /* set TPM_PCR_INFO tpm_pcr_info cache from pcrInfo */ + if (rc == 0) { + rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_certify_info->tpm_pcr_info), + &(tpm_certify_info->pcrInfo)); + } + return rc; +} +#endif + +/* TPM_CertifyInfo_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CertifyInfo_Store(TPM_STORE_BUFFER *sbuffer, + TPM_CERTIFY_INFO *tpm_certify_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CertifyInfo_Store:\n"); + /* store version */ + if (rc == 0) { + rc = TPM_StructVer_Store(sbuffer, &(tpm_certify_info->version)); + } + /* store keyUsage */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_certify_info->keyUsage); + } + /* store keyFlags */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_certify_info->keyFlags); + } + /* store authDataUsage */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info->authDataUsage), + sizeof(TPM_AUTH_DATA_USAGE)); + } + /* store algorithmParms */ + if (rc == 0) { + rc = TPM_KeyParms_Store(sbuffer, &(tpm_certify_info->algorithmParms)); + } + /* store pubkeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_certify_info->pubkeyDigest); + } + /* store data */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_certify_info->data); + } + /* store parentPCRStatus */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info->parentPCRStatus), + sizeof(TPM_BOOL)); + } + /* copy cache to pcrInfo */ + if (rc == 0) { + rc = TPM_SizedBuffer_SetStructure(&(tpm_certify_info->pcrInfo), + tpm_certify_info->tpm_pcr_info, + (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store); + } + /* copy pcrInfo to sbuffer */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info->pcrInfo)); + } + return rc; +} + +/* TPM_CertifyInfo_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_CertifyInfo_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_CertifyInfo_Delete(TPM_CERTIFY_INFO *tpm_certify_info) +{ + printf(" TPM_CertifyInfo_Delete:\n"); + if (tpm_certify_info != NULL) { + TPM_KeyParms_Delete(&(tpm_certify_info->algorithmParms)); + /* pcrInfo */ + TPM_SizedBuffer_Delete(&(tpm_certify_info->pcrInfo)); + /* pcr cache */ + TPM_PCRInfo_Delete(tpm_certify_info->tpm_pcr_info); + free(tpm_certify_info->tpm_pcr_info); + TPM_CertifyInfo_Init(tpm_certify_info); + } + return; +} + +/* TPM_CertifyInfo_Set() fills in tpm_certify_info with the information from the key pointed to be + tpm_key +*/ + +TPM_RESULT TPM_CertifyInfo_Set(TPM_CERTIFY_INFO *tpm_certify_info, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CertifyInfo_Set:\n"); + if (rc == 0) { + tpm_certify_info->keyUsage = tpm_key->keyUsage; + tpm_certify_info->keyFlags = tpm_key->keyFlags; + tpm_certify_info->authDataUsage = tpm_key->authDataUsage; + rc = TPM_KeyParms_Copy(&(tpm_certify_info->algorithmParms), + &(tpm_key->algorithmParms)); + } + /* pubkeyDigest SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY + representation of the key to be certified */ + if (rc == 0) { + rc = TPM_SHA1(tpm_certify_info->pubkeyDigest, + tpm_key->pubKey.size, tpm_key->pubKey.buffer, + 0, NULL); + } + return rc; +} + +/* + TPM_CERTIFY_INFO2 +*/ + +/* TPM_CertifyInfo2_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_CertifyInfo2_Init(TPM_CERTIFY_INFO2 *tpm_certify_info2) +{ + printf(" TPM_CertifyInfo2_Init:\n"); + tpm_certify_info2->fill = 0x00; + tpm_certify_info2->payloadType = TPM_PT_ASYM; + tpm_certify_info2->keyUsage = TPM_KEY_UNINITIALIZED; + tpm_certify_info2->keyFlags = 0; + tpm_certify_info2->authDataUsage = TPM_AUTH_ALWAYS; + TPM_KeyParms_Init(&(tpm_certify_info2->algorithmParms)); + TPM_Digest_Init(tpm_certify_info2->pubkeyDigest); + TPM_Nonce_Init(tpm_certify_info2->data); + tpm_certify_info2->parentPCRStatus = TRUE; + TPM_SizedBuffer_Init(&(tpm_certify_info2->pcrInfo)); + TPM_SizedBuffer_Init(&(tpm_certify_info2->migrationAuthority)); + tpm_certify_info2->tpm_pcr_info_short = NULL; + return; +} + +#if 0 +/* TPM_CertifyInfo2_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_CertifyInfo2_Init() + After use, call TPM_CertifyInfo2_Delete() to free memory +*/ + +TPM_RESULT TPM_CertifyInfo2_Load(TPM_CERTIFY_INFO2 *tpm_certify_info2, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CertifyInfo2_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_CERTIFY_INFO2, stream, stream_size); + } + /* load fill */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_certify_info2->fill), stream, stream_size); + } + /* check fill immediately to ease debugging */ + if (rc == 0) { + if (tpm_certify_info2->fill != 0x00) { + printf("TPM_CertifyInfo2_Load: Error checking fill %02x\n", tpm_certify_info2->fill); + rc = TPM_INVALID_STRUCTURE; + } + } + /* load payloadType */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_certify_info2->payloadType), stream, stream_size); + } + /* load keyUsage */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_certify_info2->keyUsage), stream, stream_size); + } + /* load keyFlags */ + if (rc == 0) { + rc = TPM_KeyFlags_Load(&(tpm_certify_info2->keyFlags), stream, stream_size); + } + /* load authDataUsage */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_certify_info2->authDataUsage), stream, stream_size); + } + /* load algorithmParms */ + if (rc == 0) { + rc = TPM_KeyParms_Load(&(tpm_certify_info2->algorithmParms), stream, stream_size); + } + /* load pubkeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_certify_info2->pubkeyDigest, stream, stream_size); + } + /* load data */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_certify_info2->data, stream, stream_size); + } + /* load parentPCRStatus */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_certify_info2->parentPCRStatus), stream, stream_size); + } + /* load pcrInfo */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_certify_info2->pcrInfo), stream, stream_size); + } + /* set TPM_PCR_INFO2 tpm_pcr_info cache from pcrInfo */ + if (rc == 0) { + rc = TPM_PCRInfoShort_CreateFromBuffer(&(tpm_certify_info2->tpm_pcr_info_short), + &(tpm_certify_info2->pcrInfo)); + } + /* load migrationAuthority */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_certify_info2->migrationAuthority), stream, stream_size); + } + /* check migrationAuthority immediately to ease debugging */ + if (rc == 0) { + if ((tpm_certify_info2->migrationAuthority.buffer != NULL) && + (tpm_certify_info2->migrationAuthority.size != TPM_DIGEST_SIZE)) { + printf("TPM_CertifyInfo2_Load: Error checking migrationAuthority %p, %u\n", + tpm_certify_info2->migrationAuthority.buffer, + tpm_certify_info2->migrationAuthority.size); + rc = TPM_INVALID_STRUCTURE; + } + } + return rc; +} +#endif + +/* TPM_CertifyInfo2_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CertifyInfo2_Store(TPM_STORE_BUFFER *sbuffer, + TPM_CERTIFY_INFO2 *tpm_certify_info2) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CertifyInfo2_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CERTIFY_INFO2); + } + /* store fill */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->fill), sizeof(BYTE)); + } + /* store payloadType */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->payloadType), + sizeof(TPM_PAYLOAD_TYPE)); + } + /* store keyUsage */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_certify_info2->keyUsage); + } + /* store keyFlags */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_certify_info2->keyFlags); + } + /* store authDataUsage */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->authDataUsage), + sizeof(TPM_AUTH_DATA_USAGE)); + } + /* store algorithmParms */ + if (rc == 0) { + rc = TPM_KeyParms_Store(sbuffer, &(tpm_certify_info2->algorithmParms)); + } + /* store pubkeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_certify_info2->pubkeyDigest); + } + /* store data */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_certify_info2->data); + } + /* store parentPCRStatus */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->parentPCRStatus), + sizeof(TPM_BOOL)); + } + /* copy cache to pcrInfo */ + if (rc == 0) { + rc = TPM_SizedBuffer_SetStructure(&(tpm_certify_info2->pcrInfo), + tpm_certify_info2->tpm_pcr_info_short, + (TPM_STORE_FUNCTION_T)TPM_PCRInfoShort_Store); + } + /* copy pcrInfo to sbuffer */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info2->pcrInfo)); + } + /* store migrationAuthority */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info2->migrationAuthority)); + } + return rc; +} + +/* TPM_CertifyInfo2_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_CertifyInfo2_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_CertifyInfo2_Delete(TPM_CERTIFY_INFO2 *tpm_certify_info2) +{ + printf(" TPM_CertifyInfo2_Delete:\n"); + if (tpm_certify_info2 != NULL) { + TPM_KeyParms_Delete(&(tpm_certify_info2->algorithmParms)); + /* pcrInfo */ + TPM_SizedBuffer_Delete(&(tpm_certify_info2->pcrInfo)); + /* pcr cache */ + TPM_PCRInfoShort_Delete(tpm_certify_info2->tpm_pcr_info_short); + free(tpm_certify_info2->tpm_pcr_info_short); + TPM_SizedBuffer_Delete(&(tpm_certify_info2->migrationAuthority)); + TPM_CertifyInfo2_Init(tpm_certify_info2); + } + return; +} + +/* TPM_CertifyInfo2_Set() fills in tpm_certify_info2 with the information from the key pointed to by + tpm_key. + +*/ + +TPM_RESULT TPM_CertifyInfo2_Set(TPM_CERTIFY_INFO2 *tpm_certify_info2, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_ASYMKEY *tpm_store_asymkey; + + printf(" TPM_CertifyInfo_Set:\n"); + /* get the TPM_STORE_ASYMKEY object */ + if (rc == 0) { + rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); + } + if (rc == 0) { + tpm_certify_info2->payloadType = tpm_store_asymkey->payload; + tpm_certify_info2->keyUsage = tpm_key->keyUsage; + tpm_certify_info2->keyFlags = tpm_key->keyFlags; + tpm_certify_info2->authDataUsage = tpm_key->authDataUsage; + rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); + } + if (rc == 0) { + rc = TPM_KeyParms_Copy(&(tpm_certify_info2->algorithmParms), + &(tpm_key->algorithmParms)); + } + /* pubkeyDigest SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY + representation of the key to be certified */ + if (rc == 0) { + rc = TPM_SHA1(tpm_certify_info2->pubkeyDigest, + tpm_key->pubKey.size, tpm_key->pubKey.buffer, + 0, NULL); + } + return rc; +} + +/* + TPM_SYMMETRIC_KEY +*/ + +/* TPM_SymmetricKey_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_SymmetricKey_Init(TPM_SYMMETRIC_KEY *tpm_symmetric_key) +{ + printf(" TPM_SymmetricKey_Init:\n"); + tpm_symmetric_key->algId = 0; + tpm_symmetric_key->encScheme = TPM_ES_NONE; + tpm_symmetric_key->size = 0; + tpm_symmetric_key->data = NULL; + return; +} + +/* TPM_SymmetricKey_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_SymmetricKey_Init() + After use, call TPM_SymmetricKey_Delete() to free memory +*/ + +TPM_RESULT TPM_SymmetricKey_Load(TPM_SYMMETRIC_KEY *tpm_symmetric_key, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SymmetricKey_Load:\n"); + /* load algId */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_symmetric_key->algId), stream, stream_size); + } + /* load encScheme */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_symmetric_key->encScheme), stream, stream_size); + } + /* load size */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_symmetric_key->size), stream, stream_size); + } + /* allocate memory for the data */ + if ((rc == 0) && (tpm_symmetric_key->size > 0)) { + rc = TPM_Malloc(&(tpm_symmetric_key->data), tpm_symmetric_key->size); + } + /* load data */ + if ((rc == 0) && (tpm_symmetric_key->size > 0)) { + rc = TPM_Loadn(tpm_symmetric_key->data, tpm_symmetric_key->size, stream, stream_size); + } + return rc; +} + +/* TPM_SymmetricKey_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_SymmetricKey_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SYMMETRIC_KEY *tpm_symmetric_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SymmetricKey_Store:\n"); + /* store algId */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_symmetric_key->algId); + } + /* store encScheme */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key->encScheme); + } + /* NOTE: Cannot use TPM_SizedBuffer_Store since the first parameter is a uint16_t */ + /* store size */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key->size); + } + /* store data */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key->data, tpm_symmetric_key->size); + } + return rc; +} + +/* TPM_SymmetricKey_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_SymmetricKey_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_SymmetricKey_Delete(TPM_SYMMETRIC_KEY *tpm_symmetric_key) +{ + printf(" TPM_SymmetricKey_Delete:\n"); + if (tpm_symmetric_key != NULL) { + free(tpm_symmetric_key->data); + TPM_SymmetricKey_Init(tpm_symmetric_key); + } + return; +} + +/* TPM_SymmetricKeyData_EncryptSbuffer() encrypts 'sbuffer' to 'encrypt_data' + + Padding is included, so the output may be larger than the input. + + 'encrypt_data' must be free by the caller +*/ + +TPM_RESULT TPM_SymmetricKeyData_EncryptSbuffer(TPM_SIZED_BUFFER *encrypt_data, + TPM_STORE_BUFFER *sbuffer, + const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data) +{ + TPM_RESULT rc = 0; + const unsigned char *decrypt_data; /* serialization buffer */ + uint32_t decrypt_data_size; /* serialization size */ + + printf(" TPM_SymmetricKeyData_EncryptSbuffer:\n"); + if (rc == 0) { + /* get the serialization results */ + TPM_Sbuffer_Get(sbuffer, &decrypt_data, &decrypt_data_size); + /* platform dependent symmetric key encrypt */ + rc = TPM_SymmetricKeyData_Encrypt(&(encrypt_data->buffer), /* output, caller frees */ + &(encrypt_data->size), /* output */ + decrypt_data, /* input */ + decrypt_data_size, /* input */ + tpm_symmetric_key_data); + } + return rc; +} + +/* TPM_SymmetricKeyData_StreamCrypt() encrypts or decrypts 'data_in' to 'data_out ' + + It assumes that the size of data_out and data_in are equal, and that a stream cipher mode is + used. For the supported stream ciphers, encrypt and decrypt are equivalent, so no direction flag + is required. + + AES 128 with CTR or OFB modes are supported. For CTR mode, pad is the initial count. For OFB + mode, pad is the IV. +*/ + +TPM_RESULT TPM_SymmetricKeyData_StreamCrypt(unsigned char *data_out, /* output */ + const unsigned char *data_in, /* input */ + uint32_t data_size, /* input */ + TPM_ALGORITHM_ID algId, /* algorithm */ + TPM_ENC_SCHEME encScheme, /* mode */ + const unsigned char *symmetric_key, /* input */ + uint32_t symmetric_key_size, /* input */ + unsigned char *pad_in, /* input */ + uint32_t pad_in_size) /* input */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_SymmetricKeyData_StreamCrypt:\n"); + switch (algId) { + case TPM_ALG_AES128: + switch (encScheme) { + case TPM_ES_SYM_CTR: + rc = TPM_SymmetricKeyData_CtrCrypt(data_out, + data_in, + data_size, + symmetric_key, + symmetric_key_size, + pad_in, + pad_in_size); + break; + case TPM_ES_SYM_OFB: + rc = TPM_SymmetricKeyData_OfbCrypt(data_out, + data_in, + data_size, + symmetric_key, + symmetric_key_size, + pad_in, + pad_in_size); + break; + default: + printf("TPM_SymmetricKeyData_StreamCrypt: Error, bad AES128 encScheme %04x\n", + encScheme); + rc = TPM_INAPPROPRIATE_ENC; + break; + } + break; + default: + printf("TPM_SymmetricKeyData_StreamCrypt: Error, bad algID %08x\n", algId); + rc = TPM_INAPPROPRIATE_ENC; + break; + } + return rc; +} + +/* These functions perform high-level, platform independent functions. + They call the lower level, platform dependent crypto functions in + tpm_crypto.c +*/ + +/* TPM_SHA1Sbuffer() calculates the SHA-1 digest of a TPM_STORE_BUFFER. + + This is commonly used when calculating a digest on a serialized structure. Structures are + serialized to a TPM_STORE_BUFFER. + + The TPM_STORE_BUFFER is not deleted. +*/ + +TPM_RESULT TPM_SHA1Sbuffer(TPM_DIGEST tpm_digest, + TPM_STORE_BUFFER *sbuffer) +{ + TPM_RESULT rc = 0; + const unsigned char *buffer; /* serialized buffer */ + uint32_t length; /* serialization length */ + + printf(" TPM_SHA1Sbuffer:\n"); + if (rc == 0) { + /* get the components of the TPM_STORE_BUFFER */ + TPM_Sbuffer_Get(sbuffer, &buffer, &length); + TPM_PrintFour(" TPM_SHA1Sbuffer: input", buffer); + /* hash the serialized buffer to tpm_digest */ + rc = TPM_SHA1(tpm_digest, + length, buffer, + 0, NULL); + } + return rc; +} + +/* TPM_SHA1_GenerateStructure() generates a SHA-1 digest of a structure. It serializes the + structure and hashes the result. + + tpmStructure is the structure to be serialized + storeFunction is the serialization function for the structure +*/ + +TPM_RESULT TPM_SHA1_GenerateStructure(TPM_DIGEST tpm_digest, + void *tpmStructure, + TPM_STORE_FUNCTION_T storeFunction) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ + + printf(" TPM_SHA1_GenerateStructure:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* Serialize the structure */ + if (rc == 0) { + rc = storeFunction(&sbuffer, tpmStructure); + } + /* hash the serialized buffer to tpm_hmac */ + if (rc == 0) { + rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_SHA1_CheckStructure() generates a SHA-1 digest of a structure. It serializes the structure + and hashes the result. It compares the result to 'expected_digest' and returns 'error' on + mismatch. + + tpmStructure is the structure to be serialized + storeFunction is the serialization function for the structure +*/ + + + +TPM_RESULT TPM_SHA1_CheckStructure(TPM_DIGEST expected_digest, + void *tpmStructure, + TPM_STORE_FUNCTION_T storeFunction, + TPM_RESULT error) +{ + TPM_RESULT rc = 0; + TPM_DIGEST actual_digest; + + printf(" TPM_SHA1_CheckStructure:\n"); + /* hash the serialized buffer to tpm_digest */ + if (rc == 0) { + rc = TPM_SHA1_GenerateStructure(actual_digest, tpmStructure, storeFunction); + } + /* check the digests */ + if (rc == 0) { + rc = TPM_Digest_Compare(actual_digest, expected_digest); + if (rc != 0) { + rc = error; + } + } + return rc; +} + +/* TPM_SHA1() can be called directly to hash a list of streams. + + The ... arguments to be hashed are a list of the form + size_t length, unsigned char *buffer + terminated by a 0 length + */ + +TPM_RESULT TPM_SHA1(TPM_DIGEST md, ...) +{ + TPM_RESULT rc = 0; + va_list ap; + + printf(" TPM_SHA1:\n"); + va_start(ap, md); + rc = TPM_SHA1_valist(md, 0, NULL, ap); + va_end(ap); + return rc; +} + +/* TPM_SHA1_Check() digests the list of streams and compares the result to 'digest_expect' + */ + +TPM_RESULT TPM_SHA1_Check(TPM_DIGEST digest_expect, ...) +{ + TPM_RESULT rc = 0; + TPM_DIGEST digest_actual; + va_list ap; + + printf(" TPM_SHA1_Check:\n"); + if (rc == 0) { + va_start(ap, digest_expect); + rc = TPM_SHA1_valist(digest_actual, 0, NULL, ap); + va_end(ap); + } + if (rc == 0) { + rc = TPM_Digest_Compare(digest_expect, digest_actual); + } + return rc; +} + +/* TPM_SHA1_valist() is the internal function, called with the va_list already created. + + It is called from TPM_SHA1() to do a simple hash. Typically length0==0 and buffer0==NULL. + + It can also be called from the HMAC function to hash the variable number of input parameters. In + that case, the va_list for the text is already formed. length0 and buffer0 are used to input the + padded key. +*/ + +static TPM_RESULT TPM_SHA1_valist(TPM_DIGEST md, + uint32_t length0, unsigned char *buffer0, + va_list ap) +{ + TPM_RESULT rc = 0; + uint32_t length; + unsigned char *buffer; + void *context = NULL; /* platform dependent context */ + TPM_BOOL done = FALSE; + + printf(" TPM_SHA1_valist:\n"); + if (rc == 0) { + rc = TPM_SHA1InitCmd(&context); + } + if (rc == 0) { + if (length0 !=0) { /* optional first text block */ + printf(" TPM_SHA1_valist: Digesting %u bytes\n", length0); + rc = TPM_SHA1UpdateCmd(context, buffer0, length0); /* hash the buffer */ + } + } + while ((rc == 0) && !done) { + length = va_arg(ap, uint32_t); /* first vararg is the length */ + if (length != 0) { /* loop until a zero length argument terminates */ + buffer = va_arg(ap, unsigned char *); /* second vararg is the array */ + printf(" TPM_SHA1_valist: Digesting %u bytes\n", length); + rc = TPM_SHA1UpdateCmd(context, buffer, length); /* hash the buffer */ + } + else { + done = TRUE; + } + } + if (rc == 0) { + rc = TPM_SHA1FinalCmd(md, context); + } + if (rc == 0) { + TPM_PrintFour(" TPM_SHA1_valist: Digest", md); + } + /* call TPM_SHA1Delete even if there was an error */ + TPM_SHA1Delete(&context); + return rc; +} + +/* TPM_HMAC_GenerateSbuffer() calculates the HMAC digest of a TPM_STORE_BUFFER. + + This is commonly used when calculating an HMAC on a serialized structure. Structures are + serialized to a TPM_STORE_BUFFER. + + The TPM_STORE_BUFFER is not deleted. +*/ + +TPM_RESULT TPM_HMAC_GenerateSbuffer(TPM_HMAC tpm_hmac, + const TPM_SECRET hmac_key, + TPM_STORE_BUFFER *sbuffer) +{ + TPM_RESULT rc = 0; + const unsigned char *buffer; /* serialized buffer */ + uint32_t length; /* serialization length */ + + printf(" TPM_HMAC_GenerateSbuffer:\n"); + if (rc == 0) { + /* get the components of the TPM_STORE_BUFFER */ + TPM_Sbuffer_Get(sbuffer, &buffer, &length); + /* HMAC the serialized buffer to tpm_hmac */ + rc = TPM_HMAC_Generate(tpm_hmac, + hmac_key, + length, buffer, + 0, NULL); + } + return rc; +} + +/* TPM_HMAC_GenerateStructure() generates an HMAC of a structure. It serializes the structure and + HMAC's the result. + + hmacKey is the HMAC key + tpmStructure is the structure to be serialized + storeFunction is the serialization function for the structure +*/ + +TPM_RESULT TPM_HMAC_GenerateStructure(TPM_HMAC tpm_hmac, + const TPM_SECRET hmac_key, + void *tpmStructure, + TPM_STORE_FUNCTION_T storeFunction) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ + + printf(" TPM_HMAC_GenerateStructure:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* Serialize the structure */ + if (rc == 0) { + rc = storeFunction(&sbuffer, tpmStructure); + } + /* hash the serialized buffer to tpm_hmac */ + if (rc == 0) { + rc = TPM_HMAC_GenerateSbuffer(tpm_hmac, hmac_key, &sbuffer); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_HMAC_Generate() can be called directly to HMAC a list of streams. + + The ... arguments are a message list of the form + size_t length, unsigned char *buffer + terminated by a 0 length +*/ + +TPM_RESULT TPM_HMAC_Generate(TPM_HMAC tpm_hmac, + const TPM_SECRET hmac_key, + ...) +{ + TPM_RESULT rc = 0; + va_list ap; + + printf(" TPM_HMAC_Generate:\n"); + va_start(ap, hmac_key); + rc = TPM_HMAC_Generatevalist(tpm_hmac, hmac_key, ap); + va_end(ap); + return rc; +} + +/* TPM_HMAC_Generatevalist() is the internal function, called with the va_list already created. + + It is called from TPM_HMAC_Generate() and TPM_HMAC_Check() with the va_list for the text already + formed. +*/ + +#define TPM_HMAC_BLOCK_SIZE 64 + +static TPM_RESULT TPM_HMAC_Generatevalist(TPM_HMAC tpm_hmac, + const TPM_SECRET key, + va_list ap) +{ + TPM_RESULT rc = 0; + unsigned char ipad[TPM_HMAC_BLOCK_SIZE]; + unsigned char opad[TPM_HMAC_BLOCK_SIZE]; + size_t i; + TPM_DIGEST inner_hash; + + printf(" TPM_HMAC_Generatevalist:\n"); + /* calculate key XOR ipad and key XOR opad */ + if (rc == 0) { + /* first part, key XOR pad */ + for (i = 0 ; i < TPM_AUTHDATA_SIZE ; i++) { + ipad[i] = key[i] ^ 0x36; /* magic numbers from RFC 2104 */ + opad[i] = key[i] ^ 0x5c; + } + /* second part, 0x00 XOR pad */ + memset(ipad + TPM_AUTHDATA_SIZE, 0x36, TPM_HMAC_BLOCK_SIZE - TPM_AUTHDATA_SIZE); + memset(opad + TPM_AUTHDATA_SIZE, 0x5c, TPM_HMAC_BLOCK_SIZE - TPM_AUTHDATA_SIZE); + /* calculate the inner hash, hash the key XOR ipad and the text */ + rc = TPM_SHA1_valist(inner_hash, + TPM_HMAC_BLOCK_SIZE, ipad, ap); + } + /* hash the key XOR opad and the previous hash */ + if (rc == 0) { + rc = TPM_SHA1(tpm_hmac, + TPM_HMAC_BLOCK_SIZE, opad, + TPM_DIGEST_SIZE, inner_hash, + 0, NULL); + } + if (rc == 0) { + TPM_PrintFour(" TPM_HMAC_Generatevalist: HMAC", tpm_hmac); + } + return rc; +} + +/* TPM_HMAC_CheckSbuffer() checks the HMAC of a TPM_STORE_BUFFER. + + This is commonly used when checking an HMAC on a serialized structure. Structures are serialized + to a TPM_STORE_BUFFER. + + The TPM_STORE_BUFFER is not deleted. +*/ + +TPM_RESULT TPM_HMAC_CheckSbuffer(TPM_BOOL *valid, /* result */ + TPM_HMAC expect, /* expected */ + const TPM_SECRET hmac_key, /* key */ + TPM_STORE_BUFFER *sbuffer) /* data stream */ +{ + TPM_RESULT rc = 0; + const unsigned char *buffer; /* serialized buffer */ + uint32_t length; /* serialization length */ + + printf(" TPM_HMAC_CheckSbuffer:\n"); + if (rc == 0) { + /* get the components of the TPM_STORE_BUFFER */ + TPM_Sbuffer_Get(sbuffer, &buffer, &length); + /* HMAC the serialized buffer to tpm_hmac */ + rc = TPM_HMAC_Check(valid, + expect, + hmac_key, + length, buffer, + 0, NULL); + } + return rc; +} + +/* TPM_HMAC_Check() can be called directly to check the HMAC of a list of streams. + + The ... arguments are a list of the form + size_t length, unsigned char *buffer + terminated by a 0 length + +*/ + +TPM_RESULT TPM_HMAC_Check(TPM_BOOL *valid, + TPM_HMAC expect, + const TPM_SECRET key, + ...) +{ + TPM_RESULT rc = 0; + va_list ap; + TPM_HMAC actual; + int result; + + printf(" TPM_HMAC_Check:\n"); + va_start(ap, key); + if (rc == 0) { + rc = TPM_HMAC_Generatevalist(actual, key, ap); + } + if (rc == 0) { + TPM_PrintFour(" TPM_HMAC_Check: Calculated", actual); + TPM_PrintFour(" TPM_HMAC_Check: Received ", expect); + result = memcmp(expect, actual, TPM_DIGEST_SIZE); + if (result == 0) { + *valid = TRUE; + } + else { + *valid = FALSE; + } + } + va_end(ap); + return rc; +} + +/* TPM_HMAC_CheckStructure() is a generic function that checks the integrity HMAC of a structure. + + hmacKey is the HMAC key + tpmStructure is the structure to be serialized + expect is the expected HMAC, a member of the structure + storeFunction is the serialization function for the structure + error is the failure return code + + The function saves a copy of the expected HMAC, and then NULL's the structure member. It + serializes the structure, generates an HMAC, and compares it to the expected value. + + As a side effect, the structure member is zeroed. +*/ + +TPM_RESULT TPM_HMAC_CheckStructure(const TPM_SECRET hmac_key, + void *tpmStructure, + TPM_HMAC expect, + TPM_STORE_FUNCTION_T storeFunction, + TPM_RESULT error) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ + TPM_HMAC saveExpect; + TPM_BOOL valid; + + printf(" TPM_HMAC_CheckStructure:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + if (rc == 0) { + TPM_Digest_Copy(saveExpect, expect); /* save the expected value */ + TPM_Digest_Init(expect); /* set value in structure to NULL */ + rc = storeFunction(&sbuffer, + tpmStructure); + } + /* verify the HMAC of the serialized structure */ + if (rc == 0) { + rc = TPM_HMAC_CheckSbuffer(&valid, /* result */ + saveExpect, /* expected */ + hmac_key, /* key */ + &sbuffer); /* data stream */ + } + if (rc == 0) { + if (!valid) { + printf("TPM_HMAC_CheckStructure: Error checking HMAC\n"); + rc = error; + } + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_XOR XOR's 'in1' and 'in2' of 'length', putting the result in 'out' + +*/ + +void TPM_XOR(unsigned char *out, + const unsigned char *in1, + const unsigned char *in2, + size_t length) +{ + size_t i; + + for (i = 0 ; i < length ; i++) { + out[i] = in1[i] ^ in2[i]; + } + return; +} + +/* TPM_MGF1() generates an MGF1 'array' of length 'arrayLen' from 'seed' of length 'seedlen' + + The openSSL DLL doesn't export MGF1 in Windows or Linux 1.0.0, so this version is created from + scratch. + + Algorithm and comments (not the code) from: + + PKCS #1: RSA Cryptography Specifications Version 2.1 B.2.1 MGF1 + + Prototype designed to be compatible with openSSL + + MGF1 is a Mask Generation Function based on a hash function. + + MGF1 (mgfSeed, maskLen) + + Options: + + Hash hash function (hLen denotes the length in octets of the hash + function output) + + Input: + + mgfSeed seed from which mask is generated, an octet string + maskLen intended length in octets of the mask, at most 2^32(hLen) + + Output: + mask mask, an octet string of length l; or "mask too long" + + Error: "mask too long' +*/ + +TPM_RESULT TPM_MGF1(unsigned char *mask, + uint32_t maskLen, + const unsigned char *mgfSeed, + uint32_t mgfSeedlen) +{ + TPM_RESULT rc = 0; + unsigned char counter[4]; /* 4 octets */ + uint32_t count; /* counter as an integral type */ + uint32_t outLen; + TPM_DIGEST lastDigest; + + printf(" TPM_MGF1: Output length %u\n", maskLen); + if (rc == 0) { + /* this is possible with arrayLen on a 64 bit architecture, comment to quiet beam */ + if ((maskLen / TPM_DIGEST_SIZE) > 0xffffffff) { /*constant condition*/ + printf(" TPM_MGF1: Error (fatal), Output length too large for 32 bit counter\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + /* 1.If l > 2^32(hLen), output "mask too long" and stop. */ + /* NOTE Checked by caller */ + /* 2. Let T be the empty octet string. */ + /* 3. For counter from 0 to [masklen/hLen] - 1, do the following: */ + for (count = 0, outLen = 0 ; (rc == 0) && (outLen < maskLen) ; count++) { + /* a. Convert counter to an octet string C of length 4 octets - see Section 4.1 */ + /* C = I2OSP(counter, 4) NOTE Basically big endian */ + uint32_t count_n = htonl(count); + memcpy(counter, &count_n, 4); + /* b.Concatenate the hash of the seed mgfSeed and C to the octet string T: */ + /* T = T || Hash (mgfSeed || C) */ + /* If the entire digest is needed for the mask */ + if ((outLen + TPM_DIGEST_SIZE) < maskLen) { + rc = TPM_SHA1(mask + outLen, + mgfSeedlen, mgfSeed, + 4, counter, + 0, NULL); + outLen += TPM_DIGEST_SIZE; + } + /* if the mask is not modulo TPM_DIGEST_SIZE, only part of the final digest is needed */ + else { + /* hash to a temporary digest variable */ + rc = TPM_SHA1(lastDigest, + mgfSeedlen, mgfSeed, + 4, counter, + 0, NULL); + /* copy what's needed */ + memcpy(mask + outLen, lastDigest, maskLen - outLen); + outLen = maskLen; /* outLen = outLen + maskLen - outLen */ + } + } + /* 4.Output the leading l octets of T as the octet string mask. */ + return rc; +} + +/* TPM_MGF1_GenerateArray() generates an array of length arrayLen using the varargs as the seed. + + Since the seed is a known length, it is passed in rather that extracted from the varargs. If the + seed length turns out to be wrong once the varargs are parsed, TPM_FAIL is returned. + + 'array' must be freed by the caller. +*/ + +TPM_RESULT TPM_MGF1_GenerateArray(unsigned char **array, + uint32_t arrayLen, + uint32_t seedLen, + ...) +{ + TPM_RESULT rc = 0; + va_list ap; + unsigned char *seed; /* constructed MGF1 seed */ + size_t vaLength; /* next seed segment length */ + unsigned char *vaBuffer; /* next seed segment buffer */ + uint32_t seedLeft; /* remaining seed bytes required */ + unsigned char *seedBuffer; /* running pointer to the seed array */ + TPM_BOOL done = FALSE; /* done when a vaLength == 0 is reached */ + + printf(" TPM_MGF1_GenerateArray: arrayLen %u seedLen %u\n", arrayLen, seedLen); + seed = NULL; /* freed @1 */ + *array = NULL; /* freed by caller */ + va_start(ap, seedLen); + /* allocate temporary memory for the seed */ + if (rc == 0) { + rc = TPM_Malloc(&seed, seedLen); + seedBuffer = seed; + seedLeft = seedLen; + } + /* construct the seed */ + while ((rc == 0) && !done) { + vaLength = (size_t)va_arg(ap, uint32_t); /* first vararg is the length */ + if (vaLength != 0) { /* loop until a zero length argument terminates */ + if (rc == 0) { + printf(" TPM_MGF1_GenerateArray: Appending %lu bytes\n", (unsigned long)vaLength); + if (vaLength > seedLeft) { + printf("TPM_MGF1_GenerateArray: Error (fatal), seedLen too small\n"); + rc = TPM_FAIL; /* internal error, should never occur */ + } + } + if (rc == 0) { + vaBuffer = va_arg(ap, unsigned char *); /* second vararg is the array */ + memcpy(seedBuffer, vaBuffer, vaLength); + seedBuffer += vaLength; + seedLeft-= vaLength; + } + } + else { + done = TRUE; + if (seedLeft != 0) { + printf("TPM_MGF1_GenerateArray: Error (fatal), seedLen too large by %u\n", + seedLeft); + rc = TPM_FAIL; /* internal error, should never occur */ + } + } + } + /* allocate memory for the array */ + if (rc == 0) { + rc = TPM_Malloc(array, arrayLen); + } + /* generate the MGF1 array */ + if (rc == 0) { + TPM_MGF1(*array, + arrayLen, + seed, + seedLen); + TPM_PrintFour(" TPM_MGF1_GenerateArray: MGF1", *array); + } + va_end(ap); + free(seed); /* @1 */ + return rc; +} + +/* TPM_bn2binMalloc() allocates a buffer 'bin' and loads it from 'bn'. + 'bytes' is set to the allocated size of 'bin'. + + If padBytes is non-zero, 'bin' is padded with leading zeros if necessary, so that 'bytes' will + equal 'padBytes'. This is used when TPM data structures expect a fixed length while the crypto + library 'bn to bin' function might truncates leading zeros. + + '*bin' must be freed by the caller +*/ + +TPM_RESULT TPM_bn2binMalloc(unsigned char **bin, /* freed by caller */ + unsigned int *bytes, + TPM_BIGNUM bn, + uint32_t padBytes) +{ + TPM_RESULT rc = 0; + + printf(" TPM_bn2binMalloc: padBytes %u\n", padBytes); + /* number of bytes required in the bin array */ + if (rc == 0) { + rc = TPM_BN_num_bytes(bytes, bn); + } + /* calculate the array size to malloc */ + if (rc == 0) { + /* padBytes 0 says that no padding is required */ + if (padBytes == 0) { + padBytes = *bytes; /* setting equal yields no padding */ + } + /* if the array with padding is still less than the number of bytes required by the bignum, + this function fails */ + if (padBytes < *bytes) { + printf("TPM_bn2binMalloc: Error, " + "padBytes %u less than BN bytes %u\n", padBytes, *bytes); + rc = TPM_SIZE; + } + /* log if padding is occurring */ + if (padBytes != *bytes) { + printf(" TPM_bn2binMalloc: padBytes %u bytes %u\n", padBytes, *bytes); + } + } + /* allocate for the padded array */ + if (rc == 0) { + rc = TPM_Malloc(bin, padBytes); + *bytes = padBytes; + } + /* call the bignum to bin conversion */ + if (rc == 0) { + rc = TPM_bn2binArray(*bin, padBytes, bn); + } + return rc; +} + +/* TPM_bn2binArray() loads the array 'bin' of size 'bytes' from 'bn' + + The data from 'bn' is right justified and zero padded. +*/ + +TPM_RESULT TPM_bn2binArray(unsigned char *bin, + unsigned int bytes, + TPM_BIGNUM bn) +{ + TPM_RESULT rc = 0; + unsigned int numBytes; + + printf(" TPM_bn2binArray: size %u\n", bytes); + if (rc == 0) { + /* zero pad */ + memset(bin, 0, bytes); + /* bytes required for the bignum */ + rc = TPM_BN_num_bytes(&numBytes, bn); + } + /* if the array is less than the number of bytes required by the bignum, this function fails */ + if (rc == 0) { + printf(" TPM_bn2binArray: numBytes in bignum %u\n", numBytes); + if (numBytes > bytes) { + printf("TPM_bn2binArray: Error, " + "BN bytes %u greater than array bytes %u\n", numBytes, bytes); + rc = TPM_SIZE; + } + } + if (rc == 0) { + /* if there are bytes in the bignum (it is not zero) */ + if (numBytes > 0) { + rc = TPM_bn2bin(bin + bytes - numBytes, /* store right justified */ + bn); + } + } + return rc; +} + +/* TPM_2bin2bn() converts two byte arrays to a positive BIGNUM. + + The two byte arrays are concatenated. The concatenation is used to create the BIGNUM. + + bignum must be freed by the caller. +*/ + +TPM_RESULT TPM_2bin2bn(TPM_BIGNUM *bignum_in, /* freed by caller */ + const unsigned char *bin0, uint32_t size0, + const unsigned char *bin1, uint32_t size1) +{ + TPM_RESULT rc = 0; /* TPM return code */ + TPM_STORE_BUFFER sBuffer; /* used of >1 element or first element is negative */ + const unsigned char *buffer; + uint32_t size; + + printf(" TPM_bin2bn:\n"); + TPM_Sbuffer_Init(&sBuffer); /* freed @1 */ + /* append the first element */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(&sBuffer, bin0, size0); + } + /* append the next element */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(&sBuffer, bin1, size1); + } + /* create the BIGNUM from the array */ + if (rc == 0) { + TPM_Sbuffer_Get(&sBuffer, &buffer, &size); + /* create the BIGNUM */ + rc = TPM_bin2bn(bignum_in, buffer, size); /* freed by caller */ + } + TPM_Sbuffer_Delete(&sBuffer); /* @1 */ + return rc; +} + +/* TPM_RSAPrivateDecryptMalloc() allocates a buffer 'decrypt_data' of size 'decrypt_data_size' + and then calls TPM_RSAPrivateDecryptH(). +*/ + +TPM_RESULT TPM_RSAPrivateDecryptMalloc(unsigned char **decrypt_data, /* decrypted data */ + uint32_t *decrypt_data_length, /* length of data put into + decrypt_data */ + unsigned char *encrypt_data, + uint32_t encrypt_data_size, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + /* allocate space for the decrypted blob */ + printf(" TPM_RSAPrivateDecryptMalloc: Return max data size %u bytes\n", + tpm_key->pubKey.size); + if (rc == 0) { + rc = TPM_Malloc(decrypt_data, tpm_key->pubKey.size); + } + if (rc == 0) { + rc = TPM_RSAPrivateDecryptH(*decrypt_data, + decrypt_data_length, + tpm_key->pubKey.size, + encrypt_data, + encrypt_data_size, + tpm_key); + } + return rc; +} + +/* TPM_RSAPrivateDecryptH() decrypts 'encrypt_data' using the private key in + 'tpm_key' and 'decrypt_data_length' bytes are moved to 'decrypt_data'. + + 'decrypt_data_length' is at most 'decrypt_data_size'. +*/ + +TPM_RESULT TPM_RSAPrivateDecryptH(unsigned char *decrypt_data, /* decrypted data */ + uint32_t *decrypt_data_length, /* length of data put into + decrypt_data */ + uint32_t decrypt_data_size, /* size of decrypt_data buffer */ + unsigned char *encrypt_data, + uint32_t encrypt_data_size, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + unsigned char *narr; /* public modulus */ + uint32_t nbytes; + unsigned char *earr; /* public exponent */ + uint32_t ebytes; + unsigned char *darr; /* private exponent */ + uint32_t dbytes; + + printf(" TPM_RSAPrivateDecryptH: Data size %u bytes\n", encrypt_data_size); + TPM_PrintFourLimit(" TPM_RSAPrivateDecryptH: Encrypt data", encrypt_data, encrypt_data_size); + if (rc == 0) { + if (tpm_key == NULL) { + printf("TPM_RSAPrivateDecryptH: Error, NULL key\n"); + rc = TPM_DECRYPT_ERROR; + } + } + /* extract the public key from TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); + } + /* extract the private key from TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_GetPrivateKey(&dbytes, &darr, tpm_key); + } + /* extract the exponent from TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); + } + /* check the key size vs the data size */ + if (rc == 0) { + if (encrypt_data_size > nbytes) { + printf("TPM_RSAPrivateDecryptH: Error, data size too long for key size %u bytes\n", + nbytes); + rc = TPM_BAD_DATASIZE; + } + } + if (rc == 0) { + /* debug printing */ + printf(" TPM_RSAPrivateDecryptH: Public key length %u\n", nbytes); + printf(" TPM_RSAPrivateDecryptH: Private key length %u\n", dbytes); + TPM_PrintFour(" TPM_RSAPrivateDecryptH: Public key", narr); + printf(" TPM_RSAPrivateDecryptH: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]); + TPM_PrintFour(" TPM_RSAPrivateDecryptH: Private key", darr); + /* decrypt with private key */ + rc = TPM_RSAPrivateDecrypt(decrypt_data, /* decrypted data */ + decrypt_data_length, /* length of data put into decrypt_data */ + decrypt_data_size, /* size of decrypt_data buffer */ + tpm_key->algorithmParms.encScheme, /* encryption scheme */ + encrypt_data, /* encrypted data */ + encrypt_data_size, + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + darr, /* private exponent */ + dbytes); + } + if (rc == 0) { + TPM_PrintFourLimit(" TPM_RSAPrivateDecryptH: Decrypt data", decrypt_data, *decrypt_data_length); + } + return rc; +} + +/* TPM_RSAPublicEncryptSbuffer_Key() encrypts 'sbuffer' using the public key in 'tpm_key' and + puts the results in 'encData' +*/ + +TPM_RESULT TPM_RSAPublicEncryptSbuffer_Key(TPM_SIZED_BUFFER *enc_data, + TPM_STORE_BUFFER *sbuffer, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + const unsigned char *decrypt_data; /* serialization buffer */ + uint32_t decrypt_data_size; /* serialization size */ + + printf(" TPM_RSAPublicEncryptSbuffer_Key:\n"); + /* get the serialization results */ + TPM_Sbuffer_Get(sbuffer, &decrypt_data, &decrypt_data_size); + /* encrypt the serialization buffer with the public key, and place + the result in the enc_data buffer */ + rc = TPM_RSAPublicEncrypt_Key(enc_data, + decrypt_data, + decrypt_data_size, + tpm_key); + return rc; +} + +/* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key in 'tpm_key' and + puts the results in 'encData' +*/ + +TPM_RESULT TPM_RSAPublicEncrypt_Key(TPM_SIZED_BUFFER *enc_data, + const unsigned char *decrypt_data, + size_t decrypt_data_size, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + unsigned char *narr; /* public modulus */ + uint32_t nbytes; + unsigned char *earr; /* public exponent */ + uint32_t ebytes; + + printf(" TPM_RSAPublicEncrypt_Key: Data size %lu bytes\n", (unsigned long)decrypt_data_size); + if (rc == 0) { + if (tpm_key == NULL) { + printf("TPM_RSAPublicEncrypt_Key: Error, NULL key\n"); + rc = TPM_ENCRYPT_ERROR; + } + } + /* extract the public key from TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); + } + /* extract the exponent from TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); + } + if (rc == 0) { + rc = TPM_RSAPublicEncrypt_Common(enc_data, + decrypt_data, + decrypt_data_size, + tpm_key->algorithmParms.encScheme, /* encryption scheme */ + narr, + nbytes, + earr, + ebytes); + } + return rc; +} + +/* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key in 'tpm_pubkey' and + puts the results in 'encData' +*/ + +TPM_RESULT TPM_RSAPublicEncrypt_Pubkey(TPM_SIZED_BUFFER *enc_data, + const unsigned char *decrypt_data, + size_t decrypt_data_size, + TPM_PUBKEY *tpm_pubkey) +{ + TPM_RESULT rc = 0; + unsigned char *narr; /* public modulus */ + uint32_t nbytes; + unsigned char *earr; /* public exponent */ + uint32_t ebytes; + + printf(" TPM_RSAPublicEncrypt_Pubkey: Data size %lu bytes\n", (unsigned long)decrypt_data_size); + if (rc == 0) { + if (tpm_pubkey == NULL) { + printf("TPM_RSAPublicEncrypt_Pubkey: Error, NULL key\n"); + rc = TPM_ENCRYPT_ERROR; + } + } + /* extract the public key from TPM_PUBKEY */ + if (rc == 0) { + rc = TPM_Pubkey_GetPublicKey(&nbytes, &narr, tpm_pubkey); + } + /* extract the exponent from TPM_KEY */ + if (rc == 0) { + rc = TPM_Pubkey_GetExponent(&ebytes, &earr, tpm_pubkey); + } + if (rc == 0) { + rc = TPM_RSAPublicEncrypt_Common(enc_data, + decrypt_data, + decrypt_data_size, + tpm_pubkey->algorithmParms.encScheme, + narr, + nbytes, + earr, + ebytes); + } + return rc; +} + +/* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key modulus and + exponent, and puts the results in 'encData' +*/ + +TPM_RESULT TPM_RSAPublicEncrypt_Common(TPM_SIZED_BUFFER *enc_data, + const unsigned char *decrypt_data, + size_t decrypt_data_size, + TPM_ENC_SCHEME encScheme, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) + +{ + TPM_RESULT rc = 0; + unsigned char *encrypt_data = NULL; + + printf(" TPM_RSAPublicEncrypt_Common: Data size %lu bytes\n", (unsigned long)decrypt_data_size); + TPM_PrintFourLimit(" TPM_RSAPublicEncrypt_Common: Decrypt data", decrypt_data, decrypt_data_size); + /* check the key size vs the data size */ + if (rc == 0) { + if (decrypt_data_size > nbytes) { + printf("TPM_RSAPublicEncrypt_Common: Error, data size too long for key size %u bytes\n", + nbytes); + rc = TPM_BAD_DATASIZE; + } + } + /* allocate an array for the encrypted data */ + if (rc == 0) { + rc = TPM_Malloc(&encrypt_data, nbytes); + } + /* pad and encrypt the data */ + if (rc == 0) { + TPM_PrintFour(" TPM_RSAPublicEncrypt_Common: Public key", narr); + printf(" TPM_RSAPublicEncrypt_Common: Exponent %02x %02x %02x\n", + earr[0], earr[1], earr[2]); + rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ + nbytes, /* encrypted data size */ + encScheme, /* encryption scheme */ + decrypt_data, /* decrypted data */ + decrypt_data_size, + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + /* copy the result to the sized buffer */ + if (rc == 0) { + printf(" TPM_RSAPublicEncrypt_Common: Encrypt data size %u\n", nbytes); + TPM_PrintFour(" TPM_RSAPublicEncrypt_Common: Encrypt data", encrypt_data); + rc = TPM_SizedBuffer_Set(enc_data, nbytes, encrypt_data); + } + free(encrypt_data); /* @1 */ + return rc; +} + +/* + Signing Functions + + These commands show the TPM command and the allowed signature schemes: + + SHA DER INFO + TPM_GetAuditDigestSigned y n y + TPM_CertifyKey y n y + TPM_CertifyKey2 y n y + TPM_CertifySelfTest y n y + TPM_Quote y n y + TPM_Quote2 y n y + TPM_Sign y y y + TPM_MakeIdentity y n y + TPM_GetCapabilitySigned y n y +*/ + +/* TPM_RSASignToSizedBuffer() signs 'message' using the private key in 'tpm_key' and places the + result in 'signature' + + 'signature' should be initialized and deleted by the caller +*/ + +TPM_RESULT TPM_RSASignToSizedBuffer(TPM_SIZED_BUFFER *signature, + const unsigned char *message, /* input */ + size_t message_size, /* input */ + TPM_KEY *tpm_key) /* input, signing key */ +{ + TPM_RESULT rc = 0; + TPM_RSA_KEY_PARMS *rsa_key_parms; + unsigned int signature_length; + + printf(" TPM_RSASignToSizedBuffer: Message size %lu bytes\n", (unsigned long)message_size); + if (rc == 0) { + rc = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms, + &(tpm_key->algorithmParms)); + } + /* allocating space for the signature */ + if (rc == 0) { + rc = TPM_SizedBuffer_Allocate(signature, (rsa_key_parms->keyLength)/CHAR_BIT); + } + /* sign */ + if (rc == 0) { + rc = TPM_RSASignH(signature->buffer, /* output signature */ + &signature_length, /* output, size of signature */ + signature->size, /* input, size of signature buffer */ + message, /* message */ + message_size, /* message size */ + tpm_key); /* input, signing key */ + } + /* sanity check on signature */ + if (rc == 0) { + if (signature_length != signature->size) { + printf("TPM_RSASignToSizedBuffer: Error (fatal) signature_length %u sigSize %u\n", + signature_length, signature->size); + rc = TPM_FAIL; /* internal error, should never occur */ + } + } + return rc; +} + + +/* TPM_RSASignH() signs 'message' using the private key in 'tpm_key'. 'signature_length' bytes are + moved to 'signature'. + + 'signature_length' is at most 'signature_size'. +*/ + +TPM_RESULT TPM_RSASignH(unsigned char *signature, /* output */ + unsigned int *signature_length, /* output, size of signature */ + unsigned int signature_size, /* input, size of signature buffer */ + const unsigned char *message, /* input */ + size_t message_size, /* input */ + TPM_KEY *tpm_key) /* input, signing key */ +{ + TPM_RESULT rc = 0; + unsigned char *narr; /* public modulus */ + uint32_t nbytes; + unsigned char *earr; /* public exponent */ + uint32_t ebytes; + unsigned char *darr; /* private exponent */ + uint32_t dbytes; + + printf(" TPM_RSASignH: Message size %lu bytes\n", (unsigned long)message_size); + TPM_PrintFourLimit(" TPM_RSASignH: Message", message, message_size); + /* extract the public key from TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); + } + /* extract the private key from TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_GetPrivateKey(&dbytes, &darr, tpm_key); + } + /* extract the exponent from TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); + } + if (rc == 0) { + /* debug printing */ + TPM_PrintFour(" TPM_RSASignH: Public key", narr); + printf(" TPM_RSASignH: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]); + TPM_PrintFour(" TPM_RSASignH: Private key", darr); + /* sign with private key */ + rc = TPM_RSASign(signature, /* output */ + signature_length, /* output, size of signature */ + signature_size, /* input, size of signature buffer */ + tpm_key->algorithmParms.sigScheme, /* input, type of signature */ + message, /* input */ + message_size, /* input */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + darr, /* private exponent */ + dbytes); + } + if (rc == 0) { + TPM_PrintFour(" TPM_RSASignH: Signature", signature); + } + return rc; +} + +/* TPM_RSAVerifyH() verifies 'message' using the TPM format public key in 'tpm_pubkey' +*/ + +TPM_RESULT TPM_RSAVerifyH(TPM_SIZED_BUFFER *signature, /* input */ + const unsigned char *message, /* input */ + uint32_t message_size, /* input */ + TPM_PUBKEY *tpm_pubkey) /* input, verify key */ +{ + TPM_RESULT rc = 0; + unsigned char *narr; /* public modulus */ + uint32_t nbytes; + unsigned char *earr; /* public exponent */ + uint32_t ebytes; + + printf(" TPM_RSAVerifyH: Message size %u bytes\n", message_size); + /* extract the public key from TPM_PUBKEY */ + if (rc == 0) { + rc = TPM_Pubkey_GetPublicKey(&nbytes, &narr, tpm_pubkey); + } + /* extract the exponent from TPM_PUBKEY */ + if (rc == 0) { + rc = TPM_Pubkey_GetExponent(&ebytes, &earr, tpm_pubkey); + } + if (rc == 0) { + /* debug printing */ + TPM_PrintFour(" TPM_RSAVerifyH: Public key", narr); + TPM_PrintAll(" TPM_RSAVerifyH: Public exponent", earr, ebytes); + /* verify with public key */ + rc = TPM_RSAVerify(signature->buffer, /* input signature buffer */ + signature->size, /* input, size of signature buffer */ + tpm_pubkey->algorithmParms.sigScheme, /* input, type of signature */ + message, /* message */ + message_size, /* message size */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + return rc; +} + +/* TPM_RSAVerify() verifies the 'signature' of size 'signature_size' on the 'message' of size + 'message_size' using the public key n,e and the signature scheme 'sigScheme' as specified in PKCS + #1 v2.0. +*/ + +TPM_RESULT TPM_RSAVerify(unsigned char *signature, /* input */ + unsigned int signature_size, /* input, size of signature buffer */ + TPM_SIG_SCHEME sigScheme, /* input, type of signature */ + const unsigned char *message, /* input */ + uint32_t message_size, /* input */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + TPM_RESULT rc = 0; + + printf(" TPM_RSAVerify:\n"); + /* determine the signature scheme for the key */ + if (rc == 0) { + switch(sigScheme) { + case TPM_SS_NONE: + printf("TPM_RSAVerify: Error, sigScheme TPM_SS_NONE\n"); + rc = TPM_INVALID_KEYUSAGE; + break; + case TPM_SS_RSASSAPKCS1v15_SHA1: + case TPM_SS_RSASSAPKCS1v15_INFO: + rc = TPM_RSAVerifySHA1(signature, + signature_size, + message, + message_size, + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + break; + case TPM_SS_RSASSAPKCS1v15_DER: + printf("TPM_RSAVerify: Error, sigScheme %04hx unsupported\n", sigScheme); + rc = TPM_INVALID_KEYUSAGE; + break; + default: + printf("TPM_RSAVerify: Error, sigScheme %04hx unknown\n", sigScheme); + rc = TPM_INVALID_KEYUSAGE; + break; + } + } + return rc; +} + +/* + OAEP Padding +*/ + +/* TPM_RSA_padding_add_PKCS1_OAEP() is a variation of the the openSSL function + + int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, + unsigned char *f, int fl, unsigned char *p, int pl); + + It is used for TPM migration. The "encoding parameter" pl is replaced by pHash and the generated + random seed is replaced by a seed parameter. + + This function was independently written from the PKCS1 specification "9.1.1.1 Encoding + Operation", intended to be unencumbered by any license. + + + | seed | pHash | PS | 01 | Message | + + SHA1 SHA1 flen + + | <- emLen -> | + | db + | maskDb + | dbMask | + | seedMask + | maskSeed +*/ + +TPM_RESULT TPM_RSA_padding_add_PKCS1_OAEP(unsigned char *em, uint32_t emLen, + const unsigned char *from, uint32_t fLen, + const unsigned char *pHash, /* input 20 bytes */ + const unsigned char *seed) /* input 20 bytes */ +{ + TPM_RESULT rc = 0; + unsigned char *dbMask; + unsigned char *db; + unsigned char *maskedDb; + unsigned char *seedMask; + unsigned char *maskedSeed; + + printf(" TPM_RSA_padding_add_PKCS1_OAEP: fLen %d emLen %d\n", fLen, emLen); + TPM_PrintFourLimit(" TPM_RSA_padding_add_PKCS1_OAEP: from", from, fLen); + TPM_PrintFour(" TPM_RSA_padding_add_PKCS1_OAEP: pHash", pHash); + TPM_PrintFour(" TPM_RSA_padding_add_PKCS1_OAEP: seed", seed); + + dbMask = NULL; /* freed @1 */ + + /* 1. If the length of P is greater than the input limitation for */ + /* the hash function (2^61-1 octets for SHA-1) then output "parameter */ + /* string too long" and stop. */ + /* NOTE Not done, pHash is input directly */ + /* 2. If ||M|| > emLen-2hLen-1 then output "message too long" and stop. */ + if (rc == 0) { + if (emLen < ((2 * TPM_DIGEST_SIZE) + 1 + fLen)) { + printf("TPM_RSA_padding_add_PKCS1_OAEP: Error, " + "message length %u too large for encoded length %u\n", fLen, emLen); + rc = TPM_ENCRYPT_ERROR; + } + } + /* 3. Generate an octet string PS consisting of emLen-||M||-2hLen-1 zero octets. The length of + PS may be 0. */ + /* NOTE Created directly in DB (step 5) */ + + /* 4. Let pHash = Hash(P), an octet string of length hLen. */ + /* NOTE pHash is input directly */ + + /* 5. Concatenate pHash, PS, the message M, and other padding to form a data block DB as: DB = + pHash || PS || 01 || M */ + if (rc == 0) { + /* NOTE Since db is eventually maskedDb, part of em, create directly in em */ + db = em + TPM_DIGEST_SIZE; + memcpy(db, pHash, TPM_DIGEST_SIZE); /* pHash */ + memset(db + TPM_DIGEST_SIZE, 0, /* PS */ + emLen - fLen - (2 * TPM_DIGEST_SIZE) - 1); + /* PSlen = emlen - flen - (2 * TPM_DIGEST_SIZE) - 1 + 0x01 index = TPM_DIGEST_SIZE + PSlen + = TPM_DIGEST_SIZE + emlen - flen - (2 * TPM_DIGEST_SIZE) - 1 + = emlen - fLen - TPM_DIGEST_SIZE - 1 */ + db[emLen - fLen - TPM_DIGEST_SIZE - 1] = 0x01; + memcpy(db + emLen - fLen - TPM_DIGEST_SIZE, from, fLen); /* M */ + + /* 6. Generate a random octet string seed of length hLen. */ + /* NOTE seed is input directly */ + + /* 7. Let dbMask = MGF(seed, emLen-hLen). */ + rc = TPM_Malloc(&dbMask, emLen - TPM_DIGEST_SIZE); + } + if (rc == 0) { + rc = TPM_MGF1(dbMask, emLen - TPM_DIGEST_SIZE, seed, TPM_DIGEST_SIZE); + } + if (rc == 0) { + /* 8. Let maskedDB = DB \xor dbMask. */ + /* NOTE Since maskedDB is eventually em, XOR directly to em */ + maskedDb = em + TPM_DIGEST_SIZE; + TPM_XOR(maskedDb, db, dbMask, emLen - TPM_DIGEST_SIZE); + + /* 9. Let seedMask = MGF(maskedDB, hLen). */ + /* NOTE Since seedMask is eventually em, create directly to em */ + seedMask = em; + rc = TPM_MGF1(seedMask, TPM_DIGEST_SIZE, maskedDb, emLen - TPM_DIGEST_SIZE); + } + if (rc == 0) { + /* 10. Let maskedSeed = seed \xor seedMask. */ + /* NOTE Since maskedSeed is eventually em, create directly to em */ + maskedSeed = em; + TPM_XOR(maskedSeed, seed, seedMask, TPM_DIGEST_SIZE); + + /* 11. Let EM = maskedSeed || maskedDB. */ + /* NOTE Created directly in em */ + + /* 12. Output EM. */ + TPM_PrintFourLimit(" TPM_RSA_padding_add_PKCS1_OAEP: em", em, emLen); + } + free(dbMask); /* @1 */ + return rc; +} + +/* TPM_RSA_padding_check_PKCS1_OAEP() is a variation of the openSSL function + + int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + unsigned char *f, int fl, int rsa_len, unsigned char *p, int pl); + + It is used for TPM key migration. In addition to the message 'to' and message length 'tlen', the + seed and 'pHash are returned. + + This function was independently written from the PKCS1 specification "9.1.1.2 Decoding + Operation", intended to be unencumbered by the any license. + + | seed | pHash | PS | 01 | Message | + SHA1 SHA1 + | <- emLen -> | + + | maskedSeed + | seedMask + | maskedDB + | db + | <- dbMask -> | + +*/ + +TPM_RESULT TPM_RSA_padding_check_PKCS1_OAEP(unsigned char *to, uint32_t *tLen, uint32_t tSize, + const unsigned char *em, uint32_t emLen, + unsigned char *pHash, /* output 20 bytes */ + unsigned char *seed) /* output 20 bytes */ +{ + TPM_RESULT rc = 0; + const unsigned char *maskedSeed; + const unsigned char *maskedDB; + uint32_t dbLen; + unsigned char *dbMask; + unsigned char *seedMask; + unsigned char *db; + size_t i; + + printf(" TPM_RSA_padding_check_PKCS1_OAEP: emLen %d tSize %d\n", emLen, tSize); + TPM_PrintFourLimit(" TPM_RSA_padding_check_PKCS1_OAEP: em", em, emLen); + + dbMask = NULL; /* freed @1 */ + + /* 1. If the length of P is greater than the input limitation for the hash function (2^61-1 + octets for SHA-1) then output "parameter string too long" and stop. */ + /* NOTE There is no P input. pHash is calculated for the output, but no comparison is + performed. */ + + /* 2. If ||EM|| < 2hLen+1, then output "decoding error" and stop. */ + if (rc == 0) { + if (emLen < (2 * TPM_DIGEST_SIZE) + 1) { + printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, encoded length %u too small\n", emLen); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + /* 3. Let maskedSeed be the first hLen octets of EM and let maskedDB be the remaining ||EM|| + - hLen octets. */ + maskedSeed = em; + maskedDB = em + TPM_DIGEST_SIZE; + dbLen = emLen - TPM_DIGEST_SIZE; + /* 4. Let seedMask = MGF(maskedDB, hLen). */ + /* NOTE Created directly in seed */ + seedMask = seed; + rc = TPM_MGF1(seedMask, TPM_DIGEST_SIZE, maskedDB, dbLen); + } + if (rc == 0) { + /* 5. Let seed = maskedSeed \xor seedMask. */ + TPM_XOR(seed, maskedSeed, seedMask, TPM_DIGEST_SIZE); + /* 6. Let dbMask = MGF(seed, ||EM|| - hLen). */ + rc = TPM_Malloc(&dbMask, dbLen); + } + if (rc == 0) { + rc = TPM_MGF1(dbMask, dbLen, seed, TPM_DIGEST_SIZE); + } + if (rc == 0) { + /* 7. Let DB = maskedDB \xor dbMask. */ + /* NOTE XOR back to dbMask, since dbMask no longer needed */ + db = dbMask; + TPM_XOR(db, maskedDB, dbMask, dbLen); + /* 8. Let pHash = Hash(P), an octet string of length hLen. */ + /* NOTE pHash is input directly */ + /* 9. Separate DB into an octet string pHash' consisting of the first hLen octets of DB, + ... */ + memcpy(pHash, db, TPM_DIGEST_SIZE); + /* ... a (possibly empty) octet string PS consisting of consecutive zero octets following + pHash', and a message M as: DB = pHash' || PS || 01 || M */ + for (i = TPM_DIGEST_SIZE; i < dbLen; i++) { + if (db[i] != 0x00) { + break; /* skip the PS segment */ + } + } + /* If there is no 01 octet to separate PS from M, output "decoding error" and stop. */ + if (i == dbLen) { + printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, missing 0x01\n"); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + if (db[i] != 0x01) { + printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, missing 0x01\n"); + rc = TPM_DECRYPT_ERROR; + } + } + /* 10. If pHash' does not equal pHash, output "decoding error" and stop. */ + /* NOTE No pHash input to compare */ + /* 11. Output M. */ + if (rc == 0) { + i++; /* skip the 0x01 to the beginning of the message M */ + *tLen = dbLen - i; + if (*tLen > tSize) { + printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, tSize %u too small for message %u\n", + tSize, *tLen); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + memcpy(to, db + i, *tLen); + printf(" TPM_RSA_padding_check_PKCS1_OAEP: tLen %d \n", *tLen); + TPM_PrintFourLimit(" TPM_RSA_padding_check_PKCS1_OAEP: to", to, *tLen); + TPM_PrintFour(" TPM_RSA_padding_check_PKCS1_OAEP: pHash", pHash); + TPM_PrintFour(" TPM_RSA_padding_check_PKCS1_OAEP: seed", seed); + } + free(dbMask); /* @1 */ + return rc; +} + +/* TPM_RSA_exponent_verify() validates the public exponent against a list of legal values. Some + values (e.g. even numbers) will have the key generator. +*/ + +TPM_RESULT TPM_RSA_exponent_verify(unsigned long exponent) +{ + TPM_RESULT rc = 0; + size_t i; + int found; + + static const unsigned long legalExponent[] = { 3,5,7,17,257,65537 }; + + for (i = 0, found = FALSE ; + !found && (i < (sizeof(legalExponent) / sizeof (unsigned long))) ; + i++) { + + if (exponent == legalExponent[i]) { + found = TRUE; + } + } + if (!found) { + printf("TPM_RSA_exponent_verify: Error, public exponent %lu is illegal\n", exponent ); + rc = TPM_BAD_KEY_PROPERTY; + } + return rc; +} + +/* SHA1 and HMAC test driver + + Returns TPM_FAILEDSELFTEST on error +*/ + +TPM_RESULT TPM_CryptoTest(void) +{ + TPM_RESULT rc = 0; + int not_equal; + TPM_BOOL valid; + + /* SHA1 */ + unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C, + 0x3B,0xD2,0x6E,0xBA,0xAE, + 0x4A,0xA1,0xF9,0x51,0x29, + 0xE5,0xE5,0x46,0x70,0xF1}; + TPM_DIGEST actual; + uint32_t actual_size; + + /* HMAC */ + unsigned char key2[] = {0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa}; + unsigned char expect2[] = {0x12,0x5d,0x73,0x42,0xb9,0xac,0x11,0xcd,0x91,0xa3, + 0x9a,0xf4,0x8a,0xa1,0x7b,0x4f,0x63,0xf1,0x75,0xd3}; + /* data 0xdd repeated 50 times */ + unsigned char data2[50]; + + /* oaep tests */ + const unsigned char oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; + unsigned char pHash_in[TPM_DIGEST_SIZE]; + unsigned char pHash_out[TPM_DIGEST_SIZE]; + unsigned char seed_in[TPM_DIGEST_SIZE] = {0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, + 0xf0,0xf1,0xf2,0xf3}; + unsigned char seed_out[TPM_DIGEST_SIZE]; + unsigned char oaep_in[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; + unsigned char oaep_pad[256]; + unsigned char oaep_out[8]; + uint32_t oeap_length; + + /* symmetric key with pad */ + TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data = NULL; /* opaque structure, freed @7 */ + unsigned char clrStream[64]; /* expected */ + unsigned char *encStream; /* encrypted */ + uint32_t encSize; + unsigned char *decStream; /* actual */ + uint32_t decSize; + + /* symmetric key ctr and ofb mode */ + TPM_SECRET symKey; + TPM_NONCE pad; /* CTR or IV */ + TPM_ENCAUTH symClear; + TPM_ENCAUTH symEnc; + TPM_ENCAUTH symDec; + + /* RSA encrypt and decrypt, sign and verify */ + unsigned char *n; /* public key - modulus */ + unsigned char *p; /* private key prime */ + unsigned char *q; /* private key prime */ + unsigned char *d; /* private key (private exponent) */ + unsigned char encrypt_data[2048/8]; /* encrypted data */ + unsigned char signature[2048/8]; /* signature; libtpms added */ + + printf(" TPM_CryptoTest:\n"); + encStream = NULL; /* freed @1 */ + decStream = NULL; /* freed @2 */ + n = NULL; /* freed @3 */ + p = NULL; /* freed @4 */ + q = NULL; /* freed @5 */ + d = NULL; /* freed @6 */ + + if (rc == 0) { + printf(" TPM_CryptoTest: Test 1 - SHA1 one part\n"); + rc = TPM_SHA1(actual, + sizeof(buffer1) - 1, buffer1, + 0, NULL); + } + if (rc == 0) { + not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 1\n"); + TPM_PrintFour("\texpect", expect1); + TPM_PrintFour("\tactual", actual); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + printf(" TPM_CryptoTest: Test 2 - SHA1 two parts\n"); + rc = TPM_SHA1(actual, + 16, buffer1, /* first 16 */ + sizeof(buffer1) - 17, buffer1 + 16, /* rest */ + 0, NULL); + } + if (rc == 0) { + not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 2\n"); + TPM_PrintFour("\texpect", expect1); + TPM_PrintFour("\tactual", actual); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + printf(" TPM_CryptoTest: Test 3 - HMAC generate - one part\n"); + memset(data2, 0xdd, 50); + rc = TPM_HMAC_Generate(actual, + key2, + 50, data2, + 0, NULL); + } + if (rc == 0) { + not_equal = memcmp(expect2, actual, TPM_DIGEST_SIZE); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 3\n"); + TPM_PrintFour("\texpect", expect1); + TPM_PrintFour("\tactual", actual); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + printf(" TPM_CryptoTest: Test 4 - HMAC generate - two parts\n"); + memset(data2, 0xdd, 50); + rc = TPM_HMAC_Generate(actual, + key2, + 20, data2, + 30, data2 + 20, + 0, NULL); + } + if (rc == 0) { + not_equal = memcmp(expect2, actual, TPM_DIGEST_SIZE); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 3\n"); + TPM_PrintFour("\texpect", expect2); + TPM_PrintFour("\tactual", actual); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + printf(" TPM_CryptoTest: Test 4 - HMAC check - two parts\n"); + memset(data2, 0xdd, 50); + rc = TPM_HMAC_Check(&valid, + expect2, + key2, + 20, data2, + 30, data2 + 20, + 0, NULL); + } + if (rc == 0) { + if (!valid) { + printf("TPM_CryptoTest: Error in test 4\n"); + TPM_PrintFour("\texpect", expect1); + TPM_PrintFour("\tactual", actual); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + printf(" TPM_CryptoTest: Test 5 - OAEP add and check\n"); + rc = TPM_SHA1(pHash_in, + sizeof(oaep_pad_str), oaep_pad_str, + 0, NULL); + } + if (rc == 0) { + rc = TPM_RSA_padding_add_PKCS1_OAEP(oaep_pad, sizeof(oaep_pad), + oaep_in, sizeof(oaep_in), + pHash_in, seed_in); + } + if (rc == 0) { + rc = TPM_RSA_padding_check_PKCS1_OAEP(oaep_out, &oeap_length, sizeof(oaep_out), + oaep_pad, sizeof(oaep_pad), + pHash_out, + seed_out); + } + if (rc == 0) { + if (oeap_length != sizeof(oaep_out)) { + printf("TPM_CryptoTest: Error in test 5, expect length %lu, actual length %u\n", + (unsigned long)sizeof(oaep_out), oeap_length); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + not_equal = memcmp(oaep_in, oaep_out, sizeof(oaep_out)); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 5 oaep\n"); + TPM_PrintFour("\tin ", oaep_in); + TPM_PrintFour("\tout", oaep_out); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + not_equal = memcmp(pHash_in, pHash_out, sizeof(pHash_in)); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 5 pHash\n"); + TPM_PrintFour("\tpHash_in ", pHash_in); + TPM_PrintFour("\tpHash_out", pHash_out); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + not_equal = memcmp(seed_in, seed_out, sizeof(seed_in)); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 5 seed\n"); + TPM_PrintFour("\tseed_in ", seed_in); + TPM_PrintFour("\tseed_out", seed_out); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + printf(" TPM_CryptoTest: Test 6 - Symmetric key with PKCS pad test\n"); + /* allocate memory for the key token */ + rc = TPM_SymmetricKeyData_New(&tpm_symmetric_key_data); /* freed @7 */ + } + /* generate a key */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_GenerateKey(tpm_symmetric_key_data); + } + /* generate clear text */ + if (rc == 0) { + rc = TPM_Random(clrStream, sizeof(clrStream)); + } + /* symmetric encrypt */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_Encrypt(&encStream, /* output, freed @1 */ + &encSize, /* output */ + clrStream, /* input */ + sizeof(clrStream), /* input */ + tpm_symmetric_key_data); /* key */ + } + /* symmetric decrypt */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_Decrypt(&decStream, /* output, freed by caller */ + &decSize, /* output */ + encStream, /* input */ + encSize, /* input */ + tpm_symmetric_key_data); /* key */ + } + /* symmetric compare */ + if (rc == 0) { + if (sizeof(clrStream) != decSize) { + printf("TPM_CryptoTest: Error in test 6, in %lu, out %u\n", + (unsigned long)sizeof(clrStream), decSize); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + not_equal = memcmp(clrStream, decStream, sizeof(clrStream)); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 6\n"); + TPM_PrintFour("\tclear stream in", clrStream); + TPM_PrintFour("\tdecrypted stream", decStream); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + printf(" TPM_CryptoTest: Test 7 - Symmetric key with CTR mode\n"); + /* generate a key */ + rc = TPM_Random(symKey, TPM_SECRET_SIZE); + } + /* generate CTR */ + if (rc == 0) { + rc = TPM_Random(pad, TPM_NONCE_SIZE); + } + /* generate clear text */ + if (rc == 0) { + rc = TPM_Random(symClear, TPM_AUTHDATA_SIZE); + } + if (rc == 0) { + rc = TPM_SymmetricKeyData_CtrCrypt(symEnc, /* output */ + symClear, /* input */ + TPM_AUTHDATA_SIZE, /* input */ + symKey, /* in */ + TPM_SECRET_SIZE, /* in */ + pad, /* input */ + TPM_NONCE_SIZE); /* input */ + } + if (rc == 0) { + rc = TPM_SymmetricKeyData_CtrCrypt(symDec, /* output */ + symEnc, /* input */ + TPM_AUTHDATA_SIZE, /* input */ + symKey, /* in */ + TPM_SECRET_SIZE, /* in */ + pad, /* input */ + TPM_NONCE_SIZE); /* input */ + } + /* symmetric compare */ + if (rc == 0) { + rc = TPM_Secret_Compare(symDec, symClear); + if (rc != 0) { + printf("TPM_CryptoTest: Error in test 8\n"); + TPM_PrintFour("\tclear stream in", symClear); + TPM_PrintFour("\tdecrypted stream", symDec); + } + } + if (rc == 0) { + printf(" TPM_CryptoTest: Test 8 - Symmetric key with OFB mode\n"); + /* generate a key */ + rc = TPM_Random(symKey, TPM_SECRET_SIZE); + } + /* generate IV */ + if (rc == 0) { + rc = TPM_Random(pad, TPM_NONCE_SIZE); + } + /* generate clear text */ + if (rc == 0) { + rc = TPM_Random(symClear, TPM_AUTHDATA_SIZE); + } + if (rc == 0) { + rc = TPM_SymmetricKeyData_OfbCrypt(symEnc, /* output */ + symClear, /* input */ + TPM_AUTHDATA_SIZE, /* input */ + symKey, /* in */ + TPM_SECRET_SIZE, /* in */ + pad, /* input */ + TPM_NONCE_SIZE); /* input */ + } + if (rc == 0) { + rc = TPM_SymmetricKeyData_OfbCrypt(symDec, /* output */ + symEnc, /* input */ + TPM_AUTHDATA_SIZE, /* input */ + symKey, /* in */ + TPM_SECRET_SIZE, /* in */ + pad, /* input */ + TPM_NONCE_SIZE); /* input */ + } + /* symmetric compare */ + if (rc == 0) { + rc = TPM_Secret_Compare(symDec, symClear); + if (rc != 0) { + printf("TPM_CryptoTest: Error in test 8\n"); + TPM_PrintFour("\tclear stream in", symClear); + TPM_PrintFour("\tdecrypted stream", symDec); + } + } + /* RSA OAEP encrypt and decrypt */ + if (rc == 0) { + printf(" TPM_CryptoTest: Test 9 - RSA encrypt with OAEP padding\n"); + /* generate a key */ + rc = TPM_RSAGenerateKeyPair(&n, /* public key - modulus */ + &p, /* private key prime */ + &q, /* private key prime */ + &d, /* private key (private exponent) */ + 2048, /* key size in bits */ + tpm_default_rsa_exponent, /* public exponent as an array */ + 3); + } + /* encrypt */ + if (rc == 0) { + rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ + sizeof(encrypt_data), /* size of encrypted data buffer */ + TPM_ES_RSAESOAEP_SHA1_MGF1, /* TPM_ENC_SCHEME */ + expect1, /* decrypted data */ + sizeof(expect1), + n, /* public modulus */ + 2048/8, + tpm_default_rsa_exponent, /* public exponent */ + 3); + } + if (rc == 0) { + rc = TPM_RSAPrivateDecrypt(actual, /* decrypted data */ + &actual_size, /* length of data put into + decrypt_data */ + TPM_DIGEST_SIZE, /* size of decrypt_data buffer */ + TPM_ES_RSAESOAEP_SHA1_MGF1, /* TPM_ENC_SCHEME */ + encrypt_data, /* encrypted data */ + sizeof(encrypt_data), + n, /* public modulus */ + 2048/8, + tpm_default_rsa_exponent, /* public exponent */ + 3, + d, /* private exponent */ + 2048/8); + } + if (rc == 0) { + if (actual_size != TPM_DIGEST_SIZE) { + printf("TPM_CryptoTest: Error in test 9, expect length %u, actual length %u\n", + TPM_DIGEST_SIZE, actual_size); + rc = TPM_FAILEDSELFTEST; + } + } + if (rc == 0) { + not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 9\n"); + TPM_PrintFour("\tin ", expect1); + TPM_PrintFour("\tout", actual); + rc = TPM_FAILEDSELFTEST; + } + } + /* RSA PKCS1 pad, encrypt and decrypt */ + if (rc == 0) { + printf(" TPM_CryptoTest: Test 10 - RSA encrypt with PKCS padding\n"); + /* encrypt */ + rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ + sizeof(encrypt_data), /* size of encrypted data buffer */ + TPM_ES_RSAESPKCSv15, /* TPM_ENC_SCHEME */ + expect1, /* decrypted data */ + sizeof(expect1), + n, /* public modulus */ + 2048/8, + tpm_default_rsa_exponent, /* public exponent */ + 3); + } + /* decrypt */ + if (rc == 0) { + rc = TPM_RSAPrivateDecrypt(actual, /* decrypted data */ + &actual_size, /* length of data put into + decrypt_data */ + TPM_DIGEST_SIZE, /* size of decrypt_data buffer */ + TPM_ES_RSAESPKCSv15, /* TPM_ENC_SCHEME */ + encrypt_data, /* encrypted data */ + sizeof(encrypt_data), + n, /* public modulus */ + 2048/8, + tpm_default_rsa_exponent, /* public exponent */ + 3, + d, /* private exponent */ + 2048/8); + } + /* check length after padding removed */ + if (rc == 0) { + if (actual_size != TPM_DIGEST_SIZE) { + printf("TPM_CryptoTest: Error in test 10, expect length %u, actual length %u\n", + TPM_DIGEST_SIZE, actual_size); + rc = TPM_FAILEDSELFTEST; + } + } + /* check data */ + if (rc == 0) { + not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); + if (not_equal) { + printf("TPM_CryptoTest: Error in test 10\n"); + TPM_PrintFour("\tin ", expect1); + TPM_PrintFour("\tout", actual); + rc = TPM_FAILEDSELFTEST; + } + } + +// libtpms added begin + + if (rc == 0) { + printf(" TPM_CryptoTest: Test 11a - RSA sign with PKCS1v15 padding\n"); + rc = TPM_RSASign(signature, + &actual_size, + sizeof(signature), + TPM_SS_RSASSAPKCS1v15_SHA1, + expect1, + sizeof(expect1), + n, /* public modulus */ + 2048/8, + tpm_default_rsa_exponent, /* public exponent */ + 3, + d, /* private exponent */ + 2048/8); + } + if (rc == 0) { + rc = TPM_RSAVerify(signature, /* input signature buffer */ + sizeof(signature), /* input, size of signature buffer */ + TPM_SS_RSASSAPKCS1v15_SHA1, /* input, type of signature */ + expect1, /* message */ + sizeof(expect1), /* message size */ + n, /* public modulus */ + 2048/8, + tpm_default_rsa_exponent,/* public exponent */ + 3); + } + +#if 0 + /* Verification with TPM_SS_RSASSAPKCS1v15_DER is not supported */ + if (rc == 0) { + printf(" TPM_CryptoTest: Test 11b - RSA sign with PKCS1v15_DER padding\n"); + rc = TPM_RSASign(signature, + &actual_size, + sizeof(signature), + TPM_SS_RSASSAPKCS1v15_DER, + expect1, + sizeof(expect1), + n, /* public modulus */ + 2048/8, + tpm_default_rsa_exponent, /* public exponent */ + 3, + d, /* private exponent */ + 2048/8); + } + if (rc == 0) { + rc = TPM_RSAVerify(signature, /* input signature buffer */ + sizeof(signature), /* input, size of signature buffer */ + TPM_SS_RSASSAPKCS1v15_DER, /* input, type of signature */ + expect1, /* message */ + sizeof(expect1), /* message size */ + n, /* public modulus */ + 2048/8, + tpm_default_rsa_exponent,/* public exponent */ + 3); + } +#endif // libtpms added end + + /* run library specific self tests as required */ + if (rc == 0) { + rc = TPM_Crypto_TestSpecific(); + } + if (rc != 0) { + rc = TPM_FAILEDSELFTEST; + } + free(encStream); /* @1 */ + free(decStream); /* @2 */ + free(n); /* @3 */ + free(p); /* @4 */ + free(q); /* @5 */ + free(d); /* @6 */ + TPM_SymmetricKeyData_Free(&tpm_symmetric_key_data); /* @7 */ + return rc; +} + +/* 13.5 TPM_Sign rev 111 + + The Sign command signs data and returns the resulting digital signature. + + The TPM does not allow TPM_Sign with a TPM_KEY_IDENTITY (AIK) because TPM_Sign can sign arbitrary + data and could be used to fake a quote. (This could have been relaxed to allow TPM_Sign with an + AIK if the signature scheme is _INFO For an _INFO key, the metadata prevents TPM_Sign from faking + a quote.) + + The TPM MUST support all values of areaToSignSize that are legal for the defined signature scheme + and key size. The maximum value of areaToSignSize is determined by the defined signature scheme + and key size. + + In the case of PKCS1v15_SHA1 the areaToSignSize MUST be TPM_DIGEST (the hash size of a sha1 + operation - see 8.5.1 TPM_SS_RSASSAPKCS1v15_SHA1). In the case of PKCS1v15_DER the maximum size + of areaToSign is k - 11 octets, where k is limited by the key size (see 8.5.2 + TPM_SS_RSASSAPKCS1v15_DER). +*/ + +TPM_RESULT TPM_Process_Sign(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform + digital signatures. */ + TPM_SIZED_BUFFER areaToSign; /* The value to sign */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle authorization + */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ + TPM_AUTHDATA privAuth; /* The authorization digest that authorizes the use of + keyHandle. HMAC key: key.usageAuth */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus ; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_KEY *key = NULL; /* the key specified by keyHandle */ + TPM_RSA_KEY_PARMS *rsa_key_parms; /* for key */ + TPM_BOOL parentPCRStatus; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *keyUsageAuth; + TPM_SIGN_INFO tpm_sign_info; + const unsigned char *S1_data; /* data to be signed */ + uint32_t S1_size; + TPM_DIGEST infoDigest; /* TPM_SIGN_INFO structure digest */ + TPM_STORE_BUFFER sbuffer; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ + + printf("TPM_Process_Sign: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&areaToSign); /* freed @1 */ + TPM_SignInfo_Init(&tpm_sign_info); /* freed @2 */ + TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ + TPM_SizedBuffer_Init(&sig); /* freed @4 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Sign: keyHandle %08x\n", keyHandle); + /* get areaToSignSize and areaToSign parameters */ + returnCode = TPM_SizedBuffer_Load(&areaToSign, &command, ¶mSize); /* freed @1 */ + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Sign: Signing %u bytes\n", areaToSign.size); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Sign: Error, command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not r/o, used to sign */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* check TPM_AUTH_DATA_USAGE authDataUsage */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (key->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_Sign: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + key, + keyUsageAuth, /* OIAP */ + key->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 1. The TPM validates the AuthData to use the key pointed to by keyHandle. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + /* 2. If the areaToSignSize is 0 the TPM returns TPM_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if (areaToSign.size == 0) { + printf("TPM_Process_Sign: Error, areaToSignSize is 0\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING or TPM_KEY_LEGACY, if not return + the error code TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if ((key->keyUsage != TPM_KEY_SIGNING) && ((key->keyUsage) != TPM_KEY_LEGACY)) { + printf("TPM_Process_Sign: Error, keyUsage %04hx is invalid\n", key->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. The TPM verifies that the signature scheme and key size can properly sign the areaToSign + parameter. NOTE Done in 5. - 7.*/ + /* get key -> TPM_RSA_KEY_PARMS */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms, + &(key->algorithmParms)); + } + if (returnCode == TPM_SUCCESS) { + /* 5. If signature scheme is TPM_SS_RSASSAPKCS1v15_SHA1 then */ + if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) { + printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1\n"); + /* a. Validate that areaToSignSize is 20 return TPM_BAD_PARAMETER on error */ + if (returnCode == TPM_SUCCESS) { + if (areaToSign.size != TPM_DIGEST_SIZE) { + printf("TPM_Process_Sign: Error, areaToSignSize %d should be %u\n", + areaToSign.size, TPM_DIGEST_SIZE); + returnCode = TPM_BAD_PARAMETER; + } + } + /* b. Set S1 to areaToSign */ + if (returnCode == TPM_SUCCESS) { + S1_size = areaToSign.size; + S1_data = areaToSign.buffer; + } + } + /* 6. Else if signature scheme is TPM_SS_RSASSAPKCS1v15_DER then */ + else if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_DER) { + printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_DER\n"); + /* a. Validate that areaToSignSize is at least 11 bytes less than the key size, return + TPM_BAD_PARAMETER on error */ + if (returnCode == TPM_SUCCESS) { + if (areaToSign.size > (((rsa_key_parms->keyLength)/CHAR_BIT) - 11)) { + printf("TPM_Process_Sign: Error, areaToSignSize %d should be 11-%u\n", + areaToSign.size, ((rsa_key_parms->keyLength)/CHAR_BIT)); + returnCode = TPM_BAD_PARAMETER; + } + } + /* b. Set S1 to areaToSign */ + if (returnCode == TPM_SUCCESS) { + S1_size = areaToSign.size; + S1_data = areaToSign.buffer; + } + } + /* 7. else if signature scheme is TPM_SS_RSASSAPKCS1v15_INFO then */ + else if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) { + printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_INFO\n"); + if (returnCode == TPM_SUCCESS) { + /* a. Create S2 a TPM_SIGN_INFO structure */ + /* NOTE: Done by TPM_SignInfo_Init() */ + /* b. Set S2 -> fixed to "SIGN" */ + memcpy(tpm_sign_info.fixed, "SIGN", TPM_SIGN_INFO_FIXED_SIZE); + /* c.i. If nonceOdd is not present due to an unauthorized command return + TPM_BAD_PARAMETER */ + if (tag == TPM_TAG_RQU_COMMAND) { + printf("TPM_Process_Sign: Error, TPM_SS_RSASSAPKCS1v15_INFO and no auth\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + /* c. Set S2 -> replay to nonceOdd */ + TPM_Nonce_Copy(tpm_sign_info.replay, nonceOdd); + /* d. Set S2 -> dataLen to areaToSignSize */ + /* e. Set S2 -> data to areaToSign */ + returnCode = TPM_SizedBuffer_Copy(&(tpm_sign_info.data), &areaToSign); + } + /* f. Set S1 to the SHA-1(S2) */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(infoDigest, + &tpm_sign_info, + (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); + S1_size = TPM_DIGEST_SIZE; + S1_data = infoDigest; + } + } + /* 8. Else return TPM_INVALID_KEYUSAGE */ + else { + printf("TPM_Process_Sign: Error, sigScheme %04hx\n", key->algorithmParms.sigScheme); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 9. The TPM computes the signature, sig, using the key referenced by keyHandle using S1 as the + value to sign */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintAll("TPM_Process_Sign: Digest to sign", S1_data, S1_size); + returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ + S1_data, /* message */ + S1_size, /* message size */ + key); /* input, signing key */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_Sign: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 10. Return the computed signature in Sig */ + returnCode = TPM_SizedBuffer_Store(response, &sig); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&areaToSign); /* @1 */ + TPM_SignInfo_Delete(&tpm_sign_info); /* @2 */ + TPM_Sbuffer_Delete(&sbuffer); /* @3 */ + TPM_SizedBuffer_Delete(&sig); /* @4 */ + return rcf; +} + +/* 13.1 TPM_SHA1Start rev 96 + + This capability starts the process of calculating a SHA-1 digest. + + The exposure of the SHA-1 processing is a convenience to platforms in a mode that do not have + sufficient memory to perform SHA-1 themselves. As such the use of SHA-1 is restrictive on the + TPM. + + The TPM may not allow any other types of processing during the execution of a SHA-1 + session. There is only one SHA-1 session active on a TPM. The exclusivity of a SHA-1 + context is due to the relatively large volatile buffer it requires in order to hold the + intermediate results between the SHA-1 context commands. This buffer can be in + contradiction to other command needs. + + After the execution of SHA1Start, and prior to SHA1End, the receipt of any command other than + SHA1Update will cause the invalidation of the SHA-1 session. +*/ + +TPM_RESULT TPM_Process_SHA1Start(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters - none */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + uint32_t maxNumBytes = TPM_SHA1_MAXNUMBYTES; /* Maximum number of bytes that can be sent + to TPM_SHA1Update. Must be a multiple of + 64 bytes. */ + + printf("TPM_Process_SHA1Start: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SHA1Start: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* This capability prepares the TPM for a subsequent TPM_SHA1Update, TPM_SHA1Complete or + TPM_SHA1CompleteExtend command. The capability SHALL open a thread that calculates a SHA-1 + digest. + */ + if (returnCode == TPM_SUCCESS) { + if (transportInternal == NULL) { + tpm_state->transportHandle = 0; /* SHA-1 thread not within transport */ + } + else { + tpm_state->transportHandle = transportInternal->transHandle; /* SHA-1 thread within + transport */ + } + returnCode = TPM_SHA1InitCmd(&(tpm_state->sha1_context)); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SHA1Start: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append maxNumBytes */ + returnCode = TPM_Sbuffer_Append32(response, maxNumBytes); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 13.2 TPM_SHA1Update rev 114 + + This capability inputs complete blocks of data into a pending SHA-1 digest. At the end of the + process, the digest remains pending. +*/ + +TPM_RESULT TPM_Process_SHA1Update(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_SIZED_BUFFER hashData; /* Bytes to be hashed */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SHA1Update: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&hashData); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* load hashData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SHA1Update: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* This command SHALL incorporate complete blocks of data into the digest of an existing SHA-1 + thread. Only integral numbers of complete blocks (64 bytes each) can be processed. + */ + /* 1. If there is no existing SHA-1 thread, return TPM_SHA_THREAD */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->sha1_context == NULL) { + printf("TPM_Process_SHA1Update: Error, no existing SHA1 thread\n"); + returnCode = TPM_SHA_THREAD; + } + } + /* 2. If numBytes is not a multiple of 64 */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SHA1Update: numBytes %u bytes\n", hashData.size); + if ((hashData.size % 64) != 0) { + printf("TPM_Process_SHA1Update: Error, numBytes not integral number of blocks\n"); + /* a. Return TPM_SHA_ERROR */ + returnCode = TPM_SHA_ERROR; + /* b. The TPM MAY terminate the SHA-1 thread */ + TPM_SHA1Delete(&(tpm_state->sha1_context)); + } + } + /* 3. If numBytes is greater than maxNumBytes returned by TPM_SHA1Start */ + if (returnCode == TPM_SUCCESS) { + if (hashData.size > TPM_SHA1_MAXNUMBYTES) { + /* a. Return TPM_SHA_ERROR */ + returnCode = TPM_SHA_ERROR; + /* b. The TPM MAY terminate the SHA-1 thread */ + TPM_SHA1Delete(&(tpm_state->sha1_context)); + } + } + /* 4. Incorporate hashData into the digest of the existing SHA-1 thread. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1UpdateCmd(tpm_state->sha1_context, hashData.buffer, hashData.size); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SHA1Update: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&hashData); /* @1 */ + return rcf; +} + +/* 13.3 TPM_SHA1Complete rev 87 + + This capability terminates a pending SHA-1 calculation. +*/ + +TPM_RESULT TPM_Process_SHA1Complete(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_SIZED_BUFFER hashData; /* Final bytes to be hashed */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_DIGEST hashValue; /* The output of the SHA-1 hash. */ + TPM_SizedBuffer_Init(&hashData); /* freed @1 */ + + printf("TPM_Process_SHA1Complete: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* load hashData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SHA1Complete: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* This command SHALL incorporate a partial or complete block of data into the digest of an + existing SHA-1 thread, and terminate that thread. hashDataSize MAY have values in the range + of 0 through 64, inclusive. If the SHA-1 thread has received no bytes the TPM SHALL + calculate the SHA-1 of the empty buffer. + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1CompleteCommon(hashValue, + &(tpm_state->sha1_context), + &hashData); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SHA1Complete: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append hashValue */ + returnCode = TPM_Digest_Store(response, hashValue); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&hashData); /* @1 */ + return rcf; +} + +/* 13.4 TPM_SHA1CompleteExtend rev 109 + + This capability terminates a pending SHA-1 calculation and EXTENDS the result into a Platform + Configuration Register using a SHA-1 hash process. + + This command is designed to complete a hash sequence and extend a PCR in memory-less + environments. + + This command SHALL incorporate a partial or complete block of data into the digest of an existing + SHA-1 thread, EXTEND the resultant digest into a PCR, and terminate the thread. hashDataSize MAY + have values in the range of 0 through 64, inclusive. +*/ + +TPM_RESULT TPM_Process_SHA1CompleteExtend(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_PCRINDEX pcrNum; /* Index of the PCR to be modified */ + TPM_SIZED_BUFFER hashData; /* Final bytes to be hashed */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_DIGEST h1HashValue; /* The output of the SHA-1 hash. */ + TPM_PCRVALUE outDigest; /* The PCR value after execution of the command. */ + + printf("TPM_Process_SHA1CompleteExtend: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&hashData); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get pcrNum */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&pcrNum, &command, ¶mSize); + } + /* get hashData */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SHA1CompleteExtend: pcrNum %u\n", pcrNum); + returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SHA1CompleteExtend: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. 1.Validate that pcrNum represents a legal PCR number. On error, return TPM_BADINDEX. */ + /* 2. Map V1 to TPM_STANY_DATA */ + /* 3. Map L1 to V1 -> localityModifier */ + /* 4. If the current locality, held in L1, is not selected in TPM_PERMANENT_DATA -> pcrAttrib + [PCRIndex]. pcrExtendLocal, return TPM_BAD_LOCALITY */ + /* NOTE Done in TPM_ExtendCommon() */ + /* 5. Create H1 the TPM_DIGEST of the SHA-1 session ensuring that hashData, if any, is */ + /* added to the SHA-1 session */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1CompleteCommon(h1HashValue, + &(tpm_state->sha1_context), + &hashData); + } + /* 6. Perform the actions of TPM_Extend using H1 as the data and pcrNum as the PCR to extend */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ExtendCommon(outDigest, tpm_state, ordinal, pcrNum, h1HashValue); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SHA1CompleteExtend: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append hashValue */ + returnCode = TPM_Digest_Store(response, h1HashValue); + } + /* append outDigest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Store(response, outDigest); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&hashData); /* @1 */ + return rcf; +} + +/* TPM_SHA1CompleteCommon() is common code for TPM_Process_SHA1Complete() and + TPM_Process_SHA1CompleteExtend() +*/ + +TPM_RESULT TPM_SHA1CompleteCommon(TPM_DIGEST hashValue, /* output: digest */ + void **sha1_context, /* IO: SHA1 context */ + TPM_SIZED_BUFFER *hashData) /* final data to be hashed */ +{ + TPM_RESULT rc = 0; + + /* The TPM specification says that the last data chunk must be 0-64 bytes */ + printf("TPM_SHA1CompleteCommon: %u bytes\n", hashData->size); + if (rc == 0) { + if (hashData->size > 64) { + printf("TPM_SHA1CompleteCommon: Error, hashDataSize %u not 0-64\n", + hashData->size); + rc = TPM_SHA_ERROR; + } + } + /* cannot call SHA1Complete() before SHA1Start() */ + if (rc == 0) { + if (*sha1_context == NULL) { + printf("TPM_SHA1CompleteCommon: Error, no existing SHA1 thread\n"); + rc = TPM_SHA_THREAD; + } + } + if ((rc == 0) && (hashData->size != 0)) { + rc = TPM_SHA1UpdateCmd(*sha1_context, hashData->buffer, hashData->size); + } + if (rc == 0) { + rc = TPM_SHA1FinalCmd(hashValue, *sha1_context); + } + /* the SHA1 thread should be terminated even if there is an error */ + TPM_SHA1Delete(sha1_context); + return rc; +} + +/* 13.6 TPM_GetRandom rev 87 + + GetRandom returns the next bytesRequested bytes from the random number generator to the caller. + + It is recommended that a TPM implement the RNG in a manner that would allow it to return RNG + bytes such that the frequency of bytesRequested being more than the number of bytes available is + an infrequent occurrence. +*/ + +TPM_RESULT TPM_Process_GetRandom(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + uint32_t bytesRequested; /* Number of bytes to return */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER randomBytes; /* The returned bytes */ + + printf("TPM_Process_GetRandom: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&randomBytes); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get bytesRequested parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&bytesRequested, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetRandom: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM determines if amount bytesRequested is available from the TPM. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetRandom: bytesRequested %u\n", bytesRequested); + if (bytesRequested > TPM_RANDOM_MAX) { + bytesRequested = TPM_RANDOM_MAX; + printf("TPM_Process_GetRandom: bytes available %u\n", bytesRequested); + } + } + /* 2. Set randomBytesSize to the number of bytes available from the RNG. This number MAY be less + than bytesRequested. */ + if ((returnCode == TPM_SUCCESS) && (bytesRequested > 0)) { + returnCode = TPM_SizedBuffer_Allocate(&randomBytes, bytesRequested); + } + /* 3. Set randomBytes to the next randomBytesSize bytes from the RNG */ + if ((returnCode == TPM_SUCCESS) && (bytesRequested > 0)) { + returnCode = TPM_Random(randomBytes.buffer, bytesRequested); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_GetRandom: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append randomBytes */ + returnCode = TPM_SizedBuffer_Store(response, &randomBytes); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&randomBytes); /* freed @1 */ + return rcf; +} + +/* 13.7 TPM_StirRandom rev 109 + + StirRandom adds entropy to the RNG state. +*/ + +TPM_RESULT TPM_Process_StirRandom(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_SIZED_BUFFER inData; /* Data to add entropy to RNG state, + Number of bytes of input */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_StirRandom: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&inData); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get inData parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_StirRandom: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. If dataSize is not less than 256 bytes, the TPM MAY return TPM_BAD_PARAMETER. */ + /* The TPM updates the state of the current RNG using the appropriate mixing function. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_StirRandomCmd(&inData); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_StirRandom: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&inData); /* @1 */ + return rcf; +} + +/* 13.8 TPM_CertifyKey rev 107 + + The TPM_CertifyKey operation allows one key to certify the public portion of another key. A TPM + identity key may be used to certify non-migratable keys but is not permitted to certify migratory + keys or certified migration keys. As such, it allows the TPM to make the statement "this key is + held in a TPM-shielded location, and it will never be revealed." For this statement to have + veracity, the Challenger must trust the policies used by the entity that issued the identity and + the maintenance policy of the TPM manufacturer. + + Signing and legacy keys may be used to certify both migratable and non-migratable keys. Then the + usefulness of a certificate depends on the trust in the certifying key by the recipient of the + certificate. + + The key to be certified must be loaded before TPM_CertifyKey is called. + + The determination to use the TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 on the output is based on + which PCRs and what localities the certified key is restricted to. A key to be certified that + does not have locality restrictions and which uses no PCRs greater than PCR #15 will cause this + command to return and sign a TPM_CERTIFY_INFO structure, which provides compatibility with V1.1 + TPMs. + + When this command is run to certify all other keys (those that use PCR #16 or higher, as well as + those limited by locality in any way), it will return and sign a TPM_CERTIFY_INFO2 structure. + + TPM_CertifyKey does not support the case where (a) the certifying key requires a usage + authorization to be provided but (b) the key-to-be-certified does not. In such cases, + TPM_CertifyKey2 must be used. + + If a command tag (in the parameter array) specifies only one authorisation session, then the TPM + convention is that the first session listed is ignored (authDataUsage must be TPM_AUTH_NEVER for + this key) and the incoming session data is used for the second auth session in the list. In + TPM_CertifyKey, the first session is the certifying key and the second session is the + key-to-be-certified. In TPM_CertifyKey2, the first session is the key-to-be-certified and the + second session is the certifying key. +*/ + +TPM_RESULT TPM_Process_CertifyKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE certHandle; /* Handle of the key to be used to certify the key. */ + TPM_KEY_HANDLE keyHandle; /* Handle of the key to be certified. */ + TPM_NONCE antiReplay; /* 160 bits of externally supplied data (typically a nonce + provided to prevent replay-attacks) */ + TPM_AUTHHANDLE certAuthHandle; /* The authorization session handle used for certHandle. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with certAuthHandle + */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA certAuth; /* The authorization session digest for inputs and + certHandle. HMAC key: certKey.auth. */ + TPM_AUTHHANDLE keyAuthHandle; /* The authorization session handle used for the key to be + signed. */ + TPM_NONCE keynonceOdd; /* Nonce generated by system associated with keyAuthHandle + */ + TPM_BOOL continueKeySession = TRUE; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA keyAuth; /* The authorization session digest for the inputs and key + to be signed. HMAC key: key.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_AUTH_SESSION_DATA *cert_auth_session_data = NULL; /* session data for authHandle */ + TPM_AUTH_SESSION_DATA *target_auth_session_data = NULL; /* session data for authHandle */ + TPM_BOOL certAuthHandleValid = FALSE; + TPM_BOOL keyAuthHandleValid = FALSE; + TPM_SECRET *certHmacKey; + TPM_SECRET *targetHmacKey; + TPM_BOOL certPCRStatus; + TPM_BOOL targetPCRStatus; + TPM_KEY *certKey = NULL; /* the key specified by certHandle */ + TPM_KEY *targetKey = NULL; /* the key specified by keyHandle */ + TPM_SECRET *certKeyUsageAuth; + TPM_SECRET *targetKeyUsageAuth; + TPM_BOOL pcrUsage; + TPM_LOCALITY_SELECTION localityAtRelease; + int v1Version; /* TPM 1.1 or TPM 1.2 */ + int certifyType = 0; /* TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 */ + TPM_DIGEST m1Digest; /* digest of certifyInfo */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_CERTIFY_INFO certifyInfo; /* TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 structure + that provides information relative to keyhandle + NOTE This is c1 in the Actions. */ + TPM_CERTIFY_INFO2 certifyInfo2; + TPM_SIZED_BUFFER outData; /* The signature of certifyInfo */ + + printf("TPM_Process_CertifyKey: Ordinal Entry\n"); + TPM_CertifyInfo_Init(&certifyInfo); /* freed @1 */ + TPM_CertifyInfo2_Init(&certifyInfo2); /* freed @2 */ + TPM_SizedBuffer_Init(&outData); /* freed @3 */ + /* + get inputs + */ + /* get certHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&certHandle, &command, ¶mSize); + } + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey: certHandle %08x\n", certHandle); + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey: keyHandle %08x\n", keyHandle); + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag210(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Get(&certAuthHandle, + &certAuthHandleValid, + nonceOdd, + &continueAuthSession, + certAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + printf("TPM_Process_CertifyKey: certAuthHandle %08x\n", certAuthHandle); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_AuthParams_Get(&keyAuthHandle, + &keyAuthHandleValid, + keynonceOdd, + &continueKeySession, + keyAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + printf("TPM_Process_CertifyKey: keyAuthHandle %08x\n", keyAuthHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CertifyKey: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + certAuthHandleValid = FALSE; + keyAuthHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the certHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&certKey, &certPCRStatus, tpm_state, certHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&targetKey, &targetPCRStatus, tpm_state, keyHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* 1. The TPM validates that the key pointed to by certHandle has a signature scheme of + TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */ + if (returnCode == TPM_SUCCESS) { + if ((certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { + printf("TPM_Process_CertifyKey: Error, invalid certKey sigScheme %04hx\n", + certKey->algorithmParms.sigScheme); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* 2. Verify command and key AuthData values */ + /* a. If tag is TPM_TAG_RQU_AUTH2_COMMAND */ + /* i. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key + pointed to by certHandle, return TPM_AUTHFAIL on error */ + /* ii. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key + pointed to by keyHandle, return TPM_AUTH2FAIL on error */ + /* b. else if tag is TPM_TAG_RQU_AUTH1_COMMAND */ + /* i. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return + TPM_AUTHFAIL on error. */ + /* ii. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key + pointed to by keyHandle, return TPM_AUTHFAIL on error */ + /* c. else if tag is TPM_TAG_RQU_COMMAND */ + /* i. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return + TPM_AUTHFAIL on error. */ + /* ii. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key + referenced by keyHandle, return TPM_AUTHFAIL on error. */ + + /* NOTE: Simplified the above logic as follows */ + /* If tag is TPM_TAG_RQU_AUTH2_COMMAND, process the first set of authorization data */ + /* get certHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&certKeyUsageAuth, certKey); + } + /* get the first session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&cert_auth_session_data, + &certHmacKey, + tpm_state, + certAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + certKey, + certKeyUsageAuth, /* OIAP */ + certKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* The TPM verifies the AuthData in certAuthHandle provides authorization to use the key + pointed to by certHandle, return TPM_AUTHFAIL on error */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *certHmacKey, /* HMAC key */ + inParamDigest, + cert_auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + certAuth); /* Authorization digest for input */ + } + /* If tag is not TPM_TAG_RQU_AUTH2_COMMAND */ + /* Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return + TPM_AUTHFAIL on error. */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { + if (certKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_CertifyKey: Error, cert key authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* If tag is TPM_TAG_RQU_AUTH2_COMMAND or TPM_TAG_RQU_AUTH1_COMMAND process the second set of + authorization data */ + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&targetKeyUsageAuth, targetKey); + } + /* get the second session data */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&target_auth_session_data, + &targetHmacKey, + tpm_state, + keyAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + targetKey, + targetKeyUsageAuth, /* OIAP */ + targetKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key + pointed to by keyHandle, return TPM_AUTH2FAIL on error */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_Auth2data_Check(tpm_state, + *targetHmacKey, /* HMAC key */ + inParamDigest, + target_auth_session_data, /* authorization session */ + keynonceOdd, /* Nonce generated by system + associated with authHandle */ + continueKeySession, + keyAuth); /* Authorization digest for input */ + } + /* Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced + by keyHandle, return TPM_AUTHFAIL on error. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (targetKey->authDataUsage == TPM_AUTH_ALWAYS) { + printf("TPM_Process_CertifyKey: Error, target key authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* 3. If keyHandle -> payload is not TPM_PT_ASYM, return TPM_INVALID_KEYUSAGE. */ + if (returnCode == TPM_SUCCESS) { + if (targetKey->tpm_store_asymkey->payload != TPM_PT_ASYM) { + printf("TPM_Process_CertifyKey: Error, target key invalid payload %02x\n", + targetKey->tpm_store_asymkey->payload); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. If the key pointed to by certHandle is an identity key (certHandle -> keyUsage is + TPM_KEY_IDENTITY) */ + if ((returnCode == TPM_SUCCESS) && (certKey->keyUsage == TPM_KEY_IDENTITY)) { + /* a. If keyHandle -> keyflags -> keyInfo -> migratable is TRUE return TPM_MIGRATEFAIL */ + if (targetKey->keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_CertifyKey: Error, target key is migratable\n"); + returnCode = TPM_MIGRATEFAIL; + } + } + /* 5. Validate that certHandle -> keyUsage is TPM_KEY_SIGN, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, + if not return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey: certHandle -> keyUsage %04hx\n", certKey->keyUsage); + if ((certKey->keyUsage != TPM_KEY_SIGNING) && + ((certKey->keyUsage) != TPM_KEY_IDENTITY) && + ((certKey->keyUsage) != TPM_KEY_LEGACY)) { + printf("TPM_Process_CertifyKey: Error, certHandle -> keyUsage %04hx is invalid\n", + certKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 6. Validate that keyHandle -> keyUsage is TPM_KEY_SIGN, TPM_KEY_STORAGE, TPM_KEY_IDENTITY, + TPM_KEY_BIND or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey: keyHandle -> keyUsage %04hx\n", targetKey->keyUsage); + if ((targetKey->keyUsage != TPM_KEY_SIGNING) && + ((targetKey->keyUsage) != TPM_KEY_STORAGE) && + ((targetKey->keyUsage) != TPM_KEY_IDENTITY) && + ((targetKey->keyUsage) != TPM_KEY_BIND) && + ((targetKey->keyUsage) != TPM_KEY_LEGACY)) { + printf("TPM_Process_CertifyKey: Error, keyHandle -> keyUsage %04hx is invalid\n", + targetKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 7. If keyHandle -> digestAtRelease requires the use of PCRs 16 or higher to calculate or if + keyHandle -> localityAtRelease is not 0x1F */ + /* get PCR usage 16 and higher */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetPCRUsage(&pcrUsage, targetKey, 2); + } + /* get localityAtRelease */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetLocalityAtRelease(&localityAtRelease, targetKey); + } + if (returnCode == TPM_SUCCESS) { + if (pcrUsage || (localityAtRelease != TPM_LOC_ALL)) { + /* a. Set V1 to 1.2 */ + v1Version = 2; /* locality or >2 PCR's */ + } + /* 8. Else */ + else { + /* a. Set V1 to 1.1 */ + v1Version = 1; /* no locality and <= 2 PCR's */ + } + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey: V1 %d\n", v1Version); + /* 9. If keyHandle -> pcrInfoSize is not 0 */ + if (targetKey->pcrInfo.size != 0) { + printf("TPM_Process_CertifyKey: Setting PCR info from key\n"); + /* a. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */ + /* i. Create a digestAtRelease according to the specified PCR registers and + compare to keyHandle -> digestAtRelease and if a mismatch return + TPM_WRONGPCRVAL */ + /* ii. If specified validate any locality requests on error TPM_BAD_LOCALITY */ + /* NOTE: Done by TPM_KeyHandleEntries_GetKey() */ + /* b. If V1 is 1.1 */ + if (v1Version == 1) { + certifyType = 1; + /* i. Create C1 a TPM_CERTIFY_INFO structure */ + /* NOTE: Done by TPM_CertifyInfo_Init() */ + /* ii. Fill in C1 with the information from the key pointed to by keyHandle */ + /* NOTE: Done in common _Set() code below */ + /* iii. The TPM MUST set c1 -> pcrInfoSize to 44. */ + /* iv. The TPM MUST set c1 -> pcrInfo to a TPM_PCR_INFO structure properly filled + out using the information from keyHandle. */ + /* This function actually creates the cache, which is serialized later */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRInfo_CreateFromKey(&(certifyInfo.tpm_pcr_info), + targetKey); + } + /* v. The TPM MUST set c1 -> digestAtCreation to 20 bytes of 0x00. */ + if (returnCode == TPM_SUCCESS) { + TPM_Digest_Init(certifyInfo.tpm_pcr_info->digestAtCreation); + } + } + /* c. Else */ + else { + certifyType = 2; + /* i. Create C1 a TPM_CERTIFY_INFO2 structure */ + /* NOTE: Done by TPM_CertifyInfo2_Init() */ + /* ii. Fill in C1 with the information from the key pointed to by keyHandle */ + /* NOTE: Done in common _Set() code below */ + /* iii. Set C1 -> pcrInfoSize to the size of an appropriate TPM_PCR_INFO_SHORT + structure. */ + /* iv. Set C1 -> pcrInfo to a properly filled out TPM_PCR_INFO_SHORT structure, + using the information from keyHandle. */ + /* This function actually creates the cache, which is serialized later */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRInfoShort_CreateFromKey(&(certifyInfo2.tpm_pcr_info_short), + targetKey); + } + /* v. Set C1 -> migrationAuthoritySize to 0 */ + /* NOTE: Done by TPM_CertifyInfo2_Init() */ + } + } + /* 10. Else */ + else { + certifyType = 1; + /* a. Create C1 a TPM_CERTIFY_INFO structure */ + /* NOTE: Done by TPM_CertifyInfo_Init() */ + /* b. Fill in C1 with the information from the key pointed to be keyHandle */ + /* NOTE: Done in common _Set() code below */ + /* c. The TPM MUST set c1 -> pcrInfoSize to 0 */ + /* NOTE: Done by TPM_CertifyInfo_Init() */ + } + } + /* 11. Create TPM_DIGEST H1 which is the SHA-1 hash of keyHandle -> pubKey -> key. Note that + is the actual public modulus, and does not include any structure formatting. */ + /* 12. Set C1 -> pubKeyDigest to H1 */ + /* NOTE: Done by TPM_CertifyInfo_Set() or TPM_CertifyInfo2_Set() */ + /* 13. The TPM copies the antiReplay parameter to c1 -> data. */ + /* Set C1 -> parentPCRStatus to the value from keyHandle NOTE: Implied in specification */ + /* Fill in C1 with the information from the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey: Setting certifyInfo from target key\n"); + if (certifyType == 1) { + TPM_Digest_Copy(certifyInfo.data, antiReplay); + certifyInfo.parentPCRStatus = targetPCRStatus; + returnCode = TPM_CertifyInfo_Set(&certifyInfo, targetKey); + } + else { + TPM_Digest_Copy(certifyInfo2.data, antiReplay); + certifyInfo2.parentPCRStatus = targetPCRStatus; + returnCode = TPM_CertifyInfo2_Set(&certifyInfo2, targetKey); + } + } + /* 14. The TPM sets certifyInfo to C1. */ + /* NOTE Created as certifyInfo or certifyInfo2 */ + /* 15. The TPM creates m1, a message digest formed by taking the SHA-1 of c1. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey: Digesting certifyInfo\n"); + if (certifyType == 1) { + returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo, + (TPM_STORE_FUNCTION_T)TPM_CertifyInfo_Store); + } + else { + returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo2, + (TPM_STORE_FUNCTION_T)TPM_CertifyInfo2_Store); + } + } + /* a. The TPM then computes a signature using certHandle -> sigScheme. The resulting signed blob + is returned in outData. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey: Signing certifyInfo digest with certifying key\n"); + returnCode = TPM_RSASignToSizedBuffer(&outData, /* signature */ + m1Digest, /* message */ + TPM_DIGEST_SIZE, /* message size */ + certKey); /* input, signing key */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CertifyKey: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* Return certifyInfo */ + if (certifyType == 1) { + returnCode = TPM_CertifyInfo_Store(response, &certifyInfo); + } + else { + returnCode = TPM_CertifyInfo2_Store(response, &certifyInfo2); + } + } + if (returnCode == TPM_SUCCESS) { + /* Return outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *certHmacKey, /* HMAC key */ + cert_auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *targetHmacKey, /* HMAC key */ + target_auth_session_data, + outParamDigest, + keynonceOdd, + continueKeySession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueKeySession) && + keyAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, keyAuthHandle); + } + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + certAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, certAuthHandle); + } + /* + cleanup + */ + TPM_CertifyInfo_Delete(&certifyInfo); /* @1 */ + TPM_CertifyInfo2_Delete(&certifyInfo2); /* @2 */ + TPM_SizedBuffer_Delete(&outData); /* @3 */ + return rcf; +} + +/* 13.9 TPM_CertifyKey2 rev 107 + + This command is based on TPM_CertifyKey, but includes the ability to certify a Certifiable + Migration Key (CMK), which requires extra input parameters. + + TPM_CertifyKey2 always produces a TPM_CERTIFY_INFO2 structure. + + TPM_CertifyKey2 does not support the case where (a) the key-to-be-certified requires a usage + authorization to be provided but (b) the certifying key does not. + + If a command tag (in the parameter array) specifies only one authorisation session, then the TPM + convention is that the first session listed is ignored (authDataUsage must be + TPM_NO_READ_PUBKEY_AUTH or TPM_AUTH_NEVER for this key) and the incoming session data is used for + the second auth session in the list. In TPM_CertifyKey2, the first session is the key to be + certified and the second session is the certifying key. +*/ + +TPM_RESULT TPM_Process_CertifyKey2(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* Handle of the key to be certified. */ + TPM_KEY_HANDLE certHandle; /* Handle of the key to be used to certify the key. */ + TPM_DIGEST migrationPubDigest; /* The digest of a TPM_MSA_COMPOSITE structure, + containing at least one public key of a Migration + Authority */ + TPM_NONCE antiReplay; /* 160 bits of externally supplied data (typically a nonce + provided to prevent replay-attacks) */ + TPM_AUTHHANDLE keyAuthHandle; /* The authorization session handle used for the key to be + signed. */ + TPM_NONCE keynonceOdd; /* Nonce generated by system associated with keyAuthHandle + */ + TPM_BOOL continueKeySession; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA keyAuth; /* The authorization session digest for the inputs and key + to be signed. HMAC key: key.usageAuth. */ + TPM_AUTHHANDLE certAuthHandle; /* The authorization session handle used for certHandle. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with certAuthHandle + */ + TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA certAuth; /* Authorization HMAC key: certKey.auth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_AUTH_SESSION_DATA *cert_auth_session_data = NULL; /* session data for authHandle */ + TPM_AUTH_SESSION_DATA *target_auth_session_data = NULL; /* session data for authHandle */ + TPM_BOOL certAuthHandleValid = FALSE; + TPM_BOOL keyAuthHandleValid = FALSE; + TPM_SECRET *certHmacKey; + TPM_SECRET *targetHmacKey; + TPM_BOOL certPCRStatus; + TPM_BOOL targetPCRStatus; + TPM_KEY *certKey = NULL; /* the key specified by certHandle */ + TPM_KEY *targetKey = NULL; /* the key specified by keyHandle */ + TPM_SECRET *certKeyUsageAuth; + TPM_SECRET *targetKeyUsageAuth; + TPM_STORE_ASYMKEY *targetStoreAsymkey; + TPM_CMK_MIGAUTH m2CmkMigauth; + TPM_BOOL hmacValid; + TPM_DIGEST migrationAuthority; + TPM_DIGEST m1Digest; /* digest of certifyInfo */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_CERTIFY_INFO2 certifyInfo2; /* TPM_CERTIFY_INFO2 relative to keyHandle */ + TPM_SIZED_BUFFER outData; /* The signed public key. */ + + printf("TPM_Process_CertifyKey2: Ordinal Entry\n"); + TPM_CertifyInfo2_Init(&certifyInfo2); /* freed @1 */ + TPM_SizedBuffer_Init(&outData); /* freed @2 */ + TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @3 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* get certHandle parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey2: keyHandle %08x\n", keyHandle); + returnCode = TPM_Load32(&certHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey2: certHandle %08x\n", certHandle); + /* get the migrationPubDigest parameter */ + returnCode = TPM_Digest_Load(migrationPubDigest, &command, ¶mSize); + } + /* get the antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag210(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Get(&keyAuthHandle, + &keyAuthHandleValid, + keynonceOdd, + &continueKeySession, + keyAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + printf("TPM_Process_CertifyKey2: keyAuthHandle %08x\n", keyAuthHandle); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_AuthParams_Get(&certAuthHandle, + &certAuthHandleValid, + nonceOdd, + &continueAuthSession, + certAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + printf("TPM_Process_CertifyKey2: certAuthHandle %08x\n", certAuthHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CertifyKey2: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + certAuthHandleValid = FALSE; + keyAuthHandleValid = FALSE; + } + /* + Processing + */ + /* get the keys corresponding to the certHandle and keyHandle parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&targetKey, &targetPCRStatus, tpm_state, keyHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&certKey, &certPCRStatus, tpm_state, certHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get the TPM_STORE_ASYMKEY cache for the target TPM_KEY */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetStoreAsymkey(&targetStoreAsymkey, targetKey); + } + /* 1. The TPM validates that the key pointed to by certHandle has a signature scheme of + TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */ + if (returnCode == TPM_SUCCESS) { + if ((certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { + printf("TPM_Process_CertifyKey2: Error, invalid certKey sigScheme %04hx\n", + certKey->algorithmParms.sigScheme); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* 2. Verify command and key AuthData values: */ + /* a. If tag is TPM_TAG_RQU_AUTH2_COMMAND */ + /* i. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key + pointed to by keyHandle, return TPM_AUTHFAIL on error */ + /* ii. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key + pointed to by certHandle, return TPM_AUTH2FAIL on error */ + /* b. else if tag is TPM_TAG_RQU_AUTH1_COMMAND */ + /* i. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key + referenced by keyHandle, return TPM_AUTHFAIL on error */ + /* ii. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key + pointed to by certHandle, return TPM_AUTHFAIL on error */ + /* c. else if tag is TPM_TAG_RQU_COMMAND */ + /* i. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key + referenced by keyHandle, return TPM_AUTHFAIL on error */ + /* ii. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return + TPM_AUTHFAIL on error. */ + /* NOTE: Simplified the above logic as follows */ + /* If tag is TPM_TAG_RQU_AUTH2_COMMAND, process the first set of authorization data */ + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&targetKeyUsageAuth, targetKey); + } + /* get the first session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&target_auth_session_data, + &targetHmacKey, + tpm_state, + keyAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + targetKey, + targetKeyUsageAuth, /* OIAP */ + targetKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key + pointed to by keyHandle, return TPM_AUTHFAIL on error */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *targetHmacKey, /* HMAC key */ + inParamDigest, + target_auth_session_data, /* authorization session */ + keynonceOdd, /* Nonce generated by system + associated with authHandle */ + continueKeySession, + keyAuth); /* Authorization digest for input */ + } + /* If tag is not TPM_TAG_RQU_AUTH2_COMMAND */ + /* Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced + by keyHandle, return TPM_AUTHFAIL on error. */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { + if (targetKey->authDataUsage == TPM_AUTH_ALWAYS) { + printf("TPM_Process_CertifyKey2: Error, target key authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* If tag is TPM_TAG_RQU_AUTH2_COMMAND or TPM_TAG_RQU_AUTH1_COMMAND process the second set of + authorization data */ + /* get certHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&certKeyUsageAuth, certKey); + } + /* get the second session data */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&cert_auth_session_data, + &certHmacKey, + tpm_state, + certAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + certKey, + certKeyUsageAuth, /* OIAP */ + certKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* The TPM verifies the AuthData in certAuthHandle provides authorization to use the key + pointed to by certHandle, return TPM_AUTH2FAIL on error */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_Auth2data_Check(tpm_state, + *certHmacKey, /* HMAC key */ + inParamDigest, + cert_auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + certAuth); /* Authorization digest for input */ + } + /* If the command is TPM_TAG_RQU_COMMAND */ + /* Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return + TPM_AUTHFAIL on error. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (certKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_CertifyKey2: Error, cert key authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* 3. If the key pointed to by certHandle is an identity key (certHandle -> keyUsage is + TPM_KEY_IDENTITY) */ + if ((returnCode == TPM_SUCCESS) && (certKey->keyUsage == TPM_KEY_IDENTITY)) { + /* a. If keyHandle -> keyFlags -> migratable is TRUE and + [keyHandle -> keyFlags-> migrateAuthority is FALSE or + (keyHandle -> payload != TPM_PT_MIGRATE_RESTRICTED and + keyHandle -> payload != TPM_PT_MIGRATE_EXTERNAL)] + return TPM_MIGRATEFAIL */ + if ((targetKey->keyFlags & TPM_MIGRATABLE) && + (!(targetKey->keyFlags & TPM_MIGRATEAUTHORITY) || + ((targetStoreAsymkey->payload != TPM_PT_MIGRATE_RESTRICTED) && + (targetStoreAsymkey->payload != TPM_PT_MIGRATE_EXTERNAL)))) { + printf("TPM_Process_CertifyKey2: Error, target key migrate fail\n"); + returnCode = TPM_MIGRATEFAIL; + } + } + /* 4. Validate that certHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or + TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey2: certHandle ->keyUsage %04hx\n", certKey->keyUsage); + if ((certKey->keyUsage != TPM_KEY_SIGNING) && + ((certKey->keyUsage) != TPM_KEY_IDENTITY) && + ((certKey->keyUsage) != TPM_KEY_LEGACY)) { + printf("TPM_Process_CertifyKey2: Error, keyUsage %04hx is invalid\n", + certKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 5. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_STORAGE, TPM_KEY_IDENTITY, + TPM_KEY_BIND or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey2: keyHandle -> keyUsage %04hx\n", targetKey->keyUsage); + if ((targetKey->keyUsage != TPM_KEY_SIGNING) && + ((targetKey->keyUsage) != TPM_KEY_STORAGE) && + ((targetKey->keyUsage) != TPM_KEY_IDENTITY) && + ((targetKey->keyUsage) != TPM_KEY_BIND) && + ((targetKey->keyUsage) != TPM_KEY_LEGACY)) { + printf("TPM_Process_CertifyKey2: Error, keyHandle -> keyUsage %04hx is invalid\n", + targetKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 6. The TPM SHALL create a c1 a TPM_CERTIFY_INFO2 structure from the key pointed to by + keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CertifyInfo2_Set(&certifyInfo2, targetKey); + } + /* 7. Create TPM_DIGEST H1 which is the SHA-1 hash of keyHandle -> pubKey -> key. Note that + is the actual public modulus, and does not include any structure formatting. */ + /* 8. Set C1 -> pubKeyDigest to H1 */ + /* NOTE: Done by TPM_CertifyInfo2_Set() */ + if (returnCode == TPM_SUCCESS) { + /* 9. Copy the antiReplay parameter to c1 -> data */ + TPM_Digest_Copy(certifyInfo2.data, antiReplay); + /* 10. Copy other keyHandle parameters into C1 */ + certifyInfo2.parentPCRStatus = targetPCRStatus; + /* 11. If keyHandle -> payload == TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_EXTERNAL */ + if ((targetStoreAsymkey->payload == TPM_PT_MIGRATE_RESTRICTED) || + (targetStoreAsymkey->payload == TPM_PT_MIGRATE_EXTERNAL)) { + printf("TPM_Process_CertifyKey2: " + "TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_RESTRICTED\n"); + /* a. create thisPubKey, a TPM_PUBKEY structure containing the public key, algorithm and + parameters corresponding to keyHandle */ + /* NOTE Not required. Digest is created directly below */ + /* b. Verify that the migration authorization is valid for this key */ + /* i. Create M2 a TPM_CMK_MIGAUTH structure */ + /* NOTE Done by TPM_CmkMigauth_Init() */ + if (returnCode == TPM_SUCCESS) { + /* ii. Set M2 -> msaDigest to migrationPubDigest */ + TPM_Digest_Copy(m2CmkMigauth.msaDigest, migrationPubDigest ); + /* iii. Set M2 -> pubKeyDigest to SHA-1[thisPubKey] */ + returnCode = TPM_Key_GeneratePubkeyDigest(m2CmkMigauth.pubKeyDigest, targetKey); + } + /* iv. Verify that [keyHandle -> migrationAuth] == HMAC(M2) signed by using tpmProof as + the secret and return error TPM_MA_SOURCE on mismatch */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey2: Check migrationAuth\n"); + returnCode = + TPM_CmkMigauth_CheckHMAC(&hmacValid, /* result */ + targetStoreAsymkey->migrationAuth, /* expect */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &m2CmkMigauth); + } + if (returnCode == TPM_SUCCESS) { + if (!hmacValid) { + printf("TPM_Process_CertifyKey2: Error, Invalid migrationAuth\n"); + returnCode = TPM_MA_SOURCE; + } + } + /* c. Set C1 -> migrationAuthority = SHA-1(migrationPubDigest || keyHandle -> payload) + */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey2: Set migrationAuthority\n"); + returnCode = TPM_SHA1(migrationAuthority, + TPM_DIGEST_SIZE, migrationPubDigest, + sizeof(TPM_PAYLOAD_TYPE), &(targetStoreAsymkey->payload), + 0, NULL); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Set(&(certifyInfo2.migrationAuthority), + TPM_DIGEST_SIZE, migrationAuthority); + } + /* d. if keyHandle -> payload == TPM_PT_MIGRATE_RESTRICTED */ + /* i. Set C1 -> payloadType = TPM_PT_MIGRATE_RESTRICTED */ + /* e. if keyHandle -> payload == TPM_PT_MIGRATE_EXTERNAL */ + /* i. Set C1 -> payloadType = TPM_PT_MIGRATE_EXTERNAL */ + /* NOTE: Done by TPM_CertifyInfo2_Set() */ + } + /* 12. Else */ + else { + printf("TPM_Process_CertifyKey2: " + " Not TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_RESTRICTED\n"); + /* a. set C1 -> migrationAuthority = NULL */ + /* b. set C1 -> migrationAuthoritySize = 0 */ + /* NOTE: Done by TPM_CertifyInfo2_Init() */ + /* c. Set C1 -> payloadType = TPM_PT_ASYM */ + certifyInfo2.payloadType = TPM_PT_ASYM; + } + } + if (returnCode == TPM_SUCCESS) { + /* 13. If keyHandle -> pcrInfoSize is not 0 */ + if (targetKey->pcrInfo.size != 0) { + printf("TPM_Process_CertifyKey2: Setting PCR info from key\n"); + /* a. The TPM MUST set c1 -> pcrInfoSize to match the pcrInfoSize from the keyHandle + key. */ + /* b. The TPM MUST set c1 -> pcrInfo to match the pcrInfo from the keyHandle key */ + /* This function actually creates the cache, which is serialized later */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRInfoShort_CreateFromKey(&(certifyInfo2.tpm_pcr_info_short), + targetKey); + } + /* c. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */ + /* i. Create a digestAtRelease according to the specified PCR registers and compare to + keyHandle -> digestAtRelease and if a mismatch return TPM_WRONGPCRVAL */ + /* ii. If specified validate any locality requests on error TPM_BAD_LOCALITY */ + /* NOTE: Done by TPM_KeyHandleEntries_GetKey() */ + } + /* 14. Else */ + /* a. The TPM MUST set c1 -> pcrInfoSize to 0 */ + /* NOTE: Done by TPM_CertifyInfo2_Init() */ + } + /* 15. The TPM creates m1, a message digest formed by taking the SHA-1 of c1 */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey2: Digesting certifyInfo\n"); + returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo2, + (TPM_STORE_FUNCTION_T)TPM_CertifyInfo2_Store); + } + /* a. The TPM then computes a signature using certHandle -> sigScheme. The resulting signed blob + is returned in outData */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifyKey2: Signing certifyInfo digest\n"); + returnCode = TPM_RSASignToSizedBuffer(&outData, /* signature */ + m1Digest, /* message */ + TPM_DIGEST_SIZE, /* message size */ + certKey); /* input, signing key */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CertifyKey2: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* Return certifyInfo */ + returnCode = TPM_CertifyInfo2_Store(response, &certifyInfo2); + } + if (returnCode == TPM_SUCCESS) { + /* Return outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *targetHmacKey, /* HMAC key */ + target_auth_session_data, + outParamDigest, + keynonceOdd, + continueKeySession); + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *certHmacKey, /* HMAC key */ + cert_auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueKeySession) && + keyAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, keyAuthHandle); + } + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + certAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, certAuthHandle); + } + /* + cleanup + */ + TPM_CertifyInfo2_Delete(&certifyInfo2); /* @1 */ + TPM_SizedBuffer_Delete(&outData); /* @2 */ + TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @3 */ + return rcf; +} + +/* 28.3 TPM_CertifySelfTest rev 94 + + CertifySelfTest causes the TPM to perform a full self-test and return an authenticated value if + the test passes. + + If a caller itself requires proof, it is sufficient to use any signing key for which only the TPM + and the caller have AuthData. + + If a caller requires proof for a third party, the signing key must be one whose signature is + trusted by the third party. A TPM-identity key may be suitable. + + Information returned by TPM_CertifySelfTest MUST NOT aid identification of an individual TPM. +*/ + +TPM_RESULT TPM_Process_CertifySelfTest(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform + digital signatures. */ + TPM_NONCE antiReplay; /* AntiReplay nonce to prevent replay of messages */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle + authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the + inputs and use of keyHandle. HMAC key: key.usageAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_KEY *sigKey; /* from keyHandle */ + TPM_BOOL sigKeyPCRStatus; + TPM_SECRET *sigKeyUsageAuth; + TPM_COMMAND_CODE nOrdinal; /* ordinal in nbo */ + TPM_DIGEST m2Digest; /* message to sign */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ + + printf("TPM_Process_CertifySelfTest: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&sig); /* freed @1 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get the antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifySelfTest: keyHandle %08x\n", keyHandle); + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CertifySelfTest: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. The TPM SHALL perform TPM_SelfTestFull. If the test fails the TPM returns the appropriate + error code. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifySelfTest: Running self test\n"); + returnCode = TPM_SelfTestFullCmd(tpm_state); + } + /* 2. After successful completion of the self-test the TPM then validates the authorization to + use the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &sigKeyPCRStatus, tpm_state, keyHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ + if (sigKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_CertifySelfTest: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&sigKeyUsageAuth, sigKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + sigKey, + sigKeyUsageAuth, /* OIAP */ + sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* Validate the command parameters using privAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + /* a. If the key pointed to by keyHandle has a signature scheme that is not + TPM_SS_RSASSAPKCS1v15_SHA1, the TPM may either return TPM_BAD_SCHEME or may return + TPM_SUCCESS and a vendor specific signature. */ + if (returnCode == TPM_SUCCESS) { + if (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { + printf("TPM_Process_CertifySelfTest: Error, invalid sigKey sigScheme %04hx\n", + sigKey->algorithmParms.sigScheme); + returnCode = TPM_BAD_SCHEME; + } + } + /* The key in keyHandle MUST have a KEYUSAGE value of type TPM_KEY_SIGNING or TPM_KEY_LEGACY or + TPM_KEY_IDENTITY. */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->keyUsage != TPM_KEY_SIGNING) && + (sigKey->keyUsage != TPM_KEY_LEGACY) && + (sigKey->keyUsage != TPM_KEY_IDENTITY)) { + printf("TPM_Process_CertifySelfTest: Error, Illegal keyUsage %04hx\n", + sigKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. Create t1 the NOT null terminated string of "Test Passed" */ + /* 4. The TPM creates m2 the message to sign by concatenating t1 || AntiReplay || ordinal. */ + if (returnCode == TPM_SUCCESS) { + nOrdinal = htonl(ordinal); + returnCode = TPM_SHA1(m2Digest, + sizeof("Test Passed") - 1, "Test Passed", + TPM_NONCE_SIZE, antiReplay, + sizeof(TPM_COMMAND_CODE), &nOrdinal, + 0, NULL); + } + /* 5. The TPM signs the SHA-1 of m2 using the key identified by keyHandle, and returns the + signature as sig. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CertifySelfTest: Signing certifyInfo digest\n"); + returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ + m2Digest, /* message */ + TPM_DIGEST_SIZE, /* message size */ + sigKey); /* input, signing key */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CertifySelfTest: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return sig */ + returnCode = TPM_SizedBuffer_Store(response, &sig); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&sig); /* @1 */ + return rcf; +} diff --git a/src/tpm12/tpm_cryptoh.h b/src/tpm12/tpm_cryptoh.h new file mode 100644 index 0000000..268df6c --- /dev/null +++ b/src/tpm12/tpm_cryptoh.h @@ -0,0 +1,362 @@ +/********************************************************************************/ +/* */ +/* High Level Platform Independent Crypto */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_cryptoh.h 4300 2011-01-18 18:00:27Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_CRYPTOH_H +#define TPM_CRYPTOH_H + +#include "tpm_global.h" +#include "tpm_types.h" +#include "tpm_sizedbuffer.h" +#include "tpm_structures.h" + +/* + TPM_SIGN_INFO +*/ + +void TPM_SignInfo_Init(TPM_SIGN_INFO *tpm_sign_info); +TPM_RESULT TPM_SignInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SIGN_INFO *tpm_sign_info); +void TPM_SignInfo_Delete(TPM_SIGN_INFO *tpm_sign_info); + +/* + TPM_CERTIFY_INFO +*/ + +void TPM_CertifyInfo_Init(TPM_CERTIFY_INFO *tpm_certify_info); +#if 0 +TPM_RESULT TPM_CertifyInfo_Load(TPM_CERTIFY_INFO *tpm_certify_info, + unsigned char **stream, + uint32_t *stream_size); +#endif +TPM_RESULT TPM_CertifyInfo_Store(TPM_STORE_BUFFER *sbuffer, + TPM_CERTIFY_INFO *tpm_certify_info); +void TPM_CertifyInfo_Delete(TPM_CERTIFY_INFO *tpm_certify_info); + +TPM_RESULT TPM_CertifyInfo_Set(TPM_CERTIFY_INFO *tpm_certify_info, + TPM_KEY *tpm_key); + +/* + TPM_CERTIFY_INFO2 +*/ + +void TPM_CertifyInfo2_Init(TPM_CERTIFY_INFO2 *tpm_certify_info2); +#if 0 +TPM_RESULT TPM_CertifyInfo2_Load(TPM_CERTIFY_INFO2 *tpm_certify_info2, + unsigned char **stream, + uint32_t *stream_size); +#endif +TPM_RESULT TPM_CertifyInfo2_Store(TPM_STORE_BUFFER *sbuffer, + TPM_CERTIFY_INFO2 *tpm_certify_info2); +void TPM_CertifyInfo2_Delete(TPM_CERTIFY_INFO2 *tpm_certify_info2); + +TPM_RESULT TPM_CertifyInfo2_Set(TPM_CERTIFY_INFO2 *tpm_certify_info2, + TPM_KEY *tpm_key); + +/* + TPM_SYMMETRIC_KEY +*/ + +void TPM_SymmetricKey_Init(TPM_SYMMETRIC_KEY *tpm_symmetric_key); +TPM_RESULT TPM_SymmetricKey_Load(TPM_SYMMETRIC_KEY *tpm_symmetric_key, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_SymmetricKey_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SYMMETRIC_KEY *tpm_symmetric_key); +void TPM_SymmetricKey_Delete(TPM_SYMMETRIC_KEY *tpm_symmetric_key); + +TPM_RESULT TPM_SymmetricKeyData_EncryptSbuffer(TPM_SIZED_BUFFER *encrypt_data, + TPM_STORE_BUFFER *sbuffer, + const TPM_SYMMETRIC_KEY_TOKEN + tpm_symmetric_key_data); +TPM_RESULT TPM_SymmetricKeyData_StreamCrypt(unsigned char *data_out, + const unsigned char *data_in, + uint32_t data_size, + TPM_ALGORITHM_ID algId, + TPM_ENC_SCHEME encScheme, + const unsigned char *symmetric_key, + uint32_t symmetric_key_size, + unsigned char *pad_in, + uint32_t pad_in_size); + +/* + RSA functions +*/ + + +TPM_RESULT TPM_RSAPrivateDecryptMalloc(unsigned char **decrypt_data, + uint32_t *decrypt_data_length, + unsigned char *encrypt_data, + uint32_t encrypt_data_size, + TPM_KEY *tpm_key); + +TPM_RESULT TPM_RSAPrivateDecryptH(unsigned char *decrypt_data, + uint32_t *decrypt_data_length, + uint32_t decrypt_data_size, + unsigned char *encrypt_data, + uint32_t encrypt_data_size, + TPM_KEY *tpm_key); + +TPM_RESULT TPM_RSAPublicEncryptSbuffer_Key(TPM_SIZED_BUFFER *enc_data, + TPM_STORE_BUFFER *sbuffer, + TPM_KEY *tpm_key); +TPM_RESULT TPM_RSAPublicEncrypt_Key(TPM_SIZED_BUFFER *enc_data, + const unsigned char *decrypt_data, + size_t decrypt_data_size, + TPM_KEY *tpm_key); +TPM_RESULT TPM_RSAPublicEncrypt_Pubkey(TPM_SIZED_BUFFER *enc_data, + const unsigned char *decrypt_data, + size_t decrypt_data_size, + TPM_PUBKEY *tpm_pubkey); + +TPM_RESULT TPM_RSAPublicEncrypt_Common(TPM_SIZED_BUFFER *enc_data, + const unsigned char *decrypt_data, + size_t decrypt_data_size, + TPM_ENC_SCHEME encScheme, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes); + +TPM_RESULT TPM_RSASignH(unsigned char *signature, + unsigned int *signature_length, + unsigned int signature_size, + const unsigned char *message, + size_t message_size, + TPM_KEY *tpm_key); + +TPM_RESULT TPM_RSASignToSizedBuffer(TPM_SIZED_BUFFER *signature, + const unsigned char *message, + size_t message_size, + TPM_KEY *tpm_key); + +TPM_RESULT TPM_RSAVerifyH(TPM_SIZED_BUFFER *signature, + const unsigned char *message, + uint32_t message_size, + TPM_PUBKEY *tpm_pubkey); +TPM_RESULT TPM_RSAVerify(unsigned char *signature, + unsigned int signature_size, + TPM_SIG_SCHEME sigScheme, + const unsigned char *message, + uint32_t message_size, + unsigned char *narr, + uint32_t nbytes, + unsigned char *earr, + uint32_t ebytes); + +TPM_RESULT TPM_RSA_exponent_verify(unsigned long exponent); + +/* + OAEP Padding +*/ + +TPM_RESULT TPM_RSA_padding_add_PKCS1_OAEP(unsigned char *em, uint32_t emLen, + const unsigned char *from, uint32_t fLen, + const unsigned char *pHash, + const unsigned char *seed); +TPM_RESULT TPM_RSA_padding_check_PKCS1_OAEP(unsigned char *to, uint32_t *tLen, uint32_t tSize, + const unsigned char *em, uint32_t emLen, + unsigned char *pHash, + unsigned char *seed); + +/* + Digest functions - SHA-1 and HMAC +*/ + +TPM_RESULT TPM_SHA1(TPM_DIGEST md, ...); +TPM_RESULT TPM_SHA1_Check(TPM_DIGEST digest_expect, ...); +TPM_RESULT TPM_SHA1Sbuffer(TPM_DIGEST tpm_digest, + TPM_STORE_BUFFER *sbuffer); +TPM_RESULT TPM_SHA1_GenerateStructure(TPM_DIGEST tpm_digest, + void *tpmStructure, + TPM_STORE_FUNCTION_T storeFunction); +TPM_RESULT TPM_SHA1_CheckStructure(TPM_DIGEST expected_digest, + void *tpmStructure, + TPM_STORE_FUNCTION_T storeFunction, + TPM_RESULT error); + +TPM_RESULT TPM_HMAC_GenerateSbuffer(TPM_HMAC tpm_hmac, + const TPM_SECRET hmac_key, + TPM_STORE_BUFFER *sbuffer); +TPM_RESULT TPM_HMAC_GenerateStructure(TPM_HMAC tpm_hmac, + const TPM_SECRET hmac_key, + void *tpmStructure, + TPM_STORE_FUNCTION_T storeFunction); +TPM_RESULT TPM_HMAC_Generate(TPM_HMAC tpm_hmac, + const TPM_SECRET hmac_key, + ...); + +TPM_RESULT TPM_HMAC_CheckSbuffer(TPM_BOOL *valid, + TPM_HMAC expect, + const TPM_SECRET hmac_key, + TPM_STORE_BUFFER *sbuffer); +TPM_RESULT TPM_HMAC_Check(TPM_BOOL *valid, + TPM_HMAC expect, + const TPM_SECRET key, + ...); +TPM_RESULT TPM_HMAC_CheckStructure(const TPM_SECRET hmac_key, + void *structure, + TPM_HMAC expect, + TPM_STORE_FUNCTION_T storeFunction, + TPM_RESULT error); + +/* + XOR +*/ + +void TPM_XOR(unsigned char *out, + const unsigned char *in1, + const unsigned char *in2, + size_t length); + +/* + MGF1 +*/ + +TPM_RESULT TPM_MGF1(unsigned char *array, + uint32_t arrayLen, + const unsigned char *seed, + uint32_t seedLen); +TPM_RESULT TPM_MGF1_GenerateArray(unsigned char **array, + uint32_t arrayLen, + uint32_t seedLen, + ...); +/* bignum */ + +TPM_RESULT TPM_bn2binMalloc(unsigned char **bin, + unsigned int *bytes, + TPM_BIGNUM bn_in, + uint32_t padBytes); +TPM_RESULT TPM_bn2binArray(unsigned char *bin, + unsigned int bytes, + TPM_BIGNUM bn); +TPM_RESULT TPM_2bin2bn(TPM_BIGNUM *bignum_in, + const unsigned char *bin0, uint32_t size0, + const unsigned char *bin1, uint32_t size1); + +/* + Self Test +*/ + +TPM_RESULT TPM_CryptoTest(void); + + +/* + Processing functions +*/ + +TPM_RESULT TPM_Process_Sign(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SHA1Start(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SHA1Update(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SHA1Complete(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SHA1CompleteExtend(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_GetRandom(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_StirRandom(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_CertifyKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CertifyKey2(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CertifySelfTest(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +#endif diff --git a/src/tpm12/tpm_daa.c b/src/tpm12/tpm_daa.c new file mode 100644 index 0000000..7c0056e --- /dev/null +++ b/src/tpm12/tpm_daa.c @@ -0,0 +1,5729 @@ +/********************************************************************************/ +/* */ +/* DAA Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_daa.c 4768 2017-07-28 13:19:28Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_auth.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_init.h" +#include "tpm_key.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_process.h" +#include "tpm_sizedbuffer.h" + +#include "tpm_daa.h" + +/* + TPM_DAA_SESSION_DATA (the entire array) +*/ + +void TPM_DaaSessions_Init(TPM_DAA_SESSION_DATA *daaSessions) +{ + size_t i; + + printf(" TPM_DaaSessions_Init:\n"); + for (i = 0 ; i < TPM_MIN_DAA_SESSIONS ; i++) { + TPM_DaaSessionData_Init(&(daaSessions[i])); + } + return; +} + +/* TPM_DaaSessions_Load() reads a count of the number of stored sessions and then loads those + sessions. + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DaaSessions_Init() +*/ + +TPM_RESULT TPM_DaaSessions_Load(TPM_DAA_SESSION_DATA *daaSessions, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + uint32_t activeCount; + + printf(" TPM_DaaSessions_Load:\n"); + /* load active count */ + if (rc == 0) { + rc = TPM_Load32(&activeCount, stream, stream_size); + } + if (rc == 0) { + if (activeCount > TPM_MIN_DAA_SESSIONS) { + printf("TPM_DaaSessions_Load: Error (fatal) %u sessions, %u slots\n", + activeCount, TPM_MIN_DAA_SESSIONS); + rc = TPM_FAIL; + } + } + if (rc == 0) { + printf(" TPM_DaaSessions_Load: Loading %u sessions\n", activeCount); + } + /* load DAA sessions */ + for (i = 0 ; (rc == 0) && (i < activeCount) ; i++) { + rc = TPM_DaaSessionData_Load(&(daaSessions[i]), stream, stream_size); + } + return rc; +} + +/* TPM_DaaSessions_Store() stores a count of the active sessions, followed by the sessions. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DaaSessions_Store(TPM_STORE_BUFFER *sbuffer, + TPM_DAA_SESSION_DATA *daaSessions) +{ + TPM_RESULT rc = 0; + size_t i; + uint32_t space; + uint32_t activeCount; + + /* store active count */ + if (rc == 0) { + TPM_DaaSessions_GetSpace(&space, daaSessions); + activeCount = TPM_MIN_DAA_SESSIONS - space; + printf(" TPM_DaaSessions_Store: Storing %u sessions\n", activeCount); + rc = TPM_Sbuffer_Append32(sbuffer, activeCount); + } + /* store DAA sessions */ + for (i = 0 ; (rc == 0) && (i < TPM_MIN_DAA_SESSIONS) ; i++) { + if ((daaSessions[i]).valid) { /* if the session is active */ + rc = TPM_DaaSessionData_Store(sbuffer, &(daaSessions[i])); + } + } + return rc; +} + +/* TPM_DaaSessions_Delete() terminates all loaded DAA sessions + +*/ + +void TPM_DaaSessions_Delete(TPM_DAA_SESSION_DATA *daaSessions) +{ + size_t i; + + printf(" TPM_DaaSessions_Delete:\n"); + for (i = 0 ; i < TPM_MIN_DAA_SESSIONS ; i++) { + TPM_DaaSessionData_Delete(&(daaSessions[i])); + } + return; +} + +/* TPM_DaaSessions_IsSpace() returns 'isSpace' TRUE if an entry is available, FALSE if not. + + If TRUE, 'index' holds the first free position. +*/ + +void TPM_DaaSessions_IsSpace(TPM_BOOL *isSpace, + uint32_t *index, + TPM_DAA_SESSION_DATA *daaSessions) +{ + printf(" TPM_DaaSessions_IsSpace:\n"); + for (*index = 0, *isSpace = FALSE ; *index < TPM_MIN_DAA_SESSIONS ; (*index)++) { + if (!((daaSessions[*index]).valid)) { + printf(" TPM_DaaSessions_IsSpace: Found space at %u\n", *index); + *isSpace = TRUE; + break; + } + } + return; +} + +/* TPM_DaaSessions_GetSpace() returns the number of unused daaHandle's. + +*/ + +void TPM_DaaSessions_GetSpace(uint32_t *space, + TPM_DAA_SESSION_DATA *daaSessions) +{ + uint32_t i; + + printf(" TPM_DaaSessions_GetSpace:\n"); + for (*space = 0 , i = 0 ; i < TPM_MIN_DAA_SESSIONS ; i++) { + if (!((daaSessions[i]).valid)) { + (*space)++; + } + } + return; +} + +/* TPM_DaaSessions_StoreHandles() stores + + - the number of loaded sessions + - a list of session handles +*/ + +TPM_RESULT TPM_DaaSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, + TPM_DAA_SESSION_DATA *daaSessions) +{ + TPM_RESULT rc = 0; + uint16_t i; + uint32_t space; + + printf(" TPM_DaaSessions_StoreHandles:\n"); + /* get the number of loaded handles */ + if (rc == 0) { + TPM_DaaSessions_GetSpace(&space, daaSessions); + /* store loaded handle count. Safe case because of TPM_MIN_DAA_SESSIONS value */ + rc = TPM_Sbuffer_Append16(sbuffer, (uint16_t)(TPM_MIN_DAA_SESSIONS - space)); + } + for (i = 0 ; (rc == 0) && (i < TPM_MIN_DAA_SESSIONS) ; i++) { + if ((daaSessions[i]).valid) { /* if the index is loaded */ + rc = TPM_Sbuffer_Append32(sbuffer, (daaSessions[i]).daaHandle); /* store it */ + } + } + return rc; +} + +/* TPM_DaaSessions_GetNewHandle() checks for space in the DAA sessions table. + + If there is space, it returns a TPM_DAA_SESSION_DATA entry in 'tpm_daa_session_data' and its + handle in 'daaHandle'. The entry is marked 'valid'. + + If *daaHandle non-zero, the suggested value is tried first. + + Returns TPM_RESOURCES if there is no space in the sessions table. +*/ + +TPM_RESULT TPM_DaaSessions_GetNewHandle(TPM_DAA_SESSION_DATA **tpm_daa_session_data, /* entry */ + TPM_HANDLE *daaHandle, + TPM_BOOL *daaHandleValid, + TPM_DAA_SESSION_DATA *daaSessions) /* array */ +{ + TPM_RESULT rc = 0; + uint32_t index; + TPM_BOOL isSpace; + + printf(" TPM_DaaSessions_GetNewHandle:\n"); + *daaHandle = FALSE; + /* is there an empty entry, get the location index */ + if (rc == 0) { + TPM_DaaSessions_IsSpace(&isSpace, /* TRUE if space available */ + &index, /* if space available, index into array */ + daaSessions); /* array */ + if (!isSpace) { + printf("TPM_DaaSessions_GetNewHandle: Error, no space in daaSessions table\n"); + rc = TPM_RESOURCES; + } + } + if (rc == 0) { + rc = TPM_Handle_GenerateHandle(daaHandle, /* I/O, pointer to handle */ + daaSessions, /* handle array */ + FALSE, /* keepHandle */ + FALSE, /* isKeyHandle */ + (TPM_GETENTRY_FUNCTION_T)TPM_DaaSessions_GetEntry); + } + if (rc == 0) { + printf(" TPM_DaaSessions_GetNewHandle: Assigned handle %08x\n", *daaHandle); + *tpm_daa_session_data = &(daaSessions[index]); + TPM_DaaSessionData_Init(*tpm_daa_session_data); /* should be redundant since + terminate should have done + this */ + (*tpm_daa_session_data)->daaHandle = *daaHandle; + (*tpm_daa_session_data)->valid = TRUE; + *daaHandleValid = TRUE; + } + return rc; +} + +/* TPM_DaaSessions_GetEntry() searches all entries for the entry matching the handle, and + returns the TPM_DAA_SESSION_DATA entry associated with the handle. + + Returns + 0 for success + TPM_BAD_HANDLE if the handle is not found +*/ + +TPM_RESULT TPM_DaaSessions_GetEntry(TPM_DAA_SESSION_DATA **tpm_daa_session_data, /* session for + daaHandle */ + TPM_DAA_SESSION_DATA *daaSessions, /* points to first session in + array */ + TPM_HANDLE daaHandle) /* input */ +{ + TPM_RESULT rc = 0; + size_t i; + TPM_BOOL found; + + printf(" TPM_DaaSessions_GetEntry: daaHandle %08x\n", daaHandle); + for (i = 0, found = FALSE ; (i < TPM_MIN_DAA_SESSIONS) && !found ; i++) { + if ((daaSessions[i].valid) && + (daaSessions[i].daaHandle == daaHandle)) { /* found */ + found = TRUE; + *tpm_daa_session_data = &(daaSessions[i]); + } + } + if (!found) { + printf(" TPM_DaaSessions_GetEntry: session handle %08x not found\n", + daaHandle); + rc = TPM_BAD_HANDLE; + } + return rc; +} + +/* TPM_DaaSessions_AddEntry() adds an TPM_DAA_SESSION_DATA object to the list. + + If *tpm_handle == 0, a value is assigned. If *tpm_handle != 0, that value is used if it it not + currently in use. + + The handle is returned in tpm_handle. +*/ + +TPM_RESULT TPM_DaaSessions_AddEntry(TPM_HANDLE *tpm_handle, /* i/o */ + TPM_BOOL keepHandle, /* input */ + TPM_DAA_SESSION_DATA *daaSessions, /* input */ + TPM_DAA_SESSION_DATA *tpm_daa_session_data) /* input */ +{ + TPM_RESULT rc = 0; + uint32_t index; + TPM_BOOL isSpace; + + printf(" TPM_DaaSessions_AddEntry:\n"); + /* check for valid TPM_DAA_SESSION_DATA */ + if (rc == 0) { + if (tpm_daa_session_data == NULL) { /* NOTE: should never occur */ + printf("TPM_DaaSessions_AddEntry: Error (fatal), NULL TPM_DAA_SESSION_DATA\n"); + rc = TPM_FAIL; + } + } + /* is there an empty entry, get the location index */ + if (rc == 0) { + TPM_DaaSessions_IsSpace(&isSpace, &index, daaSessions); + if (!isSpace) { + printf("TPM_DaaSessions_AddEntry: Error, session entries full\n"); + rc = TPM_RESOURCES; + } + } + if (rc == 0) { + rc = TPM_Handle_GenerateHandle(tpm_handle, /* I/O */ + daaSessions, /* handle array */ + keepHandle, /* keepHandle */ + FALSE, /* isKeyHandle */ + (TPM_GETENTRY_FUNCTION_T)TPM_DaaSessions_GetEntry); + } + if (rc == 0) { + TPM_DaaSessionData_Copy(&(daaSessions[index]), *tpm_handle, tpm_daa_session_data); + daaSessions[index].valid = TRUE; + printf(" TPM_DaaSessions_AddEntry: Index %u handle %08x\n", + index, daaSessions[index].daaHandle); + } + return rc; +} + +/* TPM_DaaSessions_TerminateHandle() terminates the session associated with 'daaHandle'. + +*/ + +TPM_RESULT TPM_DaaSessions_TerminateHandle(TPM_DAA_SESSION_DATA *daaSessions, + TPM_HANDLE daaHandle) +{ + TPM_RESULT rc = 0; + TPM_DAA_SESSION_DATA *tpm_daa_session_data; + + printf(" TPM_DaaSessions_TerminateHandle: daaHandle %08x\n", daaHandle); + /* get the TPM_DAA_SESSION_DATA associated with the TPM_HANDLE */ + if (rc == 0) { + rc = TPM_DaaSessions_GetEntry(&tpm_daa_session_data, /* returns entry in array */ + daaSessions, /* array */ + daaHandle); + } + /* invalidate the valid handle */ + if (rc == 0) { + TPM_DaaSessionData_Delete(tpm_daa_session_data); + } + return rc; +} + +/* + TPM_DAA_SESSION_DATA (one element of the array) +*/ + +/* TPM_DaaSessionData_Init() initializes the DAA session. + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DaaSessionData_Init(TPM_DAA_SESSION_DATA *tpm_daa_session_data) +{ + printf(" TPM_DaaSessionData_Init:\n"); + TPM_DAAIssuer_Init(&(tpm_daa_session_data->DAA_issuerSettings)); + TPM_DAATpm_Init(&(tpm_daa_session_data->DAA_tpmSpecific)); + TPM_DAAContext_Init(&(tpm_daa_session_data->DAA_session)); + TPM_DAAJoindata_Init(&(tpm_daa_session_data->DAA_joinSession)); + tpm_daa_session_data->daaHandle = 0; + tpm_daa_session_data->valid = FALSE; + return; +} + +/* TPM_DaaSessionData_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DaaSessionData_Init() + After use, call TPM_DaaSessionData_Delete() to free memory +*/ + +TPM_RESULT TPM_DaaSessionData_Load(TPM_DAA_SESSION_DATA *tpm_daa_session_data, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DaaSessionData_Load:\n"); + /* load DAA_issuerSettings */ + if (rc == 0) { + rc = TPM_DAAIssuer_Load(&(tpm_daa_session_data->DAA_issuerSettings), stream, stream_size); + } + /* load DAA_tpmSpecific */ + if (rc == 0) { + rc = TPM_DAATpm_Load(&(tpm_daa_session_data->DAA_tpmSpecific), stream, stream_size); + } + /* load DAA_session */ + if (rc == 0) { + rc = TPM_DAAContext_Load(&(tpm_daa_session_data->DAA_session),stream, stream_size); + } + /* load DAA_joinSession */ + if (rc == 0) { + rc = TPM_DAAJoindata_Load(&(tpm_daa_session_data->DAA_joinSession), stream, stream_size); + } + /* load daaHandle */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_daa_session_data->daaHandle), stream, stream_size); + } + /* set valid */ + if (rc == 0) { + tpm_daa_session_data->valid = TRUE; + } + return rc; +} + +/* TPM_DaaSessionData_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DaaSessionData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_SESSION_DATA *tpm_daa_session_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DaaSessionData_Store:\n"); + /* store DAA_issuerSettings */ + if (rc == 0) { + rc = TPM_DAAIssuer_Store(sbuffer, &(tpm_daa_session_data->DAA_issuerSettings)); + } + /* store DAA_tpmSpecific */ + if (rc == 0) { + rc = TPM_DAATpm_Store(sbuffer, &(tpm_daa_session_data->DAA_tpmSpecific)); + } + /* store DAA_session */ + if (rc == 0) { + rc = TPM_DAAContext_Store(sbuffer, &(tpm_daa_session_data->DAA_session)); + } + /* store DAA_joinSession */ + if (rc == 0) { + rc = TPM_DAAJoindata_Store(sbuffer, &(tpm_daa_session_data->DAA_joinSession)); + } + /* store daaHandle */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_daa_session_data->daaHandle); + } + return rc; +} + +/* TPM_DaaSessionData_Delete() terminates the DAA session. + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DaaSessionData_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DaaSessionData_Delete(TPM_DAA_SESSION_DATA *tpm_daa_session_data) +{ + printf(" TPM_DaaSessionData_Delete:\n"); + if (tpm_daa_session_data != NULL) { + TPM_DAAIssuer_Delete(&(tpm_daa_session_data->DAA_issuerSettings)); + TPM_DAATpm_Delete(&(tpm_daa_session_data->DAA_tpmSpecific)); + TPM_DAAContext_Delete(&(tpm_daa_session_data->DAA_session)); + TPM_DAAJoindata_Delete(&(tpm_daa_session_data->DAA_joinSession)); + TPM_DaaSessionData_Init(tpm_daa_session_data); + } + return; +} + +/* TPM_DaaSessionData_Copy() copies the source to the destination. The source handle is ignored, + since it might already be used. +*/ + +void TPM_DaaSessionData_Copy(TPM_DAA_SESSION_DATA *dest_daa_session_data, + TPM_HANDLE tpm_handle, + TPM_DAA_SESSION_DATA *src_daa_session_data) +{ + dest_daa_session_data->daaHandle = tpm_handle; + TPM_DAAIssuer_Copy(&(dest_daa_session_data->DAA_issuerSettings), + &(src_daa_session_data->DAA_issuerSettings)); + TPM_DAATpm_Copy(&(dest_daa_session_data->DAA_tpmSpecific), + &(src_daa_session_data->DAA_tpmSpecific)); + TPM_DAAContext_Copy(&(dest_daa_session_data->DAA_session), + &(src_daa_session_data->DAA_session)); + TPM_DAAJoindata_Copy(&(dest_daa_session_data->DAA_joinSession), + &(src_daa_session_data->DAA_joinSession)); + dest_daa_session_data->valid= src_daa_session_data->valid; + return; +} + +/* TPM_DaaSessionData_CheckStage() verifies that the actual command processing stage is consistent + with the stage expected by the TPM state. +*/ + +TPM_RESULT TPM_DaaSessionData_CheckStage(TPM_DAA_SESSION_DATA *tpm_daa_session_data, + BYTE stage) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DaaSessionData_CheckStage:\n"); + if (tpm_daa_session_data->DAA_session.DAA_stage != stage) { + printf("TPM_DaaSessionData_CheckStage: Error, stage expected %u actual %u\n", + tpm_daa_session_data->DAA_session.DAA_stage, stage); + rc = TPM_DAA_STAGE; + } + return rc; +} + +/* + TPM_DAA_ISSUER +*/ + +/* TPM_DAAIssuer_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DAAIssuer_Init(TPM_DAA_ISSUER *tpm_daa_issuer) +{ + printf(" TPM_DAAIssuer_Init:\n"); + + TPM_Digest_Init(tpm_daa_issuer->DAA_digest_R0); + TPM_Digest_Init(tpm_daa_issuer->DAA_digest_R1); + TPM_Digest_Init(tpm_daa_issuer->DAA_digest_S0); + TPM_Digest_Init(tpm_daa_issuer->DAA_digest_S1); + TPM_Digest_Init(tpm_daa_issuer->DAA_digest_n); + TPM_Digest_Init(tpm_daa_issuer->DAA_digest_gamma); + memset(tpm_daa_issuer->DAA_generic_q, 0, sizeof(tpm_daa_issuer->DAA_generic_q)); + return; +} + +/* TPM_DAAIssuer_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DAAIssuer_Init() + After use, call TPM_DAAIssuer_Delete() to free memory +*/ + +TPM_RESULT TPM_DAAIssuer_Load(TPM_DAA_ISSUER *tpm_daa_issuer, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAAIssuer_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DAA_ISSUER, stream, stream_size); + } + /* load DAA_digest_R0 */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_R0, stream, stream_size); + } + /* load DAA_digest_R1 */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_R1, stream, stream_size); + } + /* load DAA_digest_S0 */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_S0, stream, stream_size); + } + /* load DAA_digest_S1 */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_S1, stream, stream_size); + } + /* load DAA_digest_n */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_n, stream, stream_size); + } + /* load DAA_digest_gamma */ + if (rc == 0) { + rc = TPM_Digest_Load (tpm_daa_issuer->DAA_digest_gamma, stream, stream_size); + } + /* load DAA_generic_q */ + if (rc == 0) { + rc = TPM_Loadn(tpm_daa_issuer->DAA_generic_q, sizeof(tpm_daa_issuer->DAA_generic_q), + stream, stream_size); + } + return rc; +} + +/* TPM_DAAIssuer_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DAAIssuer_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_ISSUER *tpm_daa_issuer) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAAIssuer_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_ISSUER); + } + /* store DAA_digest_R0 */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_R0); + } + /* store DAA_digest_R1 */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_R1); + } + /* store DAA_digest_S0 */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_S0); + } + /* store DAA_digest_S1 */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_S1); + } + /* store DAA_digest_n */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_n); + } + /* store DAA_digest_gamma */ + if (rc == 0) { + rc = TPM_Digest_Store (sbuffer, tpm_daa_issuer->DAA_digest_gamma); + } + /* store DAA_generic_q */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + tpm_daa_issuer->DAA_generic_q, + sizeof(tpm_daa_issuer->DAA_generic_q)); + } + return rc; +} + +/* TPM_DAAIssuer_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DAAIssuer_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DAAIssuer_Delete(TPM_DAA_ISSUER *tpm_daa_issuer) +{ + printf(" TPM_DAAIssuer_Delete:\n"); + if (tpm_daa_issuer != NULL) { + TPM_DAAIssuer_Init(tpm_daa_issuer); + } + return; +} + +/* TPM_DAAIssuer_Copy() copies the source to the destination + +*/ + +void TPM_DAAIssuer_Copy(TPM_DAA_ISSUER *dest_daa_issuer, + TPM_DAA_ISSUER *src_daa_issuer) +{ + printf(" TPM_DAAIssuer_Copy:\n"); + + TPM_Digest_Copy(dest_daa_issuer->DAA_digest_R0, src_daa_issuer->DAA_digest_R0); + TPM_Digest_Copy(dest_daa_issuer->DAA_digest_R1, src_daa_issuer->DAA_digest_R1); + TPM_Digest_Copy(dest_daa_issuer->DAA_digest_S0, src_daa_issuer->DAA_digest_S0); + TPM_Digest_Copy(dest_daa_issuer->DAA_digest_S1, src_daa_issuer->DAA_digest_S1); + TPM_Digest_Copy(dest_daa_issuer->DAA_digest_n, src_daa_issuer->DAA_digest_n); + TPM_Digest_Copy(dest_daa_issuer->DAA_digest_gamma, src_daa_issuer->DAA_digest_gamma); + memcpy(dest_daa_issuer->DAA_generic_q, src_daa_issuer->DAA_generic_q, + sizeof(src_daa_issuer->DAA_generic_q)); + return; +} + +/* + TPM_DAA_TPM +*/ + +/* TPM_DAATpm_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DAATpm_Init(TPM_DAA_TPM *tpm_daa_tpm) +{ + printf(" TPM_DAATpm_Init:\n"); + TPM_Digest_Init(tpm_daa_tpm->DAA_digestIssuer); + TPM_Digest_Init(tpm_daa_tpm->DAA_digest_v0); + TPM_Digest_Init(tpm_daa_tpm->DAA_digest_v1); + TPM_Digest_Init(tpm_daa_tpm->DAA_rekey); + tpm_daa_tpm->DAA_count = 0; + return; +} + +/* TPM_DAATpm_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DAATpm_Init() + After use, call TPM_DAATpm_Delete() to free memory +*/ + +TPM_RESULT TPM_DAATpm_Load(TPM_DAA_TPM *tpm_daa_tpm, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAATpm_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DAA_TPM, stream, stream_size); + } + /* load DAA_digestIssuer */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_tpm->DAA_digestIssuer, stream, stream_size); + } + /* load DAA_digest_v0 */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_tpm->DAA_digest_v0, stream, stream_size); + } + /* load DAA_digest_v1 */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_tpm->DAA_digest_v1, stream, stream_size); + } + /* load DAA_rekey */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_tpm->DAA_rekey, stream, stream_size); + } + /* load DAA_count */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_daa_tpm->DAA_count), stream, stream_size); + } + return rc; +} + +/* TPM_DAATpm_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DAATpm_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_TPM *tpm_daa_tpm) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAATpm_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_TPM); + } + /* store DAA_digestIssuer */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_tpm->DAA_digestIssuer); + } + /* store DAA_digest_v0 */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_tpm->DAA_digest_v0); + } + /* store DAA_digest_v1 */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_tpm->DAA_digest_v1); + } + /* store DAA_rekey */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_tpm->DAA_rekey); + } + /* store DAA_count */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_daa_tpm->DAA_count); + } + return rc; +} + +/* TPM_DAATpm_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DAATpm_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DAATpm_Delete(TPM_DAA_TPM *tpm_daa_tpm) +{ + printf(" TPM_DAATpm_Delete:\n"); + if (tpm_daa_tpm != NULL) { + TPM_DAATpm_Init(tpm_daa_tpm); + } + return; +} + +/* TPM_DAATpm_Copy() copies the source to the destination + +*/ + +void TPM_DAATpm_Copy(TPM_DAA_TPM *dest_daa_tpm, TPM_DAA_TPM *src_daa_tpm) +{ + printf(" TPM_DAATpm_Copy:\n"); + TPM_Digest_Copy(dest_daa_tpm->DAA_digestIssuer, src_daa_tpm->DAA_digestIssuer); + TPM_Digest_Copy(dest_daa_tpm->DAA_digest_v0, src_daa_tpm->DAA_digest_v0); + TPM_Digest_Copy(dest_daa_tpm->DAA_digest_v1, src_daa_tpm->DAA_digest_v1); + TPM_Digest_Copy(dest_daa_tpm->DAA_rekey, src_daa_tpm->DAA_rekey); + dest_daa_tpm->DAA_count = src_daa_tpm->DAA_count; + return; +} + +/* + TPM_DAA_CONTEXT +*/ + +/* TPM_DAAContext_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DAAContext_Init(TPM_DAA_CONTEXT *tpm_daa_context) +{ + printf(" TPM_DAAContext_Init:\n"); + TPM_Digest_Init(tpm_daa_context->DAA_digestContext); + TPM_Digest_Init(tpm_daa_context->DAA_digest); + TPM_Nonce_Init(tpm_daa_context->DAA_contextSeed); + memset(tpm_daa_context->DAA_scratch, 0, sizeof(tpm_daa_context->DAA_scratch)); + tpm_daa_context->DAA_stage = 0; + tpm_daa_context->DAA_scratch_null = TRUE; + return; +} + +/* TPM_DAAContext_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DAAContext_Init() + After use, call TPM_DAAContext_Delete() to free memory +*/ + +TPM_RESULT TPM_DAAContext_Load(TPM_DAA_CONTEXT *tpm_daa_context, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAAContext_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DAA_CONTEXT, stream, stream_size); + } + /* load DAA_digestContext */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_context->DAA_digestContext, stream, stream_size); + } + /* load DAA_digest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_context->DAA_digest, stream, stream_size); + } + /* load DAA_contextSeed */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_daa_context->DAA_contextSeed, stream, stream_size); + } + /* load DAA_scratch */ + if (rc == 0) { + rc = TPM_Loadn(tpm_daa_context->DAA_scratch, sizeof(tpm_daa_context->DAA_scratch), + stream, stream_size); + } + /* load DAA_stage */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_daa_context->DAA_stage), stream, stream_size); + } + /* load DAA_scratch_null */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_daa_context->DAA_scratch_null), stream, stream_size); + } + return rc; +} + +/* TPM_DAAContext_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DAAContext_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_CONTEXT *tpm_daa_context) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAAContext_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_CONTEXT); + } + /* store DAA_digestContext */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_context->DAA_digestContext); + } + /* store DAA_digest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_context->DAA_digest); + } + /* store DAA_contextSeed */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_daa_context->DAA_contextSeed); + } + /* store DAA_scratch */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_context->DAA_scratch, + sizeof(tpm_daa_context->DAA_scratch)); + } + /* store DAA_stage */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_daa_context->DAA_stage), sizeof(BYTE)); + } + /* store DAA_scratch_null */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_daa_context->DAA_scratch_null), sizeof(TPM_BOOL)); + } + return rc; +} + +/* TPM_DAAContext_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DAAContext_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DAAContext_Delete(TPM_DAA_CONTEXT *tpm_daa_context) +{ + printf(" TPM_DAAContext_Delete:\n"); + if (tpm_daa_context != NULL) { + TPM_DAAContext_Init(tpm_daa_context); + } + return; +} + +/* TPM_DAAContext_Copy() copies the source to the destination + +*/ + +void TPM_DAAContext_Copy(TPM_DAA_CONTEXT *dest_daa_context, TPM_DAA_CONTEXT *src_daa_context) +{ + printf(" TPM_DAAContext_Copy:\n"); + TPM_Digest_Copy(dest_daa_context->DAA_digestContext, src_daa_context->DAA_digestContext); + TPM_Digest_Copy(dest_daa_context->DAA_digest, src_daa_context->DAA_digest); + TPM_Nonce_Copy(dest_daa_context->DAA_contextSeed, src_daa_context->DAA_contextSeed); + memcpy(dest_daa_context->DAA_scratch, src_daa_context->DAA_scratch, + sizeof(src_daa_context->DAA_scratch)); + dest_daa_context->DAA_stage = src_daa_context->DAA_stage; + dest_daa_context->DAA_scratch_null = src_daa_context->DAA_scratch_null; + return; +} + +/* + TPM_DAA_JOINDATA +*/ + +/* TPM_DAAJoindata_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DAAJoindata_Init(TPM_DAA_JOINDATA *tpm_daa_joindata) +{ + printf(" TPM_DAAJoindata_Init:\n"); + memset(tpm_daa_joindata->DAA_join_u0, 0, sizeof(tpm_daa_joindata->DAA_join_u0)); + memset(tpm_daa_joindata->DAA_join_u1, 0, sizeof(tpm_daa_joindata->DAA_join_u1)); + TPM_Digest_Init(tpm_daa_joindata->DAA_digest_n0); + return; +} + +/* TPM_DAAJoindata_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DAAJoindata_Init() + After use, call TPM_DAAJoindata_Delete() to free memory +*/ + +TPM_RESULT TPM_DAAJoindata_Load(TPM_DAA_JOINDATA *tpm_daa_joindata, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAAJoindata_Load:\n"); + /* load DAA_join_u0 */ + if (rc == 0) { + rc = TPM_Loadn(tpm_daa_joindata->DAA_join_u0, + sizeof(tpm_daa_joindata->DAA_join_u0), + stream, stream_size); + } + /* load DAA_join_u1 */ + if (rc == 0) { + rc = TPM_Loadn(tpm_daa_joindata->DAA_join_u1, + sizeof(tpm_daa_joindata->DAA_join_u1), + stream, stream_size); + } + /* load DAA_digest_n0 */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_joindata->DAA_digest_n0, stream, stream_size); + } + return rc; +} + +/* TPM_DAAJoindata_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DAAJoindata_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_JOINDATA *tpm_daa_joindata) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAAJoindata_Store:\n"); + /* store DAA_join_u0 */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_joindata->DAA_join_u0, + sizeof(tpm_daa_joindata->DAA_join_u0)); + } + /* store DAA_join_u1 */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_joindata->DAA_join_u1, + sizeof(tpm_daa_joindata->DAA_join_u1)); + } + /* store DAA_digest_n0 */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_joindata->DAA_digest_n0); + } + return rc; +} + +/* TPM_DAAJoindata_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DAAJoindata_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DAAJoindata_Delete(TPM_DAA_JOINDATA *tpm_daa_joindata) +{ + printf(" TPM_DAAJoindata_Delete:\n"); + if (tpm_daa_joindata != NULL) { + TPM_DAAJoindata_Init(tpm_daa_joindata); + } + return; +} + +/* TPM_DAAJoindata_Copy() copies the source to the destination + +*/ + +void TPM_DAAJoindata_Copy(TPM_DAA_JOINDATA *dest_daa_joindata, TPM_DAA_JOINDATA *src_daa_joindata) +{ + printf(" TPM_DAAJoindata_Copy:\n"); + memcpy(dest_daa_joindata->DAA_join_u0, src_daa_joindata->DAA_join_u0, + sizeof(src_daa_joindata->DAA_join_u0)); + memcpy(dest_daa_joindata->DAA_join_u1, src_daa_joindata->DAA_join_u1, + sizeof(src_daa_joindata->DAA_join_u1)); + TPM_Digest_Copy(dest_daa_joindata->DAA_digest_n0, src_daa_joindata->DAA_digest_n0); + return; +} + +/* + TPM_DAA_BLOB +*/ + +/* TPM_DAABlob_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DAABlob_Init(TPM_DAA_BLOB *tpm_daa_blob) +{ + printf(" TPM_DAABlob_Init:\n"); + tpm_daa_blob->resourceType = 0; + memset(tpm_daa_blob->label, 0, sizeof(tpm_daa_blob->label)); + TPM_Digest_Init(tpm_daa_blob->blobIntegrity); + TPM_SizedBuffer_Init(&(tpm_daa_blob->additionalData)); + TPM_SizedBuffer_Init(&(tpm_daa_blob->sensitiveData)); + return; +} + +/* TPM_DAABlob_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DAABlob_Init() + After use, call TPM_DAABlob_Delete() to free memory +*/ + +TPM_RESULT TPM_DAABlob_Load(TPM_DAA_BLOB *tpm_daa_blob, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAABlob_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DAA_BLOB, stream, stream_size); + } + /* load resourceType */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_daa_blob->resourceType), stream, stream_size); + } + /* load label */ + if (rc == 0) { + rc = TPM_Loadn(tpm_daa_blob->label, sizeof(tpm_daa_blob->label), stream, stream_size); + } + /* load blobIntegrity */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_daa_blob->blobIntegrity, stream, stream_size); + } + /* load additionalData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_daa_blob->additionalData), stream, stream_size); + } + /* load sensitiveData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_daa_blob->sensitiveData), stream, stream_size); + } + return rc; +} + +/* TPM_DAABlob_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DAABlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_BLOB *tpm_daa_blob) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAABlob_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_BLOB); + } + /* store resourceType */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_daa_blob->resourceType); + } + /* store label */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_blob->label, sizeof(tpm_daa_blob->label)); + } + /* store blobIntegrity */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_daa_blob->blobIntegrity); + } + /* store additionalData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_daa_blob->additionalData)); + } + /* store sensitiveData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_daa_blob->sensitiveData)); + } + return rc; +} + +/* TPM_DAABlob_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DAABlob_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DAABlob_Delete(TPM_DAA_BLOB *tpm_daa_blob) +{ + printf(" TPM_DAABlob_Delete:\n"); + if (tpm_daa_blob != NULL) { + TPM_SizedBuffer_Delete(&(tpm_daa_blob->additionalData)); + TPM_SizedBuffer_Delete(&(tpm_daa_blob->sensitiveData)); + TPM_DAABlob_Init(tpm_daa_blob); + } + return; +} + +/* + TPM_DAA_SENSITIVE +*/ + +/* TPM_DAASensitive_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DAASensitive_Init(TPM_DAA_SENSITIVE *tpm_daa_sensitive) +{ + printf(" TPM_DAASensitive_Init:\n"); + TPM_SizedBuffer_Init(&(tpm_daa_sensitive->internalData)); + return; +} + +/* TPM_DAASensitive_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DAASensitive_Init() + After use, call TPM_DAASensitive_Delete() to free memory +*/ + +TPM_RESULT TPM_DAASensitive_Load(TPM_DAA_SENSITIVE *tpm_daa_sensitive, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAASensitive_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DAA_SENSITIVE, stream, stream_size); + } + /* load internalData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_daa_sensitive->internalData), stream, stream_size); + } + return rc; +} + +/* TPM_DAASensitive_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DAASensitive_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_SENSITIVE *tpm_daa_sensitive) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DAASensitive_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_SENSITIVE); + } + /* store internalData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_daa_sensitive->internalData)); + } + return rc; +} + +/* TPM_DAASensitive_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DAASensitive_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DAASensitive_Delete(TPM_DAA_SENSITIVE *tpm_daa_sensitive) +{ + printf(" TPM_DAASensitive_Delete:\n"); + if (tpm_daa_sensitive != NULL) { + TPM_SizedBuffer_Delete(&(tpm_daa_sensitive->internalData)); + TPM_DAASensitive_Init(tpm_daa_sensitive); + } + return; +} + + +/* + Processing Common Stage Functions +*/ + +TPM_RESULT TPM_DAAJoin_Stage00(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA **tpm_daa_session_data, + TPM_BOOL *daaHandleValid, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + uint32_t count; + TPM_HANDLE daaHandle = 0; /* no preassigned handle */ + + printf("TPM_DAAJoin_Stage00:\n"); + if (rc == 0) { + /* a. Determine that sufficient resources are available to perform a TPM_DAA_Join. */ + /* i. The TPM MUST support sufficient resources to perform one (1) + TPM_DAA_Join/TPM_DAA_Sign. The TPM MAY support additional TPM_DAA_Join/TPM_DAA_Sign + sessions. */ + /* ii. The TPM may share internal resources between the DAA operations and other variable + resource requirements: */ + /* iii. If there are insufficient resources within the stored key pool (and one or more keys + need to be removed to permit the DAA operation to execute) return TPM_NOSPACE */ + /* iv. If there are insufficient resources within the stored session pool (and one or more + authorization or transport sessions need to be removed to permit the DAA operation to + execute), return TPM_RESOURCES. */ + rc = TPM_DaaSessions_GetNewHandle(tpm_daa_session_data, + &daaHandle, /* output */ + daaHandleValid, /* output */ + tpm_state->tpm_stclear_data.daaSessions); /* array */ + } + if (rc == 0) { + /* b. Set all fields in DAA_issuerSettings = NULL */ + /* c. set all fields in DAA_tpmSpecific = NULL */ + /* d. set all fields in DAA_session = NULL */ + /* e. Set all fields in DAA_joinSession = NULL */ + /* NOTE Done by TPM_DaaSessions_GetNewHandle() */ + /* f. Verify that sizeOf(inputData0) == sizeof(DAA_tpmSpecific -> DAA_count) and return + error TPM_DAA_INPUT_DATA0 on mismatch */ + if (inputData0->size != sizeof((*tpm_daa_session_data)->DAA_tpmSpecific.DAA_count)) { + printf("TPM_DAAJoin_Stage00: Error, inputData0 size %u should be %lu\n", + inputData0->size, + (unsigned long)sizeof((*tpm_daa_session_data)->DAA_tpmSpecific.DAA_count)); + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + /* g. Verify that inputData0 > 0, and return error TPM_DAA_INPUT_DATA0 on mismatch */ + stream = inputData0->buffer; + stream_size = inputData0->size; + rc = TPM_Load32(&count, &stream, &stream_size); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + printf("TPM_DAAJoin_Stage00: count %u\n", count); + if (count == 0) { + printf("TPM_DAAJoin_Stage00: Error, count is zero\n"); + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + /* h. Set DAA_tpmSpecific -> DAA_count = inputData0 */ + (*tpm_daa_session_data)->DAA_tpmSpecific.DAA_count = count; + /* i. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ + rc = TPM_DAADigestContext_GenerateDigestJoin + ((*tpm_daa_session_data)->DAA_session.DAA_digestContext, + (*tpm_daa_session_data)); + } + if (rc == 0) { + /* j. set DAA_session -> DAA_stage = 1 */ + (*tpm_daa_session_data)->DAA_session.DAA_stage = 1; + /* k. Assign session handle for TPM_DAA_Join */ + /* NOTE Done by TPM_DaaSessions_GetNewHandle() */ + printf("TPM_DAAJoin_Stage00: handle %08x\n", (*tpm_daa_session_data)->daaHandle); + /* l. set outputData = new session handle */ + /* i. The handle in outputData is included the output HMAC. */ + rc = TPM_SizedBuffer_Append32(outputData, (*tpm_daa_session_data)->daaHandle); + } + /* m. return TPM_SUCCESS */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage01(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + TPM_DIGEST signedDataDigest; + + printf("TPM_DAAJoin_Stage01:\n"); + outputData = outputData; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==1. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that sizeOf(inputData0) == DAA_SIZE_issuerModulus and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + if (inputData0->size != DAA_SIZE_issuerModulus) { + printf("TPM_DAAJoin_Stage01: Error, bad input0 size %u\n", inputData0->size); + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + /* d. If DAA_session -> DAA_scratch == NULL: */ + if (tpm_daa_session_data->DAA_session.DAA_scratch_null) { + printf("TPM_DAAJoin_Stage01: DAA_scratch null\n"); + if (rc == 0) { + /* i. Set DAA_session -> DAA_scratch = inputData0 */ + tpm_daa_session_data->DAA_session.DAA_scratch_null = FALSE; + memcpy(tpm_daa_session_data->DAA_session.DAA_scratch, + inputData0->buffer, DAA_SIZE_issuerModulus); + /* ii. set DAA_joinSession -> DAA_digest_n0 = SHA-1(DAA_session -> DAA_scratch) */ + rc = + TPM_SHA1(tpm_daa_session_data->DAA_joinSession.DAA_digest_n0, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + tpm_daa_session_data->DAA_session.DAA_scratch, + 0, NULL); + } + /* iii. set DAA_tpmSpecific -> DAA_rekey = SHA-1(tpmDAASeed || DAA_joinSession -> + DAA_digest_n0) */ + if (rc == 0) { + rc = TPM_SHA1(tpm_daa_session_data->DAA_tpmSpecific.DAA_rekey, + TPM_NONCE_SIZE, tpm_state->tpm_permanent_data.tpmDAASeed, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_joinSession.DAA_digest_n0, + 0, NULL); + } + } + /* e. Else (If DAA_session -> DAA_scratch != NULL): */ + else { + printf("TPM_DAAJoin_Stage01: DAA_scratch not null\n"); + /* i. Set signedData = inputData0 */ + /* ii. Verify that sizeOf(inputData1) == DAA_SIZE_issuerModulus and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + if (inputData1->size != DAA_SIZE_issuerModulus) { + printf("TPM_DAAJoin_Stage01: Error, bad input1 size %u\n", inputData1->size); + rc = TPM_DAA_INPUT_DATA1; + } + } + /* iii. Set signatureValue = inputData1 */ + /* iv. Use the RSA key == [DAA_session -> DAA_scratch] to verify that signatureValue is + a signature on signedData using TPM_SS_RSASSAPKCS1v15_SHA1 (RSA PKCS1.5 with SHA-1), + and return error TPM_DAA_ISSUER_VALIDITY on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage01: Digesting signedData\n"); + rc = TPM_SHA1(signedDataDigest, + inputData0->size, inputData0->buffer, + 0, NULL); + } + if (rc == 0) { + printf("TPM_DAAJoin_Stage01: Verifying signature\n"); + rc = TPM_RSAVerify(inputData1->buffer, /* signature */ + inputData1->size, + TPM_SS_RSASSAPKCS1v15_INFO, /* signature scheme */ + signedDataDigest, /* signed data */ + TPM_DIGEST_SIZE, + tpm_daa_session_data->DAA_session.DAA_scratch, /* pub modulus */ + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + tpm_default_rsa_exponent, /* public exponent */ + 3); + if (rc != 0) { + printf("TPM_DAAJoin_Stage01: Error, bad signature\n"); + rc = TPM_DAA_ISSUER_VALIDITY; + } + } + /* v. Set DAA_session -> DAA_scratch = signedData */ + if (rc == 0) { + memcpy(tpm_daa_session_data->DAA_session.DAA_scratch, + inputData0->buffer, inputData1->size); + } + } + } + if (rc == 0) { + /* f. Decrement DAA_tpmSpecific -> DAA_count by 1 (unity) */ + tpm_daa_session_data->DAA_tpmSpecific.DAA_count--; + /* g. If DAA_tpmSpecific -> DAA_count ==0: */ + if (tpm_daa_session_data->DAA_tpmSpecific.DAA_count == 0) { + /* h. increment DAA_session -> DAA_Stage by 1 */ + tpm_daa_session_data->DAA_session.DAA_stage++; + } + /* i. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ + rc = TPM_DAADigestContext_GenerateDigestJoin + (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); + } + /* j. set outputData = NULL */ + /* NOTE Done by caller */ + /* k. return TPM_SUCCESS */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage02(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + TPM_STORE_BUFFER signedDataSbuffer; + TPM_DIGEST signedDataDigest; + + printf("TPM_DAAJoin_Stage02:\n"); + outputData = outputData; /* not used */ + tpm_state = tpm_state; /* not used */ + TPM_Sbuffer_Init(&signedDataSbuffer); /* freed @1*/ + /* a. Verify that DAA_session ->DAA_stage==2. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that sizeOf(inputData0) == sizeOf(TPM_DAA_ISSUER) and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + /* NOTE cannot use sizeof because packing may not be exact */ + /* d. Set DAA_issuerSettings = inputData0. Verify that all fields in DAA_issuerSettings are + present and return error TPM_DAA_INPUT_DATA0 if not. */ + if (rc == 0) { + stream = inputData0->buffer; + stream_size = inputData0->size; + rc = TPM_DAAIssuer_Load(&(tpm_daa_session_data->DAA_issuerSettings), &stream, &stream_size); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + if (stream_size != 0) { + printf("TPM_DAAJoin_Stage02: Error, bad input0 size %u\n", inputData0->size); + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Verify that sizeOf(inputData1) == DAA_SIZE_issuerModulus and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + if (inputData1->size != DAA_SIZE_issuerModulus) { + printf("TPM_DAAJoin_Stage02: Error, bad input1 size %u\n", inputData1->size); + rc = TPM_DAA_INPUT_DATA1; + } + } + /* f. Set signatureValue = inputData1 */ + /* g. Set signedData = (DAA_joinSession -> DAA_digest_n0 || DAA_issuerSettings) */ + if (rc == 0) { + rc = TPM_Digest_Store(&signedDataSbuffer, + tpm_daa_session_data->DAA_joinSession.DAA_digest_n0); + } + if (rc == 0) { + rc = TPM_DAAIssuer_Store(&signedDataSbuffer, &(tpm_daa_session_data->DAA_issuerSettings)); + } + /* h. Use the RSA key [DAA_session -> DAA_scratch] to verify that signatureValue is a */ + /* signature on signedData using TPM_SS_RSASSAPKCS1v15_SHA1 (RSA PKCS1.5 with SHA-1), and return + error TPM_DAA_ISSUER_VALIDITY on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage02: Digesting signedData\n"); + rc = TPM_SHA1Sbuffer(signedDataDigest, &signedDataSbuffer); + } + if (rc == 0) { + printf("TPM_DAAJoin_Stage02: Verifying signature\n"); + rc = TPM_RSAVerify(inputData1->buffer, /* signature */ + inputData1->size, + TPM_SS_RSASSAPKCS1v15_INFO, /* signature scheme */ + signedDataDigest, /* signed data */ + TPM_DIGEST_SIZE, + tpm_daa_session_data->DAA_session.DAA_scratch, /* public modulus */ + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + tpm_default_rsa_exponent, /* public exponent */ + 3); + if (rc != 0) { + printf("TPM_DAAJoin_Stage02: Error, bad signature\n"); + rc = TPM_DAA_ISSUER_VALIDITY; + } + } + /* i. Set DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) */ + if (rc == 0) { + rc = TPM_SHA1_GenerateStructure(tpm_daa_session_data->DAA_tpmSpecific.DAA_digestIssuer, + &(tpm_daa_session_data->DAA_issuerSettings), + (TPM_STORE_FUNCTION_T)TPM_DAAIssuer_Store); + } + /* j. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ + if (rc == 0) { + rc = TPM_DAADigestContext_GenerateDigestJoin + (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); + } + if (rc == 0) { + /* k. Set DAA_session -> DAA_scratch = NULL */ + tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; + /* l. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + } + /* m. return TPM_SUCCESS */ + TPM_Sbuffer_Delete(&signedDataSbuffer); /* @1*/ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage03(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + + printf("TPM_DAAJoin_Stage03:\n"); + tpm_state = tpm_state; /* not used */ + outputData = outputData; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==3. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Verify that sizeOf(inputData0) == sizeOf(DAA_tpmSpecific -> DAA_count) and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + if (inputData0->size != sizeof(tpm_daa_session_data->DAA_tpmSpecific.DAA_count)) { + printf("TPM_DAAJoin_Stage03: Error, inputData0 size %u should be %lu\n", + inputData0->size, + (unsigned long)sizeof(tpm_daa_session_data->DAA_tpmSpecific.DAA_count)); + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Set DAA_tpmSpecific -> DAA_count = inputData0 */ + if (rc == 0) { + stream = inputData0->buffer; + stream_size = inputData0->size; + rc = TPM_Load32(&(tpm_daa_session_data->DAA_tpmSpecific.DAA_count), &stream, &stream_size); + } + /* f. Obtain random data from the RNG and store it as DAA_joinSession -> DAA_join_u0 */ + if (rc == 0) { + rc = TPM_Random(tpm_daa_session_data->DAA_joinSession.DAA_join_u0, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); + } + /* g. Obtain random data from the RNG and store it as DAA_joinSession -> DAA_join_u1 */ + if (rc == 0) { + rc = TPM_Random(tpm_daa_session_data->DAA_joinSession.DAA_join_u1, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u1)); + } + /* h. set outputData = NULL */ + /* NOTE Done by caller */ + /* i. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* j. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ + if (rc == 0) { + rc = TPM_DAADigestContext_GenerateDigestJoin + (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); + } + /* k. return TPM_SUCCESS */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage04(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + TPM_BIGNUM xBignum = NULL; /* freed @1 */ + TPM_BIGNUM nBignum = NULL; /* freed @2 */ + TPM_BIGNUM fBignum = NULL; /* freed @3 */ + TPM_BIGNUM rBignum = NULL; /* freed @4 */ + + printf("TPM_DAAJoin_Stage04:\n"); + tpm_state = tpm_state; /* not used */ + outputData = outputData; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==4. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_R0 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_R0) == DAA_issuerSettings -> DAA_digest_R0 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage04: Checking DAA_generic_R0\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_R0, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_R0 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage04: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Set X = DAA_generic_R0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage04: Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* i. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage04: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* j. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || + SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod + DAA_issuerSettings -> DAA_generic_q */ + if (rc == 0) { + rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @3 */ + } + /* k. Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0 bits of f) */ + if (rc == 0) { + rc = TPM_BN_mask_bits(fBignum, DAA_power0); /* f becomes f0 */ + } + /* l. Set DAA_session -> DAA_scratch = (X^f0) mod n */ + if (rc == 0) { + rc = TPM_ComputeAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + &rBignum, /* R */ + xBignum, /* A */ + fBignum, /* P */ + nBignum); /* n */ + } + /* m. set outputData = NULL */ + /* NOTE Done by caller */ + /* n. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* o. return TPM_SUCCESS */ + TPM_BN_free(xBignum); /* @1 */ + TPM_BN_free(nBignum); /* @2 */ + TPM_BN_free(fBignum); /* @3 */ + TPM_BN_free(rBignum); /* @4 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage05(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + TPM_BIGNUM xBignum = NULL; /* freed @1 */ + TPM_BIGNUM nBignum = NULL; /* freed @2 */ + TPM_BIGNUM fBignum = NULL; /* freed @3 */ + TPM_BIGNUM f1Bignum = NULL; /* freed @4 */ + TPM_BIGNUM zBignum = NULL; /* freed @5 */ + + printf("TPM_DAAJoin_Stage05:\n"); + tpm_state = tpm_state; /* not used */ + outputData = outputData; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==5. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_R1 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_R1) == DAA_issuerSettings -> DAA_digest_R1 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage05: Checking DAA_generic_R1\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_R1, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_R1 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage05: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Set X = DAA_generic_R1 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage05: Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* i. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage05: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* j. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || + SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod + DAA_issuerSettings -> DAA_generic_q. */ + if (rc == 0) { + rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @3 */ + } + /* k. Shift f right by DAA_power0 bits (discard the lowest DAA_power0 bits) and label the result + f1 */ + if (rc == 0) { + rc = TPM_BN_rshift(&f1Bignum, fBignum, DAA_power0); /* f becomes f1 */ + } + /* l. Set Z = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage05: Creating Z\n"); + rc = TPM_bin2bn(&zBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* m. Set DAA_session -> DAA_scratch = Z*(X^f1) mod n */ + if (rc == 0) { + rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + zBignum, /* Z */ + xBignum, /* A */ + f1Bignum, /* P */ + nBignum); /* N */ + } + /* n. set outputData = NULL */ + /* NOTE Done by caller */ + /* o. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* p. return TPM_SUCCESS */ + TPM_BN_free(xBignum); /* @1 */ + TPM_BN_free(nBignum); /* @2 */ + TPM_BN_free(fBignum); /* @3 */ + TPM_BN_free(f1Bignum); /* @4 */ + TPM_BN_free(zBignum); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage06(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + TPM_BIGNUM xBignum = NULL; /* freed @1 */ + TPM_BIGNUM nBignum = NULL; /* freed @2 */ + TPM_BIGNUM zBignum = NULL; /* freed @3 */ + TPM_BIGNUM yBignum = NULL; /* freed @4 */ + + printf("TPM_DAAJoin_Stage06:\n"); + tpm_state = tpm_state; /* not used */ + outputData = outputData; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==6. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_S0 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_S0) == DAA_issuerSettings -> DAA_digest_S0 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage06: Checking DAA_generic_S0\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S0, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_S0 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage06: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Set X = DAA_generic_S0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage06: Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* i. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage06: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* j. Set Z = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage06: Creating Z\n"); + rc = TPM_bin2bn(&zBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* k. Set Y = DAA_joinSession -> DAA_join_u0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage06: Creating Y\n"); + rc = TPM_bin2bn(&yBignum, + tpm_daa_session_data->DAA_joinSession.DAA_join_u0, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); + } + /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ + if (rc == 0) { + rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + zBignum, /* Z */ + xBignum, /* A */ + yBignum, /* P */ + nBignum); /* N */ + } + /* m. set outputData = NULL */ + /* NOTE Done by caller */ + /* n. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* o. return TPM_SUCCESS */ + TPM_BN_free(xBignum); /* @1 */ + TPM_BN_free(nBignum); /* @2 */ + TPM_BN_free(zBignum); /* @3 */ + TPM_BN_free(yBignum); /* @4 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage07(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + uint32_t nCount; /* DAA_count in nbo */ + TPM_BIGNUM xBignum = NULL; /* freed @1 */ + TPM_BIGNUM nBignum = NULL; /* freed @2 */ + TPM_BIGNUM yBignum = NULL; /* freed @3 */ + TPM_BIGNUM zBignum = NULL; /* freed @4 */ + + printf("TPM_DAAJoin_Stage07:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==7. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_S1 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_S1) == DAA_issuerSettings -> DAA_digest_S1 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage07: Checking DAA_generic_S1\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S1, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_S1 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage07: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Set X = DAA_generic_S1 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage07: Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* i. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage07: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* j. Set Y = DAA_joinSession -> DAA_join_u1 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage07: Creating Y\n"); + rc = TPM_bin2bn(&yBignum, + tpm_daa_session_data->DAA_joinSession.DAA_join_u1, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u1)); + } + /* k. Set Z = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage07: Creating Z\n"); + rc = TPM_bin2bn(&zBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ + if (rc == 0) { + rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + zBignum, /* Z */ + xBignum, /* A */ + yBignum, /* P */ + nBignum); /* N */ + } + /* m. Set DAA_session -> DAA_digest to the SHA-1 (DAA_session -> DAA_scratch || DAA_tpmSpecific + -> DAA_count || DAA_joinSession -> DAA_digest_n0) */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage07: Computing DAA_digest\n"); + nCount = htonl(tpm_daa_session_data->DAA_tpmSpecific.DAA_count); + rc = TPM_SHA1(tpm_daa_session_data->DAA_session.DAA_digest, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(uint32_t), &nCount, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_joinSession.DAA_digest_n0, + 0, NULL); + } + /* n. set outputData = DAA_session -> DAA_scratch */ + if (rc == 0) { + rc = TPM_SizedBuffer_Set(outputData, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + tpm_daa_session_data->DAA_session.DAA_scratch); + } + /* o. set DAA_session -> DAA_scratch = NULL */ + if (rc == 0) { + tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; + } + /* p. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* q. return TPM_SUCCESS */ + TPM_BN_free(xBignum); /* @1 */ + TPM_BN_free(nBignum); /* @2 */ + TPM_BN_free(yBignum); /* @3 */ + TPM_BN_free(zBignum); /* @4 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage08(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *NE = NULL; /* freed @1 */ + uint32_t NELength; + TPM_DIGEST outDigest; + + printf("TPM_DAAJoin_Stage08:\n"); + /* a. Verify that DAA_session ->DAA_stage==8. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Verify inputSize0 == DAA_SIZE_NE and return error TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + if (inputData0->size != DAA_SIZE_NE) { + printf("TPM_DAAJoin_Stage08: Error, inputData0 size %u should be %u\n", + inputData0->size, DAA_SIZE_NE); + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Set NE = decrypt(inputData0, privEK) */ + if (rc == 0) { + rc = TPM_RSAPrivateDecryptMalloc(&NE, /* decrypted data */ + &NELength, /* length of data put into decrypt_data */ + inputData0->buffer, /* encrypted data */ + inputData0->size, /* encrypted data size */ + &(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* f. set outputData = SHA-1(DAA_session -> DAA_digest || NE) */ + if (rc == 0) { + rc = TPM_SHA1(outDigest, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest, + NELength, NE, + 0, NULL); + } + if (rc == 0) { + rc = TPM_SizedBuffer_Set(outputData, TPM_DIGEST_SIZE, outDigest); + } + /* g. set DAA_session -> DAA_digest = NULL */ + if (rc == 0) { + TPM_Digest_Init(tpm_daa_session_data->DAA_session.DAA_digest); + } + /* h. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* i. return TPM_SUCCESS */ + free(NE); /* @1 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage09_Sign_Stage2(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + unsigned char *Y = NULL; /* freed @1 */ + TPM_BIGNUM yBignum = NULL; /* freed @2 */ + TPM_BIGNUM xBignum = NULL; /* freed @3 */ + TPM_BIGNUM nBignum = NULL; /* freed @4 */ + TPM_BIGNUM rBignum = NULL; /* freed @5 */ + + printf("TPM_DAAJoin_Stage09_Sign_Stage2:\n"); + tpm_state = tpm_state; /* not used */ + outputData = outputData; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==9. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific ||DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_R0 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_R0) == DAA_issuerSettings -> DAA_digest_R0 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage09_Sign_Stage2: Checking DAA_generic_R0\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_R0, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_R0 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage09_Sign_Stage2: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Obtain random data from the RNG and store it as DAA_session -> DAA_contextSeed */ + if (rc == 0) { + rc = TPM_Nonce_Generate(tpm_daa_session_data->DAA_session.DAA_contextSeed); + } + /* i. Obtain DAA_SIZE_r0 bytes using the MGF1 function and label them Y. "r0" || DAA_session -> + DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage09_Sign_Stage2: Creating Y\n"); + rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ + DAA_SIZE_r0, /* size of Y */ + /* length of the entire seed */ + sizeof("r0") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r0") -1, "r0", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r0); + } + /* j. Set X = DAA_generic_R0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage09_Sign_Stage2: Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* k. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage09_Sign_Stage2: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* l. Set DAA_session -> DAA_scratch = (X^Y) mod n */ + if (rc == 0) { + rc = TPM_ComputeAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + &rBignum, /* R */ + xBignum, /* A */ + yBignum, /* P */ + nBignum); /* n */ + + } + /* m. set outputData = NULL */ + /* NOTE Done by caller */ + /* n. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* o. return TPM_SUCCESS */ + free(Y); /* @1 */ + TPM_BN_free(yBignum); /* @2 */ + TPM_BN_free(xBignum); /* @3 */ + TPM_BN_free(nBignum); /* @4 */ + TPM_BN_free(rBignum); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage10_Sign_Stage3(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + unsigned char *Y= NULL; /* freed @1 */ + TPM_BIGNUM xBignum = NULL; /* freed @2 */ + TPM_BIGNUM nBignum = NULL; /* freed @3 */ + TPM_BIGNUM zBignum = NULL; /* freed @4 */ + TPM_BIGNUM yBignum = NULL; /* freed @5*/ + + printf("TPM_DAAJoin_Stage10_Sign_Stage3:\n"); + tpm_state = tpm_state; /* not used */ + outputData = outputData; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==10. Return TPM_DAA_STAGE and flush handle on mismatch + h */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_R1 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_R1) == DAA_issuerSettings -> DAA_digest_R1 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage10_Sign_Stage3: Checking DAA_generic_R1\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_R1, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_R1 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage10_Sign_Stage3: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Obtain DAA_SIZE_r1 bytes using the MGF1 function and label them Y. "r1" || DAA_session -> + DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage10_Sign_Stage3: Creating Y\n"); + rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ + DAA_SIZE_r1, /* size of Y */ + /* length of the entire seed */ + sizeof("r1") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r1") -1, "r1", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r1); + } + /* i. Set X = DAA_generic_R1 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage10_Sign_Stage3: Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* j. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage10_Sign_Stage3: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* k. Set Z = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage10_Sign_Stage3: Creating Z\n"); + rc = TPM_bin2bn(&zBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ + if (rc == 0) { + rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + zBignum, /* Z */ + xBignum, /* A */ + yBignum, /* P */ + nBignum); /* N */ + } + /* m. set outputData = NULL */ + /* NOTE Done by caller */ + /* n. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* o. return TPM_SUCCESS */ + free(Y); /* @1 */ + TPM_BN_free(xBignum); /* @2 */ + TPM_BN_free(nBignum); /* @3 */ + TPM_BN_free(zBignum); /* @4 */ + TPM_BN_free(yBignum); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage11_Sign_Stage4(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + unsigned char *Y= NULL; /* freed @1 */ + TPM_BIGNUM yBignum = NULL; /* freed @2 */ + TPM_BIGNUM xBignum = NULL; /* freed @3 */ + TPM_BIGNUM nBignum = NULL; /* freed @4 */ + TPM_BIGNUM zBignum = NULL; /* freed @5 */ + + printf("TPM_DAAJoin_Stage11_Sign_Stage4:\n"); + tpm_state = tpm_state; /* not used */ + outputData = outputData; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==11. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_S0 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_S0) == DAA_issuerSettings -> DAA_digest_S0 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage11_Sign_Stage4: Checking DAA_generic_S0\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S0, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_S0 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage11_Sign_Stage4: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Obtain DAA_SIZE_r2 bytes using the MGF1 function and label them Y. "r2" || DAA_session -> + DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage11_Sign_Stage4: Creating Y\n"); + rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ + DAA_SIZE_r2, /* size of Y */ + /* length of the entire seed */ + sizeof("r2") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r2") -1, "r2", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r2); + } + /* i. Set X = DAA_generic_S0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage11_Sign_Stage4: Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* j. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage11_Sign_Stage4: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* k. Set Z = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage11_Sign_Stage4: Creating Z\n"); + rc = TPM_bin2bn(&zBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ + if (rc == 0) { + rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + zBignum, /* Z */ + xBignum, /* A */ + yBignum, /* P */ + nBignum); /* N */ + } + /* m. set outputData = NULL */ + /* NOTE Done by caller */ + /* n. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* o. return TPM_SUCCESS */ + free(Y); /* @1 */ + TPM_BN_free(yBignum); /* @2 */ + TPM_BN_free(xBignum); /* @3 */ + TPM_BN_free(nBignum); /* @4 */ + TPM_BN_free(zBignum); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage12(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + unsigned char *Y = NULL; /* freed @1 */ + TPM_BIGNUM yBignum = NULL; /* freed @2 */ + TPM_BIGNUM xBignum = NULL; /* freed @3 */ + TPM_BIGNUM nBignum = NULL; /* freed @4 */ + TPM_BIGNUM zBignum = NULL; /* freed @5 */ + + printf("TPM_DAAJoin_Stage12:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==12. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings ) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_S1 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_S1) == DAA_issuerSettings -> DAA_digest_S1 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage12: Checking DAA_generic_S1\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S1, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_S1 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage12: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Obtain DAA_SIZE_r3 bytes using the MGF1 function and label them Y. "r3" || DAA_session -> + DAA_contextSeed) is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage12: Creating Y\n"); + rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ + DAA_SIZE_r3, /* size of Y */ + /* length of the entire seed */ + sizeof("r3") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r3") -1, "r3", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r3); + } + /* i. Set X = DAA_generic_S1 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage12: Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* j. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage12: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* k. Set Z = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage12: Creating Z\n"); + rc = TPM_bin2bn(&zBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ + if (rc == 0) { + rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + zBignum, /* Z */ + xBignum, /* A */ + yBignum, /* P */ + nBignum); /* N */ + } + /* m. set outputData = DAA_session -> DAA_scratch */ + if (rc == 0) { + rc = TPM_SizedBuffer_Set(outputData, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + tpm_daa_session_data->DAA_session.DAA_scratch); + } + /* n. Set DAA_session -> DAA_scratch = NULL */ + if (rc == 0) { + tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; + } + /* o. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* p. return TPM_SUCCESS */ + free(Y); /* @1 */ + TPM_BN_free(yBignum); /* @2 */ + TPM_BN_free(xBignum); /* @3 */ + TPM_BN_free(nBignum); /* @4 */ + TPM_BN_free(zBignum); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage13_Sign_Stage6(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + TPM_BIGNUM wBignum = NULL; /* freed @1 */ + TPM_BIGNUM qBignum = NULL; /* freed @2 */ + TPM_BIGNUM nBignum = NULL; /* freed @3 */ + TPM_BIGNUM w1Bignum = NULL; /* freed @4 */ + + printf("TPM_DAAJoin_Stage13_Sign_Stage6:\n"); + tpm_state = tpm_state; /* not used */ + outputData = outputData; /* not used */ + /* a. Verify that DAA_session->DAA_stage==13. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_gamma = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_gamma) == DAA_issuerSettings -> DAA_digest_gamma and return + error TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage13_Sign_Stage6: Checking DAA_generic_gamma\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_gamma, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_gamma */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Verify that inputSize1 == DAA_SIZE_w and return error TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + if (inputData1->size != DAA_SIZE_w) { + printf("TPM_DAAJoin_Stage13_Sign_Stage6: Error, inputData1 size %u should be %u\n", + inputData0->size, DAA_SIZE_w); + rc = TPM_DAA_INPUT_DATA1; + } + } + /* g. Set w = inputData1 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage13_Sign_Stage6: Creating w\n"); + rc = TPM_bin2bn(&wBignum, inputData1->buffer, inputData1->size); + } + /* FIXME added Set q = DAA_issuerSettings -> DAA_generic_q */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage13_Sign_Stage6: Creating q from DAA_generic_q\n"); + rc = TPM_bin2bn(&qBignum, + tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q, + sizeof(tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q)); + } + /* FIXME Set n = DAA_generic_gamma */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage13_Sign_Stage6: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData0->buffer, inputData0->size); + } + /* h. Set w1 = w^( DAA_issuerSettings -> DAA_generic_q) mod (DAA_generic_gamma) */ + /* FIXME w1 = (w^q) mod n */ + if (rc == 0) { + rc = TPM_ComputeAexpPmodn(NULL, + 0, + &w1Bignum, /* R */ + wBignum, /* A */ + qBignum, /* P */ + nBignum); /* n */ + } + /* i. If w1 != 1 (unity), return error TPM_DAA_WRONG_W */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage13_Sign_Stage6: Testing w1\n"); + rc = TPM_BN_is_one(w1Bignum); + } + /* j. Set DAA_session -> DAA_scratch = w */ + if (rc == 0) { + rc = TPM_ComputeDAAScratch(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + wBignum); + } + /* k. set outputData = NULL */ + /* NOTE Done by caller */ + /* l. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* m. return TPM_SUCCESS. */ + TPM_BN_free(wBignum); /* @1 */ + TPM_BN_free(qBignum); /* @2 */ + TPM_BN_free(nBignum); /* @3 */ + TPM_BN_free(w1Bignum); /* @4 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage14_Sign_Stage7(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + TPM_BIGNUM fBignum = NULL; /* freed @1 */ + TPM_BIGNUM wBignum = NULL; /* freed @2 */ + TPM_BIGNUM nBignum = NULL; /* freed @3 */ + TPM_BIGNUM eBignum = NULL; /* freed @4 */ + + unsigned int numBytes; /* for debug */ + + printf("TPM_DAAJoin_Stage14_Sign_Stage7:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==14. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings ) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_gamma = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_gamma) == DAA_issuerSettings -> DAA_digest_gamma and return + error TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage14_Sign_Stage7: Checking DAA_generic_gamma\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_gamma, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_gamma */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || + SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod + DAA_issuerSettings -> DAA_generic_q. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage14_Sign_Stage7: Creating f\n"); + rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @1 */ + } + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, fBignum); + printf("TPM_DAAJoin_Stage14_Sign_Stage7: f. f size %u\n", numBytes); + } + /* FIXME Set W = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage14_Sign_Stage7: Creating W\n"); + rc = TPM_bin2bn(&wBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, wBignum); + printf("TPM_DAAJoin_Stage14_Sign_Stage7: W size %u\n", numBytes); + } + /* FIXME Set n = DAA_generic_gamma */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage14_Sign_Stage7: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData0->buffer, inputData0->size); + } + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, nBignum); + printf("TPM_DAAJoin_Stage14_Sign_Stage7: n size %u\n", numBytes); + } + /* g. Set E = ((DAA_session -> DAA_scratch)^f) mod (DAA_generic_gamma). */ + /* FIXME E = (w^f) mod n */ + if (rc == 0) { + rc = TPM_ComputeAexpPmodn(NULL, + 0, + &eBignum, /* R */ + wBignum, /* A */ + fBignum, /* P */ + nBignum); /* n */ + } + /* h. Set outputData = E */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage14_Sign_Stage7: Output E\n"); + rc = TPM_bn2binMalloc(&(outputData->buffer), + &(outputData->size), + eBignum, 0); + } + /* i. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* j. return TPM_SUCCESS. */ + TPM_BN_free(fBignum); /* @1 */ + TPM_BN_free(wBignum); /* @2 */ + TPM_BN_free(nBignum); /* @3 */ + TPM_BN_free(eBignum); /* @4 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage15_Sign_Stage8(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *r0 = NULL; /* freed @1 */ + unsigned char *r1 = NULL; /* freed @2 */ + TPM_BIGNUM r0Bignum = NULL; /* freed @3 */ + TPM_BIGNUM r1Bignum = NULL; /* freed @4 */ + TPM_BIGNUM r1sBignum = NULL; /* freed @5 */ + TPM_BIGNUM rBignum = NULL; /* freed @6 */ + TPM_BIGNUM e1Bignum = NULL; /* freed @7 */ + TPM_BIGNUM qBignum = NULL; /* freed @8 */ + TPM_BIGNUM nBignum = NULL; /* freed @9 */ + TPM_BIGNUM wBignum = NULL; /* freed @10 */ + + printf("TPM_DAAJoin_Stage15_Sign_Stage8:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==15. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_gamma = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_gamma) == DAA_issuerSettings -> DAA_digest_gamma and return + error TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage15_Sign_Stage8: Checking DAA_generic_gamma\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_gamma, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_gamma */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Obtain DAA_SIZE_r0 bytes using the MGF1 function and label them r0. "r0" || DAA_session + -> DAA_contextSeed) is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating r0\n"); + rc = TPM_MGF1_GenerateArray(&r0, /* returned MGF1 array */ + DAA_SIZE_r0, /* size of Y */ + /* length of the entire seed */ + sizeof("r0") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r0") -1, "r0", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r0Bignum, r0, DAA_SIZE_r0); + } + /* g. Obtain DAA_SIZE_r1 bytes using the MGF1 function and label them r1. "r1" || DAA_session + -> DAA_contextSeedis the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating r1\n"); + rc = TPM_MGF1_GenerateArray(&r1, /* returned MGF1 array */ + DAA_SIZE_r1, /* size of Y */ + /* length of the entire seed */ + sizeof("r1") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r1") -1, "r1", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r1Bignum, r1, DAA_SIZE_r1); + } + /* FIXME Set q = DAA_generic_q */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating n from DAA_generic_q\n"); + rc = TPM_bin2bn(&qBignum, + tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q, + sizeof(tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q)); + } + /* h. set r = r0 + 2^DAA_power0 * r1 mod (DAA_issuerSettings -> DAA_generic_q). */ + /* FIXME added parentheses + h. set r = (r0 + (2^DAA_power0 * r1)) mod (DAA_issuerSettings -> DAA_generic_q). + h. set r = (r0 + (2^DAA_power0 * r1)) mod q */ + if (rc == 0) { + rc = TPM_BN_lshift(&r1sBignum, /* result, freed @5 */ + r1Bignum, /* input */ + DAA_power0); /* n */ + } + if (rc == 0) { + rc = TPM_ComputeApBmodn(&rBignum, /* result, freed @6 */ + r0Bignum, /* A */ + r1sBignum, /* B */ + qBignum); /* n */ + } + /* FIXME Set n = DAA_generic_gamma */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating n1 from DAA_generic_gamma\n"); + rc = TPM_bin2bn(&nBignum, inputData0->buffer, inputData0->size); + } + /* FIXME Set w = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating w from DAA_scratch\n"); + rc = TPM_bin2bn(&wBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* i. set E1 = ((DAA_session -> DAA_scratch)^r) mod (DAA_generic_gamma). */ + /* (w ^ r) mod n */ + if (rc == 0) { + rc = TPM_ComputeAexpPmodn(NULL, + 0, + &e1Bignum, /* R */ + wBignum, /* A */ + rBignum, /* P */ + nBignum); /* n */ + } + /* j. Set DAA_session -> DAA_scratch = NULL */ + if (rc == 0) { + tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; + } + /* k. Set outputData = E1 */ + if (rc == 0) { + rc = TPM_bn2binMalloc(&(outputData->buffer), + &(outputData->size), + e1Bignum, 0); + } + /* l. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* m. return TPM_SUCCESS. */ + free(r0); /* @1 */ + free(r1); /* @2 */ + TPM_BN_free(r0Bignum); /* @3 */ + TPM_BN_free(r1Bignum); /* @4 */ + TPM_BN_free(r1sBignum); /* @5 */ + TPM_BN_free(rBignum); /* @6 */ + TPM_BN_free(e1Bignum); /* @7 */ + TPM_BN_free(qBignum); /* @8 */ + TPM_BN_free(nBignum); /* @9 */ + TPM_BN_free(wBignum); /* @10 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage16_Sign_Stage9(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *nt = NULL; /* freed @1 */ + + printf("TPM_DAAJoin_Stage16_Sign_Stage9:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==16. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Verify that inputSize0 == sizeOf(TPM_DIGEST) and return error TPM_DAA_INPUT_DATA0 on + mismatch */ + if (rc == 0) { + if (inputData0->size != TPM_DIGEST_SIZE) { + printf("TPM_DAAJoin_Stage16_Sign_Stage9: Error, inputData0 size %u should be %u\n", + inputData0->size, TPM_DIGEST_SIZE); + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Set DAA_session -> DAA_digest = inputData0 */ + if (rc == 0) { + /* e. Set DAA_session -> DAA_digest = inputData0 */ + /* NOTE: This step is unnecessary, since the value is overridden in g. */ + /* f. Obtain DAA_SIZE_NT bytes from the RNG and label them NT */ + rc = TPM_Malloc(&nt, DAA_SIZE_NT); + } + if (rc == 0) { + rc = TPM_Random(nt, DAA_SIZE_NT); + } + /* g. Set DAA_session -> DAA_digest to the SHA-1 ( DAA_session -> DAA_digest || NT ) */ + if (rc == 0) { + rc = TPM_SHA1(tpm_daa_session_data->DAA_session.DAA_digest, + inputData0->size, inputData0->buffer, /* e. DAA_session -> DAA_digest */ + DAA_SIZE_NT, nt, + 0, NULL); + } + /* h. Set outputData = NT */ + if (rc == 0) { + rc = TPM_SizedBuffer_Set(outputData, DAA_SIZE_NT, nt); + } + /* i. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* j. return TPM_SUCCESS. */ + free(nt); /* @1 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage17_Sign_Stage11(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData) +{ + TPM_RESULT rc = 0; + unsigned char *r0 = NULL; /* freed @1 */ + TPM_BIGNUM r0Bignum = NULL; /* freed @2 */ + TPM_BIGNUM fBignum = NULL; /* freed @3 */ + TPM_BIGNUM s0Bignum = NULL; /* freed @4 */ + TPM_BIGNUM cBignum = NULL; /* freed @5 */ + + printf("TPM_DAAJoin_Stage17_Sign_Stage11:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==17. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Obtain DAA_SIZE_r0 bytes using the MGF1 function and label them r0. "r0" || DAA_session + -> DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage17_Sign_Stage11: Creating r0\n"); + rc = TPM_MGF1_GenerateArray(&r0, /* returned MGF1 array */ + DAA_SIZE_r0, /* size of Y */ + /* length of the entire seed */ + sizeof("r0") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r0") -1, "r0", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r0Bignum, r0, DAA_SIZE_r0); + } + /* e. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || + SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod + DAA_issuerSettings -> DAA_generic_q. */ + if (rc == 0) { + rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @3 */ + } + /* f. Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0 bits of f) */ + if (rc == 0) { + rc = TPM_BN_mask_bits(fBignum, DAA_power0); /* f becomes f0 */ + } + /* FIXME Set c = DAA_session -> DAA_digest */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage17_Sign_Stage11: Creating c from DAA_session -> DAA_digest\n"); + rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); + } + /* g. Set s0 = r0 + (DAA_session -> DAA_digest) * f0 in Z. Compute over the integers. The + computation is not reduced with a modulus. */ + /* s0 = r0 + (c * f0) */ + if (rc == 0) { + rc = TPM_ComputeApBxC(&s0Bignum, /* result */ + r0Bignum, /* A */ + cBignum, /* B */ + fBignum); /* C */ + } + /* h. set outputData = s0 */ + if (rc == 0) { + rc = TPM_bn2binMalloc(&(outputData->buffer), + &(outputData->size), + s0Bignum, 0); + } + /* i. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* j. return TPM_SUCCESS */ + free(r0); /* @1 */ + TPM_BN_free(r0Bignum); /* @2 */ + TPM_BN_free(fBignum); /* @3 */ + TPM_BN_free(s0Bignum); /* @4 */ + TPM_BN_free(cBignum); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage18_Sign_Stage12(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData) +{ + TPM_RESULT rc = 0; + unsigned char *r1 = NULL; /* freed @1 */ + TPM_BIGNUM r1Bignum = NULL; /* freed @2 */ + TPM_BIGNUM fBignum = NULL; /* freed @3 */ + TPM_BIGNUM f1Bignum = NULL; /* freed @4 */ + TPM_BIGNUM s1Bignum = NULL; /* freed @5 */ + TPM_BIGNUM cBignum = NULL; /* freed @6 */ + + printf("TPM_DAAJoin_Stage18_Sign_Stage12:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==18. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Obtain DAA_SIZE_r1 bytes using the MGF1 function and label them r1. "r1" || DAA_session + -> DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage18_Sign_Stage12: Creating r1\n"); + rc = TPM_MGF1_GenerateArray(&r1, /* returned MGF1 array */ + DAA_SIZE_r1, /* size of Y */ + /* length of the entire seed */ + sizeof("r1") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r1") -1, "r1", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r1Bignum, r1, DAA_SIZE_r1); + } + /* e. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || + SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod + DAA_issuerSettings -> DAA_generic_q. */ + if (rc == 0) { + rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @3 */ + } + /* f. Shift f right by DAA_power0 bits (discard the lowest DAA_power0 bits) and label the result + f1 */ + if (rc == 0) { + rc = TPM_BN_rshift(&f1Bignum, fBignum, DAA_power0); /* f becomes f1 */ + } + /* FIXME Set c = DAA_session -> DAA_digest */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage18_Sign_Stage12: Creating c from DAA_session -> DAA_digest\n"); + rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); + } + /* g. Set s1 = r1 + (DAA_session -> DAA_digest)* f1 in Z. Compute over the integers. The + computation is not reduced with a modulus. */ + /* s1 = r1 + (c * f1) */ + if (rc == 0) { + rc = TPM_ComputeApBxC(&s1Bignum, /* result */ + r1Bignum, /* A */ + cBignum, /* B */ + f1Bignum); /* C */ + } + /* h. set outputData = s1 */ + if (rc == 0) { + rc = TPM_bn2binMalloc(&(outputData->buffer), + &(outputData->size), + s1Bignum, 0); + } + /* i. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* j. return TPM_SUCCESS */ + free(r1); /* @1 */ + TPM_BN_free(r1Bignum); /* @2 */ + TPM_BN_free(fBignum); /* @3 */ + TPM_BN_free(f1Bignum); /* @4 */ + TPM_BN_free(s1Bignum); /* @5 */ + TPM_BN_free(cBignum); /* @6 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage19(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData) +{ + TPM_RESULT rc = 0; + unsigned char *r2 = NULL; /* freed @1 */ + TPM_BIGNUM r2Bignum = NULL; /* freed @2 */ + TPM_BIGNUM s2Bignum = NULL; /* freed @3 */ + TPM_BIGNUM cBignum = NULL; /* freed @4 */ + TPM_BIGNUM u0Bignum = NULL; /* freed @5 */ + + printf("TPM_DAAJoin_Stage19:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==19. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Obtain DAA_SIZE_r2 bytes using the MGF1 function and label them r2. "r2" || DAA_session -> + DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage19: Creating r2\n"); + rc = TPM_MGF1_GenerateArray(&r2, /* returned MGF1 array */ + DAA_SIZE_r2, /* size of Y */ + /* length of the entire seed */ + sizeof("r2") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r2") -1, "r2", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r2Bignum, r2, DAA_SIZE_r2); + } + /* e. Set s2 = r2 + (DAA_session -> DAA_digest)*( DAA_joinSession -> DAA_join_u0) mod + 2^DAA_power1 (Erase all but the lowest DAA_power1 bits of s2) */ + /* FIXME Set c = DAA_session -> DAA_digest */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage19: Creating c from DAA_session -> DAA_digest\n"); + rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); + } + /* FIXME Set u0 = DAA_joinSession -> DAA_join_u0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage19: Creating u0 from DAA_joinSession -> DAA_join_u0\n"); + rc = TPM_bin2bn(&u0Bignum, + tpm_daa_session_data->DAA_joinSession.DAA_join_u0, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); + } + /* s2 = (r2 + c * u0) mod_pow */ + if (rc == 0) { + rc = TPM_ComputeApBxC(&s2Bignum, /* result */ + r2Bignum, /* A */ + cBignum, /* B */ + u0Bignum); /* C */ + } + if (rc == 0) { + rc = TPM_BN_mask_bits(s2Bignum, DAA_power1); + } + /* f. set outputData = s2 */ + if (rc == 0) { + rc = TPM_bn2binMalloc(&(outputData->buffer), + &(outputData->size), + s2Bignum, 0); + } + /* insure that outputData is DAA_power1 bits */ + if (rc == 0) { + rc = TPM_SizedBuffer_ComputeEnlarge(outputData, DAA_power1 / 8); + } + /* g. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* h. return TPM_SUCCESS */ + free(r2); /* @1 */ + TPM_BN_free(r2Bignum); /* @2 */ + TPM_BN_free(s2Bignum); /* @3 */ + TPM_BN_free(cBignum); /* @4 */ + TPM_BN_free(u0Bignum); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage20(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData) +{ + TPM_RESULT rc = 0; + unsigned char *r2 = NULL; /* freed @1 */ + TPM_BIGNUM r2Bignum = NULL; /* freed @2 */ + TPM_BIGNUM s12Bignum = NULL; /* freed @3 */ + TPM_BIGNUM s12sBignum = NULL; /* freed @4 */ + TPM_BIGNUM cBignum = NULL; /* freed @5 */ + TPM_BIGNUM u0Bignum = NULL; /* freed @6 */ + + unsigned int numBytes; /* just for debug */ + + printf("TPM_DAAJoin_Stage20:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==20. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Obtain DAA_SIZE_r2 bytes using the MGF1 function and label them r2. "r2" || DAA_session + -> DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage20: Creating r2\n"); + rc = TPM_MGF1_GenerateArray(&r2, /* returned MGF1 array */ + DAA_SIZE_r2, /* size of Y */ + /* length of the entire seed */ + sizeof("r2") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r2") -1, "r2", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r2Bignum, r2, DAA_SIZE_r2); + } + /* e. Set s12 = r2 + (DAA_session -> DAA_digest)*( DAA_joinSession -> DAA_join_u0) */ + /* FIXME Set c = DAA_session -> DAA_digest */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage20: Creating c from DAA_session -> DAA_digest\n"); + rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); + } + /* FIXME Set u0 = DAA_joinSession -> DAA_join_u0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage20: Creating u0 from DAA_joinSession -> DAA_join_u0\n"); + rc = TPM_bin2bn(&u0Bignum, + tpm_daa_session_data->DAA_joinSession.DAA_join_u0, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); + } + /* s12 = (r2 + c * u0) mod_pow */ + if (rc == 0) { + rc = TPM_ComputeApBxC(&s12Bignum, /* result */ + r2Bignum, /* A */ + cBignum, /* B */ + u0Bignum); /* C */ + } + /* FIXME for debug */ + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, s12Bignum); + printf("TPM_DAAJoin_Stage20: e. s12 size %u\n", numBytes); + } + /* f. Shift s12 right by DAA_power1 bit (discard the lowest DAA_power1 bits). */ + if (rc == 0) { + rc = TPM_BN_rshift(&s12sBignum, s12Bignum, DAA_power1); /* s12 becomes s12s */ + } + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, s12sBignum); + printf("TPM_DAAJoin_Stage20: f. s12 size %u\n", numBytes); + } + /* g. Set DAA_session -> DAA_scratch = s12 */ + if (rc == 0) { + rc = TPM_ComputeDAAScratch(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + s12sBignum); + } + /* h. Set outputData = DAA_session -> DAA_digest */ + if (rc == 0) { + rc = TPM_SizedBuffer_Set(outputData, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest); + } + /* i. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* j. return TPM_SUCCESS */ + free(r2); /* @1 */ + TPM_BN_free(r2Bignum); /* @2 */ + TPM_BN_free(s12Bignum); /* @3 */ + TPM_BN_free(s12sBignum); /* @4 */ + TPM_BN_free(cBignum); /* @5 */ + TPM_BN_free(u0Bignum); /* @6 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage21(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData) +{ + TPM_RESULT rc = 0; + unsigned char *r3 = NULL; /* freed @1 */ + TPM_BIGNUM r3Bignum = NULL; /* freed @2 */ + TPM_BIGNUM s3Bignum = NULL; /* freed @3 */ + TPM_BIGNUM cBignum = NULL; /* freed @4 */ + TPM_BIGNUM u1Bignum = NULL; /* freed @5 */ + TPM_BIGNUM s12Bignum = NULL; /* freed @6 */ + + unsigned int numBytes; /* just for debug */ + + printf("TPM_DAAJoin_Stage21:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==21. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Obtain DAA_SIZE_r3 bytes using the MGF1 function and label them r3. "r3" || DAA_session + -> DAA_contextSeed) is the Z seed. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage21: Creating r3\n"); + rc = TPM_MGF1_GenerateArray(&r3, /* returned MGF1 array */ + DAA_SIZE_r3, /* size of r3 */ + /* length of the entire seed */ + sizeof("r3") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r3") -1, "r3", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r3Bignum, r3, DAA_SIZE_r3); + } + /* just for debug */ + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, r3Bignum); + printf("TPM_DAAJoin_Stage21: r3 size %u\n", numBytes); + } + /* e. Set s3 = r3 + (DAA_session -> DAA_digest)*( DAA_joinSession -> DAA_join_u1) + (DAA_session + -> DAA_scratch). */ + /* FIXME Set c = DAA_session -> DAA_digest */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage21: Creating c from DAA_session -> DAA_digest\n"); + rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); + } + /* just for debug */ + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, cBignum); + printf("TPM_DAAJoin_Stage21: c size %u\n", numBytes); + } + /* FIXME Set u1 = DAA_joinSession -> DAA_join_u1 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage21: Creating u1 from DAA_joinSession -> DAA_join_u1\n"); + rc = TPM_bin2bn(&u1Bignum, + tpm_daa_session_data->DAA_joinSession.DAA_join_u1, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u1)); + } + /* just for debug */ + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, u1Bignum); + printf("TPM_DAAJoin_Stage21: u1 size %u\n", numBytes); + } + /* FIXME Set s12 = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage21: Creating s12 from DAA_session -> DAA_scratch\n"); + rc = TPM_bin2bn(&s12Bignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, s12Bignum); + printf("TPM_DAAJoin_Stage21: s12 size %u\n", numBytes); + } + /* s3 = r3 + c * u1 + s12 */ + if (rc == 0) { + rc = TPM_ComputeApBxCpD(&s3Bignum, /* freed by caller */ + r3Bignum, /* A */ + cBignum, /* B */ + u1Bignum, /* C */ + s12Bignum); /* D */ + } + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, s3Bignum); + printf("TPM_DAAJoin_Stage21: s3 size %u\n", numBytes); + } + /* f. Set DAA_session -> DAA_scratch = NULL */ + if (rc == 0) { + tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; + } + /* g. set outputData = s3 */ + if (rc == 0) { + rc = TPM_bn2binMalloc(&(outputData->buffer), + &(outputData->size), + s3Bignum, 0); + } + /* h. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* i. return TPM_SUCCESS */ + free(r3); /* @1 */ + TPM_BN_free(r3Bignum); /* @2 */ + TPM_BN_free(s3Bignum); /* @3 */ + TPM_BN_free(cBignum); /* @4 */ + TPM_BN_free(u1Bignum); /* @5 */ + TPM_BN_free(s12Bignum); /* @6 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage22(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + TPM_BIGNUM v10Bignum = NULL; /* freed @1 */ + TPM_BIGNUM v10sBignum = NULL; /* freed @2 */ + TPM_BIGNUM u0Bignum = NULL; /* freed @3 */ + TPM_BIGNUM u2Bignum = NULL; /* freed @4 */ + TPM_BIGNUM v0Bignum = NULL; /* freed @5 */ + TPM_DAA_SENSITIVE tpm_daa_sensitive; + + unsigned int numBytes; /* just for debug */ + + printf("TPM_DAAJoin_Stage22:\n"); + TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @6 */ + /* a. Verify that DAA_session ->DAA_stage==22. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Verify inputSize0 == DAA_SIZE_v0 and return error TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + if (inputData0->size != DAA_SIZE_v0) { + printf("TPM_DAAJoin_Stage22: Error, inputData0 size %u should be %u\n", + inputData0->size, DAA_SIZE_v0); + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Set u2 = inputData0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage22: Creating u2\n"); + rc = TPM_bin2bn(&u2Bignum, inputData0->buffer, inputData0->size); + } + /* f. Set v0 = u2 + (DAA_joinSession -> DAA_join_u0) mod 2^DAA_power1 (Erase all but the lowest + DAA_power1 bits of v0). */ + /* FIXME Set u0 = DAA_joinSession -> DAA_join_u0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage22: Creating u0 from DAA_joinSession -> DAA_join_u0\n"); + rc = TPM_bin2bn(&u0Bignum, + tpm_daa_session_data->DAA_joinSession.DAA_join_u0, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); + } + /* FIXME factor this? */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage22: Calculate v0\n"); + rc = TPM_BN_new(&v0Bignum); + } + /* v0 = u2 + u0 */ + if (rc == 0) { + rc = TPM_BN_add(v0Bignum, u2Bignum, u0Bignum); + } + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, v0Bignum); + printf("TPM_DAAJoin_Stage22: f. v0 size before mask %u\n", numBytes); + } + /* v0 = v0 mod 2^DAA_power1 */ + if (rc == 0) { + rc = TPM_BN_mask_bits(v0Bignum, DAA_power1); + } + if (rc == 0) { + rc = TPM_BN_num_bytes(&numBytes, v0Bignum); + printf("TPM_DAAJoin_Stage22: f. v0 size after mask %u\n", numBytes); + } + /* g. Set DAA_tpmSpecific -> DAA_digest_v0 = SHA-1(v0) */ + if (rc == 0) { + rc = TPM_SHA1_BignumGenerate(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v0, + v0Bignum, + (DAA_power1 + 7) / 8); /* canonicalize the number of + bytes */ + } + /* h. Set v10 = u2 + (DAA_joinSession -> DAA_join_u0) in Z. Compute over the integers. + The computation is not reduced with a modulus. */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage22: Calculate v10\n"); + rc = TPM_BN_new(&v10Bignum); + } + /* v0 = u2 + u0 */ + if (rc == 0) { + rc = TPM_BN_add(v10Bignum, u2Bignum, u0Bignum); + } + /* i. Shift v10 right by DAA_power1 bits (erase the lowest DAA_power1 bits). */ + if (rc == 0) { + rc = TPM_BN_rshift(&v10sBignum, v10Bignum, DAA_power1); + } + /* j. Set DAA_session -> DAA_scratch = v10 */ + if (rc == 0) { + rc = TPM_ComputeDAAScratch(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + v10sBignum); + } + /* k. Set outputData */ + /* i. Fill in TPM_DAA_BLOB with a type of TPM_RT_DAA_V0 and encrypt the v0 parameters using + TPM_PERMANENT_DATA -> daaBlobKey */ + /* Create a TPM_DAA_SENSITIVE structure */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage22: Create TPM_DAA_SENSITIVE\n"); + /* Set TPM_DAA_SENSITIVE -> internalData to v0Bignum */ + rc = TPM_bn2binMalloc(&(tpm_daa_sensitive.internalData.buffer), + &(tpm_daa_sensitive.internalData.size), + v0Bignum, 0); + } + if (rc == 0) { + rc = TPM_ComputeEncrypt(outputData, + tpm_state, + &tpm_daa_sensitive, + TPM_RT_DAA_V0); + } + /* l. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* m. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ + if (rc == 0) { + rc = TPM_DAADigestContext_GenerateDigestJoin + (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); + } + /* n. return TPM_SUCCESS */ + TPM_BN_free(v10Bignum); /* @1 */ + TPM_BN_free(v10sBignum); /* @2 */ + TPM_BN_free(u0Bignum); /* @3 */ + TPM_BN_free(u2Bignum); /* @4 */ + TPM_BN_free(v0Bignum); /* @5 */ + TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @6 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage23(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + TPM_BIGNUM u1Bignum = NULL; /* freed @1 */ + TPM_BIGNUM u3Bignum = NULL; /* freed @2 */ + TPM_BIGNUM v1Bignum = NULL; /* freed @3 */ + TPM_BIGNUM v10Bignum = NULL; /* freed @4 */ + TPM_DAA_SENSITIVE tpm_daa_sensitive; + + printf("TPM_DAAJoin_Stage23:\n"); + TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @5 */ + /* a. Verify that DAA_session ->DAA_stage==23. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Verify inputSize0 == DAA_SIZE_v1 and return error TPM_DAA_INPUT_DATA0 on */ + /* mismatch */ + if (rc == 0) { + if (inputData0->size != DAA_SIZE_v1) { + printf("TPM_DAAJoin_Stage23: Error, inputData0 size %u should be %u\n", + inputData0->size, DAA_SIZE_v1); + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Set u3 = inputData0 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage23: Creating u3\n"); + rc = TPM_bin2bn(&u3Bignum, inputData0->buffer, inputData0->size); + } + /* f. Set v1 = u3 + DAA_joinSession -> DAA_join_u1 + DAA_session -> DAA_scratch */ + /* FIXME Set u1 = DAA_joinSession -> DAA_join_u1 */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage23: Creating u1 from DAA_joinSession -> DAA_join_u1\n"); + rc = TPM_bin2bn(&u1Bignum, + tpm_daa_session_data->DAA_joinSession.DAA_join_u1, + sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u1)); + } + /* FIXME Set v10 = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage23: Creating v10\n"); + rc = TPM_bin2bn(&v10Bignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + if (rc == 0) { + rc = TPM_BN_new(&v1Bignum); + } + /* f. Set v1 = u3 + u1 + v10 */ + if (rc == 0) { + rc = TPM_BN_add(v1Bignum, u3Bignum, u1Bignum); + } + if (rc == 0) { + rc = TPM_BN_add(v1Bignum, v1Bignum,v10Bignum); + } + /* g. Set DAA_tpmSpecific -> DAA_digest_v1 = SHA-1(v1) */ + if (rc == 0) { + rc = TPM_SHA1_BignumGenerate(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v1, + v1Bignum, + DAA_SIZE_v1); /* canonicalize the number of bytes */ + } + /* h. Set outputData */ + /* i. Fill in TPM_DAA_BLOB with a type of TPM_RT_DAA_V1 and encrypt the v1 parameters using + TPM_PERMANENT_DATA -> daaBlobKey */ + /* Create a TPM_DAA_SENSITIVE structure */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage23: Create TPM_DAA_SENSITIVE\n"); + /* Set TPM_DAA_SENSITIVE -> internalData to v1Bignum */ + rc = TPM_bn2binMalloc(&(tpm_daa_sensitive.internalData.buffer), + &(tpm_daa_sensitive.internalData.size), + v1Bignum, 0); + } + if (rc == 0) { + rc = TPM_ComputeEncrypt(outputData, + tpm_state, + &tpm_daa_sensitive, + TPM_RT_DAA_V1); + } + + + /* i. Set DAA_session -> DAA_scratch = NULL */ + if (rc == 0) { + tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; + } + /* j. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* k. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ + if (rc == 0) { + rc = TPM_DAADigestContext_GenerateDigestJoin + (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); + } + /* l. return TPM_SUCCESS */ + TPM_BN_free(u1Bignum); /* @1 */ + TPM_BN_free(u3Bignum); /* @2 */ + TPM_BN_free(v1Bignum); /* @3 */ + TPM_BN_free(v10Bignum); /* @4 */ + TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAAJoin_Stage24(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData) +{ + TPM_RESULT rc = 0; + TPM_DAA_SENSITIVE tpm_daa_sensitive; + + printf("TPM_DAAJoin_Stage24:\n"); + TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @1 */ + /* a. Verify that DAA_session ->DAA_stage==24. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) + and return error TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. set outputData = enc(DAA_tpmSpecific) using TPM_PERMANENT_DATA -> daaBlobKey */ + /* Create a TPM_DAA_SENSITIVE structure */ + if (rc == 0) { + printf("TPM_DAAJoin_Stage24 Create TPM_DAA_SENSITIVE\n"); + /* Set TPM_DAA_SENSITIVE -> internalData to DAA_tpmSpecific */ + rc = TPM_SizedBuffer_SetStructure(&(tpm_daa_sensitive.internalData), + &(tpm_daa_session_data->DAA_tpmSpecific), + (TPM_STORE_FUNCTION_T)TPM_DAATpm_Store); + } + if (rc == 0) { + rc = TPM_ComputeEncrypt(outputData, + tpm_state, + &tpm_daa_sensitive, + TPM_RT_DAA_TPM); + } + /* e. return TPM_SUCCESS */ + TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @2 */ + return rc; +} + +TPM_RESULT TPM_DAASign_Stage00(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA **tpm_daa_session_data, /* returns entry in + array */ + TPM_BOOL *daaHandleValid, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + TPM_HANDLE daaHandle = 0; /* no preassigned handle */ + + printf("TPM_DAASign_Stage00:\n"); + /* a. Determine that sufficient resources are available to perform a TPM_DAA_Sign. */ + /* i. The TPM MUST support sufficient resources to perform one (1) + TPM_DAA_Join/TPM_DAA_Sign. The TPM MAY support addition TPM_DAA_Join/ TPM_DAA_Sign + sessions. */ + /* ii. The TPM may share internal resources between the DAA operations and other variable + resource requirements: */ + /* iii. If there are insufficient resources within the stored key pool (and one or more keys + need to be removed to permit the DAA operation to execute) return TPM_NOSPACE */ + /* iv. If there are insufficient resources within the stored session pool (and one or more + authorization or transport sessions need to be removed to permit the DAA operation to + execute), return TPM_RESOURCES. */ + if (rc == 0) { + rc = TPM_DaaSessions_GetNewHandle(tpm_daa_session_data, /* returns entry in array */ + &daaHandle, /* output */ + daaHandleValid, /* output */ + tpm_state->tpm_stclear_data.daaSessions); /* array */ + } + /* b. Set DAA_issuerSettings = inputData0 */ + if (rc == 0) { + stream = inputData0->buffer; + stream_size = inputData0->size; + rc = TPM_DAAIssuer_Load(&((*tpm_daa_session_data)->DAA_issuerSettings), + &stream, &stream_size); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* c. Verify that all fields in DAA_issuerSettings are present and return error + TPM_DAA_INPUT_DATA0 if not. */ + if (rc == 0) { + if (stream_size != 0) { + printf("TPM_DAASign_Stage00: Error, bad input0 size %u\n", inputData0->size); + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + /* d. set all fields in DAA_session = NULL */ + /* e. Assign new handle for session */ + /* NOTE Done by TPM_DaaSessions_GetNewHandle() */ + printf("TPM_DAASign_Stage00: handle %08x\n", (*tpm_daa_session_data)->daaHandle); + /* f. Set outputData to new handle */ + /* i. The handle in outputData is included the output HMAC. */ + rc = TPM_SizedBuffer_Append32(outputData, (*tpm_daa_session_data)->daaHandle); + } + /* g. set DAA_session -> DAA_stage = 1 */ + /* NOTE Done by common code */ + /* h. return TPM_SUCCESS */ + return rc; +} + +TPM_RESULT TPM_DAASign_Stage01(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + TPM_DAA_SENSITIVE tpm_daa_sensitive; + unsigned char *stream; + uint32_t stream_size; + + printf("TPM_DAASign_Stage01:\n"); + outputData = outputData; /* not used */ + TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @1 */ + /* a. Verify that DAA_session ->DAA_stage==1. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Set DAA_tpmSpecific = unwrap(inputData0) using TPM_PERMANENT_DATA -> daaBlobKey */ + if (rc == 0) { + rc = TPM_ComputeDecrypt(&tpm_daa_sensitive, /* output */ + tpm_state, /* decryption and HMAC keys */ + inputData0, /* encrypted stream */ + TPM_RT_DAA_TPM); /* resourceType expected */ + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + stream = tpm_daa_sensitive.internalData.buffer; + stream_size = tpm_daa_sensitive.internalData.size; + rc = TPM_DAATpm_Load(&(tpm_daa_session_data->DAA_tpmSpecific), &stream, &stream_size); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* c. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + + /* d. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific) */ + if (rc == 0) { + rc = TPM_SHA1_GenerateStructure(tpm_daa_session_data->DAA_session.DAA_digestContext, + &(tpm_daa_session_data->DAA_tpmSpecific), + (TPM_STORE_FUNCTION_T)TPM_DAATpm_Store); + } + /* e set outputData = NULL */ + /* NOTE Done by caller */ + /* f. set DAA_session -> DAA_stage =2 */ + /* NOTE Done by common code */ + /* g. return TPM_SUCCESS */ + TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @1 */ + return rc; +} + +TPM_RESULT TPM_DAASign_Stage05(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + unsigned char *Y = NULL; /* freed @1 */ + TPM_BIGNUM yBignum = NULL; /* freed @2 */ + TPM_BIGNUM xBignum = NULL; /* freed @3 */ + TPM_BIGNUM nBignum = NULL; /* freed @4 */ + TPM_BIGNUM zBignum = NULL; /* freed @5 */ + + printf("TPM_DAASign_Stage05:\n"); + tpm_state = tpm_state; /* not used */ + /* a. Verify that DAA_session ->DAA_stage==5. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error + TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_generic_S1 = inputData0 */ + /* e. Verify that SHA-1(DAA_generic_S1) == DAA_issuerSettings -> DAA_digest_S1 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAASign_Stage05: Checking DAA_generic_S1\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S1, /* expect */ + inputData0->size, inputData0->buffer, /* DAA_generic_S1 */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Set DAA_generic_n = inputData1 */ + /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + printf("TPM_DAASign_Stage05: Checking DAA_digest_n\n"); + rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ + inputData1->size, inputData1->buffer, /* DAA_generic_n */ + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* h. Obtain DAA_SIZE_r4 bytes using the MGF1 function and label them Y. "r4" || DAA_session -> + DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAASign_Stage05: Creating Y\n"); + rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ + DAA_SIZE_r4, /* size of Y */ + /* length of the entire seed */ + sizeof("r4") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r4") -1, "r4", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r4); + } + /* i. Set X = DAA_generic_S1 */ + if (rc == 0) { + printf("TPM_DAASign_Stage05 Creating X\n"); + rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); + } + /* j. Set n = DAA_generic_n */ + if (rc == 0) { + printf("TPM_DAASign_Stage05: Creating n\n"); + rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); + } + /* k. Set Z = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAASign_Stage05: Creating Z\n"); + rc = TPM_bin2bn(&zBignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ + if (rc == 0) { + rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + zBignum, /* Z */ + xBignum, /* A */ + yBignum, /* P */ + nBignum); /* N */ + } + /* m. set outputData = DAA_session -> DAA_scratch */ + if (rc == 0) { + rc = TPM_SizedBuffer_Set(outputData, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + tpm_daa_session_data->DAA_session.DAA_scratch); + } + /* n. set DAA_session -> DAA_scratch = NULL */ + if (rc == 0) { + tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; + } + /* o. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* p. return TPM_SUCCESS */ + free(Y); /* @1 */ + TPM_BN_free(yBignum); /* @2 */ + TPM_BN_free(xBignum); /* @3 */ + TPM_BN_free(nBignum); /* @4 */ + TPM_BN_free(zBignum); /* @5 */ + return rc; +} + +TPM_RESULT TPM_DAASign_Stage10(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + uint8_t selector; + TPM_BOOL parentPCRStatus; + TPM_KEY_HANDLE keyHandle; + TPM_KEY *identityKey = NULL; /* the key specified by keyHandle */ + + printf("TPM_DAASign_Stage10:\n"); + /* a. Verify that DAA_session ->DAA_stage==10. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error + TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Verify that inputSize0 == sizeOf(BYTE), and return error TPM_DAA_INPUT_DATA0 on + mismatch */ + /* e. Set selector = inputData0, verify that selector == 0 or 1, and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + stream = inputData0->buffer; + stream_size = inputData0->size; + rc = TPM_Load8(&selector, &stream, &stream_size); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + if (stream_size != 0) { + printf("TPM_DAASign_Stage10: Error, bad input0 size %u\n", inputData0->size); + rc = TPM_DAA_INPUT_DATA0; + } + } + if (rc == 0) { + printf("TPM_DAASign_Stage10: selector %u\n", selector); + switch (selector) { + case 1: + /* f. If selector == 1, verify that inputSize1 == sizeOf(TPM_DIGEST), and return error + TPM_DAA_INPUT_DATA1 on mismatch */ + if (rc == 0) { + if (inputData1->size != TPM_DIGEST_SIZE) { + printf("TPM_DAASign_Stage10: Error, bad input1 size %u\n", inputData1->size); + rc = TPM_DAA_INPUT_DATA1; + } + } + /* g. Set DAA_session -> DAA_digest to SHA-1 (DAA_session -> DAA_digest || 1 || + inputData1) */ + if (rc == 0) { + rc = TPM_SHA1(tpm_daa_session_data->DAA_session.DAA_digest, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest, + 1, &selector , + inputData1->size, inputData1->buffer, + 0, NULL); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + break; + case 0: + /* h. If selector == 0, verify that inputData1 is a handle to a TPM identity key (AIK), + and return error TPM_DAA_INPUT_DATA1 on mismatch */ + /* get the key handle */ + if (rc == 0) { + stream = inputData1->buffer; + stream_size = inputData1->size; + rc = TPM_Load32(&keyHandle, &stream, &stream_size); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* validate inputData1 */ + if (rc == 0) { + if (stream_size != 0) { + printf("TPM_DAASign_Stage10: Error, bad input1 size %u\n", inputData1->size); + rc = TPM_DAA_INPUT_DATA1; + } + } + /* get the key */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_GetKey(&identityKey, &parentPCRStatus, + tpm_state, keyHandle, + TRUE, /* read only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA1; + } + } + /* validate that it's an AIK */ + if (rc == 0) { + if (identityKey->keyUsage != TPM_KEY_IDENTITY) { + printf("TPM_DAASign_Stage10: Error, " + "key keyUsage %04hx must be TPM_KEY_IDENTITY\n", identityKey->keyUsage); + rc = TPM_DAA_INPUT_DATA1; + } + } + /* i. Set DAA_session -> DAA_digest to SHA-1 (DAA_session -> DAA_digest || 0 || n2) + where n2 is the modulus of the AIK */ + if (rc == 0) { + rc = TPM_SHA1(tpm_daa_session_data->DAA_session.DAA_digest, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest, + 1, &selector, + identityKey->pubKey.size, identityKey->pubKey.buffer, + 0, NULL); + } + break; + default: + printf("TPM_DAASign_Stage10: Error, bad selector %u\n", selector); + rc = TPM_DAA_INPUT_DATA0; + break; + } + } + /* j. Set outputData = DAA_session -> DAA_digest */ + if (rc == 0) { + rc = TPM_SizedBuffer_Set(outputData, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest); + } + /* k. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* l. return TPM_SUCCESS. */ + return rc; +} + +TPM_RESULT TPM_DAASign_Stage13(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *r2 = NULL; /* freed @1 */ + TPM_BIGNUM r2Bignum = NULL; /* freed @2 */ + TPM_BIGNUM s2Bignum = NULL; /* freed @3 */ + TPM_BIGNUM cBignum = NULL; /* freed @4 */ + TPM_BIGNUM v0Bignum = NULL; /* freed @5 */ + TPM_DAA_SENSITIVE tpm_daa_sensitive; + + printf("TPM_DAASign_Stage13:\n"); + TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @6 */ + /* a. Verify that DAA_session ->DAA_stage==13. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error + TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_private_v0= unwrap(inputData0) using TPM_PERMANENT_DATA -> daaBlobKey */ + if (rc == 0) { + printf("TPM_DAASign_Stage13: unwrapping to v0\n"); + rc = TPM_ComputeDecrypt(&tpm_daa_sensitive, /* output */ + tpm_state, /* decryption and HMAC keys */ + inputData0, /* encrypted stream */ + TPM_RT_DAA_V0); /* resourceType expected */ + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Verify that SHA-1(DAA_private_v0) == DAA_tpmSpecific -> DAA_digest_v0 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAASign_Stage13: Checking v0\n"); + rc = TPM_SHA1_SizedBufferCheck(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v0, + &(tpm_daa_sensitive.internalData), + (DAA_power1 + 7) / 8); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Obtain DAA_SIZE_r2 bytes from the MGF1 function and label them r2. "r2" || DAA_session -> + DAA_contextSeed) is the Z seed. */ + if (rc == 0) { + printf("TPM_DAASign_Stage13 Creating r2\n"); + rc = TPM_MGF1_GenerateArray(&r2, /* returned MGF1 array */ + DAA_SIZE_r2, /* size of Y */ + /* length of the entire seed */ + sizeof("r2") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r2") -1, "r2", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r2Bignum, r2, DAA_SIZE_r2); + } + /* g. Set s2 = r2 + (DAA_session -> DAA_digest)*( DAA_private_v0) mod 2^DAA_power1 */ + /* (erase all but the lowest DAA_power1 bits of s2) */ + /* FIXME Set c = DAA_session -> DAA_digest */ + if (rc == 0) { + printf("TPM_DAASign_Stage13: Creating c from DAA_session -> DAA_digest\n"); + rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); + } + /* FIXME Set v0 = DAA_private_v0 */ + if (rc == 0) { + rc = TPM_bin2bn(&v0Bignum, + tpm_daa_sensitive.internalData.buffer, + tpm_daa_sensitive.internalData.size); + } + /* s2 = r2 + c * v0 mod 2^DAA_power1 */ + if (rc == 0) { + rc = TPM_ComputeApBxC(&s2Bignum, /* result */ + r2Bignum, /* A */ + cBignum, /* B */ + v0Bignum); /* C */ + } + if (rc == 0) { + rc = TPM_BN_mask_bits(s2Bignum, DAA_power1); + } + /* h. set outputData = s2 */ + if (rc == 0) { + rc = TPM_bn2binMalloc(&(outputData->buffer), + &(outputData->size), + s2Bignum, 0); + } + /* i. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* j. return TPM_SUCCESS */ + free(r2); /* @1 */ + TPM_BN_free(r2Bignum); /* @2 */ + TPM_BN_free(s2Bignum); /* @3 */ + TPM_BN_free(cBignum); /* @4 */ + TPM_BN_free(v0Bignum); /* @5 */ + TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @6 */ + return rc; +} + +TPM_RESULT TPM_DAASign_Stage14(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *r2 = NULL; /* freed @1 */ + TPM_BIGNUM r2Bignum = NULL; /* freed @2 */ + TPM_BIGNUM s12Bignum = NULL; /* freed @3 */ + TPM_BIGNUM s12sBignum = NULL; /* freed @4 */ + TPM_BIGNUM cBignum = NULL; /* freed @5 */ + TPM_BIGNUM v0Bignum = NULL; /* freed @6 */ + TPM_DAA_SENSITIVE tpm_daa_sensitive; + + printf("TPM_DAASign_Stage14:\n"); + outputData = outputData; /* not used */ + TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @7 */ + /* a. Verify that DAA_session ->DAA_stage==14. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error + TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_private_v0= unwrap(inputData0) using TPM_PERMANENT_DATA -> daaBlobKey */ + if (rc == 0) { + rc = TPM_ComputeDecrypt(&tpm_daa_sensitive, /* output */ + tpm_state, /* decryption and HMAC keys */ + inputData0, /* encrypted stream */ + TPM_RT_DAA_V0); /* resourceType expected */ + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Verify that SHA-1(DAA_private_v0) == DAA_tpmSpecific -> DAA_digest_v0 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAASign_Stage14: Checking v0\n"); + rc = TPM_SHA1_SizedBufferCheck(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v0, + &(tpm_daa_sensitive.internalData), + (DAA_power1 + 7) / 8); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Obtain DAA_SIZE_r2 bytes from the MGF1 function and label them r2. "r2" || DAA_session -> + DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAASign_Stage14: Creating r2\n"); + rc = TPM_MGF1_GenerateArray(&r2, /* returned MGF1 array */ + DAA_SIZE_r2, /* size of Y */ + /* length of the entire seed */ + sizeof("r2") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r2") -1, "r2", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r2Bignum, r2, DAA_SIZE_r2); + } + /* g. Set s12 = r2 + (DAA_session -> DAA_digest)*(DAA_private_v0). */ + /* FIXME Set c = DAA_session -> DAA_digest */ + if (rc == 0) { + printf("TPM_DAASign_Stage14: Creating c from DAA_session -> DAA_digest\n"); + rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); + } + /* FIXME Set v0 = DAA_private_v0 */ + if (rc == 0) { + rc = TPM_bin2bn(&v0Bignum, + tpm_daa_sensitive.internalData.buffer, + tpm_daa_sensitive.internalData.size); + } + /* s12 = r2 + c * v0 */ + if (rc == 0) { + rc = TPM_ComputeApBxC(&s12Bignum, /* result */ + r2Bignum, /* A */ + cBignum, /* B */ + v0Bignum); /* C */ + } + /* h. Shift s12 right by DAA_power1 bits (erase the lowest DAA_power1 bits). */ + if (rc == 0) { + rc = TPM_BN_rshift(&s12sBignum, s12Bignum, DAA_power1); /* f becomes f1 */ + } + /* i. Set DAA_session -> DAA_scratch = s12 */ + if (rc == 0) { + rc = TPM_ComputeDAAScratch(tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), + s12sBignum); + } + /* j. set outputData = NULL */ + /* NOTE Done by caller */ + /* k. increment DAA_session -> DAA_stage by 1 */ + /* NOTE Done by common code */ + /* l. return TPM_SUCCESS */ + free(r2); /* @1 */ + TPM_BN_free(r2Bignum); /* @2 */ + TPM_BN_free(s12Bignum); /* @3 */ + TPM_BN_free(s12sBignum); /* @4 */ + TPM_BN_free(cBignum); /* @5 */ + TPM_BN_free(v0Bignum); /* @6 */ + TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @7 */ + return rc; +} + +TPM_RESULT TPM_DAASign_Stage15(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0) +{ + TPM_RESULT rc = 0; + unsigned char *r4 = NULL; /* freed @1 */ + TPM_BIGNUM r4Bignum = NULL; /* freed @2 */ + TPM_BIGNUM s3Bignum = NULL; /* freed @3 */ + TPM_BIGNUM cBignum = NULL; /* freed @4 */ + TPM_BIGNUM v1Bignum = NULL; /* freed @5 */ + TPM_BIGNUM s12Bignum = NULL; /* freed @6 */ + TPM_DAA_SENSITIVE tpm_daa_sensitive; + + printf("TPM_DAASign_Stage15:\n"); + TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @7 */ + /* a. Verify that DAA_session ->DAA_stage==15. Return TPM_DAA_STAGE and flush handle on + mismatch */ + /* NOTE Done by common code */ + /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return + error TPM_DAA_ISSUER_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error + TPM_DAA_TPM_SETTINGS on mismatch */ + /* NOTE Done by common code */ + /* d. Set DAA_private_v1 = unwrap(inputData0) using TPM_PERMANENT_DATA -> daaBlobKey */ + if (rc == 0) { + rc = TPM_ComputeDecrypt(&tpm_daa_sensitive, /* output */ + tpm_state, /* decryption and HMAC keys */ + inputData0, /* encrypted stream */ + TPM_RT_DAA_V1); /* resourceType expected */ + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* e. Verify that SHA-1(DAA_private_v1) == DAA_tpmSpecific -> DAA_digest_v1 and return error + TPM_DAA_INPUT_DATA0 on mismatch */ + if (rc == 0) { + printf("TPM_DAASign_Stage15: Checking v1\n"); + rc = TPM_SHA1_SizedBufferCheck(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v1, + &(tpm_daa_sensitive.internalData), + DAA_SIZE_v1); + if (rc != 0) { + rc = TPM_DAA_INPUT_DATA0; + } + } + /* f. Obtain DAA_SIZE_r4 bytes from the MGF1 function and label them r4. "r4" || DAA_session -> + DAA_contextSeed is the Z seed. */ + if (rc == 0) { + printf("TPM_DAASign_Stage15: Creating r4\n"); + rc = TPM_MGF1_GenerateArray(&r4, /* returned MGF1 array */ + DAA_SIZE_r4, /* size of Y */ + /* length of the entire seed */ + sizeof("r4") -1 + + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + sizeof("r4") -1, "r4", + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), + tpm_daa_session_data->DAA_session.DAA_contextSeed, + 0, NULL); + } + if (rc == 0) { + rc = TPM_bin2bn(&r4Bignum, r4, DAA_SIZE_r4); + } + /* g. Set s3 = r4 + (DAA_session -> DAA_digest)*(DAA_private_v1) + (DAA_session -> + DAA_scratch). */ + /* FIXME Set c = DAA_session -> DAA_digest */ + if (rc == 0) { + printf("TPM_DAASign_Stage15: Creating c from DAA_session -> DAA_digest\n"); + rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); + } + /* FIXME Set v1 = DAA_private_v1 */ + if (rc == 0) { + rc = TPM_bin2bn(&v1Bignum, + tpm_daa_sensitive.internalData.buffer, + tpm_daa_sensitive.internalData.size); + } + /* FIXME Set s12 = DAA_session -> DAA_scratch */ + if (rc == 0) { + printf("TPM_DAASign_Stage15: Creating s12 from DAA_session -> DAA_scratch\n"); + rc = TPM_bin2bn(&s12Bignum, + tpm_daa_session_data->DAA_session.DAA_scratch, + sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); + } + /* s3 = r4 + c * v1 + s12 */ + if (rc == 0) { + rc = TPM_ComputeApBxCpD(&s3Bignum, /* freed by caller */ + r4Bignum, /* A */ + cBignum, /* B */ + v1Bignum, /* C */ + s12Bignum); /* D */ + } + /* h. Set DAA_session -> DAA_scratch = NULL */ + if (rc == 0) { + tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; + } + /* i. set outputData = s3 */ + if (rc == 0) { + rc = TPM_bn2binMalloc(&(outputData->buffer), + &(outputData->size), + s3Bignum, 0); + } + /* j. Terminate the DAA session and all resources associated with the DAA sign session + handle. */ + /* NOTE Done by caller */ + /* k. return TPM_SUCCESS */ + free(r4); /* @1 */ + TPM_BN_free(r4Bignum); /* @2 */ + TPM_BN_free(s3Bignum); /* @3 */ + TPM_BN_free(cBignum); /* @4 */ + TPM_BN_free(v1Bignum); /* @5 */ + TPM_BN_free(s12Bignum); /* @6 */ + TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @7 */ + return rc; +} + +/* + Stage Common Code +*/ + +/* TPM_DAADigestContext_GenerateDigestJoin() sets tpm_digest to SHA-1(DAA_tpmSpecific || + DAA_joinSession)) +*/ + +TPM_RESULT TPM_DAADigestContext_GenerateDigestJoin(TPM_DIGEST tpm_digest, + TPM_DAA_SESSION_DATA *tpm_daa_session_data) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* TPM_STORED_DATA serialization */ + + printf(" TPM_DAADigestContext_GenerateDigestJoin:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize DAA_tpmSpecific */ + if (rc == 0) { + rc = TPM_DAATpm_Store(&sbuffer, &(tpm_daa_session_data->DAA_tpmSpecific)); + } + /* serialize DAA_joinSession */ + if (rc == 0) { + rc = TPM_DAAJoindata_Store(&sbuffer, &(tpm_daa_session_data->DAA_joinSession)); + } + /* calculate and return the digest */ + if (rc == 0) { + rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_DAADigestContext_CheckDigestJoin() verifies that DAA_session -> DAA_digestContext == + SHA-1(DAA_tpmSpecific || DAA_joinSession). + + Returns TPM_DAA_TPM_SETTINGS on mismatch +*/ + +TPM_RESULT TPM_DAADigestContext_CheckDigestJoin(TPM_DAA_SESSION_DATA *tpm_daa_session_data) +{ + TPM_RESULT rc = 0; + TPM_DIGEST tpm_digest; /* actual digest */ + + printf(" TPM_DAADigestContext_CheckDigestJoin:\n"); + if (rc == 0) { + rc = TPM_DAADigestContext_GenerateDigestJoin(tpm_digest, tpm_daa_session_data); + } + if (rc == 0) { + rc = TPM_Digest_Compare(tpm_digest, tpm_daa_session_data->DAA_session.DAA_digestContext); + if (rc != 0) { + rc = TPM_DAA_TPM_SETTINGS; + } + } + return rc; +} + +/* TPM_ComputeF() computes the value F common to stages 4.j., 5.j., 14.f., 17.e., 18.e. + + j. Set f = SHA1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || + SHA1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) + mod DAA_issuerSettings -> DAA_generic_q +*/ + +TPM_RESULT TPM_ComputeF(TPM_BIGNUM *fBignum, /* freed by caller */ + TPM_DAA_SESSION_DATA *tpm_daa_session_data) +{ + TPM_RESULT rc = 0; + BYTE nZero = 0; + BYTE nOne = 1; + uint32_t nCount; /* DAA_count in nbo */ + TPM_DIGEST digest0; /* first SHA1 calculation */ + TPM_DIGEST digest1; /* second SHA1 calculation */ + TPM_BIGNUM dividend; /* digest0 || digest1 as a BIGNUM */ + TPM_BIGNUM modulus; /* DAA_generic_q as a BIGNUM */ + + printf(" TPM_ComputeF:\n"); + modulus = NULL; /* freed @1 */ + dividend = NULL; /* freed @2 */ + if (rc == 0) { + rc = TPM_BN_new(fBignum); + } + /* SHA1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) */ + if (rc == 0) { + printf(" TPM_ComputeF: Calculate digest0\n"); + nCount = htonl(tpm_daa_session_data->DAA_tpmSpecific.DAA_count); + rc = TPM_SHA1(digest0, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_tpmSpecific.DAA_rekey, + sizeof(uint32_t), &nCount, + sizeof(BYTE), &nZero, + 0, NULL); + } + /* SHA1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) */ + if (rc == 0) { + printf(" TPM_ComputeF: Calculate digest1\n"); + rc = TPM_SHA1(digest1, + TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_tpmSpecific.DAA_rekey, + sizeof(uint32_t), &nCount, + sizeof(BYTE), &nOne, + 0, NULL); + } + /* Construct digest0 || digest1 as a positive BIGNUM */ + if (rc == 0) { + rc = TPM_2bin2bn(÷nd, + digest0, TPM_DIGEST_SIZE, + digest1, TPM_DIGEST_SIZE); + } + /* DAA_generic_q as a positive BIGNUM */ + if (rc == 0) { + rc = TPM_bin2bn(&modulus, + tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q, + sizeof(tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q)); + } + /* digest mod DAA_generic_q */ + if (rc == 0) { + rc = TPM_BN_mod(*fBignum, dividend, modulus); + } + TPM_BN_free(modulus); /* @1 */ + TPM_BN_free(dividend); /* @2 */ + return rc; +} + +/* TPM_ComputeAexpPmodn() performs R = (A ^ P) mod n. + + rBignum is new'ed by this function and must be freed by the caller + + If DAA_scratch is not NULL, r is returned in DAA_scratch. +*/ + +TPM_RESULT TPM_ComputeAexpPmodn(BYTE *DAA_scratch, + uint32_t DAA_scratch_size, + TPM_BIGNUM *rBignum, /* freed by caller */ + TPM_BIGNUM aBignum, + TPM_BIGNUM pBignum, + TPM_BIGNUM nBignum) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ComputeAexpPmodn:\n"); + if (rc == 0) { + rc = TPM_BN_new(rBignum); + } + if (rc == 0) { + rc = TPM_BN_mod_exp(*rBignum, aBignum, pBignum, nBignum); + } + /* if the result should be returned in DAA_scratch */ + if ((rc == 0) && (DAA_scratch != NULL)) { + /* store the result in DAA_scratch */ + rc = TPM_ComputeDAAScratch(DAA_scratch, DAA_scratch_size, *rBignum); + } + return rc; +} + +/* TPM_ComputeZxAexpPmodn() performs DAA_scratch = Z * (A ^ P) mod n. + +*/ + +TPM_RESULT TPM_ComputeZxAexpPmodn(BYTE *DAA_scratch, + uint32_t DAA_scratch_size, + TPM_BIGNUM zBignum, + TPM_BIGNUM aBignum, + TPM_BIGNUM pBignum, + TPM_BIGNUM nBignum) +{ + TPM_RESULT rc = 0; + TPM_BIGNUM rBignum = NULL; /* freed @1 */ + + printf(" TPM_ComputeZxAexpPmodn:\n"); + if (rc == 0) { + printf(" TPM_ComputeZxAexpPmodn: Calculate R = A ^ P mod n\n"); + rc = TPM_ComputeAexpPmodn(NULL, /* DAA_scratch */ + 0, + &rBignum, /* R */ + aBignum, /* A */ + pBignum, + nBignum); + } + if (rc == 0) { + printf(" TPM_ComputeZxAexpPmodn: Calculate R = Z * R mod n\n"); + rc = TPM_BN_mod_mul(rBignum, zBignum, rBignum, nBignum); + } + /* store the result in DAA_scratch */ + if (rc == 0) { + rc = TPM_ComputeDAAScratch(DAA_scratch, DAA_scratch_size, rBignum); + } + TPM_BN_free(rBignum); /* @1 */ + return rc; +} + +/* TPM_ComputeApBmodn() performs R = A + B mod n + +*/ + +TPM_RESULT TPM_ComputeApBmodn(TPM_BIGNUM *rBignum, /* freed by caller */ + TPM_BIGNUM aBignum, + TPM_BIGNUM bBignum, + TPM_BIGNUM nBignum) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ComputeApBmodn:\n"); + if (rc == 0) { + rc = TPM_BN_new(rBignum); /* freed by caller */ + } + if (rc == 0) { + rc = TPM_BN_mod_add(*rBignum, aBignum, bBignum, nBignum); + } + return rc; +} + +/* TPM_ComputeApBxC() performs R = A + B * C + +*/ + +TPM_RESULT TPM_ComputeApBxC(TPM_BIGNUM *rBignum, /* freed by caller */ + TPM_BIGNUM aBignum, + TPM_BIGNUM bBignum, + TPM_BIGNUM cBignum) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ComputeApBxC:\n"); + if (rc == 0) { + rc = TPM_BN_new(rBignum); /* freed by caller */ + } + /* R = B * C */ + if (rc == 0) { + rc = TPM_BN_mul(*rBignum, bBignum, cBignum); + } + /* R = R + A */ + if (rc == 0) { + rc = TPM_BN_add(*rBignum, *rBignum, aBignum); + } + return rc; +} + +/* TPM_ComputeApBxCpD() performs R = A + B * C + D + +*/ + +TPM_RESULT TPM_ComputeApBxCpD(TPM_BIGNUM *rBignum, /* freed by caller */ + TPM_BIGNUM aBignum, + TPM_BIGNUM bBignum, + TPM_BIGNUM cBignum, + TPM_BIGNUM dBignum) +{ + TPM_RESULT rc = 0; + printf(" TPM_ComputeApBxCpD:\n"); + /* R = A + B * C */ + if (rc == 0) { + rc = TPM_ComputeApBxC(rBignum, /* freed by caller */ + aBignum, + bBignum, + cBignum); + } + /* R = R + D */ + if (rc == 0) { + rc = TPM_BN_add(*rBignum, *rBignum, dBignum); + } + return rc; +} + +/* TPM_ComputeDAAScratch() stores 'bn' in DAA_scratch + +*/ + +TPM_RESULT TPM_ComputeDAAScratch(BYTE *DAA_scratch, + uint32_t DAA_scratch_size, + TPM_BIGNUM bn) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ComputeDAAScratch:\n"); + if (rc == 0) { + rc = TPM_bn2binArray(DAA_scratch, DAA_scratch_size, bn); + } + return rc; +} + +/* TPM_ComputeEnlarge() creates a buffer of size 'outSize' + + It copies 'outSize - inSize' zero bytes and then appends 'in' + + 'out' must be freed by the caller +*/ + +TPM_RESULT TPM_ComputeEnlarge(unsigned char **out, /* freed by caller */ + uint32_t outSize, + unsigned char *in, + uint32_t inSize) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + if (outSize <= inSize) { + printf("TPM_ComputeEnlarge: Error (fatal), inSize %u outSize %u\n", inSize, outSize); + rc = TPM_FAIL; + } + } + if (rc == 0) { + rc = TPM_Malloc(out, outSize); + } + if (rc == 0) { + memset(*out, 0, outSize - inSize); /* zero left bytes */ + memcpy(*out + outSize - inSize, in, inSize); /* copy right bytes */ + } + return rc; +} + +/* TPM_SizedBuffer_ComputeEnlarge() forces 'tpm_sized_buffer' to be 'size' bytes in length. + + If generally useful, this function should be moved to tpm_sizedbuffer.c +*/ + +TPM_RESULT TPM_SizedBuffer_ComputeEnlarge(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size) +{ + TPM_RESULT rc = 0; + unsigned char *newPtr; /* new buffer, enlarged */ + + newPtr = NULL; /* freed by caller */ + /* if tpm_sized_buffer needs to be enlarged */ + if (tpm_sized_buffer->size != size) { + if (rc == 0) { + /* copy the TPM_SIZED_BUFFER data. enlarged, to newPtr */ + rc = TPM_ComputeEnlarge(&newPtr, size, /* output buffer */ + tpm_sized_buffer->buffer, + tpm_sized_buffer->size); + } + if (rc == 0) { + /* after the copy, the old buffer is no longer needed */ + free(tpm_sized_buffer->buffer); + /* assign the with the enlarged buffer to the TPM_SIZED_BUFFER */ + tpm_sized_buffer->buffer = newPtr; + /* update size */ + tpm_sized_buffer->size = size; + } + } + return rc; +} + +/* TPM_ComputeEncrypt() does join steps common to encrypting output data. + + It serializes the TPM_DAA_SENSITIVE, encrypts it to TPM_DAA_BLOB ->sensitiveData, adds the + resourceType, generates the TPM_DAA_BLOB -> blobIntegrity HMAC using daaProof, and serializes the + result to outputData. +*/ + +TPM_RESULT TPM_ComputeEncrypt(TPM_SIZED_BUFFER *outputData, + tpm_state_t *tpm_state, + TPM_DAA_SENSITIVE *tpm_daa_sensitive, + TPM_RESOURCE_TYPE resourceType) +{ + TPM_RESULT rc = 0; + TPM_DAA_BLOB tpm_daa_blob; + TPM_STORE_BUFFER daaSensitiveSbuffer; + + printf(" TPM_ComputeEncrypt:\n"); + TPM_DAABlob_Init(&tpm_daa_blob); /* freed @1 */ + TPM_Sbuffer_Init(&daaSensitiveSbuffer); /* freed @2 */ + + /* serialize the TPM_DAA_SENSITIVE */ + if (rc == 0) { + rc = TPM_DAASensitive_Store(&daaSensitiveSbuffer, tpm_daa_sensitive); + } + /* Create a TPM_DAA_BLOB structure */ + if (rc == 0) { + printf(" TPM_ComputeEncrypt: Create TPM_DAA_BLOB\n"); + tpm_daa_blob.resourceType = resourceType; + /* Set TPM_DAA_BLOB -> sensitiveData to the encryption of serialized TPM_DAA_SENSITIVE */ + rc = TPM_SymmetricKeyData_EncryptSbuffer + (&(tpm_daa_blob.sensitiveData), /* output buffer */ + &daaSensitiveSbuffer, /* input buffer */ + tpm_state->tpm_permanent_data.daaBlobKey); /* key */ + } + /* set TPM_DAA_BLOB -> blobIntegrity to the HMAC of TPM_DAA_BLOB using daaProof as the secret */ + if (rc == 0) { + rc = TPM_HMAC_GenerateStructure(tpm_daa_blob.blobIntegrity, /* HMAC */ + tpm_state->tpm_permanent_data.daaProof, /* HMAC key */ + &tpm_daa_blob, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_DAABlob_Store); /* store + function */ + } + /* ii. set outputData to the encrypted TPM_DAA_BLOB */ + if (rc == 0) { + rc = TPM_SizedBuffer_SetStructure(outputData, &tpm_daa_blob, + (TPM_STORE_FUNCTION_T )TPM_DAABlob_Store); + } + TPM_DAABlob_Delete(&tpm_daa_blob); /* @1 */ + TPM_Sbuffer_Delete(&daaSensitiveSbuffer); /* @2 */ + return rc; +} + +/* TPM_ComputeDecrypt() does sign steps common to decrypting input data + + It deserializes 'inputData" to a TPM_DAA_BLOB, and validates the resourceType and blobIntegrity + HMAC using daaProof. It decrypts TPM_DAA_BLOB ->sensitiveData and deserializes it to a + TPM_DAA_SENSITIVE. + + tpm_daa_sensitive must be deleted by the caller +*/ + +TPM_RESULT TPM_ComputeDecrypt(TPM_DAA_SENSITIVE *tpm_daa_sensitive, + tpm_state_t *tpm_state, + TPM_SIZED_BUFFER *inputData, + TPM_RESOURCE_TYPE resourceType) + +{ + TPM_RESULT rc = 0; + TPM_DAA_BLOB tpm_daa_blob; + unsigned char *stream; + uint32_t stream_size; + unsigned char *sensitiveStream; + uint32_t sensitiveStreamSize; + + printf(" TPM_ComputeDecrypt:\n"); + TPM_DAABlob_Init(&tpm_daa_blob); /* freed @1 */ + sensitiveStream = NULL; /* freed @2 */ + /* deserialize inputData to a TPM_DAA_BLOB */ + if (rc == 0) { + stream = inputData->buffer; + stream_size = inputData->size; + rc = TPM_DAABlob_Load(&tpm_daa_blob, &stream, &stream_size); + } + if (rc == 0) { + if (stream_size != 0) { + printf("TPM_ComputeDecrypt: Error, bad blob input size %u\n", inputData->size); + rc = TPM_DAA_INPUT_DATA0; + } + } + /* check blobIntegrity */ + if (rc == 0) { + rc = TPM_HMAC_CheckStructure(tpm_state->tpm_permanent_data.daaProof, /* HMAC key */ + &tpm_daa_blob, /* structure */ + tpm_daa_blob.blobIntegrity, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_DAABlob_Store, /* store function */ + TPM_DAA_INPUT_DATA0); /* error code */ + } + /* check resourceType */ + if (rc == 0) { + if (tpm_daa_blob.resourceType != resourceType) { + printf("TPM_ComputeDecrypt: Error, resourceType %08x\n", tpm_daa_blob.resourceType); + rc = TPM_DAA_INPUT_DATA0; + } + } + /* decrypt the TPM_DAA_BLOB -> sensitiveData */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_Decrypt + (&sensitiveStream, /* output, caller frees */ + &sensitiveStreamSize, /* output */ + tpm_daa_blob.sensitiveData.buffer, /* input */ + tpm_daa_blob.sensitiveData.size, /* input */ + tpm_state->tpm_permanent_data.daaBlobKey); /* dec key */ + } + if (rc == 0) { + stream = sensitiveStream; + stream_size = sensitiveStreamSize; + rc = TPM_DAASensitive_Load(tpm_daa_sensitive, &stream, &stream_size); + } + if (rc == 0) { + if (stream_size != 0) { + printf("TPM_ComputeDecrypt: Error, bad sensitive input size %u\n", sensitiveStreamSize); + rc = TPM_DAA_INPUT_DATA0; + } + } + TPM_DAABlob_Delete(&tpm_daa_blob); /* @1 */ + free(sensitiveStream); /* @2 */ + return rc; +} + +/* TPM_SHA1_BignumGenerate() converts the BIGNUM 'bn' to an array, enlarges the array to 'size', and + computes the SHA-1 hash + +*/ + +TPM_RESULT TPM_SHA1_BignumGenerate(TPM_DIGEST tpm_digest, + TPM_BIGNUM bn, + uint32_t size) +{ + TPM_RESULT rc = 0; + unsigned char *bin = NULL; /* freed @1 */ + unsigned int bytes; + unsigned char *newBin = NULL; /* freed @2, new buffer, enlarged */ + + if (rc == 0) { + rc = TPM_bn2binMalloc(&bin, &bytes, bn, 0); /* freed @1 */ + } + if (rc == 0) { + printf(" TPM_SHA1_BignumGenerate: enlarge to %u bytes, is %u bytes\n", size, bytes); + if (bytes != size) { + /* canonicalize the array size */ + if (rc == 0) { + rc = TPM_ComputeEnlarge(&newBin, size, /* output buffer */ + bin, bytes ); /* inout buffer */ + } + if (rc == 0) { + rc = TPM_SHA1(tpm_digest, + size, newBin, + 0, NULL); + } + } + else { + /* already canonicalized */ + rc = TPM_SHA1(tpm_digest, + bytes, bin, + 0, NULL); + } + } + free(bin); /* @1 */ + free(newBin); /* @2 */ + return rc; +} + +/* TPM_SHA1_SizedBufferCheck() enlarges the TPM_SIZED_BUFFER to 'size', computes the SHA-1 hash, + and validates the digest against 'tpm_digest' + + As a side effect, the TPM_SIZED_BUFFER may be enlarged. +*/ + +TPM_RESULT TPM_SHA1_SizedBufferCheck(TPM_DIGEST tpm_digest, + TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t size) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + printf(" TPM_SHA1_SizedBufferCheck: enlarge to %u bytes, is %u bytes\n", + size, tpm_sized_buffer->size); + if (tpm_sized_buffer->size != size) { + /* canonicalize the array size */ + rc = TPM_SizedBuffer_ComputeEnlarge(tpm_sized_buffer, size); + } + } + if (rc == 0) { + rc = TPM_SHA1_Check(tpm_digest, + tpm_sized_buffer->size, tpm_sized_buffer->buffer, + 0, NULL); + } + return rc; +} + +/* + Processing functions +*/ + +/* 26.1 TPM_DAA_Join rev 99 + + TPM_DAA_Join is the process that establishes the DAA parameters in the TPM for a specific DAA + issuing authority. + + outputSize and outputData are always included in the outParamDigest. This includes stage + 0, where the outputData contains the DAA session handle. +*/ + +TPM_RESULT TPM_Process_DAAJoin(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters*/ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_HANDLE daaHandle; /* Session handle */ + BYTE stage = 0; /* Processing stage of join */ + TPM_SIZED_BUFFER inputData0; /* Data to be used by this capability */ + TPM_SIZED_BUFFER inputData1; /* Data to be used by this capability */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Continue use flag, TRUE if handle is still + active */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and + owner. HMAC key: ownerAuth. */ + + /* processing */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_BOOL daaHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_DAA_SESSION_DATA *tpm_daa_session_data; /* DAA session for handle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER outputData; /* Data produced by this capability */ + + printf("TPM_Process_DAAJoin: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&inputData0); /* freed @1 */ + TPM_SizedBuffer_Init(&inputData1); /* freed @2 */ + TPM_SizedBuffer_Init(&outputData); /* freed @3 */ + /* + get inputs + */ + /* get handle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&daaHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get stage */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DAAJoin: daaHandle %08x\n", daaHandle); + returnCode = TPM_Load8(&stage, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DAAJoin: stage %u\n", stage); + /* For stages after stage 0, daaHandle is an input. Mark it valid so it can be terminated + on error. */ + if (stage > 0) { + daaHandleValid = TRUE; + } + /* get inputData0 */ + returnCode = TPM_SizedBuffer_Load(&inputData0, &command, ¶mSize); + } + /* get inputData1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&inputData1, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DAAJoin: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Use ownerAuth to verify that the Owner authorized all TPM_DAA_Join input parameters. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* + Common to most or all stages + */ + /* Validate the DAA session handle after stage 0, stage 0 assigns the handle */ + if (returnCode == TPM_SUCCESS) { + if (stage > 0) { + returnCode = + TPM_DaaSessions_GetEntry(&tpm_daa_session_data, /* returns entry in array */ + tpm_state->tpm_stclear_data.daaSessions, /* array */ + daaHandle); + } + } + /* Verify that the input state is consistent with the current TPM state */ + if (returnCode == TPM_SUCCESS) { + if (stage > 0) { + returnCode = TPM_DaaSessionData_CheckStage(tpm_daa_session_data, stage); + } + } + /* Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and + return error TPM_DAA_TPM_SETTINGS on mismatch */ + if (returnCode == TPM_SUCCESS) { + if (stage >= 1) { + returnCode = TPM_DAADigestContext_CheckDigestJoin(tpm_daa_session_data); + } + } + /* Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error + TPM_DAA_ISSUER_SETTINGS on mismatch */ + if (returnCode == TPM_SUCCESS) { + if (stage >= 3) { + returnCode = + TPM_SHA1_CheckStructure(tpm_daa_session_data->DAA_tpmSpecific.DAA_digestIssuer, + &(tpm_daa_session_data->DAA_issuerSettings), + (TPM_STORE_FUNCTION_T)TPM_DAAIssuer_Store, + TPM_DAA_ISSUER_SETTINGS); + } + } + /* Stages */ + if (returnCode == TPM_SUCCESS) { + switch (stage) { + case 0 : + returnCode = TPM_DAAJoin_Stage00(tpm_state, + &tpm_daa_session_data, /* entry in array */ + &daaHandleValid, + &outputData, &inputData0); + if (daaHandleValid) { + /* For stage 0, daaHandle may be generated. Extract it from the DAA session and + mark it valid, so the session can be terminated on error. */ + daaHandle = tpm_daa_session_data->daaHandle; + } + break; + case 1 : + returnCode = TPM_DAAJoin_Stage01(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 2 : + returnCode = TPM_DAAJoin_Stage02(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 3 : + returnCode = TPM_DAAJoin_Stage03(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0); + break; + case 4 : + returnCode = TPM_DAAJoin_Stage04(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 5 : + returnCode = TPM_DAAJoin_Stage05(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 6 : + returnCode = TPM_DAAJoin_Stage06(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 7 : + returnCode = TPM_DAAJoin_Stage07(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 8 : + returnCode = TPM_DAAJoin_Stage08(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0); + break; + case 9 : + returnCode = TPM_DAAJoin_Stage09_Sign_Stage2(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 10 : + returnCode = TPM_DAAJoin_Stage10_Sign_Stage3(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 11 : + returnCode = TPM_DAAJoin_Stage11_Sign_Stage4(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 12 : + returnCode = TPM_DAAJoin_Stage12(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 13 : + returnCode = TPM_DAAJoin_Stage13_Sign_Stage6(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0, &inputData1); + break; + case 14 : + returnCode = TPM_DAAJoin_Stage14_Sign_Stage7(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0); + break; + case 15 : + returnCode = TPM_DAAJoin_Stage15_Sign_Stage8(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0); + break; + case 16 : + returnCode = TPM_DAAJoin_Stage16_Sign_Stage9(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0); + break; + case 17 : + returnCode = TPM_DAAJoin_Stage17_Sign_Stage11(tpm_state, + tpm_daa_session_data, + &outputData); + break; + case 18 : + returnCode = TPM_DAAJoin_Stage18_Sign_Stage12(tpm_state, + tpm_daa_session_data, + &outputData); + break; + case 19 : + returnCode = TPM_DAAJoin_Stage19(tpm_state, + tpm_daa_session_data, + &outputData); + break; + case 20 : + returnCode = TPM_DAAJoin_Stage20(tpm_state, + tpm_daa_session_data, + &outputData); + break; + case 21 : + returnCode = TPM_DAAJoin_Stage21(tpm_state, + tpm_daa_session_data, + &outputData); + break; + case 22 : + returnCode = TPM_DAAJoin_Stage22(tpm_state, + tpm_daa_session_data, + &outputData, &inputData0); + break; + case 23 : + returnCode = TPM_DAAJoin_Stage23(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0); + break; + case 24 : + returnCode = TPM_DAAJoin_Stage24(tpm_state, + tpm_daa_session_data, + &outputData); + break; + default : + printf("TPM_Process_DAAJoin: Error, Illegal stage\n"); + returnCode = TPM_DAA_STAGE; + } + } + /* + Common to most or all stages + */ + if (returnCode == TPM_SUCCESS) { + if (stage >= 2) { + tpm_daa_session_data->DAA_session.DAA_stage++; + } + } + /* 24.e.Terminate the DAA session and all resources associated with the DAA join session + handle. */ + if (returnCode == TPM_SUCCESS) { + if (stage == 24) { + printf("TPM_Process_DAAJoin: Stage 24, terminating DAA session %08x\n", + tpm_daa_session_data->daaHandle); + TPM_DaaSessionData_Delete(tpm_daa_session_data); + } + } + /* 2. Any error return results in the TPM invalidating all resources associated with the + join */ + /* NOTE Done after response processing */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DAAJoin: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return outputData */ + returnCode = TPM_SizedBuffer_Store(response, &outputData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + /* no outParam's, set authorization response data */ + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* on error, terminate the DAA session */ + if (((rcf != 0) || (returnCode != TPM_SUCCESS)) && daaHandleValid) { + TPM_DaaSessions_TerminateHandle(tpm_state->tpm_stclear_data.daaSessions, + daaHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&inputData0); /* @1 */ + TPM_SizedBuffer_Delete(&inputData1); /* @2 */ + TPM_SizedBuffer_Delete(&outputData); /* @3 */ + return rcf; +} + +/* 26.2 TPM_DAA_Sign rev 99 + + TPM protected capability; user must provide authorizations from the TPM Owner. + + outputSize and outputData are always included in the outParamDigest. This includes stage + 0, where the outputData contains the DAA session handle. +*/ + +TPM_RESULT TPM_Process_DAASign(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters*/ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_HANDLE daaHandle; /* Handle to the sign session */ + BYTE stage = 0; /* Stage of the sign process */ + TPM_SIZED_BUFFER inputData0; /* Data to be used by this capability */ + TPM_SIZED_BUFFER inputData1; /* Data to be used by this capability */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Continue use flag, TRUE if handle is still + active */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and + owner. HMAC key: ownerAuth. */ + + /* processing */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_BOOL daaHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_DAA_SESSION_DATA *tpm_daa_session_data; /* DAA session for handle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER outputData; /* Data produced by this capability */ + + printf("TPM_Process_DAASign: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&inputData0); /* freed @1 */ + TPM_SizedBuffer_Init(&inputData1); /* freed @2 */ + TPM_SizedBuffer_Init(&outputData); /* freed @3 */ + /* + get inputs + */ + /* get handle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&daaHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get stage */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DAASign: daaHandle %08x\n", daaHandle); + returnCode = TPM_Load8(&stage, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DAASign: stage %u\n", stage); + /* For stages after stage 0, daaHandle is an input. Mark it valid so it can be terminated + on error. */ + if (stage > 0) { + daaHandleValid = TRUE; + } + /* get inputData0 */ + returnCode = TPM_SizedBuffer_Load(&inputData0, &command, ¶mSize); + } + /* get inputData1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&inputData1, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DAASign: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Use ownerAuth to verify that the Owner authorized all TPM_DAA_Sign input parameters. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* + Common to most or all stages + */ + /* Validate the DAA session handle after stage 0, stage 0 assigns the handle */ + if (returnCode == TPM_SUCCESS) { + if (stage > 0) { + returnCode = + TPM_DaaSessions_GetEntry(&tpm_daa_session_data, /* returns entry in array */ + tpm_state->tpm_stclear_data.daaSessions, /* array */ + daaHandle); + } + } + /* Verify that the input state is consistent with the current TPM state */ + if (returnCode == TPM_SUCCESS) { + if (stage > 0) { + returnCode = TPM_DaaSessionData_CheckStage(tpm_daa_session_data, stage); + } + } + /* Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error + TPM_DAA_TPM_SETTINGS on mismatch */ + if (returnCode == TPM_SUCCESS) { + if (stage >= 2) { + returnCode = + TPM_SHA1_CheckStructure(tpm_daa_session_data->DAA_session.DAA_digestContext, + &(tpm_daa_session_data->DAA_tpmSpecific), + (TPM_STORE_FUNCTION_T)TPM_DAATpm_Store, + TPM_DAA_TPM_SETTINGS); + } + } + /* Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error + TPM_DAA_ISSUER_SETTINGS on mismatch */ + if (returnCode == TPM_SUCCESS) { + if (stage >= 2) { + returnCode = + TPM_SHA1_CheckStructure(tpm_daa_session_data->DAA_tpmSpecific.DAA_digestIssuer, + &(tpm_daa_session_data->DAA_issuerSettings), + (TPM_STORE_FUNCTION_T)TPM_DAAIssuer_Store, + TPM_DAA_ISSUER_SETTINGS); + } + } + /* Stages */ + if (returnCode == TPM_SUCCESS) { + switch (stage) { + case 0 : + returnCode = TPM_DAASign_Stage00(tpm_state, + &tpm_daa_session_data, /* returns entry in array */ + &daaHandleValid, + &outputData, + &inputData0); + if (daaHandleValid) { + /* For stage 0, daaHandle may be generated. Extract it from the DAA session and + mark it valid, so the session can be terminated on error. */ + daaHandle = tpm_daa_session_data->daaHandle; + } + break; + case 1 : + returnCode = TPM_DAASign_Stage01(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0); + break; + case 2 : + returnCode = TPM_DAAJoin_Stage09_Sign_Stage2(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0, &inputData1); + break; + case 3 : + returnCode = TPM_DAAJoin_Stage10_Sign_Stage3(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0, &inputData1); + break; + case 4 : + returnCode = TPM_DAAJoin_Stage11_Sign_Stage4(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0, &inputData1); + break; + case 5 : + returnCode = TPM_DAASign_Stage05(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0, &inputData1); + break; + case 6 : + returnCode = TPM_DAAJoin_Stage13_Sign_Stage6(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0, &inputData1); + break; + case 7 : + returnCode = TPM_DAAJoin_Stage14_Sign_Stage7(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0); + break; + case 8 : + returnCode = TPM_DAAJoin_Stage15_Sign_Stage8(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0); + break; + case 9 : + returnCode = TPM_DAAJoin_Stage16_Sign_Stage9(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0); + break; + case 10 : + returnCode = TPM_DAASign_Stage10(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0, &inputData1); + break; + case 11 : + returnCode = TPM_DAAJoin_Stage17_Sign_Stage11(tpm_state, + tpm_daa_session_data, + &outputData); + break; + case 12 : + returnCode = TPM_DAAJoin_Stage18_Sign_Stage12(tpm_state, + tpm_daa_session_data, + &outputData); + break; + case 13 : + returnCode = TPM_DAASign_Stage13(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0); + break; + case 14 : + returnCode = TPM_DAASign_Stage14(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0); + break; + case 15 : + returnCode = TPM_DAASign_Stage15(tpm_state, + tpm_daa_session_data, + &outputData, + &inputData0); + break; + default : + printf("TPM_Process_DAASign: Error, Illegal stage\n"); + returnCode = TPM_DAA_STAGE; + } + } + /* + Common to most or all stages + */ + if (returnCode == TPM_SUCCESS) { + tpm_daa_session_data->DAA_session.DAA_stage++; + } + /* 15.j. Terminate the DAA session and all resources associated with the DAA sign session + handle. */ + if (returnCode == TPM_SUCCESS) { + if (stage == 15) { + printf("TPM_Process_DAASign: Stage 15, terminating DAA session %08x\n", + tpm_daa_session_data->daaHandle); + TPM_DaaSessionData_Delete(tpm_daa_session_data); + } + } + /* 2. Any error return results in the TPM invalidating all resources associated with the + join */ + /* NOTE Done after response processing */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DAASign: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return outputData */ + returnCode = TPM_SizedBuffer_Store(response, &outputData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + /* no outParam's, set authorization response data */ + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* on error, terminate the DAA session */ + if (((rcf != 0) || (returnCode != TPM_SUCCESS)) && daaHandleValid) { + TPM_DaaSessions_TerminateHandle(tpm_state->tpm_stclear_data.daaSessions, + daaHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&inputData0); /* @1 */ + TPM_SizedBuffer_Delete(&inputData1); /* @2 */ + TPM_SizedBuffer_Delete(&outputData); /* @3 */ + return rcf; +} diff --git a/src/tpm12/tpm_daa.h b/src/tpm12/tpm_daa.h new file mode 100644 index 0000000..ae37a34 --- /dev/null +++ b/src/tpm12/tpm_daa.h @@ -0,0 +1,405 @@ +/********************************************************************************/ +/* */ +/* DAA Functions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_daa.h 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_DAA_H +#define TPM_DAA_H + +#include "tpm_global.h" +#include "tpm_store.h" + +/* + TPM_DAA_SESSION_DATA (the entire array) +*/ + + +void TPM_DaaSessions_Init(TPM_DAA_SESSION_DATA *daaSessions); +TPM_RESULT TPM_DaaSessions_Load(TPM_DAA_SESSION_DATA *daaSessions, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DaaSessions_Store(TPM_STORE_BUFFER *sbuffer, + TPM_DAA_SESSION_DATA *daaSessions); +void TPM_DaaSessions_Delete(TPM_DAA_SESSION_DATA *daaSessions); + +void TPM_DaaSessions_IsSpace(TPM_BOOL *isSpace, + uint32_t *index, + TPM_DAA_SESSION_DATA *daaSessions); +void TPM_DaaSessions_GetSpace(uint32_t *space, + TPM_DAA_SESSION_DATA *daaSessions); +TPM_RESULT TPM_DaaSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, + TPM_DAA_SESSION_DATA *daaSessions); +TPM_RESULT TPM_DaaSessions_GetNewHandle(TPM_DAA_SESSION_DATA **tpm_daa_session_data, + TPM_HANDLE *daaHandle, + TPM_BOOL *daaHandleValid, + TPM_DAA_SESSION_DATA *daaSessions); +TPM_RESULT TPM_DaaSessions_GetEntry(TPM_DAA_SESSION_DATA **tpm_daa_session_data, + TPM_DAA_SESSION_DATA *daaSessions, + TPM_HANDLE daaHandle); +TPM_RESULT TPM_DaaSessions_AddEntry(TPM_HANDLE *tpm_handle, + TPM_BOOL keepHandle, + TPM_DAA_SESSION_DATA *daaSessions, + TPM_DAA_SESSION_DATA *tpm_daa_session_data); +TPM_RESULT TPM_DaaSessions_TerminateHandle(TPM_DAA_SESSION_DATA *daaSessions, + TPM_HANDLE daaHandle); + + +/* + TPM_DAA_SESSION_DATA (one element of the array) +*/ + +void TPM_DaaSessionData_Init(TPM_DAA_SESSION_DATA *tpm_daa_session_data); +TPM_RESULT TPM_DaaSessionData_Load(TPM_DAA_SESSION_DATA *tpm_daa_session_data, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DaaSessionData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_SESSION_DATA *tpm_daa_session_data); +void TPM_DaaSessionData_Delete(TPM_DAA_SESSION_DATA *tpm_daa_session_data); + +void TPM_DaaSessionData_Copy(TPM_DAA_SESSION_DATA *dest_daa_session_data, + TPM_HANDLE tpm_handle, + TPM_DAA_SESSION_DATA *src_daa_session_data); +TPM_RESULT TPM_DaaSessionData_CheckStage(TPM_DAA_SESSION_DATA *tpm_daa_session_data, + BYTE stage); + +/* + TPM_DAA_ISSUER +*/ + +void TPM_DAAIssuer_Init(TPM_DAA_ISSUER *tpm_daa_issuer); +TPM_RESULT TPM_DAAIssuer_Load(TPM_DAA_ISSUER *tpm_daa_issuer, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DAAIssuer_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_ISSUER *tpm_daa_issuer); +void TPM_DAAIssuer_Delete(TPM_DAA_ISSUER *tpm_daa_issuer); + +void TPM_DAAIssuer_Copy(TPM_DAA_ISSUER *dest_daa_issuer, + TPM_DAA_ISSUER *src_daa_issuer); + +/* + TPM_DAA_TPM +*/ + +void TPM_DAATpm_Init(TPM_DAA_TPM *tpm_daa_tpm); +TPM_RESULT TPM_DAATpm_Load(TPM_DAA_TPM *tpm_daa_tpm, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DAATpm_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_TPM *tpm_daa_tpm); +void TPM_DAATpm_Delete(TPM_DAA_TPM *tpm_daa_tpm); + +void TPM_DAATpm_Copy(TPM_DAA_TPM *dest_daa_tpm, TPM_DAA_TPM *src_daa_tpm); + +/* + TPM_DAA_CONTEXT +*/ + +void TPM_DAAContext_Init(TPM_DAA_CONTEXT *tpm_daa_context); +TPM_RESULT TPM_DAAContext_Load(TPM_DAA_CONTEXT *tpm_daa_context, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DAAContext_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_CONTEXT *tpm_daa_context); +void TPM_DAAContext_Delete(TPM_DAA_CONTEXT *tpm_daa_context); + +void TPM_DAAContext_Copy(TPM_DAA_CONTEXT *dest_daa_context, TPM_DAA_CONTEXT *src_daa_context); + +/* + TPM_DAA_JOINDATA +*/ + +void TPM_DAAJoindata_Init(TPM_DAA_JOINDATA *tpm_daa_joindata); +TPM_RESULT TPM_DAAJoindata_Load(TPM_DAA_JOINDATA *tpm_daa_joindata, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DAAJoindata_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_JOINDATA *tpm_daa_joindata); +void TPM_DAAJoindata_Delete(TPM_DAA_JOINDATA *tpm_daa_joindata); + +void TPM_DAAJoindata_Copy(TPM_DAA_JOINDATA *dest_daa_joindata, + TPM_DAA_JOINDATA *src_daa_joindata); + +/* + TPM_DAA_BLOB +*/ + +void TPM_DAABlob_Init(TPM_DAA_BLOB *tpm_daa_blob); +TPM_RESULT TPM_DAABlob_Load(TPM_DAA_BLOB *tpm_daa_blob, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DAABlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_BLOB *tpm_daa_blob); +void TPM_DAABlob_Delete(TPM_DAA_BLOB *tpm_daa_blob); + +/* + TPM_DAA_SENSITIVE +*/ + +void TPM_DAASensitive_Init(TPM_DAA_SENSITIVE *tpm_daa_sensitive); +TPM_RESULT TPM_DAASensitive_Load(TPM_DAA_SENSITIVE *tpm_daa_sensitive, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DAASensitive_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DAA_SENSITIVE *tpm_daa_sensitive); +void TPM_DAASensitive_Delete(TPM_DAA_SENSITIVE *tpm_daa_sensitive); + +/* + Stage Common Code +*/ + +TPM_RESULT TPM_DAADigestContext_GenerateDigestJoin(TPM_DIGEST tpm_digest, + TPM_DAA_SESSION_DATA *tpm_daa_session_data); +TPM_RESULT TPM_DAADigestContext_CheckDigestJoin(TPM_DAA_SESSION_DATA *tpm_daa_session_data); + +TPM_RESULT TPM_DAASession_CheckStage(TPM_DAA_SESSION_DATA *tpm_daa_session_data, + BYTE stage); +TPM_RESULT TPM_ComputeF(TPM_BIGNUM *fBignum, + TPM_DAA_SESSION_DATA *tpm_daa_session_data); +TPM_RESULT TPM_ComputeAexpPmodn(BYTE *DAA_scratch, + uint32_t DAA_scratch_size, + TPM_BIGNUM *rBignum, + TPM_BIGNUM xBignum, + TPM_BIGNUM fBignum, + TPM_BIGNUM nBignum); +TPM_RESULT TPM_ComputeZxAexpPmodn(BYTE *DAA_scratch, + uint32_t DAA_scratch_size, + TPM_BIGNUM zBignum, + TPM_BIGNUM aBignum, + TPM_BIGNUM pBignum, + TPM_BIGNUM nBignum); +TPM_RESULT TPM_ComputeApBmodn(TPM_BIGNUM *rBignum, + TPM_BIGNUM aBignum, + TPM_BIGNUM bBignum, + TPM_BIGNUM nBignum); +TPM_RESULT TPM_ComputeApBxC(TPM_BIGNUM *rBignum, + TPM_BIGNUM aBignum, + TPM_BIGNUM bBignum, + TPM_BIGNUM cBignum); +TPM_RESULT TPM_ComputeApBxCpD(TPM_BIGNUM *rBignum, + TPM_BIGNUM aBignum, + TPM_BIGNUM bBignum, + TPM_BIGNUM cBignum, + TPM_BIGNUM dBignum); +TPM_RESULT TPM_ComputeDAAScratch(BYTE *DAA_scratch, + uint32_t DAA_scratch_size, + TPM_BIGNUM bn); +TPM_RESULT TPM_ComputeEnlarge(unsigned char **out, + uint32_t outSize, + unsigned char *in, + uint32_t inSize); +TPM_RESULT TPM_SizedBuffer_ComputeEnlarge(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size); +TPM_RESULT TPM_ComputeEncrypt(TPM_SIZED_BUFFER *outputData, + tpm_state_t *tpm_state, + TPM_DAA_SENSITIVE *tpm_daa_sensitive, + TPM_RESOURCE_TYPE resourceType); +TPM_RESULT TPM_ComputeDecrypt(TPM_DAA_SENSITIVE *tpm_daa_sensitive, + tpm_state_t *tpm_state, + TPM_SIZED_BUFFER *inputData, + TPM_RESOURCE_TYPE resourceType); + +TPM_RESULT TPM_SHA1_BignumGenerate(TPM_DIGEST tpm_digest, + TPM_BIGNUM bn, + uint32_t size); +TPM_RESULT TPM_SHA1_SizedBufferCheck(TPM_DIGEST tpm_digest, + TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t size); + +/* + Processing Common Functions +*/ + +TPM_RESULT TPM_DAAJoin_Stage00(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA **tpm_daa_session_data, + TPM_BOOL *daaHandleValid, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAAJoin_Stage01(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage02(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage03(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAAJoin_Stage04(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage05(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage06(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage07(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage08(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAAJoin_Stage09_Sign_Stage2(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage10_Sign_Stage3(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage11_Sign_Stage4(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage12(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage13_Sign_Stage6(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAAJoin_Stage14_Sign_Stage7(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAAJoin_Stage15_Sign_Stage8(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAAJoin_Stage16_Sign_Stage9(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAAJoin_Stage17_Sign_Stage11(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData); +TPM_RESULT TPM_DAAJoin_Stage18_Sign_Stage12(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData); +TPM_RESULT TPM_DAAJoin_Stage19(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData); +TPM_RESULT TPM_DAAJoin_Stage20(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData); +TPM_RESULT TPM_DAAJoin_Stage21(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData); +TPM_RESULT TPM_DAAJoin_Stage22(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAAJoin_Stage23(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAAJoin_Stage24(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData); + +TPM_RESULT TPM_DAASign_Stage00(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA **tpm_daa_session_data, + TPM_BOOL *daaHandleValid, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAASign_Stage01(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAASign_Stage05(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAASign_Stage10(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0, + TPM_SIZED_BUFFER *inputData1); +TPM_RESULT TPM_DAASign_Stage13(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAASign_Stage14(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); +TPM_RESULT TPM_DAASign_Stage15(tpm_state_t *tpm_state, + TPM_DAA_SESSION_DATA *tpm_daa_session_data, + TPM_SIZED_BUFFER *outputData, + TPM_SIZED_BUFFER *inputData0); + +/* + Processing functions +*/ + +TPM_RESULT TPM_Process_DAAJoin(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_DAASign(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +#endif diff --git a/src/tpm12/tpm_delegate.c b/src/tpm12/tpm_delegate.c new file mode 100644 index 0000000..37ebc02 --- /dev/null +++ b/src/tpm12/tpm_delegate.c @@ -0,0 +1,3944 @@ +/********************************************************************************/ +/* */ +/* Delegate Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_delegate.c 4580 2011-06-10 17:55:41Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_auth.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_key.h" +#include "tpm_pcr.h" +#include "tpm_permanent.h" +#include "tpm_process.h" +#include "tpm_secret.h" + +#include "tpm_delegate.h" + +/* + TPM_DELEGATE_PUBLIC +*/ + +/* TPM_DelegatePublic_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DelegatePublic_Init(TPM_DELEGATE_PUBLIC *tpm_delegate_public) +{ + printf(" TPM_DelegatePublic_Init:\n"); + tpm_delegate_public->rowLabel = 0; + TPM_PCRInfoShort_Init(&(tpm_delegate_public->pcrInfo)); + TPM_Delegations_Init(&(tpm_delegate_public->permissions)); + tpm_delegate_public->familyID = 0; + tpm_delegate_public->verificationCount = 0; + return; +} + +/* TPM_DelegatePublic_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + After use, call TPM_DelegatePublic_Delete() to free memory +*/ + +TPM_RESULT TPM_DelegatePublic_Load(TPM_DELEGATE_PUBLIC *tpm_delegate_public, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegatePublic_Load:\n"); + /* check the tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DELEGATE_PUBLIC, stream, stream_size); + } + /* load rowLabel */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_delegate_public->rowLabel), stream, stream_size); + } + /* load pcrInfo */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Load(&(tpm_delegate_public->pcrInfo), stream, stream_size, FALSE); + } + /* load permissions */ + if (rc == 0) { + rc = TPM_Delegations_Load(&(tpm_delegate_public->permissions), stream, stream_size); + } + /* load the familyID */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_delegate_public->familyID), stream, stream_size); + } + /* load the verificationCount */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_delegate_public->verificationCount), stream, stream_size); + } + return rc; +} + +/* TPM_DelegatePublic_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DelegatePublic_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_PUBLIC *tpm_delegate_public) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegatePublic_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_PUBLIC); + } + /* store rowLabel */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_delegate_public->rowLabel), + sizeof(TPM_DELEGATE_LABEL)); + } + /* store pcrInfo */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_delegate_public->pcrInfo), FALSE); + } + /* store permissions */ + if (rc == 0) { + rc = TPM_Delegations_Store(sbuffer, &(tpm_delegate_public->permissions)); + } + /* store familyID */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegate_public->familyID); + } + /* store verificationCount */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegate_public->verificationCount); + } + return rc; +} + +/* TPM_DelegatePublic_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DelegatePublic_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DelegatePublic_Delete(TPM_DELEGATE_PUBLIC *tpm_delegate_public) +{ + printf(" TPM_DeleteDelegatePublic:\n"); + if (tpm_delegate_public != NULL) { + TPM_PCRInfoShort_Delete(&(tpm_delegate_public->pcrInfo)); + TPM_Delegations_Delete(&(tpm_delegate_public->permissions)); + TPM_DelegatePublic_Init(tpm_delegate_public); + } + return; +} + +/* TPM_DelegatePublic_Copy() copies the 'src' to the 'dest' structure + +*/ + +TPM_RESULT TPM_DelegatePublic_Copy(TPM_DELEGATE_PUBLIC *dest, + TPM_DELEGATE_PUBLIC *src) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegatePublic_Copy:\n"); + if (rc == 0) { + /* copy rowLabel */ + dest->rowLabel = src->rowLabel; + /* copy pcrInfo */ + rc = TPM_PCRInfoShort_Copy(&(dest->pcrInfo), &(src->pcrInfo)); + } + if (rc == 0) { + /* copy permissions */ + TPM_Delegations_Copy(&(dest->permissions), &(src->permissions)); + /* copy familyID */ + dest->familyID = src->familyID; + /* copy verificationCount */ + dest->verificationCount = src->verificationCount; + } + return rc; +} + +/* + TPM_DELEGATE_SENSITIVE +*/ + +/* TPM_DelegateSensitive_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DelegateSensitive_Init(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive) +{ + printf(" TPM_DelegateSensitive_Init:\n"); + TPM_Secret_Init(tpm_delegate_sensitive->authValue); + return; +} + +/* TPM_DelegateSensitive_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + After use, call TPM_DelegateSensitive_Delete() to free memory +*/ + +TPM_RESULT TPM_DelegateSensitive_Load(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateSensitive_Load:\n"); + /* check the tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DELEGATE_SENSITIVE, stream, stream_size); + } + /* load authValue */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_delegate_sensitive->authValue, stream, stream_size); + } + return rc; +} + +/* TPM_DelegateSensitive_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DelegateSensitive_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateSensitive_Store:\n"); + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_SENSITIVE); + } + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_delegate_sensitive->authValue); + } + return rc; +} + +/* TPM_DelegateSensitive_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DelegateSensitive_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DelegateSensitive_Delete(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive) +{ + printf(" TPM_DeleteDelegateSensitive:\n"); + if (tpm_delegate_sensitive != NULL) { + TPM_DelegateSensitive_Init(tpm_delegate_sensitive); + } + return; +} + +/* TPM_DelegateSensitive_DecryptEncData() decrypts 'sensitiveArea' to a stream using 'delegateKey' + and then deserializes the stream to a TPM_DELEGATE_SENSITIVE +*/ + +TPM_RESULT TPM_DelegateSensitive_DecryptEncData(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive, + TPM_SIZED_BUFFER *sensitiveArea, + TPM_SYMMETRIC_KEY_TOKEN delegateKey) +{ + TPM_RESULT rc = 0; + unsigned char *s1; /* decrypted sensitive data */ + uint32_t s1_length; + unsigned char *stream; /* temp input stream */ + uint32_t stream_size; + + printf(" TPM_DelegateSensitive_DecryptEncData:\n"); + s1 = NULL; /* freed @1 */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_Decrypt(&s1, /* decrypted data */ + &s1_length, /* length decrypted data */ + sensitiveArea->buffer, + sensitiveArea->size, + delegateKey); + } + if (rc == 0) { + stream = s1; + stream_size = s1_length; + rc = TPM_DelegateSensitive_Load(tpm_delegate_sensitive, &stream, &stream_size); + } + free(s1); /* @1 */ + return rc; +} + +/* + TPM_DELEGATIONS +*/ + +/* TPM_Delegations_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_Delegations_Init(TPM_DELEGATIONS *tpm_delegations) +{ + printf(" TPM_Delegations_Init:\n"); + tpm_delegations->delegateType = TPM_DEL_KEY_BITS; /* any legal value */ + tpm_delegations->per1 = 0; + tpm_delegations->per2 = 0; + return; +} + +/* TPM_Delegations_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + After use, call TPM_DeleteDelegations() to free memory +*/ + +TPM_RESULT TPM_Delegations_Load(TPM_DELEGATIONS *tpm_delegations, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Delegations_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DELEGATIONS, stream, stream_size); + } + /* load delegateType */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_delegations->delegateType), stream, stream_size); + } + /* load per1 */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_delegations->per1), stream, stream_size); + } + /* load per2 */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_delegations->per2), stream, stream_size); + } + /* validate parameters */ + if (rc == 0) { + if (tpm_delegations->delegateType == TPM_DEL_OWNER_BITS) { + if (tpm_delegations->per1 & ~TPM_DELEGATE_PER1_MASK) { + printf("TPM_Delegations_Load: Error, owner per1 %08x\n", tpm_delegations->per1); + rc = TPM_BAD_PARAMETER; + } + if (tpm_delegations->per2 & ~TPM_DELEGATE_PER2_MASK) { + printf("TPM_Delegations_Load: Error, owner per2 %08x\n", tpm_delegations->per2); + rc = TPM_BAD_PARAMETER; + } + } + else if (tpm_delegations->delegateType == TPM_DEL_KEY_BITS) { + if (tpm_delegations->per1 & ~TPM_KEY_DELEGATE_PER1_MASK) { + printf("TPM_Delegations_Load: Error, key per1 %08x\n", tpm_delegations->per1); + rc = TPM_BAD_PARAMETER; + } + if (tpm_delegations->per2 & ~TPM_KEY_DELEGATE_PER2_MASK) { + printf("TPM_Delegations_Load: Error, key per2 %08x\n", tpm_delegations->per2); + rc = TPM_BAD_PARAMETER; + } + } + else { + printf("TPM_Delegations_Load: Error, delegateType %08x\n", + tpm_delegations->delegateType); + rc = TPM_BAD_PARAMETER; + } + } + return rc; +} + +/* TPM_Delegations_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_Delegations_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATIONS *tpm_delegations) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Delegations_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATIONS); + } + /* store delegateType */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->delegateType); + } + /* store per1 */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->per1); + } + /* store per2 */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->per2); + } + return rc; +} + +/* TPM_Delegations_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_Delegations_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_Delegations_Delete(TPM_DELEGATIONS *tpm_delegations) +{ + printf(" TPM_Delegations_Delete:\n"); + if (tpm_delegations != NULL) { + TPM_Delegations_Init(tpm_delegations); + } + return; +} + +/* TPM_Delegations_Copy() copies the source to the destination + */ + +void TPM_Delegations_Copy(TPM_DELEGATIONS *dest, + TPM_DELEGATIONS *src) +{ + dest->delegateType = src->delegateType; + dest->per1 = src->per1; + dest->per2 = src->per2; + return; +} + +/* TPM_Delegations_CheckPermissionDelegation() verifies that the new delegation bits do not grant + more permissions then currently delegated. Otherwise return error TPM_AUTHFAIL. + + An error occurs if a bit is set in newDelegations -> per and clear in currentDelegations -> per +*/ + +TPM_RESULT TPM_Delegations_CheckPermissionDelegation(TPM_DELEGATIONS *newDelegations, + TPM_DELEGATIONS *currentDelegations) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Delegations_CheckPermissionDelegation:\n"); + /* check per1 */ + if (rc == 0) { + if (newDelegations->per1 & ~currentDelegations->per1) { + printf("TPM_Delegations_CheckPermissionDelegation: Error, " + "new per1 %08x current per1 %08x\n", + newDelegations->per1, currentDelegations->per1); + rc = TPM_AUTHFAIL; + } + } + /* check per2 */ + if (rc == 0) { + if (newDelegations->per2 & ~currentDelegations->per2) { + printf("TPM_Delegations_CheckPermissionDelegation: Error, " + "new per1 %08x current per1 %08x\n", + newDelegations->per1, currentDelegations->per1); + rc = TPM_AUTHFAIL; + } + } + return rc; +} + +/* TPM_Delegations_CheckPermission() verifies that the 'ordinal' has been delegated for execution + based on the TPM_DELEGATE_PUBLIC. + + It verifies that the TPM_DELEGATIONS is appropriate for the entityType. Currently, only key or + owner authorization can be delegated. + + It verifies that the TPM_DELEGATE_PUBLIC PCR's allow the delegation. +*/ + +TPM_RESULT TPM_Delegations_CheckPermission(tpm_state_t *tpm_state, + TPM_DELEGATE_PUBLIC *delegatePublic, + TPM_ENT_TYPE entityType, /* required */ + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Delegations_CheckPermission: ordinal %08x\n", ordinal); + if (rc == 0) { + switch (entityType) { + case TPM_ET_KEYHANDLE: + rc = TPM_Delegations_CheckKeyPermission(&(delegatePublic->permissions), ordinal); + break; + case TPM_ET_OWNER: + rc = TPM_Delegations_CheckOwnerPermission(&(delegatePublic->permissions), ordinal); + break; + default: + printf("TPM_Delegations_CheckPermission: Error, " + "DSAP session does not support entity type %02x\n", + entityType); + rc = TPM_AUTHFAIL; + break; + } + } + /* check that the TPM_DELEGATE_PUBLIC PCR's allow the delegation */ + if (rc == 0) { + rc = TPM_PCRInfoShort_CheckDigest(&(delegatePublic->pcrInfo), + tpm_state->tpm_stclear_data.PCRS, + tpm_state->tpm_stany_flags.localityModifier); + } + return rc; +} + +/* TPM_Delegations_CheckOwnerPermission() verifies that the 'ordinal' has been delegated for + execution based on the TPM_DELEGATIONS. +*/ + +TPM_RESULT TPM_Delegations_CheckOwnerPermission(TPM_DELEGATIONS *tpm_delegations, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + uint16_t ownerPermissionBlock; /* 0:unused, 1:per1 2:per2 */ + uint32_t ownerPermissionPosition; /* owner permission bit position */ + + printf(" TPM_Delegations_CheckOwnerPermission: ordinal %08x\n", ordinal); + /* check that the TPM_DELEGATIONS structure is the correct type */ + if (rc == 0) { + if (tpm_delegations->delegateType != TPM_DEL_OWNER_BITS) { + printf("TPM_Delegations_CheckOwnerPermission: Error," + "Ordinal requires owner auth but delegateType is %08x\n", + tpm_delegations->delegateType); + rc = TPM_AUTHFAIL; + } + } + /* get the block and position in the block from the ordinals table */ + if (rc == 0) { + rc = TPM_OrdinalTable_GetOwnerPermission(&ownerPermissionBlock, + &ownerPermissionPosition, + ordinal); + } + /* check that the permission bit is set in the TPM_DELEGATIONS bit map */ + if (rc == 0) { + printf(" TPM_Delegations_CheckOwnerPermission: block %u position %u\n", + ownerPermissionBlock, ownerPermissionPosition); + switch (ownerPermissionBlock) { + case 1: /* per1 */ + if (!(tpm_delegations->per1 & (1 << ownerPermissionPosition))) { + printf("TPM_Delegations_CheckOwnerPermission: Error, per1 %08x\n", + tpm_delegations->per1); + rc = TPM_AUTHFAIL; + } + break; + case 2: /* per2 */ + if (!(tpm_delegations->per2 & (1 << ownerPermissionPosition))) { + printf("TPM_Delegations_CheckOwnerPermission: Error, per2 %08x\n", + tpm_delegations->per2); + rc = TPM_AUTHFAIL; + } + break; + default: + printf("TPM_Delegations_CheckOwnerPermission: Error, block not 1 or 2\n"); + rc = TPM_AUTHFAIL; + break; + } + } + return rc; +} + +/* TPM_Delegations_CheckKeyPermission() verifies that the 'ordinal' has been delegated for + execution based on the TPM_DELEGATIONS. +*/ + +TPM_RESULT TPM_Delegations_CheckKeyPermission(TPM_DELEGATIONS *tpm_delegations, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + uint16_t keyPermissionBlock; /* 0:unused, 1:per1 2:per2 */ + uint32_t keyPermissionPosition; /* key permission bit position */ + + printf(" TPM_Delegations_CheckKeyPermission: ordinal %08x\n", ordinal); + /* check that the TPM_DELEGATIONS structure is the correct type */ + if (rc == 0) { + if (tpm_delegations->delegateType != TPM_DEL_KEY_BITS) { + printf("TPM_Delegations_CheckKeyPermission: Error," + "Ordinal requires key auth but delegateType is %08x\n", + tpm_delegations->delegateType); + rc = TPM_AUTHFAIL; + } + } + /* get the block and position in the block from the ordinals table */ + if (rc == 0) { + rc = TPM_OrdinalTable_GetKeyPermission(&keyPermissionBlock, + &keyPermissionPosition, + ordinal); + } + /* check that the permission bit is set in the TPM_DELEGATIONS bit map */ + if (rc == 0) { + printf(" TPM_Delegations_CheckKeyPermission: block %u position %u\n", + keyPermissionBlock, keyPermissionPosition); + switch (keyPermissionBlock) { + case 1: /* per1 */ + if (!(tpm_delegations->per1 & (1 << keyPermissionPosition))) { + printf("TPM_Delegations_CheckKeyPermission: Error, per1 %08x\n", + tpm_delegations->per1); + rc = TPM_AUTHFAIL; + } + break; + case 2: /* per2 */ + if (!(tpm_delegations->per2 & (1 << keyPermissionPosition))) { + printf("TPM_Delegations_CheckKeyPermission: Error, per2 %08x\n", + tpm_delegations->per2); + rc = TPM_AUTHFAIL; + } + break; + default: + printf("TPM_Delegations_CheckKeyPermission: Error, block not 1 or 2\n"); + rc = TPM_AUTHFAIL; + break; + } + } + return rc; +} + +/* + TPM_DELEGATE_OWNER_BLOB +*/ + +/* TPM_DelegateOwnerBlob_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DelegateOwnerBlob_Init(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob) +{ + printf(" TPM_DelegateOwnerBlob_Init:\n"); + TPM_DelegatePublic_Init(&(tpm_delegate_owner_blob->pub)); + TPM_Digest_Init(tpm_delegate_owner_blob->integrityDigest); + TPM_SizedBuffer_Init(&(tpm_delegate_owner_blob->additionalArea)); + TPM_SizedBuffer_Init(&(tpm_delegate_owner_blob->sensitiveArea)); + return; +} + +/* TPM_DelegateOwnerBlob_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DelegateOwnerBlob_Init() + After use, call TPM_DelegateOwnerBlob_Delete() to free memory +*/ + +TPM_RESULT TPM_DelegateOwnerBlob_Load(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateOwnerBlob_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DELEGATE_OWNER_BLOB, stream, stream_size); + } + /* load pub */ + if (rc == 0) { + rc = TPM_DelegatePublic_Load(&(tpm_delegate_owner_blob->pub), stream, stream_size); + } + /* check that permissions are owner */ + if (rc == 0) { + if (tpm_delegate_owner_blob->pub.permissions.delegateType != TPM_DEL_OWNER_BITS) { + printf("TPM_DelegateOwnerBlob_Load: Error, delegateType expected %08x found %08x\n", + TPM_DEL_OWNER_BITS, tpm_delegate_owner_blob->pub.permissions.delegateType); + rc = TPM_INVALID_STRUCTURE; + } + } + /* load integrityDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_delegate_owner_blob->integrityDigest, stream, stream_size); + } + /* load additionalArea */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_delegate_owner_blob->additionalArea), stream, stream_size); + } + /* load sensitiveArea */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_delegate_owner_blob->sensitiveArea), stream, stream_size); + } + return rc; +} + +/* TPM_DelegateOwnerBlob_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DelegateOwnerBlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateOwnerBlob_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_OWNER_BLOB); + } + /* store pub */ + if (rc == 0) { + rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_owner_blob->pub)); + } + /* store integrityDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_delegate_owner_blob->integrityDigest); + } + /* store additionalArea */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_owner_blob->additionalArea)); + } + /* store sensitiveArea */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_owner_blob->sensitiveArea)); + } + return rc; +} + +/* TPM_DelegateOwnerBlob_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DelegateOwnerBlob_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DelegateOwnerBlob_Delete(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob) +{ + printf(" TPM_DelegateOwnerBlob_Delete:\n"); + if (tpm_delegate_owner_blob != NULL) { + TPM_DelegatePublic_Delete(&(tpm_delegate_owner_blob->pub)); + TPM_SizedBuffer_Delete(&(tpm_delegate_owner_blob->additionalArea)); + TPM_SizedBuffer_Delete(&(tpm_delegate_owner_blob->sensitiveArea)); + TPM_DelegateOwnerBlob_Init(tpm_delegate_owner_blob); + } + return; +} + +/* + TPM_DELEGATE_KEY_BLOB +*/ + +/* TPM_DelegateKeyBlob_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DelegateKeyBlob_Init(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob) +{ + printf(" TPM_DelegateKeyBlob_Init:\n"); + TPM_DelegatePublic_Init(&(tpm_delegate_key_blob->pub)); + TPM_Digest_Init(tpm_delegate_key_blob->integrityDigest); + TPM_Digest_Init(tpm_delegate_key_blob->pubKeyDigest); + TPM_SizedBuffer_Init(&(tpm_delegate_key_blob->additionalArea)); + TPM_SizedBuffer_Init(&(tpm_delegate_key_blob->sensitiveArea)); + return; +} + +/* TPM_DelegateKeyBlob_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DelegateKeyBlob_Init() + After use, call TPM_DelegateKeyBlob_Delete() to free memory +*/ + +TPM_RESULT TPM_DelegateKeyBlob_Load(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateKeyBlob_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DELG_KEY_BLOB, stream, stream_size); + } + /* load pub */ + if (rc == 0) { + rc = TPM_DelegatePublic_Load(&(tpm_delegate_key_blob->pub), stream, stream_size); + } + /* check that permissions are key */ + if (rc == 0) { + if (tpm_delegate_key_blob->pub.permissions.delegateType != TPM_DEL_KEY_BITS) { + printf("TPM_DelegateKeyBlob_Load: Error, delegateType expected %08x found %08x\n", + TPM_DEL_KEY_BITS, tpm_delegate_key_blob->pub.permissions.delegateType); + rc = TPM_INVALID_STRUCTURE; + } + } + /* load integrityDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_delegate_key_blob->integrityDigest, stream, stream_size); + } + /* load pubKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_delegate_key_blob->pubKeyDigest, stream, stream_size); + } + /* load additionalArea */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_delegate_key_blob->additionalArea), stream, stream_size); + } + /* load sensitiveArea */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_delegate_key_blob->sensitiveArea), stream, stream_size); + } + return rc; +} + +/* TPM_DelegateKeyBlob_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DelegateKeyBlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateKeyBlob_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELG_KEY_BLOB); + } + /* store pub */ + if (rc == 0) { + rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_key_blob->pub)); + } + /* store integrityDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_delegate_key_blob->integrityDigest); + } + /* store pubKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_delegate_key_blob->pubKeyDigest); + } + /* store additionalArea */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_key_blob->additionalArea)); + } + /* store sensitiveArea */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_key_blob->sensitiveArea)); + } + return rc; +} + +/* TPM_DelegateKeyBlob_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DelegateKeyBlob_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DelegateKeyBlob_Delete(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob) +{ + printf(" TPM_DelegateKeyBlob_Delete:\n"); + if (tpm_delegate_key_blob != NULL) { + TPM_DelegatePublic_Delete(&(tpm_delegate_key_blob->pub)); + TPM_SizedBuffer_Delete(&(tpm_delegate_key_blob->additionalArea)); + TPM_SizedBuffer_Delete(&(tpm_delegate_key_blob->sensitiveArea)); + TPM_DelegateKeyBlob_Init(tpm_delegate_key_blob); + } + return; +} + +/* + TPM_FAMILY_TABLE +*/ + +/* TPM_FamilyTable_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_FamilyTable_Init(TPM_FAMILY_TABLE *tpm_family_table) +{ + size_t i; + + printf(" TPM_FamilyTable_Init: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); + for (i = 0 ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN ; i++) { + TPM_FamilyTableEntry_Init(&(tpm_family_table->famTableRow[i])); + } + return; +} + +/* TPM_FamilyTable_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_FamilyTable_Init() + After use, call TPM_FamilyTable_Delete() to free memory +*/ + +TPM_RESULT TPM_FamilyTable_Load(TPM_FAMILY_TABLE *tpm_family_table, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_FamilyTable_Load: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); + for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) { + rc = TPM_FamilyTableEntry_Load(&(tpm_family_table->famTableRow[i]), + stream, + stream_size); + } + return rc; +} + +/* TPM_FamilyTable_Store() + + If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_FamilyTable_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_FAMILY_TABLE *tpm_family_table, + TPM_BOOL store_tag) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_FamilyTable_Store: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); + for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) { + rc = TPM_FamilyTableEntry_Store(sbuffer, + &(tpm_family_table->famTableRow[i]), store_tag); + } + return rc; +} + +/* TPM_FamilyTable_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_FamilyTable_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_FamilyTable_Delete(TPM_FAMILY_TABLE *tpm_family_table) +{ + size_t i; + + printf(" TPM_FamilyTable_Delete: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); + if (tpm_family_table != NULL) { + for (i = 0 ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN ; i++) { + TPM_FamilyTableEntry_Delete(&(tpm_family_table->famTableRow[i])); + } + TPM_FamilyTable_Init(tpm_family_table); + } + return; +} + +/* TPM_FamilyTable_GetEntry() searches all entries for the entry matching the familyID, and returns + the TPM_FAMILY_TABLE_ENTRY associated with the familyID. + + Returns + 0 for success + TPM_BADINDEX if the familyID is not found +*/ + +TPM_RESULT TPM_FamilyTable_GetEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, /* output */ + TPM_FAMILY_TABLE *tpm_family_table, + TPM_FAMILY_ID familyID) +{ + TPM_RESULT rc = 0; + size_t i; + TPM_BOOL found; + + printf(" TPM_FamilyTable_GetEntry: familyID %08x\n", familyID); + for (i = 0, found = FALSE ; (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) && !found ; i++) { + if (tpm_family_table->famTableRow[i].valid && + (tpm_family_table->famTableRow[i].familyID == familyID)) { /* found */ + found = TRUE; + *tpm_family_table_entry = &(tpm_family_table->famTableRow[i]); + } + } + if (!found) { + printf("TPM_FamilyTable_GetEntry: Error, familyID %08x not found\n", familyID); + rc = TPM_BADINDEX; + } + return rc; +} + +/* TPM_FamilyTable_GetEnabledEntry() searches all entries for the entry matching the familyID, and + returns the TPM_FAMILY_TABLE_ENTRY associated with the familyID. + + Similar to TPM_FamilyTable_GetEntry() but returns an error if the entry is disabled. + + Returns + 0 for success + TPM_BADINDEX if the familyID is not found + TPM_DISABLED_CMD if the TPM_FAMILY_TABLE_ENTRY -> TPM_FAMFLAG_ENABLED is FALSE +*/ + +TPM_RESULT TPM_FamilyTable_GetEnabledEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, + TPM_FAMILY_TABLE *tpm_family_table, + TPM_FAMILY_ID familyID) +{ + TPM_RESULT rc = 0; + + printf(" TPM_FamilyTable_GetEnabledEntry: familyID %08x\n", familyID); + if (rc == 0) { + rc = TPM_FamilyTable_GetEntry(tpm_family_table_entry, + tpm_family_table, + familyID); + } + if (rc == 0) { + if (!((*tpm_family_table_entry)->flags & TPM_FAMFLAG_ENABLED)) { + printf("TPM_FamilyTable_GetEnabledEntry: Error, family %08x disabled\n", familyID); + rc = TPM_DISABLED_CMD; + } + } + return rc; +} + +/* TPM_FamilyTable_IsSpace() returns success if an entry is available, an error if not. + + If success, 'family_table_entry' holds the first free family table row. +*/ + +TPM_RESULT TPM_FamilyTable_IsSpace(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, /* output */ + TPM_FAMILY_TABLE *tpm_family_table) +{ + size_t i; + TPM_BOOL isSpace; + TPM_RESULT rc = 0; + + + printf(" TPM_FamilyTable_IsSpace:\n"); + for (i = 0, isSpace = FALSE ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN; i++) { + *tpm_family_table_entry = &(tpm_family_table->famTableRow[i]); + if (!((*tpm_family_table_entry)->valid)) { + printf(" TPM_FamilyTable_IsSpace: Found space at %lu\n", (unsigned long)i); + isSpace = TRUE; + break; + } + } + if (!isSpace) { + printf(" TPM_FamilyTable_IsSpace: Error, no space found\n"); + rc = TPM_RESOURCES; + } + return rc; +} + +/* TPM_FamilyTable_StoreValid() stores only the valid (occupied) entries + + If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_FamilyTable_StoreValid(TPM_STORE_BUFFER *sbuffer, + const TPM_FAMILY_TABLE *tpm_family_table, + TPM_BOOL store_tag) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_FamilyTable_StoreValid: \n"); + for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) { + /* store only the valid rows */ + if (tpm_family_table->famTableRow[i].valid) { + /* store only the publicly visible members */ + printf(" TPM_FamilyTable_StoreValid: Entry %lu is valid\n", (unsigned long)i); + printf(" TPM_FamilyTable_StoreValid: Entry family ID is %08x\n", + tpm_family_table->famTableRow[i].familyID); + rc = TPM_FamilyTableEntry_StorePublic(sbuffer, + &(tpm_family_table->famTableRow[i]), store_tag); + } + } + return rc; +} + +/* + TPM_FAMILY_TABLE_ENTRY +*/ + +/* TPM_FamilyTableEntry_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_FamilyTableEntry_Init(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry) +{ + printf(" TPM_FamilyTableEntry_Init:\n"); + tpm_family_table_entry->familyLabel = 0; + tpm_family_table_entry->familyID = 0; + tpm_family_table_entry->verificationCount = 0; + tpm_family_table_entry->flags = 0; + tpm_family_table_entry->valid = FALSE; + return; +} + +/* TPM_FamilyTableEntry_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_FamilyTableEntry_Init() + After use, call TPM_FamilyTableEntry_Delete() to free memory +*/ + +TPM_RESULT TPM_FamilyTableEntry_Load(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_FamilyTableEntry_Load:\n"); + /* load tag */ + /* the tag is not serialized when storing TPM_PERMANENT_DATA, to save NV space */ + /* load familyLabel */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_family_table_entry->familyLabel), stream, stream_size); + } + /* load familyID */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_family_table_entry->familyID), stream, stream_size); + } + /* load verificationCount */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_family_table_entry->verificationCount), stream, stream_size); + } + /* load flags */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_family_table_entry->flags), stream, stream_size); + } + /* load valid */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_family_table_entry->valid), stream, stream_size); + } + if (rc == 0) { + printf(" TPM_FamilyTableEntry_Load: label %02x familyID %08x valid %u\n", + tpm_family_table_entry->familyLabel, + tpm_family_table_entry->familyID, + tpm_family_table_entry->valid); + } + return rc; +} + +/* TPM_FamilyTableEntry_Store() stores all members of the structure + + If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_FamilyTableEntry_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, + TPM_BOOL store_tag) +{ + TPM_RESULT rc = 0; + + printf(" TPM_FamilyTableEntry_Store:\n"); + /* store public, visible members */ + if (rc == 0) { + rc = TPM_FamilyTableEntry_StorePublic(sbuffer, tpm_family_table_entry, store_tag); + } + /* store valid */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_family_table_entry->valid), + sizeof(TPM_BOOL)); + } + return rc; +} + +/* TPM_FamilyTableEntry_StorePublic() stores only the public, visible members of the structure + + If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_FamilyTableEntry_StorePublic(TPM_STORE_BUFFER *sbuffer, + const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, + TPM_BOOL store_tag) +{ + TPM_RESULT rc = 0; + + printf(" TPM_FamilyTableEntry_StorePublic:\n"); + /* store tag */ + if ((rc == 0) && (store_tag)) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_FAMILY_TABLE_ENTRY); + } + /* store familyLabel */ + if (rc == 0) { + TPM_Sbuffer_Append(sbuffer, &(tpm_family_table_entry->familyLabel), + sizeof(TPM_FAMILY_LABEL)); + } + /* store familyID */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->familyID); + } + /* store verificationCount */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->verificationCount); + } + /* store flags */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->flags); + } + return rc; +} + +/* TPM_FamilyTableEntry_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_FamilyTableEntry_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_FamilyTableEntry_Delete(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry) +{ + printf(" TPM_FamilyTableEntry_Delete:\n"); + if (tpm_family_table_entry != NULL) { + TPM_FamilyTableEntry_Init(tpm_family_table_entry); + } + return; +} + +/* + TPM_DELEGATE_TABLE +*/ + +/* TPM_DelegateTable_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DelegateTable_Init(TPM_DELEGATE_TABLE *tpm_delegate_table) +{ + size_t i; + + printf(" TPM_DelegateTable_Init: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); + for (i = 0 ; i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN ; i++) { + TPM_DelegateTableRow_Init(&(tpm_delegate_table->delRow[i])); + } + return; +} + +/* TPM_DelegateTable_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DelegateTable_Init() + After use, call TPM_DelegateTable_Delete() to free memory +*/ + +TPM_RESULT TPM_DelegateTable_Load(TPM_DELEGATE_TABLE *tpm_delegate_table, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_DelegateTable_Load: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); + for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) ; i++) { + rc = TPM_DelegateTableRow_Load(&(tpm_delegate_table->delRow[i]), + stream, + stream_size); + } + return rc; +} + +/* TPM_DelegateTable_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DelegateTable_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_TABLE *tpm_delegate_table) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_DelegateTable_Store: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); + for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) ; i++) { + rc = TPM_DelegateTableRow_Store(sbuffer, &(tpm_delegate_table->delRow[i])); + } + return rc; +} + +/* TPM_DelegateTable_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DelegateTable_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DelegateTable_Delete(TPM_DELEGATE_TABLE *tpm_delegate_table) +{ + size_t i; + + printf(" TPM_DelegateTable_Delete: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); + if (tpm_delegate_table != NULL) { + for (i = 0 ; i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN ; i++) { + TPM_DelegateTableRow_Delete(&(tpm_delegate_table->delRow[i])); + } + TPM_DelegateTable_Init(tpm_delegate_table); + } + return; +} + +/* TPM_DelegateTable_StoreValid() store only the valid (occupied) entries. Each entry is prepended + with it's index. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DelegateTable_StoreValid(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_TABLE *tpm_delegate_table) +{ + TPM_RESULT rc = 0; + uint32_t i; + + printf(" TPM_DelegateTable_StoreValid:\n"); + for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) ; i++) { + /* store only the valid rows */ + if (tpm_delegate_table->delRow[i].valid) { + /* a. Write the TPM_DELEGATE_INDEX to delegateTable */ + printf(" TPM_DelegateTable_StoreValid: Entry %u is valid\n", i); + printf(" TPM_DelegateTable_StoreValid: Entry family ID is %08x\n", + tpm_delegate_table->delRow[i].pub.familyID); + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, i); + } + /* b. Copy the TPM_DELEGATE_PUBLIC to delegateTable */ + if (rc == 0) { + rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_table->delRow[i].pub)); + } + } + } + return rc; +} + +/* TPM_DelegateTable_GetRow() maps 'rowIndex' to a TPM_DELEGATE_TABLE_ROW in the delegate table. + + The row may not have valid data. + */ + +TPM_RESULT TPM_DelegateTable_GetRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow, + TPM_DELEGATE_TABLE *tpm_delegate_table, + uint32_t rowIndex) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateTable_GetRow: index %u\n", rowIndex); + if (rc == 0) { + if (rowIndex >= TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) { + printf("TPM_DelegateTable_GetRow: index %u out of range\n", rowIndex); + rc = TPM_BADINDEX; + } + } + if (rc == 0) { + *delegateTableRow = &(tpm_delegate_table->delRow[rowIndex]); + } + return rc; +} + +/* TPM_DelegateTable_GetValidRow() maps 'rowIndex' to a TPM_DELEGATE_TABLE_ROW in the delegate + table. + + The row must have valid data. + */ + +TPM_RESULT TPM_DelegateTable_GetValidRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow, + TPM_DELEGATE_TABLE *tpm_delegate_table, + uint32_t rowIndex) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + rc = TPM_DelegateTable_GetRow(delegateTableRow, + tpm_delegate_table, + rowIndex); + } + if (rc == 0) { + *delegateTableRow = &(tpm_delegate_table->delRow[rowIndex]); + if (!(*delegateTableRow)->valid) { + printf("TPM_DelegateTable_GetValidRow: index %u invalid\n", rowIndex); + rc = TPM_BADINDEX; + } + } + return rc; +} + +/* + TPM_DELEGATE_TABLE_ROW +*/ + +/* TPM_DelegateTableRow_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_DelegateTableRow_Init(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row) +{ + printf(" TPM_DelegateTableRow_Init:\n"); + TPM_DelegatePublic_Init(&(tpm_delegate_table_row->pub)); + TPM_Secret_Init(tpm_delegate_table_row->authValue); + tpm_delegate_table_row->valid = FALSE; + return; +} + +/* TPM_DelegateTableRow_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_DelegateTableRow_Init() + After use, call TPM_DelegateTableRow_Delete() to free memory +*/ + +TPM_RESULT TPM_DelegateTableRow_Load(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateTableRow_Load:\n"); + /* check the tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_DELEGATE_TABLE_ROW, stream, stream_size); + } + /* load pub */ + if (rc == 0) { + rc = TPM_DelegatePublic_Load(&(tpm_delegate_table_row->pub), stream, stream_size); + } + /* load authValue */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_delegate_table_row->authValue, stream, stream_size); + } + /* load valid */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_delegate_table_row->valid), stream, stream_size); + } + return rc; +} + +/* TPM_DelegateTableRow_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_DelegateTableRow_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row) +{ + TPM_RESULT rc = 0; + + printf(" TPM_DelegateTableRow_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_TABLE_ROW); + } + /* store pub */ + if (rc == 0) { + rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_table_row->pub)); + } + /* store authValue */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_delegate_table_row->authValue); + } + /* store valid */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_delegate_table_row->valid), sizeof(TPM_BOOL)); + } + return rc; +} + +/* TPM_DelegateTableRow_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_DelegateTableRow_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_DelegateTableRow_Delete(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row) +{ + printf(" TPM_DelegateTableRow_Delete:\n"); + if (tpm_delegate_table_row != NULL) { + TPM_DelegatePublic_Delete(&(tpm_delegate_table_row->pub)); + TPM_DelegateTableRow_Init(tpm_delegate_table_row); + } + return; +} + +/* + Processing Functions +*/ + +/* 19.1 TPM_Delegate_Manage rev 115 + + TPM_Delegate_Manage is the fundamental process for managing the Family tables, including + enabling/disabling Delegation for a selected Family. Normally TPM_Delegate_Manage must be + executed at least once (to create Family tables for a particular family) before any other type of + Delegation command in that family can succeed. + + Delegate_Manage is authorized by the TPM Owner if an Owner is installed, because changing a table + is a privileged Owner operation. If no Owner is installed, Delegate_Manage requires no privilege + to execute. This does not disenfranchise an Owner, since there is no Owner, and simplifies + loading of tables during platform manufacture or on first-boot. Burn-out of TPM non-volatile + storage by inappropriate use is mitigated by the TPM's normal limits on NV-writes in the absence + of an Owner. Tables can be locked after loading, to prevent subsequent tampering, and only + unlocked by the Owner, his delegate, or the act of removing the Owner (even if there is no + Owner). + + TPM_Delegate_Manage command is customized by opcode: + + (1) TPM_FAMILY_ENABLE enables/disables use of a family and all the rows of the delegate table + belonging to that family, + + (2) TPM_FAMILY_ADMIN can be used to prevent further management of the Tables until an Owner is + installed, or until the Owner is removed from the TPM. (Note that the Physical Presence command + TPM_ForceClear always enables further management, even if TPM_ForceClear is used when no Owner is + installed.) + + (3) TPM_FAMILY_CREATE creates a new family. + + (4) TPM_FAMILY_INVALIDATE invalidates an existing family. +*/ + +TPM_RESULT TPM_Process_DelegateManage(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_FAMILY_ID familyID; /* The familyID that is to be managed */ + TPM_FAMILY_OPERATION opCode = 0; /* Operation to be performed by this command. */ + TPM_SIZED_BUFFER opData; /* Data necessary to implement opCode */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with + authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the + authorization session handle */ + TPM_AUTHDATA ownerAuth; /* HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_SECRET savedAuth; /* saved copy for response */ + TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ + TPM_FAMILY_TABLE_ENTRY *familyRow = NULL; /* family table row containing familyID */ + uint32_t nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; + /* temp for noOwnerNVWrite, initialize to + silence compiler */ + TPM_BOOL nv1Incremented = FALSE; /* flag that nv1 was incremented */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back data */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORE_BUFFER retData; /* Returned data */ + + printf("TPM_Process_DelegateManage: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&opData); /* freed @1 */ + TPM_Sbuffer_Init(&retData); /* freed @2 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get familyID parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&familyID, &command, ¶mSize); + } + /* get opCode parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateManage: familyID %08x\n", familyID); + returnCode = TPM_Load32(&opCode, &command, ¶mSize); + } + /* get opData parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateManage: opCode %u\n", opCode); + returnCode = TPM_SizedBuffer_Load(&opData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DelegateManage: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. If opCode != TPM_FAMILY_CREATE */ + /* a. Locate familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return + TPM_BADINDEX if not found */ + /* b. Set FR, a TPM_FAMILY_TABLE_ENTRY, to TPM_FAMILY_TABLE. famTableRow[familyRow] */ + if ((returnCode == TPM_SUCCESS) && (opCode != TPM_FAMILY_CREATE)) { + printf("TPM_Process_DelegateManage: Not creating, get entry for familyID %08x\n", + familyID); + returnCode = TPM_FamilyTable_GetEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + familyID); + } + /* 2. If tag = TPM_TAG_RQU_AUTH1_COMMAND */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + /* a. Validate the command and parameters using ownerAuth, return TPM_AUTHFAIL on error */ + returnCode = + TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth),/* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + /* make a copy of the HMAC key for the response, since it MAY be invalidated */ + TPM_Secret_Copy(savedAuth, *hmacKey); + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + /* b. If the command is delegated (authHandle session type is TPM_PID_DSAP or through + ownerReference delegation) */ + if ((auth_session_data->protocolID == TPM_PID_DSAP) || + (tpm_state->tpm_stclear_data.ownerReference != TPM_KH_OWNER)) { + /* i. If opCode = TPM_FAMILY_CREATE */ + /* (1) The TPM MUST ignore familyID */ + /* ii. Else */ + if (opCode != TPM_FAMILY_CREATE) { + /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, + auth_session_data); + } + /* (1) Verify that the familyID associated with authHandle matches the familyID + parameter, return TPM_DELEGATE_FAMILY on error */ + if (returnCode == TPM_SUCCESS) { + if (delegatePublic->familyID != familyID) { + printf("TPM_Process_DelegateManage: Error, familyID %08x should be %08x\n", + familyID, delegatePublic->familyID); + returnCode = TPM_DELEGATE_FAMILY; + } + } + } + } + } + /* 3. Else */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) { + /* a. If TPM_PERMANENT_DATA -> ownerAuth is valid, return TPM_AUTHFAIL */ + if (tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_Process_DelegateManage: Error, owner installed but no authorization\n"); + returnCode = TPM_AUTHFAIL ; + } + } + /* b. If opCode != TPM_FAMILY_CREATE and FR -> flags -> TPM_DELEGATE_ADMIN_LOCK is TRUE, return + TPM_DELEGATE_LOCK */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) { + if ((opCode != TPM_FAMILY_CREATE) && (familyRow->flags & TPM_DELEGATE_ADMIN_LOCK)) { + printf("TPM_Process_DelegateManage: Error, row locked\n"); + returnCode = TPM_DELEGATE_LOCK; + } + } + /* c. Validate max NV writes without an owner */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) { + /* i. Set NV1 to TPM_PERMANENT_DATA -> noOwnerNVWrite */ + nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; + /* ii. Increment NV1 by 1 */ + nv1++; + /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */ + if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) { + printf("TPM_Process_DelegateManage: Error, max NV writes %d w/o owner reached\n", + tpm_state->tpm_permanent_data.noOwnerNVWrite); + returnCode = TPM_MAXNVWRITES; + } + if (returnCode == TPM_SUCCESS){ + /* iv. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */ + /* NOTE Don't update the noOwnerNVWrite value until determining that the write will be + performed */ + nv1Incremented = TRUE; + } + } + /* 4. The TPM invalidates sessions */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateManage: Invalidate sessions\n"); + /* a. MUST invalidate all DSAP sessions */ + /* b. MUST invalidate all OSAP sessions associated with the delegation table */ + /* d. MAY invalidate any other session */ + TPM_AuthSessions_TerminatexSAP(&continueAuthSession, + authHandle, + tpm_state->tpm_stclear_data.authSessions); + /* c. MUST set TPM_STCLEAR_DATA -> ownerReference to TPM_KH_OWNER */ + tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER; + } + /* + 5. If opCode == TPM_FAMILY_CREATE + */ + if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_CREATE)) { + printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_CREATE\n"); + /* a. Validate that sufficient space exists within the TPM to store an additional family and + map F2 to the newly allocated space. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_FamilyTable_IsSpace(&familyRow, /* output */ + &(tpm_state->tpm_permanent_data.familyTable)); + } + /* b. Validate that opData is a TPM_FAMILY_LABEL */ + if (returnCode == TPM_SUCCESS) { + /* i. If opDataSize != sizeof(TPM_FAMILY_LABEL) return TPM_BAD_PARAM_SIZE */ + if (opData.size != sizeof(TPM_FAMILY_LABEL)) { + printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* c. Map F2 to a TPM_FAMILY_TABLE_ENTRY */ + /* NOTE Done by TPM_FamilyTable_IsSpace() */ + /* i. Set F2 -> tag to TPM_TAG_FAMILY_TABLE_ENTRY */ + /* NOTE Done by TPM_FamilyTableEntry_Init() */ + if (returnCode == TPM_SUCCESS) { + /* ii. Set F2 -> familyLabel to opData */ + familyRow->familyLabel = *(opData.buffer); + /* d. Increment TPM_PERMANENT_DATA -> lastFamilyID by 1 */ + tpm_state->tpm_permanent_data.lastFamilyID++; + /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after NVRAM is written */ + writeAllNV = TRUE; + /* e. Set F2 -> familyID = TPM_PERMANENT_DATA -> lastFamilyID */ + familyRow->familyID = tpm_state->tpm_permanent_data.lastFamilyID; + /* f. Set F2 -> verificationCount = 1 */ + familyRow->verificationCount = 1; + /* g. Set F2 -> flags -> TPM_FAMFLAG_ENABLED to FALSE */ + familyRow->flags &= ~TPM_FAMFLAG_ENABLED; + /* h. Set F2 -> flags -> TPM_DELEGATE_ADMIN_LOCK to FALSE */ + familyRow->flags &= ~TPM_DELEGATE_ADMIN_LOCK; + /* i. Set retDataSize = 4 */ + /* j. Set retData = F2 -> familyID */ + printf("TPM_Process_DelegateManage: Created familyID %08x\n", familyRow->familyID); + familyRow->valid = TRUE; + returnCode = TPM_Sbuffer_Append32(&retData, familyRow->familyID); + } + /* k. Return TPM_SUCCESS */ + } + /* 6. If authHandle is of type DSAP then continueAuthSession MUST set to FALSE */ + if ((returnCode == TPM_SUCCESS) && (opCode != TPM_FAMILY_CREATE) && + (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { /* only if auth-1 */ + + if (auth_session_data->protocolID == TPM_PID_DSAP) { + continueAuthSession = FALSE; + } + } + /* 7. If opCode == TPM_FAMILY_ADMIN */ + if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_ADMIN)) { + printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_ADMIN\n"); + /* a. Validate that opDataSize == 1, and that opData is a Boolean value. */ + if (returnCode == TPM_SUCCESS) { + if (opData.size != sizeof(TPM_BOOL)) { + printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* b. Set (FR -> flags -> TPM_DELEGATE_ADMIN_LOCK) = opData */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateManage: TPM_FAMILY_ADMIN opData %02x\n", + opData.buffer[0]); + if (*(TPM_BOOL *)(opData.buffer)) { + familyRow->flags |= TPM_DELEGATE_ADMIN_LOCK; + } + else { + familyRow->flags &= ~TPM_DELEGATE_ADMIN_LOCK; + } + printf("TPM_Process_DelegateManage: new TPM_FAMILY_TABLE_ENTRY.flags %08x\n", + familyRow->flags); + /* c. Set retDataSize = 0 */ + /* NOTE Done by TPM_Sbuffer_Init() */ + /* d. Return TPM_SUCCESS */ + } + if (returnCode == TPM_SUCCESS) { + writeAllNV = TRUE; + } + } + /* 8. else If opflag == TPM_FAMILY_ENABLE */ + if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_ENABLE)) { + printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_ENABLE\n"); + /* a. Validate that opDataSize == 1, and that opData is a Boolean value. */ + if (returnCode == TPM_SUCCESS) { + if (opData.size != sizeof(TPM_BOOL)) { + printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* b. Set FR -> flags-> TPM_FAMFLAG_ENABLED = opData */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateManage: TPM_FAMILY_ENABLE opData %02x\n", + opData.buffer[0]); + if (*(TPM_BOOL *)(opData.buffer)) { + familyRow->flags |= TPM_FAMFLAG_ENABLED; + } + else { + familyRow->flags &= ~TPM_FAMFLAG_ENABLED; + } + printf("TPM_Process_DelegateManage: new TPM_FAMILY_TABLE_ENTRY.flags %08x\n", + familyRow->flags); + /* c. Set retDataSize = 0 */ + /* NOTE Done by TPM_Sbuffer_Init() */ + /* d. Return TPM_SUCCESS */ + } + if (returnCode == TPM_SUCCESS) { + writeAllNV = TRUE; + } + } + /* 9. else If opflag == TPM_FAMILY_INVALIDATE */ + if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_INVALIDATE)) { + printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_INVALIDATE\n"); + /* a. Invalidate all data associated with familyRow */ + /* i. All data is all information pointed to by FR */ + /* ii. return TPM_SELFTEST_FAILED on failure */ + TPM_FamilyTableEntry_Delete(familyRow); + /* b.The TPM MAY invalidate delegate rows that contain the same familyID. */ + /* c. Set retDataSize = 0 */ + /* NOTE Done by TPM_Sbuffer_Init() */ + /* d. Return TPM_SUCCESS */ + writeAllNV = TRUE; + } + /* 10. Else return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if ((opCode != TPM_FAMILY_CREATE) && + (opCode != TPM_FAMILY_ADMIN) && + (opCode != TPM_FAMILY_ENABLE) && + (opCode != TPM_FAMILY_INVALIDATE)) { + printf("TPM_Process_DelegateManage: Error, bad opCode %08x\n", opCode); + returnCode = TPM_BAD_PARAMETER; + } + } + /* if writing NV and this is a no owner NV write, update the count with the previously + incremented value */ + if (returnCode == TPM_SUCCESS) { + if (writeAllNV && nv1Incremented) { + printf("TPM_Process_DelegateManage: noOwnerNVWrite %u\n", nv1); + tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1; + } + } + /* write back TPM_PERMANENT_DATA if required */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DelegateManage: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append retDataSize and retData */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &retData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + savedAuth, /* saved HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&opData); /* @1 */ + TPM_Sbuffer_Delete(&retData); /* @2 */ + return rcf; +} + +/* 19.2 TPM_Delegate_CreateKeyDelegation rev 109 + + This command delegates privilege to use a key by creating a blob that can be used by TPM_DSAP. + + There is no check for appropriateness of the key's key usage against the key permission + settings. If the key usage is incorrect, this command succeeds, but the delegated command will + fail. + + These blobs CANNOT be used as input data for TPM_LoadOwnerDelegation because the internal TPM + delegate table can store owner delegations only. + + (TPM_Delegate_CreateOwnerDelegation must be used to delegate Owner privilege.) + + The use restrictions that may be present on the key pointed to by keyHandle are not enforced for + this command. Stated another way CreateKeyDelegation is not a use of the key. + + The publicInfo -> familyID can specify a disabled family row. The family row is checked when the + key delegation is used in a DSAP session, not when it is created. +*/ + +TPM_RESULT TPM_Process_DelegateCreateKeyDelegation(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key. */ + TPM_DELEGATE_PUBLIC publicInfo; /* The public information necessary to fill in the blob */ + TPM_ENCAUTH delAuth; /* The encrypted new AuthData for the blob. The encryption + key is the shared secret from the authorization session + protocol.*/ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle + authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the use + of keyHandle. HMAC key: key.usageAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_BOOL parentPCRStatus; + TPM_KEY *key = NULL; /* the key specified by keyHandle */ + TPM_SECRET *keyUsageAuth; + TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ + TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ + TPM_DIGEST a1Auth; + TPM_DELEGATE_SENSITIVE m1DelegateSensitive; + TPM_STORE_BUFFER delegateSensitive_sbuffer; + TPM_DELEGATE_KEY_BLOB p1DelegateKeyBlob; + + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORE_BUFFER blobSbuffer; /* The partially encrypted delegation information. + */ + + printf("TPM_Process_DelegateCreateKeyDelegation: Ordinal Entry\n"); + TPM_DelegatePublic_Init(&publicInfo); /* freed @1 */ + TPM_DelegateSensitive_Init(&m1DelegateSensitive); /* freed @2 */ + TPM_Sbuffer_Init(&delegateSensitive_sbuffer); /* freed @3 */ + TPM_DelegateKeyBlob_Init(&p1DelegateKeyBlob); /* freed @4 */ + TPM_Sbuffer_Init(&blobSbuffer); /* freed @5 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get publicInfo parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateCreateKeyDelegation: keyHandle %08x\n", keyHandle); + returnCode = TPM_DelegatePublic_Load(&publicInfo, &command, ¶mSize); + } + /* get delAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Load(delAuth, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DelegateCreateKeyDelegation: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Verify AuthData for the command and parameters using privAuth */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get keyHandle -> usageAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); + } + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_KEYHANDLE, + ordinal, + key, + NULL, /* OIAP */ + key->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* Validate the authorization */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + /* 2. Locate publicInfo -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, + return TPM_BADINDEX if not found */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_FamilyTable_GetEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + publicInfo.familyID); + } + /* 3. If the key authentication is in fact a delegation, then the TPM SHALL validate the command + and parameters using Delegation authorisation, then */ + if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) { + printf("TPM_Process_DelegateCreateKeyDelegation: Authentication is a delegation\n"); + /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, + auth_session_data); + } + /* a. Validate that authHandle -> familyID equals publicInfo -> familyID return + TPM_DELEGATE_FAMILY on error */ + if (returnCode == TPM_SUCCESS) { + if (publicInfo.familyID != delegatePublic->familyID) { + printf("TPM_Process_DelegateCreateKeyDelegation: Error, " + "familyID %u should be %u\n", + publicInfo.familyID, delegatePublic->familyID); + returnCode = TPM_DELEGATE_FAMILY; + } + } + /* b. If TPM_FAMILY_TABLE.famTableRow[ authHandle -> familyID] -> flags -> + TPM_FAMFLAG_ENABLED is FALSE, return error TPM_DISABLED_CMD. */ + if (returnCode == TPM_SUCCESS) { + if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) { + printf("TPM_Process_DelegateCreateKeyDelegation: Error, family %u disabled\n", + publicInfo.familyID); + returnCode = TPM_DISABLED_CMD; + } + } + /* c. Verify that the delegation bits in publicInfo do not grant more permissions then + currently delegated. Otherwise return error TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_Delegations_CheckPermissionDelegation(&(publicInfo.permissions), + &(delegatePublic->permissions)); + } + } + /* 4. Check that publicInfo -> delegateType is TPM_DEL_KEY_BITS */ + if (returnCode == TPM_SUCCESS) { + if (publicInfo.permissions.delegateType != TPM_DEL_KEY_BITS) { + printf("TPM_Process_DelegateCreateKeyDelegation: Error, " + "delegateType %08x not a key delegation\n", + publicInfo.permissions.delegateType); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 5. Verify that authHandle indicates an OSAP or DSAP session return TPM_INVALID_AUTHHANDLE on + error */ + /* NOTE Done by TPM_AuthSessions_GetData() */ + /* 6. Create a1 by decrypting delAuth according to the ADIP indicated by authHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_Decrypt(a1Auth, + NULL, + delAuth, + auth_session_data, + NULL, + NULL, + FALSE); /* even and odd */ + } + /* 7. Create h1 the SHA-1 of TPM_STORE_PUBKEY structure of the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_DelegateCreateKeyDelegation: Decrypted a1", a1Auth); + returnCode = TPM_SHA1_GenerateStructure(p1DelegateKeyBlob.pubKeyDigest, + &(key->pubKey), + (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store); + } + /* 8. Create M1 a TPM_DELEGATE_SENSITIVE structure */ + /* a. Set M1 -> tag to TPM_TAG_DELEGATE_SENSITIVE */ + /* NOTE Done by TPM_DelegateSensitive_Init() */ + /* b. Set M1 -> authValue to a1 */ + if (returnCode == TPM_SUCCESS) { + TPM_Secret_Copy(m1DelegateSensitive.authValue, a1Auth); + /* c. The TPM MAY add additional information of a sensitive nature relative to the + delegation */ + /* 9. Create M2 the encryption of M1 using TPM_DELEGATE_KEY */ + /* serialize M1 */ + returnCode = TPM_DelegateSensitive_Store(&delegateSensitive_sbuffer, &m1DelegateSensitive); + } + /* encrypt with delegate key */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateCreateKeyDelegation: Encrypting TPM_DELEGATE_SENSITIVE\n"); + returnCode = + TPM_SymmetricKeyData_EncryptSbuffer(&(p1DelegateKeyBlob.sensitiveArea), + &delegateSensitive_sbuffer, + tpm_state->tpm_permanent_data.delegateKey); + } + /* 10. Create P1 a TPM_DELEGATE_KEY_BLOB */ + /* a. Set P1 -> tag to TPM_TAG_DELG_KEY_BLOB */ + /* NOTE Done by TPM_DelegateKeyBlob_Init() */ + /* b. Set P1 -> pubKeyDigest to H1 */ + /* NOTE Done by TPM_StorePubkey_GenerateDigest() */ + /* c. Set P1 -> pub to PublicInfo */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegatePublic_Copy(&(p1DelegateKeyBlob.pub), &publicInfo); + } + /* d. Set P1 -> pub -> verificationCount to familyRow -> verificationCount */ + if (returnCode == TPM_SUCCESS) { + p1DelegateKeyBlob.pub.verificationCount = familyRow->verificationCount; + /* e. Set P1 -> integrityDigest to NULL */ + /* NOTE Done by TPM_DelegateKeyBlob_Init() */ + /* f. The TPM sets additionalArea and additionalAreaSize appropriate for this TPM. The + information MAY include symmetric IV, symmetric mode of encryption and other data that + allows the TPM to process the blob in the future. */ + /* g. Set P1 -> sensitiveSize to the size of M2 */ + /* h. Set P1 -> sensitiveArea to M2 */ + /* NOTE Encrypted directly into p1DelegateKeyBlob.sensitiveArea */ + /* 11. Calculate H2 the HMAC of P1 using tpmProof as the secret */ + /* 12. Set P1 -> integrityDigest to H2 */ + /* NOTE It is safe to HMAC directly into TPM_DELEGATE_KEY_BLOB, since the structure + is serialized before the HMAC is performed */ + returnCode = TPM_HMAC_GenerateStructure + (p1DelegateKeyBlob.integrityDigest, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &p1DelegateKeyBlob, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store); /* store function */ + } + /* 13. Ignore continueAuthSession on input set continueAuthSession to FALSE on output */ + if (returnCode == TPM_SUCCESS) { + continueAuthSession = FALSE; + } + /* 14. Return P1 as blob */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateKeyBlob_Store(&blobSbuffer, &p1DelegateKeyBlob); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DelegateCreateKeyDelegation: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return blobSize and blob */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &blobSbuffer); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_DelegatePublic_Delete(&publicInfo); /* @1 */ + TPM_DelegateSensitive_Delete(&m1DelegateSensitive); /* @2 */ + TPM_Sbuffer_Delete(&delegateSensitive_sbuffer); /* @3 */ + TPM_DelegateKeyBlob_Delete(&p1DelegateKeyBlob); /* @4 */ + TPM_Sbuffer_Delete(&blobSbuffer); /* @5 */ + return rcf; +} + +/* 19.3 TPM_Delegate_CreateOwnerDelegation rev 98 + + TPM_Delegate_CreateOwnerDelegation delegates the Owner's privilege to use a set of command + ordinals, by creating a blob. Such blobs can be used as input data for TPM_DSAP or + TPM_Delegate_LoadOwnerDelegation. + + TPM_Delegate_CreateOwnerDelegation includes the ability to void all existing delegations (by + incrementing the verification count) before creating the new delegation. This ensures that the + new delegation will be the only delegation that can operate at Owner privilege in this + family. This new delegation could be used to enable a security monitor (a local separate entity, + or remote separate entity, or local host entity) to reinitialize a family and perhaps perform + external verification of delegation settings. Normally the ordinals for a delegated security + monitor would include TPM_Delegate_CreateOwnerDelegation (this command) in order to permit the + monitor to create further delegations, and TPM_Delegate_UpdateVerification to reactivate some + previously voided delegations. + + If the verification count is incremented and the new delegation does not delegate any privileges + (to any ordinals) at all, or uses an authorisation value that is then discarded, this family's + delegations are all void and delegation must be managed using actual Owner authorisation. + + (TPM_Delegate_CreateKeyDelegation must be used to delegate privilege to use a key.) +*/ + +TPM_RESULT TPM_Process_DelegateCreateOwnerDelegation(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_BOOL increment; /* Flag dictates whether verificationCount will be + incremented */ + TPM_DELEGATE_PUBLIC publicInfo; /* The public parameters for the blob */ + TPM_ENCAUTH delAuth; /* The encrypted new AuthData for the blob. The encryption + key is the shared secret from the OSAP protocol.*/ + TPM_AUTHHANDLE authHandle; /* The authorization session handle TPM Owner authentication + */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest. HMAC key:ownerAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_SECRET savedAuth; /* saved copy for response */ + TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ + TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ + TPM_BOOL writeAllNV = FALSE; + TPM_DIGEST a1Auth; + TPM_DELEGATE_SENSITIVE m1DelegateSensitive; + TPM_STORE_BUFFER delegateSensitive_sbuffer; /* serialization of delegateSensitive */ + TPM_DELEGATE_OWNER_BLOB b1DelegateOwnerBlob; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORE_BUFFER blobSbuffer; /* The partially encrypted delegation + information. */ + + printf("TPM_Process_DelegateCreateOwnerDelegation: Ordinal Entry\n"); + TPM_DelegatePublic_Init(&publicInfo); /* freed @1 */ + TPM_DelegateSensitive_Init(&m1DelegateSensitive); /* freed @2 */ + TPM_Sbuffer_Init(&delegateSensitive_sbuffer); /* freed @3 */ + TPM_DelegateOwnerBlob_Init(&b1DelegateOwnerBlob); /* freed @4 */ + TPM_Sbuffer_Init(&blobSbuffer); /* freed @5 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get increment parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadBool(&increment, &command, ¶mSize); + } + /* get publicInfo parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateCreateOwnerDelegation: increment %02x\n", increment); + returnCode = TPM_DelegatePublic_Load(&publicInfo, &command, ¶mSize); + } + /* get delAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Load(delAuth, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DelegateCreateOwnerDelegation: Error, " + "command has %u extra bytes\n", paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. The TPM SHALL authenticate the command using TPM Owner authentication. Return TPM_AUTHFAIL + on failure. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_OWNER, + ordinal, + NULL, + NULL, /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + /* make a copy of the HMAC key for the response, since it MAY be invalidated */ + TPM_Secret_Copy(savedAuth, *hmacKey); + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Locate publicInfo -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate the + row return TPM_BADINDEX if not found */ + /* a. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_FamilyTable_GetEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + publicInfo.familyID); + } + /* 3. If the TPM Owner authentication is in fact a delegation, then the TPM SHALL validate the + command and parameters using Delegation authorisation, then */ + if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) { + /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, + auth_session_data); + } + /* a. Validate that authHandle -> familyID equals publicInfo -> familyID return + TPM_DELEGATE_FAMILY */ + if (returnCode == TPM_SUCCESS) { + if (publicInfo.familyID != delegatePublic->familyID) { + printf("TPM_Process_DelegateCreateOwnerDelegation: Error, " + "familyID %u should be %u\n", + publicInfo.familyID, delegatePublic->familyID); + returnCode = TPM_DELEGATE_FAMILY; + } + } + /* b. If FR -> flags -> TPM_FAMFLAG_ENABLED is FALSE, return error TPM_DISABLED_CMD. */ + if (returnCode == TPM_SUCCESS) { + if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) { + printf("TPM_Process_DelegateCreateOwnerDelegation: Error, family %u disabled\n", + publicInfo.familyID); + returnCode = TPM_DISABLED_CMD; + } + } + /* c. Verify that the delegation bits in publicInfo do not grant more permissions then + currently delegated. Otherwise return error TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_Delegations_CheckPermissionDelegation(&(publicInfo.permissions), + &(delegatePublic->permissions)); + } + } + /* 4. Check that publicInfo -> delegateType is TPM_DEL_OWNER_BITS */ + if (returnCode == TPM_SUCCESS) { + if (publicInfo.permissions.delegateType != TPM_DEL_OWNER_BITS) { + printf("TPM_Process_DelegateCreateOwnerDelegation: Error, bad delegateType %08x\n", + publicInfo.permissions.delegateType); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 5. Verify that authHandle indicates an OSAP or DSAP session return TPM_INVALID_AUTHHANDLE on + error */ + /* NOTE Done by TPM_AuthSessions_GetData() */ + /* 7. Create a1 by decrypting delAuth according to the ADIP indicated by authHandle */ + /* NOTE 7. moved before 6. because it needs the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_Decrypt(a1Auth, + NULL, + delAuth, + auth_session_data, + NULL, + NULL, + FALSE); /* even and odd */ + } + /* 6. If increment == TRUE */ + if ((returnCode == TPM_SUCCESS) && increment) { + /* a. Increment FR -> verificationCount */ + familyRow->verificationCount++; + writeAllNV = TRUE; + /* b. Set TPM_STCLEAR_DATA -> ownerReference to TPM_KH_OWNER */ + tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER; + /* c. The TPM invalidates sessions */ + /* i. MUST invalidate all DSAP sessions */ + /* ii. MUST invalidate all OSAP sessions associated with the delegation table */ + /* iii. MAY invalidate any other session */ + TPM_AuthSessions_TerminatexSAP(&continueAuthSession, + authHandle, + tpm_state->tpm_stclear_data.authSessions); + } + /* 8. Create M1 a TPM_DELEGATE_SENSITIVE structure */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateCreateOwnerDelegation: Creating TPM_DELEGATE_SENSITIVE\n"); + /* a. Set M1 -> tag to TPM_TAG_DELEGATE_SENSITIVE */ + /* NOTE Done by TPM_DelegateSensitive_Init() */ + /* b. Set M1 -> authValue to a1 */ + TPM_Secret_Copy(m1DelegateSensitive.authValue, a1Auth); + /* c. Set other M1 fields as determined by the TPM vendor */ + } + /* 9. Create M2 the encryption of M1 using TPM_DELEGATE_KEY */ + /* serialize M1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateSensitive_Store(&delegateSensitive_sbuffer, &m1DelegateSensitive); + } + /* encrypt with delegate key */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateCreateOwnerDelegation: Encrypting TPM_DELEGATE_SENSITIVE\n"); + returnCode = + TPM_SymmetricKeyData_EncryptSbuffer(&(b1DelegateOwnerBlob.sensitiveArea), + &delegateSensitive_sbuffer, + tpm_state->tpm_permanent_data.delegateKey); + } + /* 10. Create B1 a TPM_DELEGATE_OWNER_BLOB */ + /* a. Set B1 -> tag to TPM_TAG_DELG_OWNER_BLOB */ + /* NOTE Done by TPM_DelegateOwnerBlob_Init() */ + /* b. Set B1 -> pub to publicInfo */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateCreateOwnerDelegation: Creating TPM_DELEGATE_OWNER_BLOB\n"); + returnCode = TPM_DelegatePublic_Copy(&(b1DelegateOwnerBlob.pub), &publicInfo); + } + /* c. Set B1 -> sensitiveSize to the size of M2 */ + /* d. Set B1 -> sensitiveArea to M2 */ + /* NOTE Encrypted directly into b1DelegateOwnerBlob */ + /* e. Set B1 -> integrityDigest to NULL */ + /* NOTE Done by TPM_DelegateOwnerBlob_Init() */ + if (returnCode == TPM_SUCCESS) { + /* f. Set B1 pub -> verificationCount to FR -> verificationCount */ + b1DelegateOwnerBlob.pub.verificationCount = familyRow->verificationCount; + /* 11. The TPM sets additionalArea and additionalAreaSize appropriate for this TPM. The + information MAY include symmetric IV, symmetric mode of encryption and other data that + allows the TPM to process the blob in the future. */ + /* 12. Create H1 the HMAC of B1 using tpmProof as the secret */ + /* 13. Set B1 -> integrityDigest to H1 */ + /* NOTE It is safe to HMAC directly into TPM_DELEGATE_OWNER_BLOB, since the structure + is serialized before the HMAC is performed */ + returnCode = TPM_HMAC_GenerateStructure + (b1DelegateOwnerBlob.integrityDigest, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &b1DelegateOwnerBlob, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store); /* store function */ + } + /* 14. Ignore continueAuthSession on input set continueAuthSession to FALSE on output */ + if (returnCode == TPM_SUCCESS) { + continueAuthSession = FALSE; + } + /* 15. Return B1 as blob */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateOwnerBlob_Store(&blobSbuffer, &b1DelegateOwnerBlob); + } + /* write back TPM_PERMANENT_DATA if required */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DelegateCreateOwnerDelegation: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return blobSize and blob */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &blobSbuffer); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + savedAuth, /* saved HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_DelegatePublic_Delete(&publicInfo); /* @1 */ + TPM_DelegateSensitive_Delete(&m1DelegateSensitive); /* @2 */ + TPM_Sbuffer_Delete(&delegateSensitive_sbuffer); /* @3 */ + TPM_DelegateOwnerBlob_Delete(&b1DelegateOwnerBlob); /* @4 */ + TPM_Sbuffer_Delete(&blobSbuffer); /* @5 */ + return rcf; +} + +/* 19.4 TPM_Delegate_LoadOwnerDelegation rev 109 + + This command loads a delegate table row blob into a non-volatile delegate table row. + Delegate_LoadOwnerDelegation can be used during manufacturing or on first boot (when no Owner is + installed), or after an Owner is installed. If an Owner is installed, Delegate_LoadOwnerDelegation + requires Owner authorisation, and sensitive information must be encrypted. + + Burn-out of TPM non-volatile storage by inappropriate use is mitigated by the TPM's normal limits + on NV- writes in the absence of an Owner. Tables can be locked after loading using + TPM_Delegate_Manage, to prevent subsequent tampering. + + A management system outside the TPM is expected to manage the delegate table rows stored on the + TPM, and can overwrite any previously stored data. There is no way to explicitly delete a + delegation entry. A new entry can overwrite an invalid entry. + + This command cannot be used to load key delegation blobs into the TPM +*/ + +TPM_RESULT TPM_Process_DelegateLoadOwnerDelegation(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_DELEGATE_INDEX index; /* The index of the delegate row to be written */ + uint32_t blobSize; /* The size of the delegate blob */ + TPM_DELEGATE_OWNER_BLOB d1Blob; /* Delegation information, including encrypted + portions as appropriate */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle TPM Owner + authentication */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with + authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the + authorization session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest. HMAC + key:ownerAuth */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_SECRET savedAuth; /* saved copy for response */ + TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ + TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ + TPM_DELEGATE_SENSITIVE s1DelegateSensitive; + TPM_DELEGATE_TABLE_ROW *delegateTableRow; + unsigned char *stream; + uint32_t stream_size; + uint32_t nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; + /* temp for noOwnerNVWrite, initialize to + silence compiler */ + TPM_BOOL nv1Incremented = FALSE; /* flag that nv1 was incremented */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back data */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_DelegateLoadOwnerDelegation: Ordinal Entry\n"); + TPM_DelegateOwnerBlob_Init(&d1Blob); /* freed @1 */ + TPM_DelegateSensitive_Init(&s1DelegateSensitive); /* freed @2 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get index parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&index, &command, ¶mSize); + } + /* get blobSize parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateLoadOwnerDelegation: index %u\n", index); + returnCode = TPM_Load32(&blobSize, &command, ¶mSize); + } + /* get blob parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateOwnerBlob_Load(&d1Blob, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DelegateLoadOwnerDelegation: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Map blob to D1 a TPM_DELEGATE_OWNER_BLOB. */ + /* a. Validate that D1 -> tag == TPM_TAG_DELEGATE_OWNER_BLOB */ + /* Done by TPM_DelegateOwnerBlob_Load() */ + /* 2. Locate D1 -> pub -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, + return TPM_BADINDEX if not found */ + /* 3. Set FR to TPM_FAMILY_TABLE -> famTableRow[familyRow] */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + d1Blob.pub.familyID); + } + /* 4. If TPM Owner is installed */ + if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) { + /* a. Validate the command and parameters using TPM Owner authorization, return + TPM_AUTHFAIL on error */ + if (returnCode == TPM_SUCCESS) { + if (tag != TPM_TAG_RQU_AUTH1_COMMAND) { + printf("TPM_Process_DelegateLoadOwnerDelegation: Error, " + "owner installed but no authorization\n"); + returnCode = TPM_AUTHFAIL; + } + } + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth),/* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + /* make a copy of the HMAC key for the response, since it MAY be invalidated */ + TPM_Secret_Copy(savedAuth, *hmacKey); + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* b. If the command is delegated (authHandle session type is TPM_PID_DSAP or through + ownerReference delegation), verify that D1 -> pub -> familyID matches authHandle -> + familyID, on error return TPM_DELEGATE_FAMILY */ + if ((returnCode == TPM_SUCCESS) && + ((auth_session_data->protocolID == TPM_PID_DSAP) || + (tpm_state->tpm_stclear_data.ownerReference != TPM_KH_OWNER))) { + /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, + auth_session_data); + } + if (returnCode == TPM_SUCCESS) { + if (d1Blob.pub.familyID != delegatePublic->familyID) { + printf("TPM_Process_DelegateLoadOwnerDelegation: Error, " + "familyID %u should be %u\n", + d1Blob.pub.familyID, delegatePublic->familyID); + returnCode = TPM_DELEGATE_FAMILY; + } + } + } + } + /* 5. Else */ + if ((returnCode == TPM_SUCCESS) && !tpm_state->tpm_permanent_data.ownerInstalled) { + /* a. If FR -> flags -> TPM_DELEGATE_ADMIN_LOCK is TRUE return TPM_DELEGATE_LOCK */ + if (returnCode == TPM_SUCCESS) { + if (familyRow->flags & TPM_DELEGATE_ADMIN_LOCK) { + printf("TPM_Process_DelegateLoadOwnerDelegation: Error, row locked\n"); + returnCode = TPM_DELEGATE_LOCK; + } + } + /* b. Validate max NV writes without an owner */ + if (returnCode == TPM_SUCCESS) { + /* i. Set NV1 to PD -> noOwnerNVWrite */ + nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; + /* ii. Increment NV1 by 1 */ + nv1++; + /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */ + if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) { + printf("TPM_Process_DelegateLoadOwnerDelegation: Error, " + "max NV writes %d w/o owner reached\n", + tpm_state->tpm_permanent_data.noOwnerNVWrite); + returnCode = TPM_MAXNVWRITES; + } + } + /* iv. Set PD -> noOwnerNVWrite to NV1 */ + if (returnCode == TPM_SUCCESS) { + /* NOTE Don't update the noOwnerNVWrite value until determining that the write will be + performed */ + nv1Incremented = TRUE; + } + } + /* 6. If FR -> flags -> TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ + /* NOTE Done by TPM_FamilyTable_GetEnabledEntry() */ + /* 7. If TPM Owner is installed, validate the integrity of the blob */ + if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_Process_DelegateLoadOwnerDelegation: Checking integrityDigest\n"); + /* a. Copy D1 -> integrityDigest to H2 */ + /* b. Set D1 -> integrityDigest to NULL */ + /* c. Create H3 the HMAC of D1 using tpmProof as the secret */ + /* d. Compare H2 to H3, return TPM_AUTHFAIL on mismatch */ + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &d1Blob, /* structure */ + d1Blob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store, /* store function */ + TPM_AUTHFAIL); /* error code */ + } + /* 8. If TPM Owner is installed, create S1 a TPM_DELEGATE_SENSITIVE area by decrypting D1 -> + sensitiveArea using TPM_DELEGATE_KEY. */ + if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) { + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateLoadOwnerDelegation: Decrypting sensitiveArea\n"); + returnCode = + TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive, /* decrypted data */ + &(d1Blob.sensitiveArea), /* encrypted */ + tpm_state->tpm_permanent_data.delegateKey); + } + } + /* 8. Otherwise set S1 = D1 -> sensitiveArea */ + if ((returnCode == TPM_SUCCESS) && !tpm_state->tpm_permanent_data.ownerInstalled) { + stream = d1Blob.sensitiveArea.buffer; + stream_size = d1Blob.sensitiveArea.size; + returnCode = TPM_DelegateSensitive_Load(&s1DelegateSensitive, &stream, &stream_size); + } + /* 9. Validate S1 */ + /* a. Validate that S1 -> tag == TPM_TAG_DELEGATE_SENSITIVE, return TPM_INVALID_STRUCTURE on + error */ + /* NOTE Done by TPM_DelegateSensitive_Load() */ + /* 10. Validate that index is a valid value for delegateTable, return TPM_BADINDEX on error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateTable_GetRow(&delegateTableRow, + &(tpm_state->tpm_permanent_data.delegateTable), + index); + } + /* 11. The TPM invalidates sessions */ + if (returnCode == TPM_SUCCESS) { + /* a. MUST invalidate all DSAP sessions */ + /* b. MUST invalidate all OSAP sessions associated with the delegation table */ + /* c. MAY invalidate any other session */ + TPM_AuthSessions_TerminatexSAP(&continueAuthSession, + authHandle, + tpm_state->tpm_stclear_data.authSessions); + } + /* 12. Copy data to the delegate table row */ + if (returnCode == TPM_SUCCESS) { + /* a. Copy the TPM_DELEGATE_PUBLIC from D1 -> pub to TPM_DELEGATE_TABLE -> delRow[index] -> + pub. */ + returnCode = TPM_DelegatePublic_Copy(&delegateTableRow->pub, &(d1Blob.pub)); + writeAllNV = TRUE; + } + if (returnCode == TPM_SUCCESS) { + delegateTableRow->valid = TRUE; + /* b. Copy the TPM_SECRET from S1 -> authValue to TPM_DELEGATE_TABLE -> delRow[index] -> + authValue. */ + TPM_Secret_Copy(delegateTableRow->authValue, s1DelegateSensitive.authValue); + /* c. Set TPM_STCLEAR_DATA-> ownerReference to TPM_KH_OWNER */ + tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER; + } + if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) { + /* d. If authHandle is of type DSAP then continueAuthSession MUST set to FALSE */ + if (auth_session_data->protocolID == TPM_PID_DSAP) { + continueAuthSession = FALSE; + } + } + /* if writing NV and this is a no owner NV write, update the count with the previously + incremented value */ + if (returnCode == TPM_SUCCESS) { + if (writeAllNV && nv1Incremented) { + printf("TPM_Process_DelegateLoadOwnerDelegation: noOwnerNVWrite %u\n", nv1); + tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1; + } + } + /* write back TPM_PERMANENT_DATA */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DelegateLoadOwnerDelegation: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + savedAuth, /* saved HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_DelegateOwnerBlob_Delete(&d1Blob); /* @1 */ + TPM_DelegateSensitive_Delete(&s1DelegateSensitive); /* @2 */ + return rcf; +} + +/* 19.5 TPM_Delegate_ReadTable rev 87 + + This command is used to read from the TPM the public contents of the family and delegate tables + that are stored on the TPM. Such data is required during external verification of tables. + + There are no restrictions on the execution of this command; anyone can read this information + regardless of the state of the PCRs, regardless of whether they know any specific AuthData value + and regardless of whether or not the enable and admin bits are set one way or the other. +*/ + +TPM_RESULT TPM_Process_DelegateReadTable(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORE_BUFFER familySbuffer; /* Array of TPM_FAMILY_TABLE_ENTRY + elements */ + TPM_STORE_BUFFER delegateSbuffer; /* Array of TPM_DELEGATE_INDEX and + TPM_DELEGATE_PUBLIC elements */ + + printf("TPM_Process_DelegateReadTable: Ordinal Entry\n"); + TPM_Sbuffer_Init(&familySbuffer); /* freed @1 */ + TPM_Sbuffer_Init(&delegateSbuffer); /* freed @2 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DelegateReadTable: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Set familyTableSize to the number of valid families on the TPM times + sizeof(TPM_FAMILY_TABLE_ELEMENT). */ + /* NOTE Done below by TPM_Sbuffer_AppendAsSizedBuffer() */ + /* 2. Copy the valid entries in the internal family table to the output array familyTable */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_FamilyTable_StoreValid(&familySbuffer, + &(tpm_state->tpm_permanent_data.familyTable), + TRUE); /* standard, store the tag */ + } + /* 3. Set delegateTableSize to the number of valid delegate table entries on the TPM times + (sizeof(TPM_DELEGATE_PUBLIC) + 4). */ + /* NOTE Done below by TPM_Sbuffer_AppendAsSizedBuffer() */ + /* 4. For each valid entry */ + /* a. Write the TPM_DELEGATE_INDEX to delegateTable */ + /* b. Copy the TPM_DELEGATE_PUBLIC to delegateTable */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateTable_StoreValid(&delegateSbuffer, + &(tpm_state->tpm_permanent_data.delegateTable)); + } + /* 5. Return TPM_SUCCESS */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DelegateReadTable: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append familyTableSize and familyTable */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &familySbuffer); + } + if (returnCode == TPM_SUCCESS) { + /* append delegateTableSize and delegateTable */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &delegateSbuffer); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&familySbuffer); /* @1 */ + TPM_Sbuffer_Delete(&delegateSbuffer); /* @2 */ + return rcf; +} + +/* 19.6 TPM_Delegate_UpdateVerification rev 87 + + UpdateVerification sets the verificationCount in an entity (a blob or a delegation row) to the + current family value, in order that the delegations represented by that entity will continue to + be accepted by the TPM. +*/ + +TPM_RESULT TPM_Process_DelegateUpdateVerification(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_SIZED_BUFFER inputData; /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB or + TPM_DELEGATE_INDEX */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* Authorization HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey = NULL; + unsigned char *stream; /* temp input stream */ + uint32_t stream_size; + TPM_STRUCTURE_TAG d1Tag; /* input structure tag */ + TPM_DELEGATE_INDEX d1DelegateIndex; + TPM_DELEGATE_OWNER_BLOB d1DelegateOwnerBlob; + TPM_DELEGATE_KEY_BLOB d1DelegateKeyBlob; + TPM_DELEGATE_TABLE_ROW *d1DelegateTableRow = NULL; + TPM_FAMILY_ID familyID = 0; + TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ + TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORE_BUFFER outputDataSbuffer; /* TPM_DELEGATE_KEY_BLOB or + TPM_DELEGATE_OWNER_BLOB */ + + printf("TPM_Process_DelegateUpdateVerification: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&inputData); /* freed @1 */ + TPM_DelegateOwnerBlob_Init(&d1DelegateOwnerBlob); /* freed @2 */ + TPM_DelegateKeyBlob_Init(&d1DelegateKeyBlob); /* freed @3 */ + TPM_Sbuffer_Init(&outputDataSbuffer); /* freed @4 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get inputData parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&inputData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DelegateUpdateVerification: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Verify the TPM Owner, directly or indirectly through delegation, authorizes the command + and parameters, on error return TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Determine the type of inputData (TPM_DELEGATE_TABLE_ROW or TPM_DELEGATE_OWNER_BLOB + or TPM_DELEGATE_KEY_BLOB) and map D1 to that structure */ + if (returnCode == TPM_SUCCESS) { + /* use a temporary copy so the original values are not moved */ + stream = inputData.buffer; + stream_size = inputData.size; + /* the inputData is either a table index or a blob */ + if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) { + /* if it's an index, get the index */ + returnCode = TPM_Load32(&d1DelegateIndex, &stream, &stream_size); + } + else { + /* if it's a blob, get the blob structure tag to determine the blob type */ + returnCode = TPM_Load16(&d1Tag, &stream, &stream_size); + } + } + if (returnCode == TPM_SUCCESS) { + /* use a temporary copy so the original values are not moved */ + stream = inputData.buffer; + stream_size = inputData.size; + /* if inputData is a table index */ + if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) { + /* a. Mapping to TPM_DELEGATE_TABLE_ROW requires taking inputData as a tableIndex and + locating the appropriate row in the table */ + returnCode = + TPM_DelegateTable_GetValidRow(&d1DelegateTableRow, + &(tpm_state->tpm_permanent_data.delegateTable), + d1DelegateIndex); + familyID = d1DelegateTableRow->pub.familyID; + } + /* if inputData is a blob */ + else { + switch (d1Tag) { + case TPM_TAG_DELEGATE_OWNER_BLOB: + returnCode = TPM_DelegateOwnerBlob_Load(&d1DelegateOwnerBlob, + &stream, &stream_size); + familyID = d1DelegateOwnerBlob.pub.familyID; + break; + case TPM_TAG_DELG_KEY_BLOB: + returnCode = TPM_DelegateKeyBlob_Load(&d1DelegateKeyBlob, + &stream, &stream_size); + familyID = d1DelegateKeyBlob.pub.familyID; + break; + default: + printf("TPM_Process_DelegateUpdateVerification: Error, invalid tag %04hx\n", d1Tag); + returnCode = TPM_BAD_PARAMETER; + break; + } + } + } + /* 3. If D1 is TPM_DELEGATE_OWNER_BLOB or TPM_DELEGATE_KEY_BLOB Validate the integrity of + D1 */ + if ((returnCode == TPM_SUCCESS) && (inputData.size != sizeof(TPM_DELEGATE_INDEX))) { + /* a. Copy D1 -> integrityDigest to H2 */ + /* b. Set D1 -> integrityDigest to NULL */ + /* c. Create H3 the HMAC of D1 using tpmProof as the secret */ + /* d. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */ + switch (d1Tag) { + case TPM_TAG_DELEGATE_OWNER_BLOB: + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &d1DelegateOwnerBlob, /* structure */ + d1DelegateOwnerBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store, /* store function */ + TPM_AUTHFAIL); /* error code */ + break; + case TPM_TAG_DELG_KEY_BLOB: + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &d1DelegateKeyBlob, /* structure */ + d1DelegateKeyBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store, /* store function */ + TPM_AUTHFAIL); /* error code */ + break; + /* default error tested above */ + } + } + /* 4. Locate (D1 -> pub -> familyID) in the TPM_FAMILY_TABLE and set familyRow to indicate row, + return TPM_BADINDEX if not found */ + /* 5. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_FamilyTable_GetEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + familyID); + } + if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) { + /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, + auth_session_data); + } + /* 6. If delegated, verify that family of the delegated Owner-auth is the same as D1: + (authHandle -> familyID) == (D1 -> pub -> familyID); otherwise return error + TPM_DELEGATE_FAMILY */ + if (returnCode == TPM_SUCCESS) { + if (familyID != delegatePublic->familyID) { + printf("TPM_Process_DelegateUpdateVerification: Error, " + "familyID %u should be %u\n", + familyID, delegatePublic->familyID); + returnCode = TPM_DELEGATE_FAMILY; + } + } + /* 7. If delegated, verify that the family of the delegated Owner-auth is enabled: if + (authHandle -> familyID -> flags TPM_FAMFLAG_ENABLED) is FALSE, return + TPM_DISABLED_CMD */ + if (returnCode == TPM_SUCCESS) { + if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) { + printf("TPM_Process_DelegateUpdateVerification: Error, family %u disabled\n", + familyID); + returnCode = TPM_DISABLED_CMD; + } + } + } + /* 8. Set D1 -> verificationCount to FR -> verificationCount */ + if (returnCode == TPM_SUCCESS) { + if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) { + d1DelegateTableRow->pub.verificationCount = familyRow->verificationCount; + writeAllNV = TRUE; + } + else { + switch (d1Tag) { + case TPM_TAG_DELEGATE_OWNER_BLOB: + d1DelegateOwnerBlob.pub.verificationCount = familyRow->verificationCount; + break; + case TPM_TAG_DELG_KEY_BLOB: + d1DelegateKeyBlob.pub.verificationCount = familyRow->verificationCount; + break; + /* default error tested above */ + } + } + } + /* 9. If D1 is TPM_DELEGATE_OWNER_BLOB or TPM_DELEGATE_KEY_BLOB set the integrity of D1 */ + if ((returnCode == TPM_SUCCESS) && (inputData.size != sizeof(TPM_DELEGATE_INDEX))) { + /* a. Set D1 -> integrityDigest to NULL */ + /* NOTE Done by TPM_HMAC_GenerateStructure() */ + /* b. Create H1 the HMAC of D1 using tpmProof as the secret */ + /* c. Set D1 -> integrityDigest to H1 */ + /* NOTE It is safe to HMAC directly into the blob, since the structure is serialized before + the HMAC is performed */ + switch (d1Tag) { + case TPM_TAG_DELEGATE_OWNER_BLOB: + returnCode = TPM_HMAC_GenerateStructure + (d1DelegateOwnerBlob.integrityDigest, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &d1DelegateOwnerBlob, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store); /* store function */ + break; + case TPM_TAG_DELG_KEY_BLOB: + returnCode = TPM_HMAC_GenerateStructure + (d1DelegateKeyBlob.integrityDigest, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &d1DelegateKeyBlob, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store); /* store function */ + break; + } + } + /* If updating a delegate row, write back TPM_PERMANENT_DATA */ + if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) { + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + } + /* 10. If D1 is a blob recreate the blob and return it */ + else { + if (returnCode == TPM_SUCCESS) { + switch (d1Tag) { + case TPM_TAG_DELEGATE_OWNER_BLOB: + returnCode = TPM_DelegateOwnerBlob_Store(&outputDataSbuffer, + &d1DelegateOwnerBlob); + break; + case TPM_TAG_DELG_KEY_BLOB: + returnCode = TPM_DelegateKeyBlob_Store(&outputDataSbuffer, + &d1DelegateKeyBlob); + break; + /* default error tested above */ + } + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DelegateUpdateVerification: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return outputSize and outputData */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &outputDataSbuffer); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&inputData); /* @1 */ + TPM_DelegateOwnerBlob_Delete(&d1DelegateOwnerBlob); /* @2 */ + TPM_DelegateKeyBlob_Delete(&d1DelegateKeyBlob); /* @3 */ + TPM_Sbuffer_Delete(&outputDataSbuffer); /* @4 */ + return rcf; +} + +/* 19.7 TPM_Delegate_VerifyDelegation rev 105 + + VerifyDelegation interprets a delegate blob and returns success or failure, depending on whether + the blob is currently valid. The delegate blob is NOT loaded into the TPM. +*/ + +TPM_RESULT TPM_Process_DelegateVerifyDelegation(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_SIZED_BUFFER delegation; /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + unsigned char *stream; /* temp input stream */ + uint32_t stream_size; + TPM_STRUCTURE_TAG d1Tag; /* input structure tag */ + TPM_DELEGATE_OWNER_BLOB d1DelegateOwnerBlob; + TPM_DELEGATE_KEY_BLOB d1DelegateKeyBlob; + TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ + TPM_FAMILY_ID familyID; + TPM_FAMILY_VERIFICATION verificationCount = 0; + TPM_DELEGATE_SENSITIVE s1DelegateSensitive; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_DelegateVerifyDelegation: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&delegation); /* freed @1 */ + TPM_DelegateOwnerBlob_Init(&d1DelegateOwnerBlob); /* freed @2 */ + TPM_DelegateKeyBlob_Init(&d1DelegateKeyBlob); /* freed @3 */ + TPM_DelegateSensitive_Init(&s1DelegateSensitive); /* freed @4 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get delegation parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&delegation, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DelegateVerifyDelegation: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Determine the type of blob */ + if (returnCode == TPM_SUCCESS) { + /* use a temporary copy so the original values are not moved */ + stream = delegation.buffer; + stream_size = delegation.size; + returnCode = TPM_Load16(&d1Tag, &stream, &stream_size); + } + if (returnCode == TPM_SUCCESS) { + /* use a temporary copy so the original values are not moved */ + stream = delegation.buffer; + stream_size = delegation.size; + switch (d1Tag) { + /* 1. If delegation -> tag is equal to TPM_TAG_DELEGATE_OWNER_BLOB then */ + case TPM_TAG_DELEGATE_OWNER_BLOB: + /* a. Map D1 a TPM_DELEGATE_BLOB_OWNER to delegation */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateOwnerBlob_Load(&d1DelegateOwnerBlob, + &stream, &stream_size); + } + if (returnCode == TPM_SUCCESS) { + familyID = d1DelegateOwnerBlob.pub.familyID; + verificationCount = d1DelegateOwnerBlob.pub.verificationCount; + } + break; + /* 2. Else if delegation -> tag = TPM_TAG_DELG_KEY_BLOB */ + case TPM_TAG_DELG_KEY_BLOB: + /* a. Map D1 a TPM_DELEGATE_KEY_BLOB to delegation */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateKeyBlob_Load(&d1DelegateKeyBlob, &stream, &stream_size); + } + if (returnCode == TPM_SUCCESS) { + familyID = d1DelegateKeyBlob.pub.familyID; + verificationCount = d1DelegateKeyBlob.pub.verificationCount; + } + break; + /* 3. Else return TPM_BAD_PARAMETER */ + default: + printf("TPM_Process_DelegateVerifyDelegation: Error, invalid tag %04hx\n", d1Tag); + returnCode = TPM_BAD_PARAMETER; + break; + } + } + /* 4. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return + TPM_BADINDEX if not found */ + /* 5. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ + /* 6. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + familyID); + } + /* 7. Validate that D1 -> pub -> verificationCount matches FR -> verificationCount, on mismatch + return TPM_FAMILYCOUNT */ + if (returnCode == TPM_SUCCESS) { + if (verificationCount != familyRow->verificationCount) { + printf("TPM_Process_DelegateVerifyDelegation: Error, " + "verificationCount mismatch %u %u\n", + verificationCount, familyRow->verificationCount); + returnCode = TPM_FAMILYCOUNT; + } + } + /* 8. Validate the integrity of D1 */ + /* a. Copy D1 -> integrityDigest to H2 */ + /* b. Set D1 -> integrityDigest to NULL */ + /* c. Create H3 the HMAC of D1 using tpmProof as the secret */ + /* d. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */ + if (returnCode == TPM_SUCCESS) { + if (d1Tag == TPM_TAG_DELEGATE_OWNER_BLOB) { + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &d1DelegateOwnerBlob, /* structure */ + d1DelegateOwnerBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store, /* store function */ + TPM_AUTHFAIL); /* error code */ + } + else { + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &d1DelegateKeyBlob, /* structure */ + d1DelegateKeyBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store, /* store function */ + TPM_AUTHFAIL); /* error code */ + } + } + /* 9. Create S1 a TPM_DELEGATE_SENSITIVE area by decrypting D1 -> sensitiveArea using + TPM_DELEGATE_KEY */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DelegateVerifyDelegation: Decrypting sensitiveArea\n"); + if (d1Tag == TPM_TAG_DELEGATE_OWNER_BLOB) { + returnCode = + TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive, + &(d1DelegateOwnerBlob.sensitiveArea), + tpm_state->tpm_permanent_data.delegateKey); + } + else { + returnCode = + TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive, + &(d1DelegateKeyBlob.sensitiveArea), + tpm_state->tpm_permanent_data.delegateKey); + } + } + /* 10. Validate S1 values */ + /* a. S1 -> tag is TPM_TAG_DELEGATE_SENSITIVE */ + /* NOTE Done by TPM_DelegateSensitive_DecryptEncData() */ + /* b. Return TPM_BAD_PARAMETER on error */ + /* 11. Return TPM_SUCCESS */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DelegateVerifyDelegation: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&delegation); /* @1 */ + TPM_DelegateOwnerBlob_Delete(&d1DelegateOwnerBlob); /* @2 */ + TPM_DelegateKeyBlob_Delete(&d1DelegateKeyBlob); /* @3 */ + TPM_DelegateSensitive_Delete(&s1DelegateSensitive); /* @4 */ + return rcf; +} diff --git a/src/tpm12/tpm_delegate.h b/src/tpm12/tpm_delegate.h new file mode 100644 index 0000000..d4f6cb6 --- /dev/null +++ b/src/tpm12/tpm_delegate.h @@ -0,0 +1,257 @@ +/********************************************************************************/ +/* */ +/* Delegate Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_delegate.h 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_DELEGATE_H +#define TPM_DELEGATE_H + +#include "tpm_structures.h" + +/* + TPM_DELEGATE_PUBLIC +*/ + +void TPM_DelegatePublic_Init(TPM_DELEGATE_PUBLIC *tpm_delegate_public); +TPM_RESULT TPM_DelegatePublic_Load(TPM_DELEGATE_PUBLIC *tpm_delegate_public, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DelegatePublic_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_PUBLIC *tpm_delegate_public); +void TPM_DelegatePublic_Delete(TPM_DELEGATE_PUBLIC *tpm_delegate_public); + +TPM_RESULT TPM_DelegatePublic_Copy(TPM_DELEGATE_PUBLIC *dest, + TPM_DELEGATE_PUBLIC *src); + +/* + TPM_DELEGATE_SENSITIVE +*/ + +void TPM_DelegateSensitive_Init(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive); +TPM_RESULT TPM_DelegateSensitive_Load(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DelegateSensitive_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive); +void TPM_DelegateSensitive_Delete(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive); + +TPM_RESULT TPM_DelegateSensitive_DecryptEncData(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive, + TPM_SIZED_BUFFER *sensitiveArea, + TPM_SYMMETRIC_KEY_TOKEN delegateKey); + +/* + TPM_DELEGATIONS +*/ + +void TPM_Delegations_Init(TPM_DELEGATIONS *tpm_delegations); +TPM_RESULT TPM_Delegations_Load(TPM_DELEGATIONS *tpm_delegations, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Delegations_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATIONS *tpm_delegations); +void TPM_Delegations_Delete(TPM_DELEGATIONS *tpm_delegations); + +void TPM_Delegations_Copy(TPM_DELEGATIONS *dest, + TPM_DELEGATIONS *src); +TPM_RESULT TPM_Delegations_CheckPermissionDelegation(TPM_DELEGATIONS *newDelegations, + TPM_DELEGATIONS *currentDelegations); +TPM_RESULT TPM_Delegations_CheckPermission(tpm_state_t *tpm_state, + TPM_DELEGATE_PUBLIC *delegatePublic, + TPM_ENT_TYPE entityType, + TPM_COMMAND_CODE ordinal); +TPM_RESULT TPM_Delegations_CheckOwnerPermission(TPM_DELEGATIONS *tpm_delegations, + TPM_COMMAND_CODE ordinal); +TPM_RESULT TPM_Delegations_CheckKeyPermission(TPM_DELEGATIONS *tpm_delegations, + TPM_COMMAND_CODE ordinal); + +/* + TPM_DELEGATE_OWNER_BLOB +*/ + +void TPM_DelegateOwnerBlob_Init(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob); +TPM_RESULT TPM_DelegateOwnerBlob_Load(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DelegateOwnerBlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob); +void TPM_DelegateOwnerBlob_Delete(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob); + +/* + TPM_DELEGATE_KEY_BLOB +*/ + +void TPM_DelegateKeyBlob_Init(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob); +TPM_RESULT TPM_DelegateKeyBlob_Load(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DelegateKeyBlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob); +void TPM_DelegateKeyBlob_Delete(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob); + +/* + TPM_FAMILY_TABLE +*/ + +void TPM_FamilyTable_Init(TPM_FAMILY_TABLE *tpm_family_table); +TPM_RESULT TPM_FamilyTable_Load(TPM_FAMILY_TABLE *tpm_family_table, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_FamilyTable_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_FAMILY_TABLE *tpm_family_table, + TPM_BOOL store_tag); +void TPM_FamilyTable_Delete(TPM_FAMILY_TABLE *tpm_family_table); + +TPM_RESULT TPM_FamilyTable_StoreValid(TPM_STORE_BUFFER *sbuffer, + const TPM_FAMILY_TABLE *tpm_family_table, + TPM_BOOL store_tag); +TPM_RESULT TPM_FamilyTable_GetEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, + TPM_FAMILY_TABLE *tpm_family_table, + TPM_FAMILY_ID familyID); +TPM_RESULT TPM_FamilyTable_GetEnabledEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, + TPM_FAMILY_TABLE *tpm_family_table, + TPM_FAMILY_ID familyID); +TPM_RESULT TPM_FamilyTable_IsSpace(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, + TPM_FAMILY_TABLE *tpm_family_table); + +/* + TPM_FAMILY_TABLE_ENTRY +*/ + +void TPM_FamilyTableEntry_Init(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry); +TPM_RESULT TPM_FamilyTableEntry_Load(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_FamilyTableEntry_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, + TPM_BOOL store_tag); +TPM_RESULT TPM_FamilyTableEntry_StorePublic(TPM_STORE_BUFFER *sbuffer, + const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, + TPM_BOOL store_tag); +void TPM_FamilyTableEntry_Delete(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry); + +/* + TPM_DELEGATE_TABLE +*/ + +void TPM_DelegateTable_Init(TPM_DELEGATE_TABLE *tpm_delegate_table); +TPM_RESULT TPM_DelegateTable_Load(TPM_DELEGATE_TABLE *tpm_delegate_table, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DelegateTable_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_TABLE *tpm_delegate_table); +void TPM_DelegateTable_Delete(TPM_DELEGATE_TABLE *tpm_delegate_table); + +TPM_RESULT TPM_DelegateTable_StoreValid(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_TABLE *tpm_delegate_table); +TPM_RESULT TPM_DelegateTable_GetRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow, + TPM_DELEGATE_TABLE *tpm_delegate_table, + uint32_t rowIndex); +TPM_RESULT TPM_DelegateTable_GetValidRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow, + TPM_DELEGATE_TABLE *tpm_delegate_table, + uint32_t rowIndex); + + +/* + TPM_DELEGATE_TABLE_ROW +*/ + +void TPM_DelegateTableRow_Init(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row); +TPM_RESULT TPM_DelegateTableRow_Load(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_DelegateTableRow_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row); +void TPM_DelegateTableRow_Delete(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row); + + + + +/* + Processing Functions +*/ + +TPM_RESULT TPM_Process_DelegateManage(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DelegateCreateKeyDelegation(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DelegateCreateOwnerDelegation(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DelegateLoadOwnerDelegation(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DelegateReadTable(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DelegateUpdateVerification(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DelegateVerifyDelegation(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +#endif diff --git a/src/tpm12/tpm_digest.c b/src/tpm12/tpm_digest.c new file mode 100644 index 0000000..0893912 --- /dev/null +++ b/src/tpm12/tpm_digest.c @@ -0,0 +1,162 @@ +/********************************************************************************/ +/* */ +/* Digest Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_digest.c 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_structures.h" + +#include "tpm_digest.h" + +/* TPM_Digest_Init resets a digest structure to zeros */ + +void TPM_Digest_Init(TPM_DIGEST tpm_digest) +{ + printf(" TPM_Digest_Init:\n"); + memset(tpm_digest, 0, TPM_DIGEST_SIZE); + return; +} + +/* TPM_Digest_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes +*/ + +TPM_RESULT TPM_Digest_Load(TPM_DIGEST tpm_digest, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Digest_Load:\n"); + rc = TPM_Loadn(tpm_digest, TPM_DIGEST_SIZE, stream, stream_size); + return rc; +} + +/* TPM_Digest_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + After use, call TPM_Sbuffer_Delete() to free memory +*/ + +TPM_RESULT TPM_Digest_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DIGEST tpm_digest) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Digest_Store:\n"); + rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE); + return rc; +} + +void TPM_Digest_Set(TPM_DIGEST tpm_digest) +{ + printf(" TPM_Digest_Set:\n"); + memset(tpm_digest, 0xff, TPM_DIGEST_SIZE); +} + +void TPM_Digest_Copy(TPM_DIGEST destination, const TPM_DIGEST source) +{ + printf(" TPM_Digest_Copy:\n"); + memcpy(destination, source, TPM_DIGEST_SIZE); + return; +} + +void TPM_Digest_XOR(TPM_DIGEST out, const TPM_DIGEST in1, const TPM_DIGEST in2) +{ + size_t i; + + printf(" TPM_Digest_XOR:\n"); + for (i = 0 ; i < TPM_DIGEST_SIZE ; i++) { + out[i] = in1[i] ^ in2[i]; + } + return; +} + +/* TPM_Digest_Compare() compares two digests, returning 0 if they are equal + */ + +TPM_RESULT TPM_Digest_Compare(const TPM_DIGEST expect, const TPM_DIGEST actual) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Digest_Compare:\n"); + rc = memcmp(expect, actual, TPM_DIGEST_SIZE); + if (rc != 0) { + printf("TPM_Digest_Compare: Error comparing digest\n"); + TPM_PrintFour(" TPM_Digest_Compare: Expect", expect); + TPM_PrintFour(" TPM_Digest_Compare: Actual", actual); + rc = TPM_AUTHFAIL; + } + return rc; +} + +void TPM_Digest_IsZero(TPM_BOOL *isZero, TPM_DIGEST tpm_digest) +{ + size_t i; + + printf(" TPM_Digest_IsZero:\n"); + for (i = 0, *isZero = TRUE ; (i < TPM_DIGEST_SIZE) && *isZero ; i++) { + if (tpm_digest[i] != 0) { + *isZero = FALSE; + } + } + return; +} + +#if 0 +void TPM_Digest_IsMinusOne(TPM_BOOL *isMinusOne, TPM_DIGEST tpm_digest) +{ + size_t i; + + printf(" TPM_Digest_IsMinusOne:\n"); + for (i = 0, *isMinusOne = TRUE ; (i < TPM_DIGEST_SIZE) && *isMinusOne ; i++) { + if (tpm_digest[i] != 0xff) { + *isMinusOne = FALSE; + } + } + return; +} +#endif diff --git a/src/tpm12/tpm_digest.h b/src/tpm12/tpm_digest.h new file mode 100644 index 0000000..6c3b342 --- /dev/null +++ b/src/tpm12/tpm_digest.h @@ -0,0 +1,64 @@ +/********************************************************************************/ +/* */ +/* Digest Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_digest.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_DIGEST_H +#define TPM_DIGEST_H + +#include "tpm_structures.h" +#include "tpm_store.h" + +void TPM_Digest_Init(TPM_DIGEST tpm_digest); +TPM_RESULT TPM_Digest_Load(TPM_DIGEST tpm_digest, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Digest_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_DIGEST tpm_digest); + +void TPM_Digest_Set(TPM_DIGEST tpm_digest); +void TPM_Digest_Copy(TPM_DIGEST destination, const TPM_DIGEST source); +void TPM_Digest_XOR(TPM_DIGEST out, + const TPM_DIGEST in1, + const TPM_DIGEST in2); +TPM_RESULT TPM_Digest_Compare(const TPM_DIGEST expect, const TPM_DIGEST actual); +void TPM_Digest_IsZero(TPM_BOOL *isZero, TPM_DIGEST tpm_digest); +#if 0 +void TPM_Digest_IsMinusOne(TPM_BOOL *isMinusOne, TPM_DIGEST tpm_digest); +#endif + +#endif diff --git a/src/tpm12/tpm_error.c b/src/tpm12/tpm_error.c new file mode 100644 index 0000000..b4c47d8 --- /dev/null +++ b/src/tpm12/tpm_error.c @@ -0,0 +1,43 @@ +/********************************************************************************/ +/* */ +/* Error Response */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_error.c 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#include "tpm_error.h" + diff --git a/src/tpm12/tpm_global.c b/src/tpm12/tpm_global.c new file mode 100644 index 0000000..411adde --- /dev/null +++ b/src/tpm12/tpm_global.c @@ -0,0 +1,252 @@ +/********************************************************************************/ +/* */ +/* Global Variables */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_global.c 4621 2011-09-09 20:19:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_crypto.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_init.h" +#include "tpm_key.h" +#include "tpm_nvfile.h" +#include "tpm_nvram.h" +#include "tpm_permanent.h" +#include "tpm_platform.h" +#include "tpm_startup.h" +#include "tpm_structures.h" + + +#include "tpm_global.h" + +/* state for the TPM's */ +tpm_state_t *tpm_instances[TPMS_MAX]; + +/* TPM_Global_Init initializes the tpm_state to default values. + + It does not load any data from or store data to NVRAM +*/ + +TPM_RESULT TPM_Global_Init(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + + printf("TPM_Global_Init: TPMs %lu\n", + (unsigned long)sizeof(tpm_instances)/sizeof(tpm_state_t *)); + /* initialize the TPM_STANY_FLAGS structure */ + if (rc == 0) { + /* set the structure to 0 for security, clean out old secrets */ + memset(tpm_state, 0 , sizeof(tpm_state_t)); + /* the virtual TPM number NOTE: This must be done early as it is used to construct + nn.permall file names */ + tpm_state->tpm_number = TPM_ILLEGAL_INSTANCE_HANDLE; + /* initialize the TPM_PERMANENT_FLAGS structure */ + printf("TPM_Global_Init: Initializing TPM_PERMANENT_FLAGS\n"); + TPM_PermanentFlags_Init(&(tpm_state->tpm_permanent_flags)); + /* initialize the TPM_STCLEAR_FLAGS structure */ + printf("TPM_Global_Init: Initializing TPM_STCLEAR_FLAGS\n"); + TPM_StclearFlags_Init(&(tpm_state->tpm_stclear_flags)); + /* initialize the TPM_STANY_FLAGS structure */ + printf("TPM_Global_Init: Initializing TPM_STANY_FLAGS\n"); + TPM_StanyFlags_Init(&(tpm_state->tpm_stany_flags)); + /* initialize TPM_PERMANENT_DATA structure */ + printf("TPM_Global_Init: Initializing TPM_PERMANENT_DATA\n"); + rc = TPM_PermanentData_Init(&(tpm_state->tpm_permanent_data), TRUE); + } + if (rc == 0) { + /* initialize TPM_STCLEAR_DATA structure */ + printf("TPM_Global_Init: Initializing TPM_STCLEAR_DATA\n"); + TPM_StclearData_Init(&(tpm_state->tpm_stclear_data), + tpm_state->tpm_permanent_data.pcrAttrib, + TRUE); /* initialize the PCR's */ + /* initialize TPM_STANY_DATA structure */ + printf("TPM_Global_Init: Initializing TPM_STANY_DATA\n"); + rc = TPM_StanyData_Init(&(tpm_state->tpm_stany_data)); + } + /* initialize the TPM_KEY_HANDLE_LIST structure */ + if (rc == 0) { + printf("TPM_Global_Init: Initializing TPM_KEY_HANDLE_LIST\n"); + TPM_KeyHandleEntries_Init(tpm_state->tpm_key_handle_entries); + /* initialize the SHA1 thread context */ + tpm_state->sha1_context = NULL; + /* initialize the TIS SHA1 thread context */ + tpm_state->sha1_context_tis = NULL; + tpm_state->transportHandle = 0; + printf("TPM_Global_Init: Initializing TPM_NV_INDEX_ENTRIES\n"); + TPM_NVIndexEntries_Init(&(tpm_state->tpm_nv_index_entries)); + } + /* comes up in limited operation mode */ + /* shutdown is set on a self test failure, before calling TPM_Global_Init() */ + if (rc == 0) { + printf(" TPM_Global_Init: Set testState to %u \n", TPM_TEST_STATE_LIMITED); + tpm_state->testState = TPM_TEST_STATE_LIMITED; + } + else { + printf(" TPM_Global_Init: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + return rc; +} + +#if 0 +/* TPM_Global_Load() loads the tpm_state_t global structures for the TPM instance from NVRAM. + + tpm_state->tpm_number must be set by the caller. + + Returns + + 0 on success. + TPM_FAIL on failure to load (fatal), since it should never occur +*/ + +TPM_RESULT TPM_Global_Load(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + + printf("TPM_Global_Load:\n"); + /* TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys, and NV defined space. */ + if (rc == 0) { + rc = TPM_PermanentAll_NVLoad(tpm_state); + } + if (rc == 0) { + rc = TPM_VolatileAll_NVLoad(tpm_state); + } + return rc; +} + +/* TPM_Global_Store() store the tpm_state_t global structure for the TPM instance to NVRAM + + tpm_state->tpm_number must be set by the caller. +*/ + +TPM_RESULT TPM_Global_Store(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Global_Store:\n"); + if (rc == 0) { + rc = TPM_PermanentAll_NVStore(tpm_state, TRUE, 0); + } + if (rc == 0) { + rc = TPM_VolatileAll_NVStore(tpm_state); + } + return rc; +} +#endif + +/* TPM_Global_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_Global_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_Global_Delete(tpm_state_t *tpm_state) +{ + printf(" TPM_Global_Delete:\n"); + if (tpm_state != NULL) { + /* TPM_PERMANENT_FLAGS have no allocated memory or secrets */ + /* TPM_STCLEAR_FLAGS have no allocated memory or secrets */ + /* TPM_STANY_FLAGS have no allocated memory or secrets */ + printf(" TPM_Global_Delete: Deleting TPM_PERMANENT_DATA\n"); + TPM_PermanentData_Delete(&(tpm_state->tpm_permanent_data), TRUE); + printf(" TPM_Global_Delete: Deleting TPM_STCLEAR_DATA\n"); + TPM_StclearData_Delete(&(tpm_state->tpm_stclear_data), + tpm_state->tpm_permanent_data.pcrAttrib, + TRUE); /* reset the PCR's */ + printf(" TPM_Global_Delete: Deleting TPM_STANY_DATA\n"); + TPM_StanyData_Delete(&(tpm_state->tpm_stany_data)); + printf(" TPM_Global_Delete: Deleting key handle entries\n"); + TPM_KeyHandleEntries_Delete(tpm_state->tpm_key_handle_entries); + printf(" TPM_Global_Delete: Deleting SHA1 contexts\n"); + TPM_SHA1Delete(&(tpm_state->sha1_context)); + TPM_SHA1Delete(&(tpm_state->sha1_context_tis)); + TPM_NVIndexEntries_Delete(&(tpm_state->tpm_nv_index_entries)); + } + return; +} + + +/* TPM_Global_GetPhysicalPresence() returns 'physicalPresence' TRUE if either TPM_STCLEAR_FLAGS -> + physicalPresence is TRUE or hardware physical presence is indicated. + + The physicalPresenceHWEnable and physicalPresenceCMDEnable flags MUST mask their respective + signals before further processing. The hardware signal, if enabled by the + physicalPresenceHWEnable flag, MUST be logically ORed with the PhysicalPresence flag, if enabled, + to obtain the final physical presence value used to allow or disallow local commands. +*/ + +TPM_RESULT TPM_Global_GetPhysicalPresence(TPM_BOOL *physicalPresence, + const tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + *physicalPresence = FALSE; + + /* is CMD physical presence enabled */ + printf(" TPM_Global_GetPhysicalPresence: physicalPresenceCMDEnable is %02x\n", + tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable); + if (tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable) { + printf(" TPM_Global_GetPhysicalPresence: physicalPresence flag is %02x\n", + tpm_state->tpm_stclear_flags.physicalPresence); + /* if enabled, check for physicalPresence set by the command ordinal */ + *physicalPresence = tpm_state->tpm_stclear_flags.physicalPresence; + } + + /* if the software flag is true, result is true, no need to check the hardware */ + /* if the TPM_STCLEAR_FLAGS flag is FALSE, check the hardware */ + if (!(*physicalPresence)) { + printf(" TPM_Global_GetPhysicalPresence: physicalPresenceHWEnable is %02x\n", + tpm_state->tpm_permanent_flags.physicalPresenceHWEnable); + /* if physicalPresenceHWEnable is FALSE, the hardware signal is disabled */ + if (tpm_state->tpm_permanent_flags.physicalPresenceHWEnable) { + /* if enabled, check the hardware signal */ + rc = TPM_IO_GetPhysicalPresence(physicalPresence, tpm_state->tpm_number); + printf(" TPM_Global_GetPhysicalPresence: physicalPresence HW is %02x\n", + *physicalPresence); + } + } + printf(" TPM_Global_GetPhysicalPresence: physicalPresence is %02x\n", + *physicalPresence); + return rc; +} + diff --git a/src/tpm12/tpm_global.h b/src/tpm12/tpm_global.h new file mode 100644 index 0000000..09cb7eb --- /dev/null +++ b/src/tpm12/tpm_global.h @@ -0,0 +1,103 @@ +/********************************************************************************/ +/* */ +/* Global Variables */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_global.h 4285 2011-01-17 21:27:05Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_GLOBAL_H +#define TPM_GLOBAL_H + +#include "tpm_nvram_const.h" +#include "tpm_types.h" +#include "tpm_structures.h" + +#define TPM_TEST_STATE_LIMITED 1 /* limited operation mode */ +#define TPM_TEST_STATE_FULL 2 /* full operation mode */ +#define TPM_TEST_STATE_FAILURE 3 /* failure mode */ + +typedef struct tdTPM_STATE +{ + /* the number of the virtual TPM */ + uint32_t tpm_number; + /* 7.1 TPM_PERMANENT_FLAGS */ + TPM_PERMANENT_FLAGS tpm_permanent_flags; + /* 7.2 TPM_STCLEAR_FLAGS */ + TPM_STCLEAR_FLAGS tpm_stclear_flags; + /* 7.3 TPM_STANY_FLAGS */ + TPM_STANY_FLAGS tpm_stany_flags; + /* 7.4 TPM_PERMANENT_DATA */ + TPM_PERMANENT_DATA tpm_permanent_data; + /* 7.5 TPM_STCLEAR_DATA */ + TPM_STCLEAR_DATA tpm_stclear_data; + /* 7.6 TPM_STANY_DATA */ + TPM_STANY_DATA tpm_stany_data; + /* 5.6 TPM_KEY_HANDLE_ENTRY */ + TPM_KEY_HANDLE_ENTRY tpm_key_handle_entries[TPM_KEY_HANDLES]; + /* Context for SHA1 functions */ + void *sha1_context; + void *sha1_context_tis; + TPM_TRANSHANDLE transportHandle; /* non-zero if the context was set up in a transport + session */ + /* self test shutdown */ + uint32_t testState; + /* NVRAM volatile data marker. Cleared at TPM_Startup(ST_Clear), it holds all indexes which + have been read. The index not being present indicates that some volatile fields should be + cleared at first read. */ + TPM_NV_INDEX_ENTRIES tpm_nv_index_entries; + /* NOTE: members added here should be initialized by TPM_Global_Init() and possibly added to + TPM_SaveState_Load() and TPM_SaveState_Store() */ +} tpm_state_t; + +/* state for the TPM */ +extern tpm_state_t *tpm_instances[]; + + +/* + tpm_state_t +*/ + +TPM_RESULT TPM_Global_Init(tpm_state_t *tpm_state); +#if 0 +TPM_RESULT TPM_Global_Load(tpm_state_t *tpm_state); +TPM_RESULT TPM_Global_Store(tpm_state_t *tpm_state); +#endif +void TPM_Global_Delete(tpm_state_t *tpm_state); + + +TPM_RESULT TPM_Global_GetPhysicalPresence(TPM_BOOL *physicalPresence, + const tpm_state_t *tpm_state); + +#endif diff --git a/src/tpm12/tpm_identity.c b/src/tpm12/tpm_identity.c new file mode 100644 index 0000000..742bccd --- /dev/null +++ b/src/tpm12/tpm_identity.c @@ -0,0 +1,1448 @@ +/********************************************************************************/ +/* */ +/* TPM Identity Handling */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_identity.c 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_auth.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_memory.h" +#include "tpm_pcr.h" +#include "tpm_process.h" +#include "tpm_secret.h" +#include "tpm_storage.h" +#include "tpm_ver.h" +#include "tpm_identity.h" + +/* + TPM_EK_BLOB +*/ + +/* TPM_EKBlob_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_EKBlob_Init(TPM_EK_BLOB *tpm_ek_blob) +{ + printf(" TPM_EKBlob_Init:\n"); + tpm_ek_blob->ekType = 0; + TPM_SizedBuffer_Init(&(tpm_ek_blob->blob)); + return; +} + +/* TPM_EKBlob_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_EKBlob_Init() + After use, call TPM_EKBlob_Delete() to free memory +*/ + +TPM_RESULT TPM_EKBlob_Load(TPM_EK_BLOB *tpm_ek_blob, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_EKBlob_Load:\n"); + /* check the tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_EK_BLOB, stream, stream_size); + } + /* load ekType */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_ek_blob->ekType), stream, stream_size); + } + /* load blob */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_ek_blob->blob), stream, stream_size); + } + return rc; +} + +#if 0 +/* TPM_EKBlob_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_EKBlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_EK_BLOB *tpm_ek_blob) +{ + TPM_RESULT rc = 0; + + printf(" TPM_EKBlob_Store:\n"); + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_ek_blob->ekType); + } + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_ek_blob->blob)); + } + return rc; +} +#endif + +/* TPM_EKBlob_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_EKBlob_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_EKBlob_Delete(TPM_EK_BLOB *tpm_ek_blob) +{ + printf(" TPM_EKBlob_Delete:\n"); + if (tpm_ek_blob != NULL) { + TPM_SizedBuffer_Delete(&(tpm_ek_blob->blob)); + TPM_EKBlob_Init(tpm_ek_blob); + } + return; +} + +/* + TPM_EK_BLOB_ACTIVATE +*/ + +/* TPM_EKBlobActivate_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_EKBlobActivate_Init(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate) +{ + printf(" TPM_EKBlobActivate_Init:\n"); + TPM_SymmetricKey_Init(&(tpm_ek_blob_activate->sessionKey)); + TPM_Digest_Init(tpm_ek_blob_activate->idDigest); + TPM_PCRInfoShort_Init(&(tpm_ek_blob_activate->pcrInfo)); + return; +} + +/* TPM_EKBlobActivate_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_EKBlobActivate_Init() + After use, call TPM_EKBlobActivate_Delete() to free memory +*/ + +TPM_RESULT TPM_EKBlobActivate_Load(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_EKBlobActivate_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_EK_BLOB_ACTIVATE, stream, stream_size); + } + /* load sessionKey */ + if (rc == 0) { + rc = TPM_SymmetricKey_Load(&(tpm_ek_blob_activate->sessionKey), stream, stream_size); + } + /* load idDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_ek_blob_activate->idDigest, stream, stream_size); + } + /* load pcrInfo */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Load(&(tpm_ek_blob_activate->pcrInfo), stream, stream_size, FALSE); + } + return rc; +} + +#if 0 +/* TPM_EKBlobActivate_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_EKBlobActivate_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate) +{ + TPM_RESULT rc = 0; + + printf(" TPM_EKBlobActivate_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB_ACTIVATE); + } + /* store sessionKey */ + if (rc == 0) { + rc = TPM_SymmetricKey_Store(sbuffer, &(tpm_ek_blob_activate->sessionKey)); + } + /* store idDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_ek_blob_activate->idDigest); + } + /* store pcrInfo */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_ek_blob_activate->pcrInfo), FALSE); + } + return rc; +} +#endif + +/* TPM_EKBlobActivate_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_EKBlobActivate_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_EKBlobActivate_Delete(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate) +{ + printf(" TPM_EKBlobActivate_Delete:\n"); + if (tpm_ek_blob_activate != NULL) { + TPM_SymmetricKey_Delete(&(tpm_ek_blob_activate->sessionKey)); + TPM_PCRInfoShort_Delete(&(tpm_ek_blob_activate->pcrInfo)); + TPM_EKBlobActivate_Init(tpm_ek_blob_activate); + } + return; +} + +/* + TPM_EK_BLOB_AUTH +*/ + +#if 0 +/* TPM_EKBlobAuth_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_EKBlobAuth_Init(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth) +{ + printf(" TPM_EKBlobAuth_Init:\n"); + TPM_Secret_Init(tpm_ek_blob_auth->authValue); + return; +} + +/* TPM_EKBlobAuth_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_EKBlobAuth_Init() + After use, call TPM_EKBlobAuth_Delete() to free memory +*/ + +TPM_RESULT TPM_EKBlobAuth_Load(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_EKBlobAuth_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_EK_BLOB_AUTH, stream, stream_size); + } + /* load authValue */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_ek_blob_auth->authValue, stream, stream_size); + } + return rc; +} + +/* TPM_EKBlobAuth_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_EKBlobAuth_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_EK_BLOB_AUTH *tpm_ek_blob_auth) +{ + TPM_RESULT rc = 0; + + printf(" TPM_EKBlobAuth_Store:\n"); + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB_AUTH); + } + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_ek_blob_auth->authValue); + } + return rc; +} + +/* TPM_EKBlobAuth_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_EKBlobAuth_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_EKBlobAuth_Delete(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth) +{ + printf(" TPM_EKBlobAuth_Delete:\n"); + if (tpm_ek_blob_auth != NULL) { + TPM_EKBlobAuth_Init(tpm_ek_blob_auth); + } + return; +} +#endif + +/* + TPM_IDENTITY_CONTENTS +*/ + +/* TPM_IdentityContents_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_IdentityContents_Init(TPM_IDENTITY_CONTENTS *tpm_identity_contents) +{ + printf(" TPM_IdentityContents_Init:\n"); + TPM_StructVer_Init(&(tpm_identity_contents->ver)); + tpm_identity_contents->ordinal = TPM_ORD_MakeIdentity; + TPM_Digest_Init(tpm_identity_contents->labelPrivCADigest); + TPM_Pubkey_Init(&(tpm_identity_contents->identityPubKey)); + return; +} + +/* TPM_IdentityContents_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_IdentityContents_Init() + After use, call TPM_IdentityContents_Delete() to free memory + + NOTE: Never called. +*/ +#if 0 +TPM_RESULT TPM_IdentityContents_Load(TPM_IDENTITY_CONTENTS *tpm_identity_contents, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_IdentityContents_Load:\n"); + /* load ver */ + if (rc == 0) { + rc = TPM_StructVer_Load(&(tpm_identity_contents->ver), stream, stream_size); + } + /* check ver immediately to ease debugging */ + if (rc == 0) { + rc = TPM_StructVer_CheckVer(&(tpm_identity_contents->ver)); + } + /* load ordinal */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_identity_contents->ordinal), stream, stream_size); + } + /* load labelPrivCADigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_identity_contents->labelPrivCADigest, stream, stream_size); + } + /* load identityPubKey */ + if (rc == 0) { + rc = TPM_Pubkey_Load(&(tpm_identity_contents->identityPubKey), stream, stream_size); + } + return rc; +} +#endif + +/* TPM_IdentityContents_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_IdentityContents_Store(TPM_STORE_BUFFER *sbuffer, + TPM_IDENTITY_CONTENTS *tpm_identity_contents) +{ + TPM_RESULT rc = 0; + + printf(" TPM_IdentityContents_Store:\n"); + /* store ver */ + if (rc == 0) { + rc = TPM_StructVer_Store(sbuffer, &(tpm_identity_contents->ver)); + } + /* store ordinal */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_identity_contents->ordinal); + } + /* store labelPrivCADigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_identity_contents->labelPrivCADigest); + } + /* store identityPubKey */ + if (rc == 0) { + rc = TPM_Pubkey_Store(sbuffer, &(tpm_identity_contents->identityPubKey)); + } + return rc; +} + +/* TPM_IdentityContents_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_IdentityContents_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_IdentityContents_Delete(TPM_IDENTITY_CONTENTS *tpm_identity_contents) +{ + printf(" TPM_IdentityContents_Delete:\n"); + if (tpm_identity_contents != NULL) { + TPM_Pubkey_Delete(&(tpm_identity_contents->identityPubKey)); + TPM_IdentityContents_Init(tpm_identity_contents); + } + return; +} + +/* + TPM_ASYM_CA_CONTENTS +*/ + +/* TPM_AsymCaContents_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_AsymCaContents_Init(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents) +{ + printf(" TPM_AsymCaContents_Init:\n"); + TPM_SymmetricKey_Init(&(tpm_asym_ca_contents->sessionKey)); + TPM_Digest_Init(tpm_asym_ca_contents->idDigest); + return; +} + +/* TPM_AsymCaContents_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_AsymCaContents_Init() + After use, call TPM_AsymCaContents_Delete() to free memory +*/ + +TPM_RESULT TPM_AsymCaContents_Load(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_AsymCaContents_Load:\n"); + if (rc == 0) { + rc = TPM_SymmetricKey_Load(&(tpm_asym_ca_contents->sessionKey), stream, stream_size); + } + if (rc == 0) { + rc = TPM_Digest_Load(tpm_asym_ca_contents->idDigest, stream, stream_size); + } + return rc; +} + +#if 0 +/* TPM_AsymCaContents_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_AsymCaContents_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents) +{ + TPM_RESULT rc = 0; + + printf(" TPM_AsymCaContents_Store:\n"); + if (rc == 0) { + rc = TPM_SymmetricKey_Store(sbuffer, &(tpm_asym_ca_contents->sessionKey)); + } + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_asym_ca_contents->idDigest); + } + return rc; +} +#endif + +/* TPM_AsymCaContents_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_AsymCaContents_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_AsymCaContents_Delete(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents) +{ + printf(" TPM_AsymCaContents_Delete:\n"); + if (tpm_asym_ca_contents != NULL) { + TPM_SymmetricKey_Delete(&(tpm_asym_ca_contents->sessionKey)); + TPM_AsymCaContents_Init(tpm_asym_ca_contents); + } + return; +} + + + + + + +/* + Processing Functions +*/ + +/* 15.1 TPM_MakeIdentity rev 114 + + Generate a new Attestation Identity Key (AIK) + + labelPrivCADigest identifies the privacy CA that the owner expects to be the target CA for the + AIK. The selection is not enforced by the TPM. It is advisory only. It is included because the + TSS cannot be trusted to send the AIK to the correct privacy CA. The privacy CA can use this + parameter to validate that it is the target privacy CA and label intended by the TPM owner at the + time the key was created. The label can be used to indicate an application purpose. + + The public key of the new TPM identity SHALL be identityPubKey. The private key of the new TPM + identity SHALL be tpm_signature_key. + + Properties of the new identity + + TPM_PUBKEY identityPubKey This SHALL be the public key of a previously unused asymmetric key + pair. + + TPM_STORE_ASYMKEY tpm_signature_key This SHALL be the private key that forms a pair with + identityPubKey and SHALL be extant only in a TPM-shielded location. + + This capability also generates a TPM_KEY containing the tpm_signature_key. + + If identityPubKey is stored on a platform it SHALL exist only in storage to which access is + controlled and is available to authorized entities. +*/ + +TPM_RESULT TPM_Process_MakeIdentity(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_ENCAUTH identityAuth; /* Encrypted usage authorization data for the new identity + */ + TPM_CHOSENID_HASH labelPrivCADigest; /* The digest of the identity label and privacy CA + chosen for the new TPM identity. */ + TPM_KEY idKeyParams; /* Structure containing all parameters of new identity + key. pubKey.keyLength & idKeyParams.encData are both 0 + MAY be TPM_KEY12 */ + TPM_AUTHHANDLE srkAuthHandle; /* The authorization handle used for SRK authorization. */ + TPM_NONCE srknonceOdd; /* Nonce generated by system associated with srkAuthHandle + */ + TPM_BOOL continueSrkSession = TRUE; /* Ignored */ + TPM_AUTHDATA srkAuth; /* The authorization digest for the inputs and the SRK. HMAC + key: srk.usageAuth. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner + authorization. Session type MUST be OSAP. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner. HMAC key: + ownerAuth. */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL srkAuthHandleValid = FALSE; + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *srk_auth_session_data = NULL; /* session data for authHandle */ + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */ + TPM_SECRET *srkHmacKey; + TPM_SECRET *hmacKey; + TPM_SECRET a1Auth; + TPM_STORE_ASYMKEY *idKeyStoreAsymkey; + TPM_IDENTITY_CONTENTS idContents; + TPM_DIGEST h1Digest; /* digest of TPM_IDENTITY_CONTENTS structure */ + int ver; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_KEY idKey; /* The newly created identity key. MAY be TPM_KEY12 + */ + TPM_SIZED_BUFFER identityBinding; /* Signature of TPM_IDENTITY_CONTENTS using + idKey.private. */ + printf("TPM_Process_MakeIdentity: Ordinal Entry\n"); + TPM_Key_Init(&idKeyParams); /* freed @1 */ + TPM_Key_Init(&idKey); /* freed @2 */ + TPM_SizedBuffer_Init(&identityBinding); /* freed @3 */ + TPM_IdentityContents_Init(&idContents); /* freed @4 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get identityAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Load(identityAuth, &command, ¶mSize); + } + /* get labelPrivCADigest parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(labelPrivCADigest, &command, ¶mSize); + } + /* get idKeyParams parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_Load(&idKeyParams, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag21(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Get(&srkAuthHandle, + &srkAuthHandleValid, + srknonceOdd, + &continueSrkSession, + srkAuth, + &command, ¶mSize); + printf("TPM_Process_MakeIdentity: srkAuthHandle %08x\n", srkAuthHandle); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_MakeIdentity: authHandle %08x\n", authHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_MakeIdentity: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + srkAuthHandleValid = FALSE; + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the idKeyParams parameters for the key description */ + /* a. If the algorithm type is RSA the key length MUST be a minimum of 2048 and MUST use the + default exponent. For interoperability the key length SHOULD be 2048 */ + /* b. If the algorithm type is other than RSA the strength provided by the key MUST be + comparable to RSA 2048 */ + /* c. If the TPM is not designed to create a key of the requested type, return the error code + TPM_BAD_KEY_PROPERTY */ + /* d. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then */ + /* i. If authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_CheckProperties(&ver, &idKeyParams, 2048, + tpm_state->tpm_permanent_flags.FIPS); + printf("TPM_Process_MakeIdentity: key parameters v = %d\n", ver); + } + /* 2. Use authHandle to verify that the Owner authorized all TPM_MakeIdentity input + parameters. */ + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_OWNER, + ordinal, + NULL, + NULL, + tpm_state->tpm_permanent_data.ownerAuth); + } + /* Validate the authorization to use the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Auth2data_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 3. Use srkAuthHandle to verify that the SRK owner authorized all TPM_MakeIdentity input + parameters. */ + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthSessions_GetData + (&srk_auth_session_data, + &srkHmacKey, + tpm_state, + srkAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + &(tpm_state->tpm_permanent_data.srk), + /* OIAP */ + &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->usageAuth), + /* OSAP */ + tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); + } + /* Validate the authorization to use the key pointed to by keyHandle */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *srkHmacKey, /* HMAC key */ + inParamDigest, + srk_auth_session_data, /* authorization session */ + srknonceOdd, /* Nonce generated by system + associated with authHandle */ + continueSrkSession, + srkAuth); /* Authorization digest for input */ + } + /* if there is no SRK authorization, check that the SRK authDataUsage is TPM_AUTH_NEVER */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { + if (tpm_state->tpm_permanent_data.srk.authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_MakeIdentity: Error, SRK authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* 4. Verify that idKeyParams -> keyUsage is TPM_KEY_IDENTITY. If it is not, return + TPM_INVALID_KEYUSAGE */ + /* NOTE: TPM_KEY_IDENTITY keys must use TPM_SS_RSASSAPKCS1v15_SHA1 */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_MakeIdentity: Checking key parameters\n"); + if (idKeyParams.keyUsage != TPM_KEY_IDENTITY) { + printf("TPM_Process_MakeIdentity: Error, " + "idKeyParams keyUsage %08x should be TPM_KEY_IDENTITY\n", + idKeyParams.keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 5. Verify that idKeyParams -> keyFlags -> migratable is FALSE. If it is not, return + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (idKeyParams.keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_MakeIdentity: Error, " + "idKeyParams keyFlags %08x cannot be migratable\n", + idKeyParams.keyFlags); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 6. Create a1 by decrypting identityAuth according to the ADIP indicated by authHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_Decrypt(a1Auth, + NULL, + identityAuth, + auth_session_data, + NULL, + NULL, + FALSE); /* even and odd */ + } + /* 7. Set continueAuthSession and continueSRKSession to FALSE. */ + if (returnCode == TPM_SUCCESS) { + continueAuthSession = FALSE; + continueSrkSession = FALSE; + /* 8. Determine the structure version */ + /* a. If idKeyParams -> tag is TPM_TAG_KEY12 */ + /* i. Set V1 to 2 */ + /* ii. Create idKey a TPM_KEY12 structure using idKeyParams as the default values for the + structure */ + /* b. If idKeyParams -> ver is 1.1 */ + /* i. Set V1 to 1 */ + /* ii. Create idKey a TPM_KEY structure using idKeyParams as the default values for the + structure */ + /* NOTE Done by TPM_Key_CheckProperties() */ + /* NOTE The creation determination is done by TPM_Key_GenerateRSA() */ + } + /* 9. Set the digestAtCreation values for pcrInfo */ + /* NOTE Done as the key is generated */ + /* a. For PCR_INFO_LONG include the locality of the current command */ + /* 10. Create an asymmetric key pair (identityPubKey and tpm_signature_key) using a + TPM-protected capability, in accordance with the algorithm specified in idKeyParams */ + if (returnCode == TPM_SUCCESS) { + /* generate the key pair, create the tpm_store_asymkey cache, copy key parameters, create + tpm_pcr_info cache, copies pcr parameters, sets digestAtCreation, sets pubKey, serializes + pcrInfo + + does not set encData */ + printf("TPM_Process_MakeIdentity: Generating key\n"); + returnCode = TPM_Key_GenerateRSA(&idKey, + tpm_state, + &(tpm_state->tpm_permanent_data.srk), /* parent key */ + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + ver, + idKeyParams.keyUsage, + idKeyParams.keyFlags, + idKeyParams.authDataUsage, /* TPM_AUTH_DATA_USAGE */ + &(idKeyParams.algorithmParms), /* TPM_KEY_PARMS */ + idKeyParams.tpm_pcr_info, /* TPM_PCR_INFO */ + idKeyParams.tpm_pcr_info_long);/* TPM_PCR_INFO_LONG */ + + } + /* 11. Ensure that the authorization information in A1 is properly stored in the idKey as + usageAuth. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetStoreAsymkey(&idKeyStoreAsymkey, + &idKey); + } + if (returnCode == TPM_SUCCESS) { + TPM_Secret_Copy(idKeyStoreAsymkey->usageAuth, a1Auth); + /* 12. Attach identityPubKey and tpm_signature_key to idKey */ + /* Note: Done as the key is generated */ + /* 13. Set idKey -> migrationAuth to TPM_PERMANENT_DATA -> tpmProof */ + TPM_Secret_Copy(idKeyStoreAsymkey->migrationAuth, tpm_state->tpm_permanent_data.tpmProof); + /* 14. Ensure that all TPM_PAYLOAD_TYPE structures identity this key as TPM_PT_ASYM */ + /* NOTE Done as the key is generated */ + } + /* 15. Encrypt the private portion of idKey using the SRK as the parent key */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_MakeIdentity: Encrypting key private part with SRK\n"); + returnCode = TPM_Key_GenerateEncData(&idKey, &(tpm_state->tpm_permanent_data.srk)); + } + /* 16. Create a TPM_IDENTITY_CONTENTS structure named idContents using labelPrivCADigest and the + information from idKey */ + if (returnCode == TPM_SUCCESS) { + TPM_Digest_Copy(idContents.labelPrivCADigest, labelPrivCADigest); + returnCode = TPM_Pubkey_Set(&(idContents.identityPubKey), &idKey); + } + /* 17. Sign idContents using tpm_signature_key and TPM_SS_RSASSAPKCS1v15_SHA1. Store the result + in identityBinding. */ + /* NOTE: TPM_Key_CheckProperties() verified TPM_SS_RSASSAPKCS1v15_SHA1 */ + /* serialize tpm_identity_contents and hash the results*/ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(h1Digest, + &idContents, + (TPM_STORE_FUNCTION_T)TPM_IdentityContents_Store); + } + /* sign the digest */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_MakeIdentity: Signing digest of TPM_IDENTITY_CONTENTS\n"); + returnCode = TPM_RSASignToSizedBuffer(&identityBinding, h1Digest, TPM_DIGEST_SIZE, &idKey); + } +#if 0 /* NOTE Debug code to reverse the signature */ + if (returnCode == TPM_SUCCESS) { + unsigned char *message = NULL; + unsigned char *narr = NULL; + uint32_t nbytes; + unsigned char *earr = NULL; + uint32_t ebytes; + if (returnCode == 0) { + returnCode = TPM_Malloc(&message, identityBinding.size); /* freed @10 */ + } + if (returnCode == 0) { + returnCode = TPM_Key_GetPublicKey(&nbytes, &narr, &idKey); + } + if (returnCode == 0) { + returnCode = TPM_Key_GetExponent(&ebytes, &earr, &idKey); + } + if (returnCode == 0) { + returnCode = TPM_RSAPublicEncryptRaw(message, /* output */ + identityBinding.size, + identityBinding.buffer, /* input */ + identityBinding.size, + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } + free(message); /* @10 */ + } +#endif + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_MakeIdentity: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return idKey */ + returnCode = TPM_Key_Store(response, &idKey); + } + if (returnCode == TPM_SUCCESS) { + /* return identityBinding */ + returnCode = TPM_SizedBuffer_Store(response, &identityBinding); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *srkHmacKey, /* owner HMAC key */ + srk_auth_session_data, + outParamDigest, + srknonceOdd, + continueSrkSession); + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueSrkSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueSrkSession) && + srkAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, srkAuthHandle); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_Key_Delete(&idKeyParams); /* freed @1 */ + TPM_Key_Delete(&idKey); /* freed @2 */ + TPM_SizedBuffer_Delete(&identityBinding); /* freed @3 */ + TPM_IdentityContents_Delete(&idContents); /* freed @4 */ + return rcf; +} + +/* 15.2 TPM_ActivateIdentity rev 107 + + The purpose of TPM_ActivateIdentity is to twofold. The first purpose is to obtain assurance that + the credential in the TPM_SYM_CA_ATTESTATION is for this TPM. The second purpose is to obtain the + session key used to encrypt the TPM_IDENTITY_CREDENTIAL. + + The command TPM_ActivateIdentity activates a TPM identity created using the command + TPM_MakeIdentity. + + The command assumes the availability of the private key associated with the identity. The command + will verify the association between the keys during the process. + + The command will decrypt the input blob and extract the session key and verify the connection + between the public and private keys. The input blob can be in 1.1 or 1.2 format. +*/ + +TPM_RESULT TPM_Process_ActivateIdentity(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE idKeyHandle; /* handle of identity key to be activated */ + TPM_SIZED_BUFFER blob; /* The encrypted ASYM_CA_CONTENTS or TPM_EK_BLOB */ + TPM_AUTHHANDLE idKeyAuthHandle; /* The authorization handle used for ID key + authorization. */ + TPM_NONCE idKeynonceOdd; /* Nonce generated by system associated with idKeyAuthHandle + */ + TPM_BOOL continueIdKeySession = TRUE; /* Continue usage flag for idKeyAuthHandle. */ + TPM_AUTHDATA idKeyAuth; /* The authorization digest for the inputs and ID key. HMAC + key: idKey.usageAuth. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and + owner. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL idKeyAuthHandleValid = FALSE; + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *id_key_auth_session_data = NULL; /* session data for authHandle */ + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */ + TPM_SECRET *idKeyHmacKey; + TPM_SECRET *hmacKey; + TPM_KEY *idKey; /* Identity key to be activated */ + TPM_SECRET *idKeyUsageAuth; + TPM_BOOL idPCRStatus; + TPM_DIGEST h1Digest; /* digest of public key in idKey */ + unsigned char *b1Blob = NULL; /* decrypted blob */ + uint32_t b1BlobLength = 0; /* actual valid data */ + TPM_STRUCTURE_TAG hTag; /* b1 tag in host byte order */ + int vers = 0; /* version of blob */ + unsigned char *stream; + uint32_t stream_size; + TPM_EK_BLOB b1EkBlob; + TPM_ASYM_CA_CONTENTS b1AsymCaContents; + TPM_SYMMETRIC_KEY *k1 = NULL; + TPM_EK_BLOB_ACTIVATE a1; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SYMMETRIC_KEY symmetricKey; /* The decrypted symmetric key. */ + + printf("TPM_Process_ActivateIdentity: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&blob); /* freed @1 */ + TPM_SymmetricKey_Init(&symmetricKey); /* freed @2 */ + TPM_AsymCaContents_Init(&b1AsymCaContents); /* freed @4 */ + TPM_EKBlob_Init(&b1EkBlob); /* freed @5 */ + TPM_EKBlobActivate_Init(&a1); /* freed @6 */ + /* + get inputs + */ + /* get idKey parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&idKeyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get blob parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&blob, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag21(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Get(&idKeyAuthHandle, + &idKeyAuthHandleValid, + idKeynonceOdd, + &continueIdKeySession, + idKeyAuth, + &command, ¶mSize); + printf("TPM_Process_ActivateIdentity: idKeyAuthHandle %08x\n", idKeyAuthHandle); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ActivateIdentity: authHandle %08x\n", authHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ActivateIdentity: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + idKeyAuthHandleValid = FALSE; + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Using the authHandle field, validate the owner's authorization to execute the command and + all of the incoming parameters. */ + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + /* Validate the authorization to use the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Using the idKeyAuthHandle, validate the authorization to execute command and all of the + incoming parameters */ + /* get the idKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&idKey, &idPCRStatus, tpm_state, idKeyHandle, + FALSE, /* not r/o, using to authenticate */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get keyHandle -> usageAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetUsageAuth(&idKeyUsageAuth, idKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&id_key_auth_session_data, + &idKeyHmacKey, + tpm_state, + idKeyAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + idKey, + idKeyUsageAuth, /* OIAP */ + idKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* Validate the authorization to use the key pointed to by keyHandle */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Auth2data_Check(tpm_state, + *idKeyHmacKey, /* HMAC key */ + inParamDigest, + id_key_auth_session_data, /* authorization session */ + idKeynonceOdd, /* Nonce generated by system + associated with authHandle */ + continueIdKeySession, + idKeyAuth); /* Authorization digest for input */ + } + /* if there is no idKey authorization, check that the idKey -> authDataUsage is TPM_AUTH_NEVER + */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { + if (idKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_ActivateIdentity: Error, ID key authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* 3. Validate that the idKey is the public key of a valid TPM identity by checking that + idKeyHandle -> keyUsage is TPM_KEY_IDENTITY. Return TPM_BAD_PARAMETER on mismatch */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ActivateIdentity: Checking for identity key\n"); + if (idKey->keyUsage != TPM_KEY_IDENTITY) { + printf("TPM_Process_ActivateIdentity: Error, keyUsage %04hx must be TPM_KEY_IDENTITY\n", + idKey->keyUsage); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 4. Create H1 the digest of a TPM_PUBKEY derived from idKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GeneratePubkeyDigest(h1Digest, idKey); + } + /* 5. Decrypt blob creating B1 using PRIVEK as the decryption key */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ActivateIdentity: Decrypting blob with EK\n"); + returnCode = TPM_RSAPrivateDecryptMalloc(&b1Blob, /* decrypted data */ + &b1BlobLength, /* actual size of b1 data */ + blob.buffer, + blob.size, + &(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* 6. Determine the type and version of B1 */ + if (returnCode == TPM_SUCCESS) { + stream = b1Blob; /* b1 must be preserved for the free */ + stream_size = b1BlobLength; + /* convert possible tag to uint16_t */ + hTag = ntohs(*(TPM_STRUCTURE_TAG *)b1Blob); + /* a. If B1 -> tag is TPM_TAG_EK_BLOB then */ + if (hTag == TPM_TAG_EK_BLOB) { + /* i. B1 is a TPM_EK_BLOB */ + printf("TPM_Process_ActivateIdentity: b1 is TPM_EK_BLOB\n"); + vers = 2; + returnCode = TPM_EKBlob_Load(&b1EkBlob, &stream, &stream_size); + } + /* b. Else */ + else { + /* i. B1 is a TPM_ASYM_CA_CONTENTS. As there is no tag for this structure it is possible + for the TPM to make a mistake here but other sections of the structure undergo + validation */ + printf("TPM_Process_ActivateIdentity: b1 is TPM_ASYM_CA_CONTENTS\n"); + vers = 1; + returnCode = TPM_AsymCaContents_Load(&b1AsymCaContents, &stream, &stream_size); + } + } + /* 7. If B1 is a version 1.1 TPM_ASYM_CA_CONTENTS then */ + if ((returnCode == TPM_SUCCESS) && (vers == 1)) { + /* a. Compare H1 to B1 -> idDigest on mismatch return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Compare(h1Digest, b1AsymCaContents.idDigest); + if (returnCode != 0) { + printf("TPM_Process_ActivateIdentity: Error " + "comparing TPM_ASYM_CA_CONTENTS idDigest\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* b. Set K1 to B1 -> sessionKey */ + if (returnCode == TPM_SUCCESS) { + k1 = &(b1AsymCaContents.sessionKey); + } + } + /* 8. If B1 is a TPM_EK_BLOB then */ + if ((returnCode == TPM_SUCCESS) && (vers == 2)) { + /* a. Validate that B1 -> ekType is TPM_EK_TYPE_ACTIVATE, return TPM_BAD_TYPE if not. */ + if (returnCode == TPM_SUCCESS) { + if (b1EkBlob.ekType != TPM_EK_TYPE_ACTIVATE) { + printf("TPM_Process_ActivateIdentity: Error, " + "TPM_EK_BLOB not ekType TPM_EK_TYPE_ACTIVATE\n"); + returnCode = TPM_BAD_TYPE; + } + } + /* b. Assign A1 as a TPM_EK_BLOB_ACTIVATE structure from B1 -> blob */ + if (returnCode == TPM_SUCCESS) { + stream = b1EkBlob.blob.buffer; + stream_size = b1EkBlob.blob.size; + returnCode = TPM_EKBlobActivate_Load(&a1, &stream, &stream_size); + } + /* c. Compare H1 to A1 -> idDigest on mismatch return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Compare(h1Digest, a1.idDigest); + if (returnCode != 0) { + printf("TPM_Process_ActivateIdentity: Error " + "comparing TPM_EK_TYPE_ACTIVATE idDigest\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* d. If A1 -> pcrSelection is not NULL */ + /* i. Compute a composite hash C1 using the PCR selection A1 -> pcrSelection */ + /* ii. Compare C1 to A1 -> pcrInfo -> digestAtRelease and return TPM_WRONGPCRVAL on a + mismatch */ + /* e. If A1 -> pcrInfo specifies a locality ensure that the appropriate locality has been + asserted, return TPM_BAD_LOCALITY on error */ + if (returnCode == TPM_SUCCESS) { + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_PCRInfoShort_CheckDigest(&(a1.pcrInfo), + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + tpm_state->tpm_stany_flags.localityModifier); + } + } + /* f. Set K1 to A1 -> symmetricKey */ + if (returnCode == TPM_SUCCESS) { + k1 = &(a1.sessionKey); + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ActivateIdentity: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 9. Return K1 */ + returnCode = TPM_SymmetricKey_Store(response, k1); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *idKeyHmacKey, /* owner HMAC key */ + id_key_auth_session_data, + outParamDigest, + idKeynonceOdd, + continueIdKeySession); + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueIdKeySession) && + idKeyAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, idKeyAuthHandle); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + + + /* + cleanup + */ + TPM_SizedBuffer_Delete(&blob); /* @1 */ + TPM_SymmetricKey_Delete(&symmetricKey); /* @2 */ + free(b1Blob); /* @3 */ + TPM_AsymCaContents_Delete(&b1AsymCaContents); /* @4 */ + TPM_EKBlob_Delete(&b1EkBlob); /* @5 */ + TPM_EKBlobActivate_Delete(&a1); /* @6 */ + return rcf; +} diff --git a/src/tpm12/tpm_identity.h b/src/tpm12/tpm_identity.h new file mode 100644 index 0000000..0f882d9 --- /dev/null +++ b/src/tpm12/tpm_identity.h @@ -0,0 +1,138 @@ +/********************************************************************************/ +/* */ +/* TPM Identity Handling */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_identity.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_IDENTITY_H +#define TPM_IDENTITY_H + +#include "tpm_global.h" + +/* + TPM_EK_BLOB +*/ + +void TPM_EKBlob_Init(TPM_EK_BLOB *tpm_ek_blob); +TPM_RESULT TPM_EKBlob_Load(TPM_EK_BLOB *tpm_ek_blob, + unsigned char **stream, + uint32_t *stream_size); +#if 0 +TPM_RESULT TPM_EKBlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_EK_BLOB *tpm_ek_blob); +#endif +void TPM_EKBlob_Delete(TPM_EK_BLOB *tpm_ek_blob); + +/* + TPM_EK_BLOB_ACTIVATE +*/ + +void TPM_EKBlobActivate_Init(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate); +TPM_RESULT TPM_EKBlobActivate_Load(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate, + unsigned char **stream, + uint32_t *stream_size); +#if 0 +TPM_RESULT TPM_EKBlobActivate_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate); +#endif +void TPM_EKBlobActivate_Delete(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate); + +/* + TPM_EK_BLOB_AUTH +*/ + +#if 0 +void TPM_EKBlobAuth_Init(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth); +TPM_RESULT TPM_EKBlobAuth_Load(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_EKBlobAuth_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_EK_BLOB_AUTH *tpm_ek_blob_auth); +void TPM_EKBlobAuth_Delete(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth); +#endif + + +/* + TPM_IDENTITY_CONTENTS +*/ + +void TPM_IdentityContents_Init(TPM_IDENTITY_CONTENTS *tpm_identity_contents); +#if 0 +TPM_RESULT TPM_IdentityContents_Load(TPM_IDENTITY_CONTENTS *tpm_identity_contents, + unsigned char **stream, + uint32_t *stream_size); +#endif +TPM_RESULT TPM_IdentityContents_Store(TPM_STORE_BUFFER *sbuffer, + TPM_IDENTITY_CONTENTS *tpm_identity_contents); +void TPM_IdentityContents_Delete(TPM_IDENTITY_CONTENTS *tpm_identity_contents); + +/* + TPM_ASYM_CA_CONTENTS +*/ + +void TPM_AsymCaContents_Init(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents); +TPM_RESULT TPM_AsymCaContents_Load(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents, + unsigned char **stream, + uint32_t *stream_size); +#if 0 +TPM_RESULT TPM_AsymCaContents_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents); +#endif +void TPM_AsymCaContents_Delete(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents); + + +/* + Processing Functions +*/ + + +TPM_RESULT TPM_Process_MakeIdentity(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ActivateIdentity(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +#endif diff --git a/src/tpm12/tpm_init.c b/src/tpm12/tpm_init.c new file mode 100644 index 0000000..3a66da5 --- /dev/null +++ b/src/tpm12/tpm_init.c @@ -0,0 +1,1144 @@ +/********************************************************************************/ +/* */ +/* TPM Initialization */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_init.c 4623 2011-09-28 15:15:09Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include +#include + +#include "tpm_admin.h" +#include "tpm_cryptoh.h" +#include "tpm_crypto.h" +#include "tpm_daa.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_nvfile.h" +#include "tpm_pcr.h" +#include "tpm_process.h" +#include "tpm_permanent.h" +#include "tpm_platform.h" +#include "tpm_session.h" +#include "tpm_startup.h" +#include "tpm_structures.h" +#include "tpm_ticks.h" +#include "tpm_transport.h" + + +#include "tpm_init.h" + +/* local prototypes */ + +static TPM_RESULT TPM_CheckTypes(void); + + +/* TPM_Init transitions the TPM from a power-off state to one where the TPM begins an initialization + process. TPM_Init could be the result of power being applied to the platform or a hard reset. + TPM_Init sets an internal flag to indicate that the TPM is undergoing initialization. The TPM + must complete initialization before it is operational. The completion of initialization requires + the receipt of the TPM_Startup command. + + This is different from the debug function TPM_Process_Init(), which initializes a TPM. + + The call tree for initialization is as follows: + + main() + TPM_MainInit() + TPM_IO_Init() - initializes the TPM I/O interface + TPM_Crypto_Init() - initializes cryptographic libraries + TPM_NVRAM_Init() - get NVRAM path once + TPM_LimitedSelfTest() - as per the specification + TPM_Global_Init() - initializes the TPM state + + Returns: 0 on success + + non-zero on a fatal error where the TPM should not continue. These are fatal errors + where the TPM just exits. It can't even enter shutdown. + + A self test error may cause one or all TPM's to enter shutdown, but is not fatal. +*/ + +TPM_RESULT TPM_MainInit(void) +{ + TPM_RESULT rc = 0; /* results for common code, fatal errors */ + uint32_t i; + TPM_RESULT testRc = 0; /* temporary place to hold common self tests failure before the tpm + state is created */ + tpm_state_t *tpm_state; /* TPM instance state */ + bool has_cached_state = false; + + tpm_state = NULL; /* freed @1 */ + /* preliminary check that platform specific sizes are correct */ + if (rc == 0) { + rc = TPM_CheckTypes(); + } + /* initialize the TPM to host interface */ + if (rc == 0) { + printf("TPM_MainInit: Initialize the TPM to host interface\n"); + rc = TPM_IO_Init(); + } + /* initialize cryptographic functions */ + if (rc == 0) { + printf("TPM_MainInit: Initialize the TPM crypto support\n"); + rc = TPM_Crypto_Init(); + } + /* initialize NVRAM static variables. This must be called before the global TPM state is + loaded */ + if (rc == 0) { + printf("TPM_MainInit: Initialize the TPM NVRAM\n"); + rc = TPM_NVRAM_Init(); + } + /* run the initial subset of self tests once */ + if (rc == 0) { + printf("TPM_MainInit: Run common limited self tests\n"); + /* an error is a fatal error, causes a shutdown of the TPM */ + testRc = TPM_LimitedSelfTestCommon(); + } + /* initialize the global structure for the TPM */ + for (i = 0 ; (rc == 0) && (i < TPMS_MAX) ; i++) { + printf("TPM_MainInit: Initializing global TPM %lu\n", (unsigned long)i); + /* Need to malloc and init a TPM state if this is the first time through or if the + state was saved in the array. Otherwise, the malloc'ed structure from the previous + time through the loop can be reused. */ + if ((rc == 0) && (tpm_state == NULL)) { + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)&tpm_state, sizeof(tpm_state_t)); + } + /* initialize the global instance state */ + if (rc == 0) { + rc = TPM_Global_Init(tpm_state); /* freed @2 */ + } + } + if (rc == 0) { + has_cached_state = HasCachedState(TPMLIB_STATE_PERMANENT); + + /* record the TPM number in the state */ + tpm_state->tpm_number = i; + /* If the instance exists in NVRAM, it it initialized and saved in the tpm_instances[] + array. Restores TPM_PERMANENT_FLAGS and TPM_PERMANENT_DATA to in-memory + structures. */ + /* Returns TPM_RETRY on non-existent file */ + rc = TPM_PermanentAll_NVLoad(tpm_state); + } + /* If there was no state for TPM 0 (instance 0 does not exist), initialize state for the + first time using TPM_Global_Init() above. It is created and set to default values. */ + if ((rc == TPM_RETRY) && (i == 0)) { + /* save the state for TPM 0 (first time through) */ + rc = TPM_PermanentAll_NVStore(tpm_state, + TRUE, /* write NV */ + 0); /* no roll back */ + } +#ifdef TPM_VOLATILE_LOAD + /* if volatile state exists at startup, load it. This is used for fail-over restart. */ + if (rc == 0) { + rc = TPM_VolatileAll_NVLoad(tpm_state); + } +#endif /* TPM_VOLATILE_LOAD */ + /* libtpms: due to the SetState() API we have to write the permanent state back to + a file now */ + if (rc == 0 && has_cached_state) { + rc = TPM_PermanentAll_NVStore(tpm_state, + TRUE, /* write NV */ + 0); /* no roll back */ + } + /* if permanent state was loaded successfully (or stored successfully for TPM 0 the first + time) */ + if (rc == 0) { + printf("TPM_MainInit: Creating global TPM instance %lu\n", (unsigned long)i); + /* set the testState for the TPM based on the common selftest result */ + if (testRc != 0) { + /* a. When the TPM detects a failure during any self-test, it SHOULD delete values + preserved by TPM_SaveState. */ + TPM_SaveState_NVDelete(tpm_state, + FALSE); /* ignore error if the state does not exist */ + printf(" TPM_MainInit: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + /* save state in array */ + tpm_instances[i] = tpm_state; + tpm_state = NULL; /* flag that the malloc'ed structure was used. It should not be + freed, and a new instance is needed the next time through the + loop */ + } + /* If there was the non-fatal error TPM_RETRY, the instance does not exist. If instance > 0 + does not exist, the array entry is set to NULL. Continue */ + else if (rc == TPM_RETRY) { + printf("TPM_MainInit: Not Creating global TPM %lu\n", (unsigned long)i); + tpm_instances[i] = NULL; /* flag that the instance does not exist */ + rc = 0; /* Instance does not exist, not fatal error */ + } + } + /* run individual self test on a TPM */ + for (i = 0 ; + (rc == 0) && (i < TPMS_MAX) && (tpm_instances[i] != NULL) && + (tpm_instances[i]->testState != TPM_TEST_STATE_FAILURE) ; /* don't continue if already + error */ + i++) { + printf("TPM_MainInit: Run limited self tests on TPM %lu\n", (unsigned long)i); + testRc = TPM_LimitedSelfTestTPM(tpm_instances[i]); + if (testRc != 0) { + /* a. When the TPM detects a failure during any self-test, it SHOULD delete values + preserved by TPM_SaveState. */ + TPM_SaveState_NVDelete(tpm_state, + FALSE); /* ignore error if the state does not exist */ + } + } + /* the _Delete(), free() clean up if the last created instance was not required */ + TPM_Global_Delete(tpm_state); /* @2 */ + free(tpm_state); /* @1 */ + return rc; +} + +/* TPM_CheckTypes() checks that the assumed TPM types are correct for the platform + */ + +static TPM_RESULT TPM_CheckTypes(void) +{ + TPM_RESULT rc = 0; /* fatal errors */ + + /* These should be removed at compile time */ + if (rc == 0) { + if (sizeof(uint16_t) != 2) { + printf("TPM_CheckTypes: Error (fatal), uint16_t size %lu not supported\n", + (unsigned long)sizeof(uint16_t)); + rc = TPM_FAIL; + } + } + if (rc == 0) { + if (sizeof(uint32_t) != 4) { + printf("TPM_CheckTypes: Error (fatal), uint32_t size %lu not supported\n", + (unsigned long)sizeof(uint32_t)); + rc = TPM_FAIL; + } + } + if (rc == 0) { + if ((sizeof(time_t) != 4) && /* for 32-bit machines */ + (sizeof(time_t) != 8)) { /* for 64-bit machines */ + printf("TPM_CheckTypes: Error (fatal), time_t size %lu not supported\n", + (unsigned long)sizeof(time_t)); + rc = TPM_FAIL; + } + } + return rc; +} + +/* + TPM_STANY_FLAGS +*/ + +/* TPM_StanyFlags_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_StanyFlags_Init(TPM_STANY_FLAGS *tpm_stany_flags) +{ + printf(" TPM_StanyFlags_Init:\n"); + tpm_stany_flags->postInitialise = TRUE; + tpm_stany_flags->localityModifier = 0; + tpm_stany_flags->transportExclusive = 0; + tpm_stany_flags->TOSPresent = FALSE; + /* NOTE added */ + tpm_stany_flags->stateSaved = FALSE; + return; +} + +/* TPM_StanyFlags_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_StanyFlags_Init() +*/ + +TPM_RESULT TPM_StanyFlags_Load(TPM_STANY_FLAGS *tpm_stany_flags, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StanyFlags_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_STANY_FLAGS, stream, stream_size); + } + /* load postInitialise*/ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stany_flags->postInitialise), stream, stream_size); + } + /* load localityModifier */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_stany_flags->localityModifier), stream, stream_size); + } + /* load transportExclusive */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_stany_flags->transportExclusive), stream, stream_size); + } + /* load TOSPresent */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stany_flags->TOSPresent), stream, stream_size); + } + /* load stateSaved */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stany_flags->stateSaved), stream, stream_size); + } + return rc; +} + +/* TPM_StanyFlags_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_StanyFlags_Store(TPM_STORE_BUFFER *sbuffer, + TPM_STANY_FLAGS *tpm_stany_flags) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StanyFlags_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STANY_FLAGS); + } + /* store postInitialise*/ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stany_flags->postInitialise), sizeof(TPM_BOOL)); + } + /* store localityModifier */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_stany_flags->localityModifier); + } + /* store transportExclusive */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_stany_flags->transportExclusive); + } + /* store TOSPresent */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stany_flags->TOSPresent), sizeof(TPM_BOOL)); + } + /* store stateSaved */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stany_flags->stateSaved), sizeof(TPM_BOOL)); + } + return rc; +} + +/* + TPM_STCLEAR_FLAGS +*/ + +/* TPM_StclearFlags_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_StclearFlags_Init(TPM_STCLEAR_FLAGS *tpm_stclear_flags) +{ + printf(" TPM_StclearFlags_Init:\n"); + /* tpm_stclear_flags->deactivated; no default state */ + tpm_stclear_flags->disableForceClear = FALSE; + tpm_stclear_flags->physicalPresence = FALSE; + tpm_stclear_flags->physicalPresenceLock = FALSE; + tpm_stclear_flags->bGlobalLock = FALSE; + return; +} + +/* TPM_StclearFlags_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_StclearFlags_Init() +*/ + +TPM_RESULT TPM_StclearFlags_Load(TPM_STCLEAR_FLAGS *tpm_stclear_flags, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StclearFlags_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_STCLEAR_FLAGS, stream, stream_size); + } + /* load deactivated */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stclear_flags->deactivated), stream, stream_size); + } + /* load disableForceClear */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stclear_flags->disableForceClear), stream, stream_size); + } + /* load physicalPresence */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stclear_flags->physicalPresence), stream, stream_size); + } + /* load physicalPresenceLock */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stclear_flags->physicalPresenceLock), stream, stream_size); + } + /* load bGlobalLock */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stclear_flags->bGlobalLock), stream, stream_size); + } + return rc; +} + +/* TPM_StclearFlags_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_StclearFlags_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_STCLEAR_FLAGS *tpm_stclear_flags) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StclearFlags_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STCLEAR_FLAGS); + } + /* store deactivated */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->deactivated), + sizeof(TPM_BOOL)); + } + /* store disableForceClear */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->disableForceClear), + sizeof(TPM_BOOL)); + } + /* store physicalPresence */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->physicalPresence), + sizeof(TPM_BOOL)); + } + /* store physicalPresenceLock */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->physicalPresenceLock), + sizeof(TPM_BOOL)); + } + /* store bGlobalLock */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->bGlobalLock), + sizeof(TPM_BOOL)); + } + return rc; +} + +/* TPM_StclearFlags_StoreBitmap() serializes TPM_STCLEAR_FLAGS structure into a bit map + + */ + +TPM_RESULT TPM_StclearFlags_StoreBitmap(uint32_t *tpm_bitmap, + const TPM_STCLEAR_FLAGS *tpm_stclear_flags) +{ + TPM_RESULT rc = 0; + uint32_t pos = 0; /* position in bitmap */ + + printf(" TPM_StclearFlags_StoreBitmap:\n"); + *tpm_bitmap = 0; + /* store deactivated */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->deactivated, &pos); + } + /* store disableForceClear */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->disableForceClear, &pos); + } + /* store physicalPresence */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->physicalPresence, &pos); + } + /* store physicalPresenceLock */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->physicalPresenceLock, &pos); + } + /* store bGlobalLock */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->bGlobalLock, &pos); + } + return rc; +} + +/* + TPM_STANY_DATA +*/ + +/* TPM_StanyData_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 +*/ + +TPM_RESULT TPM_StanyData_Init(TPM_STANY_DATA *tpm_stany_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StanyData_Init:\n"); + if (rc == 0) { + /* The tpm_stany_data->currentTicks holds the time of day at initialization. Both nonce + generation and current time of day can return an error */ + TPM_CurrentTicks_Init(&(tpm_stany_data->currentTicks)); + rc = TPM_CurrentTicks_Start(&(tpm_stany_data->currentTicks)); + } + return rc; +} + +/* TPM_StanyData_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_StanyData_Init() + After use, call TPM_StanyData_Delete() to free memory +*/ + +TPM_RESULT TPM_StanyData_Load(TPM_STANY_DATA *tpm_stany_data, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StanyData_Load:\n"); + tpm_stany_data = tpm_stany_data; + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_STANY_DATA, stream, stream_size); + } + /* load currentTicks */ + if (rc == 0) { + rc = TPM_CurrentTicks_LoadAll(&(tpm_stany_data->currentTicks), stream, stream_size); + } + return rc; +} + +/* TPM_StanyData_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_StanyData_Store(TPM_STORE_BUFFER *sbuffer, + TPM_STANY_DATA *tpm_stany_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StanyData_Store:\n"); + tpm_stany_data = tpm_stany_data; + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STANY_DATA); + } + /* store currentTicks*/ + if (rc == 0) { + rc = TPM_CurrentTicks_StoreAll(sbuffer, &(tpm_stany_data->currentTicks)); + } + return rc; +} + +/* TPM_StanyData_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + set members back to default values + The object itself is not freed +*/ + +void TPM_StanyData_Delete(TPM_STANY_DATA *tpm_stany_data) +{ + printf(" TPM_StanyData_Delete:\n"); + /* nothing to free */ + tpm_stany_data = tpm_stany_data; + return; +} + +/* + TPM_STCLEAR_DATA +*/ + +/* TPM_StclearData_Init() + + If pcrInit is TRUE, resets the PCR's + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_StclearData_Init(TPM_STCLEAR_DATA *tpm_stclear_data, + TPM_PCR_ATTRIBUTES *pcrAttrib, + TPM_BOOL pcrInit) +{ + printf(" TPM_StclearData_Init:\n"); + TPM_Nonce_Init(tpm_stclear_data->contextNonceKey); + tpm_stclear_data->countID = TPM_COUNT_ID_NULL; /* NULL value - unselected counter */ + tpm_stclear_data->ownerReference = TPM_KH_OWNER; + tpm_stclear_data->disableResetLock = FALSE; + /* initialize PCR's */ + if (pcrInit) { + printf("TPM_StclearData_Init: Initializing PCR's\n"); + TPM_PCRs_Init(tpm_stclear_data->PCRS, pcrAttrib); + } +#if (TPM_REVISION >= 103) /* added for rev 103 */ + tpm_stclear_data->deferredPhysicalPresence = 0; +#endif + tpm_stclear_data->authFailCount = 0; + tpm_stclear_data->authFailTime = 0; + /* initialize authorization, transport, DAA sessions, and saved sessions */ + TPM_StclearData_SessionInit(tpm_stclear_data); + TPM_Digest_Init(tpm_stclear_data->auditDigest); + TPM_Sbuffer_Init(&(tpm_stclear_data->ordinalResponse)); + return; +} + +/* TPM_StclearData_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_StclearData_Init() + After use, call TPM_StclearData_Delete() to free memory +*/ + +TPM_RESULT TPM_StclearData_Load(TPM_STCLEAR_DATA *tpm_stclear_data, + unsigned char **stream, + uint32_t *stream_size, + TPM_PCR_ATTRIBUTES *pcrAttrib) +{ + TPM_RESULT rc = 0; + TPM_STRUCTURE_TAG tag = 0; + + printf(" TPM_StclearData_Load:\n"); + /* get tag */ + if (rc == 0) { + rc = TPM_Load16(&tag, stream, stream_size); + } + /* check tag */ + if (rc == 0) { + printf(" TPM_StclearData_Load: stream version %04hx\n", tag); + switch (tag) { + case TPM_TAG_STCLEAR_DATA: + case TPM_TAG_STCLEAR_DATA_V2: + break; + default: + printf("TPM_StclearData_Load: Error (fatal), version %04x unsupported\n", tag); + rc = TPM_FAIL; + break; + } + } + /* load contextNonceKey */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_stclear_data->contextNonceKey, stream, stream_size); + } + /* load countID */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_stclear_data->countID), stream, stream_size); + } + /* load ownerReference */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_stclear_data->ownerReference), stream, stream_size); + } + /* load disableResetLock */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_stclear_data->disableResetLock), stream, stream_size); + } + /* load PCR's */ + if (rc == 0) { + rc = TPM_PCRs_Load(tpm_stclear_data->PCRS, pcrAttrib, stream, stream_size); + } +#if (TPM_REVISION >= 103) /* added for rev 103 */ + /* load deferredPhysicalPresence */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_stclear_data->deferredPhysicalPresence), stream, stream_size); + } +#endif + /* load authFailCount */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_stclear_data->authFailCount), stream, stream_size); + } + /* load authFailTime */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_stclear_data->authFailTime), stream, stream_size); + } + /* load authorization sessions */ + if (rc == 0) { + rc = TPM_AuthSessions_Load(tpm_stclear_data->authSessions, stream, stream_size); + } + /* load transport sessions */ + if (rc == 0) { + rc = TPM_TransportSessions_Load(tpm_stclear_data->transSessions, stream, stream_size); + } + /* load DAA sessions */ + if (rc == 0) { + rc = TPM_DaaSessions_Load(tpm_stclear_data->daaSessions, stream, stream_size); + } + /* load contextNonceSession */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_stclear_data->contextNonceSession, stream, stream_size); + } + /* load contextCount */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_stclear_data->contextCount), stream, stream_size); + } + /* load contextList */ + if (rc == 0) { + rc = TPM_ContextList_Load(tpm_stclear_data->contextList, stream, stream_size); + } + /* load auditDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_stclear_data->auditDigest, stream, stream_size); + TPM_PrintFour(" TPM_StclearData_Load: auditDigest", tpm_stclear_data->auditDigest); + } + /* no need to store and load ordinalResponse */ + if (tag == TPM_TAG_STCLEAR_DATA) { + /* but it's there for some versions */ + if (rc == 0) { + TPM_STORE_BUFFER ordinalResponse; + TPM_Sbuffer_Init(&ordinalResponse); + rc = TPM_Sbuffer_Load(&ordinalResponse, stream, stream_size); + TPM_Sbuffer_Delete(&ordinalResponse); + } + if (rc == 0) { + uint32_t responseCount; + rc = TPM_Load32(&responseCount, stream, stream_size); + } + } + return rc; +} + +/* TPM_StclearData_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_StclearData_Store(TPM_STORE_BUFFER *sbuffer, + TPM_STCLEAR_DATA *tpm_stclear_data, + TPM_PCR_ATTRIBUTES *pcrAttrib) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StclearData_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STCLEAR_DATA_V2); + } + /* store contextNonceKey */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_stclear_data->contextNonceKey); + } + /* store countID */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->countID); + } + /* store ownerReference */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->ownerReference); + } + /* store disableResetLock */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_data->disableResetLock), + sizeof(TPM_BOOL)); + } + /* store PCR's */ + if (rc == 0) { + rc = TPM_PCRs_Store(sbuffer, tpm_stclear_data->PCRS, pcrAttrib); + } +#if (TPM_REVISION >= 103) /* added for rev 103 */ + /* store deferredPhysicalPresence */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->deferredPhysicalPresence); + } +#endif + /* store authFailCount */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->authFailCount); + } + /* store authFailTime */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->authFailTime); + } + /* store authorization sessions */ + if (rc == 0) { + rc = TPM_AuthSessions_Store(sbuffer, tpm_stclear_data->authSessions); + } + /* store transport sessions */ + if (rc == 0) { + rc = TPM_TransportSessions_Store(sbuffer, tpm_stclear_data->transSessions); + } + /* store DAA sessions */ + if (rc == 0) { + rc = TPM_DaaSessions_Store(sbuffer, tpm_stclear_data->daaSessions); + } + /* store contextNonceSession */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_stclear_data->contextNonceSession); + } + /* store contextCount */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->contextCount); + } + /* store contextList */ + if (rc == 0) { + rc = TPM_ContextList_Store(sbuffer, tpm_stclear_data->contextList); + } + /* store auditDigest */ + if (rc == 0) { + TPM_PrintFour(" TPM_StclearData_Store: auditDigest", tpm_stclear_data->auditDigest); + rc = TPM_Digest_Store(sbuffer, tpm_stclear_data->auditDigest); + } + /* no need to store and load ordinalResponse */ + return rc; +} + +/* TPM_StclearData_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_StclearData_Init to set members back to default values + The object itself is not freed +*/ + +/* TPM_StclearData_Delete() frees any memory associated with TPM_STCLEAR_DATA, and then + reinitializes the structure. + + If pcrInit is TRUE, the PCR's are initialized. +*/ + +void TPM_StclearData_Delete(TPM_STCLEAR_DATA *tpm_stclear_data, + TPM_PCR_ATTRIBUTES *pcrAttrib, + TPM_BOOL pcrInit) +{ + printf(" TPM_StclearData_Delete:\n"); + if (tpm_stclear_data != NULL) { + TPM_StclearData_SessionDelete(tpm_stclear_data);/* authorization, transport, and DAA + sessions */ + TPM_Sbuffer_Delete(&(tpm_stclear_data->ordinalResponse)); + TPM_StclearData_Init(tpm_stclear_data, pcrAttrib, pcrInit); + } + return; +} + +/* TPM_StclearData_SessionInit() initializes the structure members associated with authorization, + transport, and DAA sessions. + + It must be called whenever the sessions are invalidated. +*/ + +void TPM_StclearData_SessionInit(TPM_STCLEAR_DATA *tpm_stclear_data) +{ + printf(" TPM_StclearData_SessionInit:\n"); + /* active sessions */ + TPM_AuthSessions_Init(tpm_stclear_data->authSessions); + TPM_TransportSessions_Init(tpm_stclear_data->transSessions); + TPM_DaaSessions_Init(tpm_stclear_data->daaSessions); + /* saved sessions */ + TPM_Nonce_Init(tpm_stclear_data->contextNonceSession); + tpm_stclear_data->contextCount = 0; + TPM_ContextList_Init(tpm_stclear_data->contextList); + return; +} + +/* TPM_StclearData_SessionDelete() deletes the structure members associated with authorization, + transport, and DAA sessions. + + It must be called whenever the sessions are invalidated. +*/ + +void TPM_StclearData_SessionDelete(TPM_STCLEAR_DATA *tpm_stclear_data) +{ + printf(" TPM_StclearData_SessionDelete:\n"); + /* active and saved authorization sessions, the authSessions table and the 3 contextList + entries */ + TPM_StclearData_AuthSessionDelete(tpm_stclear_data); + /* loaded transport sessions */ + TPM_TransportSessions_Delete(tpm_stclear_data->transSessions); + /* loaded DAA sessions */ + TPM_DaaSessions_Delete(tpm_stclear_data->daaSessions); + return; +} + +/* TPM_StclearData_AuthSessionDelete() deletes the structure members associated with authorization + sessions. It clears the authSessions table and the 3 contextList members. + + It must be called whenever the sessions are invalidated. +*/ + +void TPM_StclearData_AuthSessionDelete(TPM_STCLEAR_DATA *tpm_stclear_data) +{ + printf(" TPM_StclearData_AuthSessionDelete:\n"); + /* active sessions */ + TPM_AuthSessions_Delete(tpm_stclear_data->authSessions); + /* saved sessions */ + TPM_Nonce_Init(tpm_stclear_data->contextNonceSession); + tpm_stclear_data->contextCount = 0; + TPM_ContextList_Init(tpm_stclear_data->contextList); + return; +} + +/* + TPM_InitCmd() executes the actions of the TPM_Init 'ordinal' +*/ + +TPM_RESULT TPM_InitCmd(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + uint32_t tpm_number; + + printf(" TPM_Init:\n"); + /* Release all resources for the TPM and reinitialize */ + if (rc == TPM_SUCCESS) { + tpm_number = tpm_state->tpm_number; /* save the TPM value */ + TPM_Global_Delete(tpm_state); /* delete all the state */ + rc = TPM_Global_Init(tpm_state); /* re-allocate the state */ + } + /* Reload non-volatile memory */ + if (rc == TPM_SUCCESS) { + tpm_state->tpm_number = tpm_number; /* restore the TPM number */ + /* Returns TPM_RETRY on non-existent file */ + rc = TPM_PermanentAll_NVLoad(tpm_state); /* reload the state */ + if (rc == TPM_RETRY) { + printf("TPM_Init: Error (fatal), non-existent instance\n"); + rc = TPM_FAIL; + } + } + return rc; +} + +/* + TPM_Handle_GenerateHandle() is a utility function that returns an unused handle. + + It's really not an initialization function, but as the handle arrays are typically in + TPM_STCLEAR_DATA, it's a reasonable home. + + If 'tpm_handle' is non-zero, it is the first value tried. If 'keepHandle' is TRUE, it is the only + value tried. + + If 'tpm_handle' is zero, a random value is assigned. If 'keepHandle' is TRUE, an error returned, + as zero is an illegal handle value. + + If 'isKeyHandle' is TRUE, special checking is performed to avoid reserved values. + + 'getEntryFunction' is a function callback to check whether the handle has already been assigned to + an entry in the appropriate handle list. +*/ + +TPM_RESULT TPM_Handle_GenerateHandle(TPM_HANDLE *tpm_handle, + void *tpm_handle_entries, + TPM_BOOL keepHandle, + TPM_BOOL isKeyHandle, + TPM_GETENTRY_FUNCTION_T getEntryFunction) +{ + TPM_RESULT rc = 0; + TPM_RESULT getRc = 0; + unsigned int timeout; /* collision timeout */ + void *used_handle_entry; /* place holder for discarded entry */ + TPM_BOOL done; + + printf(" TPM_Handle_GenerateHandle: handle %08x, keepHandle %u\n", + *tpm_handle, keepHandle); + /* if the input value must be used */ + if (keepHandle) { + /* 0 is illegal and cannot be kept */ + if (rc == 0) { + if (*tpm_handle == 0) { + printf("TPM_Handle_GenerateHandle: Error, cannot keep handle 0\n"); + rc = TPM_BAD_HANDLE; + } + } + /* key handles beginning with 0x40 are reserved special values */ + if (rc == 0) { + if (isKeyHandle) { + if ((*tpm_handle & 0xff000000) == 0x40000000) { + printf("TPM_Handle_GenerateHandle: Error, cannot keep reserved key handle\n"); + rc = TPM_BAD_HANDLE; + } + } + } + /* check if the handle is already used */ + if (rc == 0) { + getRc = getEntryFunction(&used_handle_entry, /* discarded entry */ + tpm_handle_entries, /* handle array */ + *tpm_handle); /* search for handle */ + /* success mean the handle has already been assigned */ + if (getRc == 0) { + printf("TPM_Handle_GenerateHandle: Error handle already in use\n"); + rc = TPM_BAD_HANDLE; + } + } + } + /* input value is recommended but not required */ + else { + /* implement a crude timeout in case the random number generator fails and there are too + many collisions */ + for (done = FALSE, timeout = 0 ; (rc == 0) && !done && (timeout < 1000) ; timeout++) { + /* If no handle has been assigned, try a random value. If a handle has been assigned, + try it first */ + if (rc == 0) { + if (*tpm_handle == 0) { + rc = TPM_Random((BYTE *)tpm_handle, sizeof(uint32_t)); + } + } + /* if the random value is 0, reject it immediately */ + if (rc == 0) { + if (*tpm_handle == 0) { + printf(" TPM_Handle_GenerateHandle: Random value 0 rejected\n"); + continue; + } + } + /* if the value is a reserved key handle, reject it immediately */ + if (rc == 0) { + if (isKeyHandle) { + if ((*tpm_handle & 0xff000000) == 0x40000000) { + printf(" TPM_Handle_GenerateHandle: Random value %08x rejected\n", + *tpm_handle); + *tpm_handle = 0; /* ignore the assigned value */ + continue; + } + } + } + /* test if the handle has already been used */ + if (rc == 0) { + getRc = getEntryFunction(&used_handle_entry, /* discarded entry */ + tpm_handle_entries, /* handle array */ + *tpm_handle); /* search for handle */ + if (getRc != 0) { /* not found, done */ + printf(" TPM_Handle_GenerateHandle: Assigned Handle %08x\n", + *tpm_handle); + done = TRUE; + } + else { /* found, try again */ + *tpm_handle = 0; /* ignore the assigned value */ + printf(" TPM_Handle_GenerateHandle: Handle %08x already used\n", + *tpm_handle); + } + } + } + if (!done) { + printf("TPM_Handle_GenerateHandle: Error (fatal), random number generator failed\n"); + rc = TPM_FAIL; + } + } + return rc; +} + +/* + Processing Functions +*/ + +/* TPM_Init + + This ordinal should not be implemented, since it allows software to imitate a reboot. That would + be a major security hole, since the PCR's are reset. + + It is only here for regression tests. +*/ + +TPM_RESULT TPM_Process_Init(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + printf("TPM_Process_Init: Ordinal Entry\n"); + ordinal = ordinal; /* not used */ + command = command; /* not used */ + transportInternal = transportInternal; /* not used */ + /* check state */ + /* NOTE: Allow at any time. */ + /* + get inputs + */ + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Init: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { +#ifdef TPM_TEST + returnCode = TPM_InitCmd(tpm_state); +#else + tpm_state = tpm_state; /* to quiet the compiler */ + printf("TPM_Process_Init: Error, bad ordinal\n"); + returnCode = TPM_BAD_ORDINAL; +#endif + } + /* + response + */ + if (rcf == 0) { + printf("TPM_Process_Init: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + return rcf; +} + diff --git a/src/tpm12/tpm_init.h b/src/tpm12/tpm_init.h new file mode 100644 index 0000000..276e537 --- /dev/null +++ b/src/tpm12/tpm_init.h @@ -0,0 +1,136 @@ +/********************************************************************************/ +/* */ +/* TPM Initialization */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_init.h 4403 2011-02-08 18:28:22Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_INIT_H +#define TPM_INIT_H + +#include "tpm_global.h" +#include "tpm_store.h" +#include "tpm_structures.h" + +/* Power up initialization */ +TPM_RESULT TPM_MainInit(void); + +/* + TPM_STANY_FLAGS +*/ + +void TPM_StanyFlags_Init(TPM_STANY_FLAGS *tpm_stany_flags); + +TPM_RESULT TPM_StanyFlags_Load(TPM_STANY_FLAGS *tpm_stany_flags, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_StanyFlags_Store(TPM_STORE_BUFFER *sbuffer, + TPM_STANY_FLAGS *tpm_stany_flags); + +/* + TPM_STCLEAR_FLAGS +*/ + +void TPM_StclearFlags_Init(TPM_STCLEAR_FLAGS *tpm_stclear_flags); +TPM_RESULT TPM_StclearFlags_Load(TPM_STCLEAR_FLAGS *tpm_stclear_flags, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_StclearFlags_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_STCLEAR_FLAGS *tpm_stclear_flags); +TPM_RESULT TPM_StclearFlags_StoreBitmap(uint32_t *tpm_bitmap, + const TPM_STCLEAR_FLAGS *tpm_stclear_flags); +/* + TPM_STANY_DATA +*/ + +TPM_RESULT TPM_StanyData_Init(TPM_STANY_DATA *tpm_stany_data); +TPM_RESULT TPM_StanyData_Load(TPM_STANY_DATA *tpm_stany_data, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_StanyData_Store(TPM_STORE_BUFFER *sbuffer, + TPM_STANY_DATA *tpm_stany_data); +void TPM_StanyData_Delete(TPM_STANY_DATA *tpm_stany_data); + +/* + TPM_STCLEAR_DATA +*/ + +void TPM_StclearData_Init(TPM_STCLEAR_DATA *tpm_stclear_data, + TPM_PCR_ATTRIBUTES *pcrAttrib, + TPM_BOOL pcrInit); +TPM_RESULT TPM_StclearData_Load(TPM_STCLEAR_DATA *tpm_stclear_data, + unsigned char **stream, + uint32_t *stream_size, + TPM_PCR_ATTRIBUTES *pcrAttrib); +TPM_RESULT TPM_StclearData_Store(TPM_STORE_BUFFER *sbuffer, + TPM_STCLEAR_DATA *tpm_stclear_data, + TPM_PCR_ATTRIBUTES *pcrAttrib); +void TPM_StclearData_Delete(TPM_STCLEAR_DATA *tpm_stclear_data, + TPM_PCR_ATTRIBUTES *pcrAttrib, + TPM_BOOL pcrInit); + +void TPM_StclearData_SessionInit(TPM_STCLEAR_DATA *tpm_stclear_data); +void TPM_StclearData_SessionDelete(TPM_STCLEAR_DATA *tpm_stclear_data); +void TPM_StclearData_AuthSessionDelete(TPM_STCLEAR_DATA *tpm_stclear_data); + +/* Actions */ + +TPM_RESULT TPM_InitCmd(tpm_state_t *tpm_state); + +/* + Processing Functions +*/ + +TPM_RESULT TPM_Process_Init(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +/* generic function prototype for a handle array getEntry callback function */ + +typedef TPM_RESULT (*TPM_GETENTRY_FUNCTION_T )(void **entry, + void *entries, + TPM_HANDLE handle); + +TPM_RESULT TPM_Handle_GenerateHandle(TPM_HANDLE *tpm_handle, + void *tpm_handle_entries, + TPM_BOOL keepHandle, + TPM_BOOL isKeyHandle, + TPM_GETENTRY_FUNCTION_T getEntryFunction); + +#endif diff --git a/src/tpm12/tpm_io.h b/src/tpm12/tpm_io.h new file mode 100644 index 0000000..055b0ba --- /dev/null +++ b/src/tpm12/tpm_io.h @@ -0,0 +1,71 @@ +/********************************************************************************/ +/* */ +/* TPM Host IO */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_io.h 4211 2010-11-22 21:07:24Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_IO_H +#define TPM_IO_H + +#include "tpm_types.h" + +/* non-portable structure to pass around IO file descriptor */ + +typedef struct TPM_CONNECTION_FD { +#ifdef TPM_POSIX + int fd; /* for socket, just an int */ +#endif +} TPM_CONNECTION_FD; + + +TPM_RESULT TPM_IO_IsNotifyAvailable(TPM_BOOL *isAvailable); +TPM_RESULT TPM_IO_Connect(TPM_CONNECTION_FD *connection_fd, + void *mainLoopArgs); +TPM_RESULT TPM_IO_Read(TPM_CONNECTION_FD *connection_fd, + unsigned char *buffer, + uint32_t *paramSize, + size_t buffer_size, + void *mainLoopArgs); +TPM_RESULT TPM_IO_Write(TPM_CONNECTION_FD *connection_fd, + const unsigned char *buffer, + size_t buffer_length); +TPM_RESULT TPM_IO_Disconnect(TPM_CONNECTION_FD *connection_fd); + +/* function for notifying listener(s) about PCRExtend events */ +TPM_RESULT TPM_IO_ClientSendNotification(const void *buf, size_t count); + + +#endif diff --git a/src/tpm12/tpm_key.c b/src/tpm12/tpm_key.c new file mode 100644 index 0000000..6fce495 --- /dev/null +++ b/src/tpm12/tpm_key.c @@ -0,0 +1,5529 @@ +/********************************************************************************/ +/* */ +/* Key Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_key.c 4655 2011-12-21 21:03:15Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_auth.h" +#include "tpm_commands.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_init.h" +#include "tpm_io.h" +#include "tpm_load.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_nvfile.h" +#include "tpm_nvram.h" +#include "tpm_owner.h" +#include "tpm_pcr.h" +#include "tpm_sizedbuffer.h" +#include "tpm_store.h" +#include "tpm_structures.h" +#include "tpm_startup.h" +#include "tpm_permanent.h" +#include "tpm_process.h" +#include "tpm_ver.h" + +#include "tpm_key.h" + +/* The default RSA exponent */ +unsigned char tpm_default_rsa_exponent[] = {0x01, 0x00, 0x01}; + +/* local prototypes */ + +static TPM_RESULT TPM_Key_CheckTag(TPM_KEY12 *tpm_key12); + +/* + TPM_KEY, TPM_KEY12 + + These functions generally handle either a TPM_KEY or TPM_KEY12. Where structure members differ, + the function checks the version or tag and adapts the processing to the structure type. This + handling is opaque to the caller. +*/ + + +/* TPM_Key_Init initializes a key structure. The default is TPM_KEY. Typically, a TPM_Key_Set() or + TPM_Key_Load() will adjust to TPM_KEY or TPM_KEY12 */ + +void TPM_Key_Init(TPM_KEY *tpm_key) +{ + printf(" TPM_Key_Init:\n"); + TPM_StructVer_Init(&(tpm_key->ver)); + tpm_key->keyUsage = TPM_KEY_UNINITIALIZED; + tpm_key->keyFlags = 0; + tpm_key->authDataUsage = 0; + TPM_KeyParms_Init(&(tpm_key->algorithmParms)); + TPM_SizedBuffer_Init(&(tpm_key->pcrInfo)); + TPM_SizedBuffer_Init(&(tpm_key->pubKey)); + TPM_SizedBuffer_Init(&(tpm_key->encData)); + tpm_key->tpm_pcr_info = NULL; + tpm_key->tpm_pcr_info_long = NULL; + tpm_key->tpm_store_asymkey = NULL; + tpm_key->tpm_migrate_asymkey = NULL; + return; +} + +/* TPM_Key_InitTag12() alters the tag and fill from TPM_KEY to TPM_KEY12 */ + +void TPM_Key_InitTag12(TPM_KEY *tpm_key) +{ + printf(" TPM_Key_InitTag12:\n"); + ((TPM_KEY12 *)tpm_key)->tag = TPM_TAG_KEY12; + ((TPM_KEY12 *)tpm_key)->fill = 0x0000; + return; +} + +/* TPM_Key_Set() sets a TPM_KEY structure to the specified values. + + The tpm_pcr_info digestAtCreation is calculated. + + It serializes the tpm_pcr_info or tpm_pcr_info_long cache to pcrInfo. One or the other may be + specified, but not both. The tag/version is set correctly. + + If the parent_key is NULL, encData is set to the clear text serialization of the + tpm_store_asymkey member. + + If parent_key is not NULL, encData is not set yet, since further processing may be done before + encryption. + + Must call TPM_Key_Delete() to free + */ + +TPM_RESULT TPM_Key_Set(TPM_KEY *tpm_key, /* output created key */ + tpm_state_t *tpm_state, + TPM_KEY *parent_key, /* NULL for root keys */ + TPM_DIGEST *tpm_pcrs, /* points to the TPM PCR array */ + int ver, /* TPM_KEY or TPM_KEY12 */ + TPM_KEY_USAGE keyUsage, /* input */ + TPM_KEY_FLAGS keyFlags, /* input */ + TPM_AUTH_DATA_USAGE authDataUsage, /* input */ + TPM_KEY_PARMS *tpm_key_parms, /* input */ + TPM_PCR_INFO *tpm_pcr_info, /* must copy */ + TPM_PCR_INFO_LONG *tpm_pcr_info_long, /* must copy */ + uint32_t keyLength, /* public key length in bytes */ + BYTE* publicKey, /* public key byte array */ + TPM_STORE_ASYMKEY *tpm_store_asymkey, /* cache TPM_STORE_ASYMKEY */ + TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey) /* cache TPM_MIGRATE_ASYMKEY */ +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; + + printf(" TPM_Key_Set:\n"); + TPM_Sbuffer_Init(&sbuffer); + /* version must be TPM_KEY or TPM_KEY12 */ + if (rc == 0) { + if ((ver != 1) && (ver != 2)) { + printf("TPM_Key_Set: Error (fatal), " + "TPM_KEY version %d is not 1 or 2\n", ver); + rc = TPM_FAIL; /* should never occur */ + } + } + /* either tpm_pcr_info != NULL for TPM_KEY or tpm_pcr_info_long != NULL for TPM_KEY12, but not + both */ + if (rc == 0) { + if ((ver == 1) && (tpm_pcr_info_long != NULL)) { + printf("TPM_Key_Set: Error (fatal), " + "TPM_KEY and TPM_PCR_INFO_LONG both specified\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + if ((ver == 2) && (tpm_pcr_info != NULL)) { + printf("TPM_Key_Set: Error (fatal), " + "TPM_KEY12 and TPM_PCR_INFO both specified\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + TPM_Key_Init(tpm_key); + if (ver == 2) { + TPM_Key_InitTag12(tpm_key); /* change tag to TPM_KEY12 */ + } + tpm_key->keyUsage = keyUsage; + tpm_key->keyFlags = keyFlags; + tpm_key->authDataUsage = authDataUsage; + rc = TPM_KeyParms_Copy(&(tpm_key->algorithmParms), /* freed by caller */ + tpm_key_parms); + } + /* The pcrInfo serialization is deferred, since PCR data is be altered after the initial + 'set'. */ + if (rc == 0) { + /* generate the TPM_PCR_INFO member cache, directly copying from the tpm_pcr_info */ + if (tpm_pcr_info != NULL) { /* TPM_KEY */ + rc = TPM_PCRInfo_CreateFromInfo(&(tpm_key->tpm_pcr_info), tpm_pcr_info); + } + /* generate the TPM_PCR_INFO_LONG member cache, directly copying from the + tpm_pcr_info_long */ + else if (tpm_pcr_info_long != NULL) { /* TPM_KEY12 */ + rc = TPM_PCRInfoLong_CreateFromInfoLong(&(tpm_key->tpm_pcr_info_long), + tpm_pcr_info_long); + } + } + if (rc == 0) { + /* if there are PCR's specified, set the digestAtCreation */ + if (tpm_pcr_info != NULL) { + rc = TPM_PCRInfo_SetDigestAtCreation(tpm_key->tpm_pcr_info, tpm_pcrs); + } + /* if there are PCR's specified, set the localityAtCreation, digestAtCreation */ + else if (tpm_pcr_info_long != NULL) { /* TPM_KEY12 */ + if (rc == 0) { + rc = TPM_Locality_Set(&(tpm_key->tpm_pcr_info_long->localityAtCreation), + tpm_state->tpm_stany_flags.localityModifier); + } + if (rc == 0) { + rc = TPM_PCRInfoLong_SetDigestAtCreation(tpm_key->tpm_pcr_info_long, tpm_pcrs); + } + } + } + /* set TPM_SIZED_BUFFER pubKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Set(&(tpm_key->pubKey), + keyLength, /* in bytes */ + publicKey); + } + if (rc == 0) { + if (tpm_store_asymkey == NULL) { + printf("TPM_Key_Set: Error (fatal), No TPM_STORE_ASYMKEY supplied\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + /* sanity check, currently no need to set TPM_MIGRATE_ASYMKEY */ + if (rc == 0) { + if (tpm_migrate_asymkey != NULL) { + printf("TPM_Key_Set: Error (fatal), TPM_MIGRATE_ASYMKEY supplied\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + /* root key, no parent, just serialize the TPM_STORE_ASYMKEY structure */ + if (parent_key == NULL) { + if (rc == 0) { + rc = TPM_StoreAsymkey_Store(&sbuffer, FALSE, tpm_store_asymkey); /* freed @1 */ + } + if (rc == 0) { + rc = TPM_SizedBuffer_SetFromStore(&(tpm_key->encData), &sbuffer); + } + } + } + if (rc == 0) { + tpm_key->tpm_store_asymkey = tpm_store_asymkey; /* cache TPM_STORE_ASYMKEY */ + tpm_key->tpm_migrate_asymkey = tpm_migrate_asymkey; /* cache TPM_MIGRATE_ASYMKEY */ + } + /* Generate the TPM_STORE_ASYMKEY -> pubDataDigest. Serializes pcrInfo as a side effect. */ + if (rc == 0) { + rc = TPM_Key_GeneratePubDataDigest(tpm_key); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_Key_Copy() copies the source TPM_KEY to the destination. + + The destination should be initialized before the call. +*/ + +TPM_RESULT TPM_Key_Copy(TPM_KEY *tpm_key_dest, + TPM_KEY *tpm_key_src, + TPM_BOOL copyEncData) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + TPM_StructVer_Copy(&(tpm_key_dest->ver), &(tpm_key_src->ver)); /* works for TPM_KEY12 + also */ + tpm_key_dest->keyUsage = tpm_key_src->keyUsage; + tpm_key_dest->keyFlags = tpm_key_src->keyFlags; + tpm_key_dest->authDataUsage = tpm_key_src->authDataUsage; + rc = TPM_KeyParms_Copy(&(tpm_key_dest->algorithmParms), &(tpm_key_src->algorithmParms)); + } + if (rc == 0) { + rc = TPM_SizedBuffer_Copy(&(tpm_key_dest->pcrInfo), &(tpm_key_src->pcrInfo)); + } + /* copy TPM_PCR_INFO cache */ + if (rc == 0) { + if (tpm_key_src->tpm_pcr_info != NULL) { /* TPM_KEY */ + rc = TPM_PCRInfo_CreateFromInfo(&(tpm_key_dest->tpm_pcr_info), + tpm_key_src->tpm_pcr_info); + } + else if (tpm_key_src->tpm_pcr_info_long != NULL) { /* TPM_KEY12 */ + rc = TPM_PCRInfoLong_CreateFromInfoLong(&(tpm_key_dest->tpm_pcr_info_long), + tpm_key_src->tpm_pcr_info_long); + } + } + /* copy pubKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Copy(&(tpm_key_dest->pubKey), &(tpm_key_src->pubKey)); + } + /* copy encData */ + if (rc == 0) { + if (copyEncData) { + rc = TPM_SizedBuffer_Copy(&(tpm_key_dest->encData), &(tpm_key_src->encData)); + } + } + return rc; +} + +/* TPM_Key_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + The TPM_PCR_INFO or TPM_PCR_INFO_LONG cache is set from the deserialized pcrInfo stream. + + After use, call TPM_Key_Delete() to free memory +*/ + + +TPM_RESULT TPM_Key_Load(TPM_KEY *tpm_key, /* result */ + unsigned char **stream, /* pointer to next parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_Load:\n"); + /* load public data, and create PCR cache */ + if (rc == 0) { + rc = TPM_Key_LoadPubData(tpm_key, FALSE, stream, stream_size); + } + /* load encDataSize and encData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_key->encData), stream, stream_size); + } + return rc; +} + +/* TPM_Key_LoadClear() load a serialized key where the TPM_STORE_ASYMKEY structure is serialized in + clear text. + + The TPM_PCR_INFO or TPM_PCR_INFO_LONG cache is set from the deserialized pcrInfo stream. + + This function is used to load internal keys (e.g. EK, SRK, owner evict keys) or keys saved as + part of a save state. +*/ + +TPM_RESULT TPM_Key_LoadClear(TPM_KEY *tpm_key, /* result */ + TPM_BOOL isEK, /* key being loaded is EK */ + unsigned char **stream, /* pointer to next parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + uint32_t storeAsymkeySize; + + printf(" TPM_Key_LoadClear:\n"); + /* load public data */ + if (rc == 0) { + rc = TPM_Key_LoadPubData(tpm_key, isEK, stream, stream_size); + } + /* load TPM_STORE_ASYMKEY size */ + if (rc == 0) { + rc = TPM_Load32(&storeAsymkeySize, stream, stream_size); + } + /* The size might be 0 for an uninitialized internal key. That case is not an error. */ + if ((rc == 0) && (storeAsymkeySize > 0)) { + rc = TPM_Key_LoadStoreAsymKey(tpm_key, isEK, stream, stream_size); + } + return rc; +} + +/* TPM_Key_LoadPubData() deserializes a TPM_KEY or TPM_KEY12 structure, excluding encData, to + 'tpm_key'. + + The TPM_PCR_INFO or TPM_PCR_INFO_LONG cache is set from the deserialized pcrInfo stream. + If the pcrInfo stream is empty, the caches remain NULL. + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + After use, call TPM_Key_Delete() to free memory +*/ + +TPM_RESULT TPM_Key_LoadPubData(TPM_KEY *tpm_key, /* result */ + TPM_BOOL isEK, /* key being loaded is EK */ + unsigned char **stream, /* pointer to next parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_LoadPubData:\n"); + /* peek at the first byte */ + if (rc == 0) { + /* TPM_KEY[0] is major (non zero) */ + if ((*stream)[0] != 0) { + /* load ver */ + if (rc == 0) { + rc = TPM_StructVer_Load(&(tpm_key->ver), stream, stream_size); + } + /* check ver immediately to ease debugging */ + if (rc == 0) { + rc = TPM_StructVer_CheckVer(&(tpm_key->ver)); + } + } + else { + /* TPM_KEY12 is tag (zero) */ + /* load tag */ + if (rc == 0) { + rc = TPM_Load16(&(((TPM_KEY12 *)tpm_key)->tag), stream, stream_size); + } + /* load fill */ + if (rc == 0) { + rc = TPM_Load16(&(((TPM_KEY12 *)tpm_key)->fill), stream, stream_size); + } + if (rc == 0) { + rc = TPM_Key_CheckTag((TPM_KEY12 *)tpm_key); + } + } + } + /* load keyUsage */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_key->keyUsage), stream, stream_size); + } + /* load keyFlags */ + if (rc == 0) { + rc = TPM_KeyFlags_Load(&(tpm_key->keyFlags), stream, stream_size); + } + /* load authDataUsage */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_key->authDataUsage), stream, stream_size); + } + /* load algorithmParms */ + if (rc == 0) { + rc = TPM_KeyParms_Load(&(tpm_key->algorithmParms), stream, stream_size); + } + /* load PCRInfo */ + if ((rc == 0) && !isEK) { + rc = TPM_SizedBuffer_Load(&(tpm_key->pcrInfo), stream, stream_size); + } + /* set TPM_PCR_INFO tpm_pcr_info cache from PCRInfo stream. If the stream is empty, a NULL is + returned. + */ + if ((rc == 0) && !isEK) { + if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ + rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_key->tpm_pcr_info), + &(tpm_key->pcrInfo)); + } + else { /* TPM_KEY12 */ + rc = TPM_PCRInfoLong_CreateFromBuffer(&(tpm_key->tpm_pcr_info_long), + &(tpm_key->pcrInfo)); + } + } + /* load pubKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_key->pubKey), stream, stream_size); + } + return rc; +} + +/* TPM_Key_StorePubData() serializes a TPM_KEY or TPM_KEY12 structure, excluding encData, appending + results to 'sbuffer'. + + As a side effect, it serializes the tpm_pcr_info cache to pcrInfo. +*/ + +TPM_RESULT TPM_Key_StorePubData(TPM_STORE_BUFFER *sbuffer, + TPM_BOOL isEK, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_StorePubData:\n"); + + if (rc == 0) { + /* store ver */ + if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ + rc = TPM_StructVer_Store(sbuffer, &(tpm_key->ver)); + } + else { /* TPM_KEY12 */ + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_KEY12); + } + /* store fill */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, 0x0000); + } + } + } + /* store keyUsage */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_key->keyUsage); + } + /* store keyFlags */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_key->keyFlags); + } + /* store authDataUsage */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_key->authDataUsage), sizeof(TPM_AUTH_DATA_USAGE)); + } + /* store algorithmParms */ + if (rc == 0) { + rc = TPM_KeyParms_Store(sbuffer, &(tpm_key->algorithmParms)); + } + /* store pcrInfo */ + if ((rc == 0) && !isEK) { + /* copy cache to pcrInfo */ + if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ + rc = TPM_SizedBuffer_SetStructure(&(tpm_key->pcrInfo), + tpm_key->tpm_pcr_info, + (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store); + } + else { /* TPM_KEY12 */ + rc = TPM_SizedBuffer_SetStructure(&(tpm_key->pcrInfo), + tpm_key->tpm_pcr_info_long, + (TPM_STORE_FUNCTION_T)TPM_PCRInfoLong_Store); + } + } + /* copy pcrInfo to sbuffer */ + if ((rc == 0) && !isEK) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_key->pcrInfo)); + } + /* store pubKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_key->pubKey)); + } + return rc; +} + +/* TPM_Key_Store() serializes a TPM_KEY structure, appending results to 'sbuffer' + + As a side effect, it serializes the tpm_pcr_info cache to pcrInfo. +*/ + +TPM_RESULT TPM_Key_Store(TPM_STORE_BUFFER *sbuffer, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_Store:\n"); + /* store the pubData */ + if (rc == 0) { + rc = TPM_Key_StorePubData(sbuffer, FALSE, tpm_key); + } + /* store encDataSize and encData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_key->encData)); + } + return rc; +} + +/* TPM_Key_StoreClear() serializes a TPM_KEY structure, appending results to 'sbuffer' + + TPM_Key_StoreClear() serializes the tpm_store_asymkey member as cleartext. It is used for keys + such as the SRK, which never leave the TPM. It is also used for saving state, where the entire + blob is encrypted. + + As a side effect, it serializes the tpm_pcr_info cache to pcrInfo. +*/ + +TPM_RESULT TPM_Key_StoreClear(TPM_STORE_BUFFER *sbuffer, + TPM_BOOL isEK, /* key being stored is EK */ + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER asymSbuffer; + const unsigned char *asymBuffer; + uint32_t asymLength; + + printf(" TPM_Key_StoreClear:\n"); + TPM_Sbuffer_Init(&asymSbuffer); /* freed @1 */ + /* store the pubData */ + if (rc == 0) { + rc = TPM_Key_StorePubData(sbuffer, isEK, tpm_key); + } + /* store TPM_STORE_ASYMKEY cache as cleartext */ + if (rc == 0) { + /* if the TPM_STORE_ASYMKEY cache exists */ + if (tpm_key->tpm_store_asymkey != NULL) { + /* , serialize it */ + if (rc == 0) { + rc = TPM_StoreAsymkey_Store(&asymSbuffer, isEK, tpm_key->tpm_store_asymkey); + } + /* get the result */ + TPM_Sbuffer_Get(&asymSbuffer, &asymBuffer, &asymLength); + /* store the result as a sized buffer */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, asymLength); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, asymBuffer, asymLength); + } + } + /* If there is no TPM_STORE_ASYMKEY cache, mark it empty. This can occur for an internal + key that has not been created yet. */ + else { + rc = TPM_Sbuffer_Append32(sbuffer, 0); + } + } + TPM_Sbuffer_Delete(&asymSbuffer); /* @1 */ + return rc; +} + +/* TPM_KEY_StorePubkey() gets (as a stream) the TPM_PUBKEY derived from a TPM_KEY + + There is no need to actually assemble the structure, since only the serialization of its two + members are needed. + + The stream is returned as a TPM_STORE_BUFFER (that must be initialized and deleted by the + caller), and it's components (buffer and size). +*/ + +TPM_RESULT TPM_Key_StorePubkey(TPM_STORE_BUFFER *pubkeyStream, /* output */ + const unsigned char **pubkeyStreamBuffer, /* output */ + uint32_t *pubkeyStreamLength, /* output */ + TPM_KEY *tpm_key) /* input */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_StorePubkey:\n"); + /* the first part is a TPM_KEY_PARMS */ + if (rc == 0) { + rc = TPM_KeyParms_Store(pubkeyStream, &(tpm_key->algorithmParms)); + } + /* the second part is the TPM_SIZED_BUFFER pubKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(pubkeyStream, &(tpm_key->pubKey)); + } + /* retrieve the resulting pubkey stream */ + if (rc == 0) { + TPM_Sbuffer_Get(pubkeyStream, + pubkeyStreamBuffer, + pubkeyStreamLength); + } + return rc; +} + +/* TPM_Key_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_Key_Init to set members back to default values + The TPM_KEY itself is not freed + + The key is not freed because it might be a local variable rather than a malloc'ed pointer. +*/ + +void TPM_Key_Delete(TPM_KEY *tpm_key) +{ + if (tpm_key != NULL) { + printf(" TPM_Key_Delete:\n"); + TPM_KeyParms_Delete(&(tpm_key->algorithmParms)); + /* pcrInfo */ + TPM_SizedBuffer_Delete(&(tpm_key->pcrInfo)); + /* pcr caches */ + TPM_PCRInfo_Delete(tpm_key->tpm_pcr_info); + free(tpm_key->tpm_pcr_info); + TPM_PCRInfoLong_Delete(tpm_key->tpm_pcr_info_long); + free(tpm_key->tpm_pcr_info_long); + + TPM_SizedBuffer_Delete(&(tpm_key->pubKey)); + TPM_SizedBuffer_Delete(&(tpm_key->encData)); + TPM_StoreAsymkey_Delete(tpm_key->tpm_store_asymkey); + free(tpm_key->tpm_store_asymkey); + TPM_MigrateAsymkey_Delete(tpm_key->tpm_migrate_asymkey); + free(tpm_key->tpm_migrate_asymkey); + TPM_Key_Init(tpm_key); + } + return; +} + +/* TPM_Key_CheckStruct() verifies that the 'tpm_key' has either a TPM_KEY -> ver of a TPM_KEY12 tag + and fill +*/ + +TPM_RESULT TPM_Key_CheckStruct(int *ver, TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + /* The key can be either a TPM_KEY or TPM_KEY12 */ + if (*(unsigned char *)tpm_key == 0x01) { + *ver = 1; + rc = TPM_StructVer_CheckVer(&(tpm_key->ver)); /* check for TPM_KEY */ + if (rc == 0) { /* if found TPM_KEY */ + printf(" TPM_Key_CheckStruct: TPM_KEY version %u.%u\n", + tpm_key->ver.major, tpm_key->ver.minor); + } + } + else { /* else check for TPM_KEY12 */ + *ver = 2; + rc = TPM_Key_CheckTag((TPM_KEY12 *)tpm_key); + if (rc == 0) { + printf(" TPM_Key_CheckStruct: TPM_KEY12\n"); + } + else { /* not TPM_KEY or TPM_KEY12 */ + printf("TPM_Key_CheckStruct: Error checking structure, bytes 0:3 %02x %02x %02x %02x\n", + tpm_key->ver.major, tpm_key->ver.minor, + tpm_key->ver.revMajor, tpm_key->ver.revMinor); + rc = TPM_BAD_KEY_PROPERTY; + } + } + return rc; +} + +/* TPM_Key_CheckTag() checks that the TPM_KEY12 tag is correct + */ + +static TPM_RESULT TPM_Key_CheckTag(TPM_KEY12 *tpm_key12) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + if (tpm_key12->tag != TPM_TAG_KEY12) { + printf("TPM_Key_CheckTag: Error, TPM_KEY12 tag %04x should be TPM_TAG_KEY12\n", + tpm_key12->tag); + rc = TPM_BAD_KEY_PROPERTY; + } + } + if (rc == 0) { + if (tpm_key12->fill != 0x0000) { + printf("TPM_Key_CheckTag: Error, TPM_KEY12 fill %04x should be 0x0000\n", + tpm_key12->fill); + rc = TPM_BAD_KEY_PROPERTY; + } + } + return rc; +} + +/* TPM_Key_CheckProperties() checks that the TPM can generate a key of the type requested in + 'tpm_key'. + + if keyLength is non-zero, checks that the tpm_key specifies the correct key length. If keyLength + is 0, any tpm_key key length is accepted. + + Returns TPM_BAD_KEY_PROPERTY on error. + */ + +TPM_RESULT TPM_Key_CheckProperties(int *ver, + TPM_KEY *tpm_key, + uint32_t keyLength, /* in bits */ + TPM_BOOL FIPS) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_CheckProperties:\n"); + /* check the version */ + if (rc == 0) { + rc = TPM_Key_CheckStruct(ver, tpm_key); + } + /* if FIPS */ + if ((rc == 0) && FIPS) { + /* b. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ + if (tpm_key->authDataUsage == TPM_AUTH_NEVER) { + printf("TPM_Key_CheckProperties: Error, FIPS authDataUsage TPM_AUTH_NEVER\n"); + rc = TPM_NOTFIPS; + } + } + /* most of the work is done by TPM_KeyParms_CheckProperties() */ + if (rc == 0) { + printf(" TPM_Key_CheckProperties: authDataUsage %02x\n", tpm_key->authDataUsage); + rc = TPM_KeyParms_CheckProperties(&(tpm_key->algorithmParms), + tpm_key->keyUsage, + keyLength, /* in bits */ + FIPS); + } + return rc; +} + +/* TPM_Key_LoadStoreAsymKey() deserializes a stream to a TPM_STORE_ASYMKEY structure and stores it + in the TPM_KEY cache. + + Call this function when a key is loaded, either from the host (stream is decrypted encData) or + from permanent data or saved state (stream was clear text). +*/ + +TPM_RESULT TPM_Key_LoadStoreAsymKey(TPM_KEY *tpm_key, + TPM_BOOL isEK, + unsigned char **stream, /* decrypted encData (clear text) */ + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + /* This function should never be called when the TPM_STORE_ASYMKEY structure has already been + loaded. This indicates an internal error. */ + printf(" TPM_Key_LoadStoreAsymKey:\n"); + if (rc == 0) { + if (tpm_key->tpm_store_asymkey != NULL) { + printf("TPM_Key_LoadStoreAsymKey: Error (fatal), TPM_STORE_ASYMKEY already loaded\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + /* If the stream size is 0, there is an internal error. */ + if (rc == 0) { + if (*stream_size == 0) { + printf("TPM_Key_LoadStoreAsymKey: Error (fatal), stream size is 0\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + /* allocate memory for the structure */ + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)&(tpm_key->tpm_store_asymkey), + sizeof(TPM_STORE_ASYMKEY)); + } + if (rc == 0) { + TPM_StoreAsymkey_Init(tpm_key->tpm_store_asymkey); + rc = TPM_StoreAsymkey_Load(tpm_key->tpm_store_asymkey, isEK, + stream, stream_size, + &(tpm_key->algorithmParms), &(tpm_key->pubKey)); + TPM_PrintFour(" TPM_Key_LoadStoreAsymKey: usageAuth", + tpm_key->tpm_store_asymkey->usageAuth); + } + return rc; +} + +/* TPM_Key_GetStoreAsymkey() gets the TPM_STORE_ASYMKEY from a TPM_KEY cache. + */ + +TPM_RESULT TPM_Key_GetStoreAsymkey(TPM_STORE_ASYMKEY **tpm_store_asymkey, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_GetStoreAsymkey:\n"); + if (rc == 0) { + /* return the cached structure */ + *tpm_store_asymkey = tpm_key->tpm_store_asymkey; + if (tpm_key->tpm_store_asymkey == NULL) { + printf("TPM_Key_GetStoreAsymkey: Error (fatal), no cache\n"); + rc = TPM_FAIL; /* indicate no cache */ + } + } + return rc; +} + +/* TPM_Key_GetMigrateAsymkey() gets the TPM_MIGRATE_ASYMKEY from a TPM_KEY cache. + */ + +TPM_RESULT TPM_Key_GetMigrateAsymkey(TPM_MIGRATE_ASYMKEY **tpm_migrate_asymkey, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_GetMigrateAsymkey:\n"); + if (rc == 0) { + /* return the cached structure */ + *tpm_migrate_asymkey = tpm_key->tpm_migrate_asymkey; + if (tpm_key->tpm_migrate_asymkey == NULL) { + printf("TPM_Key_GetMigrateAsymkey: Error (fatal), no cache\n"); + rc = TPM_FAIL; /* indicate no cache */ + } + } + return rc; +} + +/* TPM_Key_GetUsageAuth() gets the usageAuth from the TPM_STORE_ASYMKEY or TPM_MIGRATE_ASYMKEY + contained in a TPM_KEY +*/ + +TPM_RESULT TPM_Key_GetUsageAuth(TPM_SECRET **usageAuth, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_ASYMKEY *tpm_store_asymkey; + TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey; + + printf(" TPM_Key_GetUsageAuth:\n"); + /* check that the TPM_KEY_USAGE indicates a valid key */ + if (rc == 0) { + if ((tpm_key == NULL) || + (tpm_key->keyUsage == TPM_KEY_UNINITIALIZED)) { + printf("TPM_Key_GetUsageAuth: Error, key not initialized\n"); + rc = TPM_INVALID_KEYUSAGE; + } + } + /* get the TPM_STORE_ASYMKEY object */ + if (rc == 0) { + rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); + + /* found a TPM_STORE_ASYMKEY */ + if (rc == 0) { + *usageAuth = &(tpm_store_asymkey->usageAuth); + } + /* get the TPM_MIGRATE_ASYMKEY object */ + else { + rc = TPM_Key_GetMigrateAsymkey(&tpm_migrate_asymkey, tpm_key); + /* found a TPM_MIGRATE_ASYMKEY */ + if (rc == 0) { + *usageAuth = &(tpm_migrate_asymkey->usageAuth); + } + } + } + if (rc != 0) { + printf("TPM_Key_GetUsageAuth: Error (fatal), " + "could not get TPM_STORE_ASYMKEY or TPM_MIGRATE_ASYMKEY\n"); + rc = TPM_FAIL; /* should never occur */ + } + /* get the usageAuth element */ + if (rc == 0) { + TPM_PrintFour(" TPM_Key_GetUsageAuth: Auth", **usageAuth); + } + return rc; +} + +/* TPM_Key_GetPublicKey() gets the public key from the TPM_STORE_PUBKEY contained in a TPM_KEY + */ + +TPM_RESULT TPM_Key_GetPublicKey(uint32_t *nbytes, + unsigned char **narr, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_GetPublicKey:\n"); + if (rc == 0) { + *nbytes = tpm_key->pubKey.size; + *narr = tpm_key->pubKey.buffer; + } + return rc; +} + +/* TPM_Key_GetPrimeFactorP() gets the prime factor p from the TPM_STORE_ASYMKEY contained in a + TPM_KEY +*/ + +TPM_RESULT TPM_Key_GetPrimeFactorP(uint32_t *pbytes, + unsigned char **parr, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_ASYMKEY *tpm_store_asymkey; + + printf(" TPM_Key_GetPrimeFactorP:\n"); + if (rc == 0) { + rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); + } + if (rc == 0) { + *pbytes = tpm_store_asymkey->privKey.p_key.size; + *parr = tpm_store_asymkey->privKey.p_key.buffer; + } + return rc; +} + +/* TPM_Key_GetPrivateKey() gets the private key from the TPM_STORE_ASYMKEY contained in a TPM_KEY + */ + +TPM_RESULT TPM_Key_GetPrivateKey(uint32_t *dbytes, + unsigned char **darr, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_ASYMKEY *tpm_store_asymkey; + + printf(" TPM_Key_GetPrivateKey:\n"); + if (rc == 0) { + rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); + } + if (rc == 0) { + *dbytes = tpm_store_asymkey->privKey.d_key.size; + *darr = tpm_store_asymkey->privKey.d_key.buffer; + } + return rc; +} + +/* TPM_Key_GetExponent() gets the exponent key from the TPM_RSA_KEY_PARMS contained in a TPM_KEY + */ + +TPM_RESULT TPM_Key_GetExponent(uint32_t *ebytes, + unsigned char **earr, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_GetExponent:\n"); + if (rc == 0) { + rc = TPM_KeyParms_GetExponent(ebytes, earr, &(tpm_key->algorithmParms)); + } + return rc; +} + +/* TPM_Key_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit mask. + + 'start_pcr' indicates the starting byte index into pcrSelect[] +*/ + +TPM_RESULT TPM_Key_GetPCRUsage(TPM_BOOL *pcrUsage, + TPM_KEY *tpm_key, + size_t start_index) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_GetPCRUsage: Start %lu\n", (unsigned long)start_index); + if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ + rc = TPM_PCRInfo_GetPCRUsage(pcrUsage, tpm_key->tpm_pcr_info, start_index); + } + else { /* TPM_KEY12 */ + rc = TPM_PCRInfoLong_GetPCRUsage(pcrUsage, tpm_key->tpm_pcr_info_long, start_index); + } + return rc; +} + +/* TPM_Key_GetLocalityAtRelease() the localityAtRelease for a TPM_PCR_INFO_LONG. + For a TPM_PCR_INFO is returns TPM_LOC_ALL (all localities). +*/ + +TPM_RESULT TPM_Key_GetLocalityAtRelease(TPM_LOCALITY_SELECTION *localityAtRelease, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_GetLocalityAtRelease:\n"); + if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ + /* locality not used for TPM_PCR_INFO */ + *localityAtRelease = TPM_LOC_ALL; + } + /* TPM_KEY12 */ + else if (tpm_key->tpm_pcr_info_long == NULL) { + /* locality not used if TPM_PCR_INFO_LONG was not specified */ + *localityAtRelease = TPM_LOC_ALL; + } + else { + *localityAtRelease = tpm_key->tpm_pcr_info_long->localityAtRelease; + } + return rc; +} + +/* TPM_Key_GenerateRSA() generates a TPM_KEY using TPM_KEY_PARMS. The tag/version is set correctly. + + The TPM_STORE_ASYMKEY member cache is set. pcrInfo is set as a serialized tpm_pcr_info or + tpm_pcr_info_long. + + For exported keys, encData is not set yet. It later becomes the encryption of TPM_STORE_ASYMKEY. + + For internal 'root' keys (endorsement key, srk), encData is stored as clear text. + + It returns the TPM_KEY object. + + Call tree: + local - sets tpm_store_asymkey->privkey + TPM_Key_Set - sets keyUsage, keyFlags, authDataUsage, algorithmParms + tpm_pcr_info cache, digestAtCreation, pubKey, + TPM_Key_GeneratePubDataDigest - pubDataDigest + TPM_Key_Store + TPM_Key_StorePubData - serializes tpm_pcr_info cache +*/ + +TPM_RESULT TPM_Key_GenerateRSA(TPM_KEY *tpm_key, /* output created key */ + tpm_state_t *tpm_state, + TPM_KEY *parent_key, /* NULL for root keys */ + TPM_DIGEST *tpm_pcrs, /* PCR array from state */ + int ver, /* TPM_KEY or TPM_KEY12 */ + TPM_KEY_USAGE keyUsage, /* input */ + TPM_KEY_FLAGS keyFlags, /* input */ + TPM_AUTH_DATA_USAGE authDataUsage, /* input */ + TPM_KEY_PARMS *tpm_key_parms, /* input */ + TPM_PCR_INFO *tpm_pcr_info, /* input */ + TPM_PCR_INFO_LONG *tpm_pcr_info_long) /* input */ +{ + TPM_RESULT rc = 0; + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; + unsigned char *earr; /* public exponent */ + uint32_t ebytes; + + /* generated RSA key */ + unsigned char *n = NULL; /* public key */ + unsigned char *p = NULL; /* prime factor */ + unsigned char *q = NULL; /* prime factor */ + unsigned char *d = NULL; /* private key */ + + printf(" TPM_Key_GenerateRSA:\n"); + /* extract the TPM_RSA_KEY_PARMS from TPM_KEY_PARMS */ + if (rc == 0) { + rc = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, tpm_key_parms); + } + /* get the public exponent, with conversion */ + if (rc == 0) { + rc = TPM_RSAKeyParms_GetExponent(&ebytes, &earr, tpm_rsa_key_parms); + } + /* allocate storage for TPM_STORE_ASYMKEY. The structure is not freed. It is cached in the + TPM_KEY->TPM_STORE_ASYMKEY member and freed when they are deleted. */ + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)&(tpm_key->tpm_store_asymkey), + sizeof(TPM_STORE_ASYMKEY)); + } + if (rc == 0) { + TPM_StoreAsymkey_Init(tpm_key->tpm_store_asymkey); + } + /* generate the key pair */ + if (rc == 0) { + rc = TPM_RSAGenerateKeyPair(&n, /* public key (modulus) freed @3 */ + &p, /* private prime factor freed @4 */ + &q, /* private prime factor freed @5 */ + &d, /* private key (private exponent) freed @6 */ + tpm_rsa_key_parms->keyLength, /* key size in bits */ + earr, /* public exponent */ + ebytes); + } + /* construct the TPM_STORE_ASYMKEY member */ + if (rc == 0) { + TPM_PrintFour(" TPM_Key_GenerateRSA: Public key n", n); + TPM_PrintAll(" TPM_Key_GenerateRSA: Exponent", earr, ebytes); + TPM_PrintFour(" TPM_Key_GenerateRSA: Private prime p", p); + TPM_PrintFour(" TPM_Key_GenerateRSA: Private prime q", q); + TPM_PrintFour(" TPM_Key_GenerateRSA: Private key d", d); + /* add the private primes and key to the TPM_STORE_ASYMKEY object */ + rc = TPM_SizedBuffer_Set(&(tpm_key->tpm_store_asymkey->privKey.d_key), + tpm_rsa_key_parms->keyLength/CHAR_BIT, + d); + } + if (rc == 0) { + rc = TPM_SizedBuffer_Set(&(tpm_key->tpm_store_asymkey->privKey.p_key), + tpm_rsa_key_parms->keyLength/(CHAR_BIT * 2), + p); + } + if (rc == 0) { + rc = TPM_SizedBuffer_Set(&(tpm_key->tpm_store_asymkey->privKey.q_key), + tpm_rsa_key_parms->keyLength/(CHAR_BIT * 2), + q); + } + if (rc == 0) { + rc = TPM_Key_Set(tpm_key, + tpm_state, + parent_key, + tpm_pcrs, + ver, /* TPM_KEY or TPM_KEY12 */ + keyUsage, /* TPM_KEY_USAGE */ + keyFlags, /* TPM_KEY_FLAGS */ + authDataUsage, /* TPM_AUTH_DATA_USAGE */ + tpm_key_parms, /* TPM_KEY_PARMS */ + tpm_pcr_info, /* TPM_PCR_INFO */ + tpm_pcr_info_long, /* TPM_PCR_INFO_LONG */ + tpm_rsa_key_parms->keyLength/CHAR_BIT, /* TPM_STORE_PUBKEY.keyLength */ + n, /* TPM_STORE_PUBKEY.key (public key) */ + /* FIXME redundant */ + tpm_key->tpm_store_asymkey, /* cache the TPM_STORE_ASYMKEY structure */ + NULL); /* TPM_MIGRATE_ASYMKEY */ + } + free(n); /* @3 */ + free(p); /* @4 */ + free(q); /* @5 */ + free(d); /* @6 */ + return rc; +} + +/* TPM_Key_GeneratePubkeyDigest() serializes a TPM_PUBKEY derived from the TPM_KEY and calculates + its digest. +*/ + +TPM_RESULT TPM_Key_GeneratePubkeyDigest(TPM_DIGEST tpm_digest, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER pubkeyStream; /* from tpm_key */ + const unsigned char *pubkeyStreamBuffer; + uint32_t pubkeyStreamLength; + + printf(" TPM_Key_GeneratePubkeyDigest:\n"); + TPM_Sbuffer_Init(&pubkeyStream); /* freed @1 */ + /* serialize a TPM_PUBKEY derived from the TPM_KEY */ + if (rc == 0) { + rc = TPM_Key_StorePubkey(&pubkeyStream, /* output */ + &pubkeyStreamBuffer, /* output */ + &pubkeyStreamLength, /* output */ + tpm_key); /* input */ + } + if (rc == 0) { + rc = TPM_SHA1(tpm_digest, + pubkeyStreamLength, pubkeyStreamBuffer, + 0, NULL); + } + TPM_Sbuffer_Delete(&pubkeyStream); /* @1 */ + return rc; + +} + +/* TPM_Key_ComparePubkey() serializes and hashes the TPM_PUBKEY derived from a TPM_KEY and a + TPM_PUBKEY and compares the results +*/ + +TPM_RESULT TPM_Key_ComparePubkey(TPM_KEY *tpm_key, + TPM_PUBKEY *tpm_pubkey) +{ + TPM_RESULT rc = 0; + TPM_DIGEST key_digest; + TPM_DIGEST pubkey_digest; + + if (rc == 0) { + rc = TPM_Key_GeneratePubkeyDigest(key_digest, tpm_key); + } + if (rc == 0) { + rc = TPM_SHA1_GenerateStructure(pubkey_digest, tpm_pubkey, + (TPM_STORE_FUNCTION_T)TPM_Pubkey_Store); + } + if (rc == 0) { + rc = TPM_Digest_Compare(key_digest, pubkey_digest); + } + return rc; +} + +/* TPM_Key_GeneratePubDataDigest() generates and stores a TPM_STORE_ASYMKEY -> pubDataDigest + + As a side effect, it serializes the tpm_pcr_info cache to pcrInfo. +*/ + +TPM_RESULT TPM_Key_GeneratePubDataDigest(TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* TPM_KEY serialization */ + TPM_STORE_ASYMKEY *tpm_store_asymkey; + + printf(" TPM_Key_GeneratePubDataDigest:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize the TPM_KEY excluding the encData fields */ + if (rc == 0) { + rc = TPM_Key_StorePubData(&sbuffer, FALSE, tpm_key); + } + /* get the TPM_STORE_ASYMKEY structure */ + if (rc == 0) { + rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); + } + /* hash the serialized buffer to tpm_digest */ + if (rc == 0) { + rc = TPM_SHA1Sbuffer(tpm_store_asymkey->pubDataDigest, &sbuffer); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_Key_CheckPubDataDigest() generates a TPM_STORE_ASYMKEY -> pubDataDigest and compares it to + the stored value. + + Returns: Error id + */ + +TPM_RESULT TPM_Key_CheckPubDataDigest(TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* TPM_KEY serialization */ + TPM_STORE_ASYMKEY *tpm_store_asymkey; + TPM_DIGEST tpm_digest; /* calculated pubDataDigest */ + + printf(" TPM_Key_CheckPubDataDigest:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize the TPM_KEY excluding the encData fields */ + if (rc == 0) { + rc = TPM_Key_StorePubData(&sbuffer, FALSE, tpm_key); + } + /* get the TPM_STORE_ASYMKEY structure */ + if (rc == 0) { + rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); + } + if (rc == 0) { + rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); + } + if (rc == 0) { + rc = TPM_Digest_Compare(tpm_store_asymkey->pubDataDigest, tpm_digest); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_Key_GenerateEncData() generates an TPM_KEY -> encData structure member by serializing the + cached TPM_KEY -> TPM_STORE_ASYMKEY member and encrypting the result using the parent_key public + key. +*/ + +TPM_RESULT TPM_Key_GenerateEncData(TPM_KEY *tpm_key, + TPM_KEY *parent_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_ASYMKEY *tpm_store_asymkey; + + printf(" TPM_Key_GenerateEncData;\n"); + /* get the TPM_STORE_ASYMKEY structure */ + if (rc == 0) { + rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); + } + if (rc == 0) { + rc = TPM_StoreAsymkey_GenerateEncData(&(tpm_key->encData), + tpm_store_asymkey, + parent_key); + } + return rc; +} + + +/* TPM_Key_DecryptEncData() decrypts the TPM_KEY -> encData using the parent private key. The + result is deserialized and stored in the TPM_KEY -> TPM_STORE_ASYMKEY cache. + +*/ + +TPM_RESULT TPM_Key_DecryptEncData(TPM_KEY *tpm_key, /* result */ + TPM_KEY *parent_key) /* parent for decrypting encData */ +{ + TPM_RESULT rc = 0; + unsigned char *decryptData = NULL; /* freed @1 */ + uint32_t decryptDataLength = 0; /* actual valid data */ + unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_Key_DecryptEncData\n"); + /* allocate space for the decrypted data */ + if (rc == 0) { + rc = TPM_RSAPrivateDecryptMalloc(&decryptData, /* decrypted data */ + &decryptDataLength, /* actual size of decrypted + data */ + tpm_key->encData.buffer, /* encrypted data */ + tpm_key->encData.size, /* encrypted data size */ + parent_key); + } + /* load the TPM_STORE_ASYMKEY cache from the 'encData' member stream */ + if (rc == 0) { + stream = decryptData; + stream_size = decryptDataLength; + rc = TPM_Key_LoadStoreAsymKey(tpm_key, FALSE, &stream, &stream_size); + } + free(decryptData); /* @1 */ + return rc; +} + +/* TPM_Key_GeneratePCRDigest() generates a digest based on the current PCR state and the PCR's + specified with the key. + + The key can be either TPM_KEY or TPM_KEY12. + + This function assumes that TPM_Key_GetPCRUsage() has determined that PCR's are in use, so + a NULL PCR cache will return an error here. + + See Part 1 25.1 +*/ + +TPM_RESULT TPM_Key_CheckPCRDigest(TPM_KEY *tpm_key, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Key_GeneratePCRDigest:\n"); + if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ + /* i. Calculate H1 a TPM_COMPOSITE_HASH of the PCR selected by LK -> pcrInfo -> + releasePCRSelection */ + /* ii. Compare H1 to LK -> pcrInfo -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ + if (rc == 0) { + rc = TPM_PCRInfo_CheckDigest(tpm_key->tpm_pcr_info, + tpm_state->tpm_stclear_data.PCRS); /* array of PCR's */ + } + } + else { /* TPM_KEY12 */ + /* i. Calculate H1 a TPM_COMPOSITE_HASH of the PCR selected by LK -> pcrInfo -> + releasePCRSelection */ + /* ii. Compare H1 to LK -> pcrInfo -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ + if (rc == 0) { + rc = TPM_PCRInfoLong_CheckDigest(tpm_key->tpm_pcr_info_long, + tpm_state->tpm_stclear_data.PCRS, /* array of PCR's */ + tpm_state->tpm_stany_flags.localityModifier); + } + } + /* 4. Allow use of the key */ + if (rc != 0) { + printf("TPM_Key_CheckPCRDigest: Error, wrong digestAtRelease value\n"); + rc = TPM_WRONGPCRVAL; + } + return rc; +} + +/* TPM_Key_CheckRestrictDelegate() checks the restrictDelegate data against the TPM_KEY properties. + It determines how the TPM responds to delegated requests to use a certified migration key. + + Called from TPM_AuthSessions_GetData() if it's a DSAP session using a key entity.. + + TPM_PERMANENT_DATA -> restrictDelegate is used as follows: + + 1. If the session type is TPM_PID_DSAP and TPM_KEY -> keyFlags -> migrateAuthority is TRUE + a. If + TPM_KEY_USAGE is TPM_KEY_SIGNING and restrictDelegate -> TPM_CMK_DELEGATE_SIGNING is TRUE, or + TPM_KEY_USAGE is TPM_KEY_STORAGE and restrictDelegate -> TPM_CMK_DELEGATE_STORAGE is TRUE, or + TPM_KEY_USAGE is TPM_KEY_BIND and restrictDelegate -> TPM_CMK_DELEGATE_BIND is TRUE, or + TPM_KEY_USAGE is TPM_KEY_LEGACY and restrictDelegate -> TPM_CMK_DELEGATE_LEGACY is TRUE, or + TPM_KEY_USAGE is TPM_KEY_MIGRATE and restrictDelegate -> TPM_CMK_DELEGATE_MIGRATE is TRUE + then the key can be used. + b. Else return TPM_INVALID_KEYUSAGE. + +*/ + +TPM_RESULT TPM_Key_CheckRestrictDelegate(TPM_KEY *tpm_key, + TPM_CMK_DELEGATE restrictDelegate) +{ + TPM_RESULT rc = 0; + + printf("TPM_Key_CheckRestrictDelegate:\n"); + if (rc == 0) { + if (tpm_key == NULL) { + printf("TPM_Key_CheckRestrictDelegate: Error (fatal), key NULL\n"); + rc = TPM_FAIL; /* internal error, should never occur */ + } + } + /* if it's a certified migration key */ + if (rc == 0) { + if (tpm_key->keyFlags & TPM_MIGRATEAUTHORITY) { + if (!( + ((restrictDelegate & TPM_CMK_DELEGATE_SIGNING) && + (tpm_key->keyUsage == TPM_KEY_SIGNING)) || + + ((restrictDelegate & TPM_CMK_DELEGATE_STORAGE) && + (tpm_key->keyUsage == TPM_KEY_STORAGE)) || + + ((restrictDelegate & TPM_CMK_DELEGATE_BIND) && + (tpm_key->keyUsage == TPM_KEY_BIND)) || + + ((restrictDelegate & TPM_CMK_DELEGATE_LEGACY) && + (tpm_key->keyUsage == TPM_KEY_LEGACY)) || + + ((restrictDelegate & TPM_CMK_DELEGATE_MIGRATE) && + (tpm_key->keyUsage == TPM_KEY_MIGRATE)) + )) { + printf("TPM_Key_CheckRestrictDelegate: Error, " + "invalid keyUsage %04hx restrictDelegate %08x\n", + tpm_key->keyUsage, restrictDelegate); + rc = TPM_INVALID_KEYUSAGE; + } + } + } + return rc; +} + +/* + TPM_KEY_FLAGS +*/ + +/* TPM_KeyFlags_Load() deserializes a TPM_KEY_FLAGS value and checks for a legal value. + */ + +TPM_RESULT TPM_KeyFlags_Load(TPM_KEY_FLAGS *tpm_key_flags, /* result */ + unsigned char **stream, /* pointer to next parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + + /* load keyFlags */ + if (rc == 0) { + rc = TPM_Load32(tpm_key_flags, stream, stream_size); + } + /* check TPM_KEY_FLAGS validity, look for extra bits set */ + if (rc == 0) { + if (*tpm_key_flags & ~TPM_KEY_FLAGS_MASK) { + printf("TPM_KeyFlags_Load: Error, illegal keyFlags value %08x\n", + *tpm_key_flags); + rc = TPM_BAD_KEY_PROPERTY; + } + } + return rc; +} + +/* + TPM_KEY_PARMS +*/ + +void TPM_KeyParms_Init(TPM_KEY_PARMS *tpm_key_parms) +{ + printf(" TPM_KeyParms_Init:\n"); + tpm_key_parms->algorithmID = 0; + tpm_key_parms->encScheme = TPM_ES_NONE; + tpm_key_parms->sigScheme = TPM_SS_NONE; + TPM_SizedBuffer_Init(&(tpm_key_parms->parms)); + tpm_key_parms->tpm_rsa_key_parms = NULL; + return; +} + +#if 0 +/* TPM_KeyParms_SetRSA() is a 'Set' version specific to RSA keys */ + +TPM_RESULT TPM_KeyParms_SetRSA(TPM_KEY_PARMS *tpm_key_parms, + TPM_ALGORITHM_ID algorithmID, + TPM_ENC_SCHEME encScheme, + TPM_SIG_SCHEME sigScheme, + uint32_t keyLength, /* in bits */ + TPM_SIZED_BUFFER *exponent) +{ + TPM_RESULT rc = 0; + + printf(" TPM_KeyParms_SetRSA:\n"); + /* copy the TPM_KEY_PARMS members */ + if (rc == 0) { + tpm_key_parms->algorithmID = algorithmID; + tpm_key_parms->encScheme = encScheme; + tpm_key_parms->sigScheme = sigScheme; + /* construct the TPM_RSA_KEY_PARMS cache member object */ + rc = TPM_RSAKeyParms_New(&tpm_key_parms->tpm_rsa_key_parms); + } + if (rc == 0) { + /* copy the TPM_RSA_KEY_PARMS members */ + tpm_key_parms->tpm_rsa_key_parms->keyLength = keyLength; + tpm_key_parms->tpm_rsa_key_parms->numPrimes = 2; + rc = TPM_SizedBuffer_Copy(&(tpm_key_parms->tpm_rsa_key_parms->exponent), exponent); + } + /* serialize the TPM_RSA_KEY_PARMS object back to TPM_KEY_PARMS */ + if (rc == 0) { + rc = TPM_SizedBuffer_SetStructure(&(tpm_key_parms->parms), + tpm_key_parms->tpm_rsa_key_parms, + (TPM_STORE_FUNCTION_T)TPM_RSAKeyParms_Store); + } + return rc; +} +#endif + + +/* TPM_KeyParms_Copy() copies the source to the destination. + + If the algorithmID is TPM_ALG_RSA, the tpm_rsa_key_parms cache is allocated and copied. + + Must be freed by TPM_KeyParms_Delete() after use +*/ + +TPM_RESULT TPM_KeyParms_Copy(TPM_KEY_PARMS *tpm_key_parms_dest, + TPM_KEY_PARMS *tpm_key_parms_src) +{ + TPM_RESULT rc = 0; + + printf(" TPM_KeyParms_Copy:\n"); + if (rc == 0) { + tpm_key_parms_dest->algorithmID = tpm_key_parms_src->algorithmID; + tpm_key_parms_dest->encScheme = tpm_key_parms_src->encScheme; + tpm_key_parms_dest->sigScheme = tpm_key_parms_src->sigScheme; + rc = TPM_SizedBuffer_Copy(&(tpm_key_parms_dest->parms), + &(tpm_key_parms_src->parms)); + } + /* if there is a destination TPM_RSA_KEY_PARMS cache */ + if ((rc == 0) && (tpm_key_parms_dest->algorithmID == TPM_ALG_RSA)) { + /* construct the TPM_RSA_KEY_PARMS cache member object */ + if (rc == 0) { + rc = TPM_RSAKeyParms_New(&(tpm_key_parms_dest->tpm_rsa_key_parms)); + } + /* copy the TPM_RSA_KEY_PARMS member */ + if (rc == 0) { + rc = TPM_RSAKeyParms_Copy(tpm_key_parms_dest->tpm_rsa_key_parms, + tpm_key_parms_src->tpm_rsa_key_parms); + } + } + return rc; +} + +/* TPM_KeyParms_Load deserializes a stream to a TPM_KEY_PARMS structure. + + Must be freed by TPM_KeyParms_Delete() after use +*/ + +TPM_RESULT TPM_KeyParms_Load(TPM_KEY_PARMS *tpm_key_parms, /* result */ + unsigned char **stream, /* pointer to next parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + unsigned char *parms_stream; + uint32_t parms_stream_size; + + printf(" TPM_KeyParms_Load:\n"); + /* load algorithmID */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_key_parms->algorithmID), stream, stream_size); + } + /* load encScheme */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_key_parms->encScheme), stream, stream_size); + } + /* load sigScheme */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_key_parms->sigScheme), stream, stream_size); + } + /* load parmSize and parms */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_key_parms->parms), stream, stream_size); + } + if (rc == 0) { + switch (tpm_key_parms->algorithmID) { + /* Allow load of uninitialized structures */ + case 0: + break; + + case TPM_ALG_RSA: + /* load the TPM_RSA_KEY_PARMS cache if the algorithmID indicates an RSA key */ + if (rc == 0) { + rc = TPM_RSAKeyParms_New(&(tpm_key_parms->tpm_rsa_key_parms)); + } + /* deserialize the parms stream, but don't move the pointer */ + if (rc == 0) { + parms_stream = tpm_key_parms->parms.buffer; + parms_stream_size = tpm_key_parms->parms.size; + rc = TPM_RSAKeyParms_Load(tpm_key_parms->tpm_rsa_key_parms, + &parms_stream, &parms_stream_size); + } + break; + + /* NOTE Only handles TPM_RSA_KEY_PARMS, could handle TPM_SYMMETRIC_KEY_PARMS */ + case TPM_ALG_AES128: + case TPM_ALG_AES192: + case TPM_ALG_AES256: + default: + printf("TPM_KeyParms_Load: Cannot handle algorithmID %08x\n", + tpm_key_parms->algorithmID); + rc = TPM_BAD_KEY_PROPERTY; + break; + } + } + return rc; +} + +TPM_RESULT TPM_KeyParms_GetExponent(uint32_t *ebytes, + unsigned char **earr, + TPM_KEY_PARMS *tpm_key_parms) +{ + TPM_RESULT rc = 0; + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; + + printf(" TPM_KeyParms_GetExponent:\n"); + if (rc == 0) { + rc = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, tpm_key_parms); + } + if (rc == 0) { + rc = TPM_RSAKeyParms_GetExponent(ebytes, earr, tpm_rsa_key_parms); + } + return rc; +} + + +/* TPM_KeyParms_Store serializes a TPM_KEY_PARMS structure, appending results to 'sbuffer' +*/ + +TPM_RESULT TPM_KeyParms_Store(TPM_STORE_BUFFER *sbuffer, + TPM_KEY_PARMS *tpm_key_parms) +{ + TPM_RESULT rc = 0; + + printf(" TPM_KeyParms_Store:\n"); + /* store algorithmID */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_key_parms->algorithmID); + } + /* store encScheme */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_key_parms->encScheme); + } + /* store sigScheme */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_key_parms->sigScheme); + } + /* copy cache to parms */ + if (rc == 0) { + switch (tpm_key_parms->algorithmID) { + /* Allow store of uninitialized structures */ + case 0: + break; + case TPM_ALG_RSA: + rc = TPM_SizedBuffer_SetStructure(&(tpm_key_parms->parms), + tpm_key_parms->tpm_rsa_key_parms, + (TPM_STORE_FUNCTION_T)TPM_RSAKeyParms_Store); + break; + /* NOTE Only handles TPM_RSA_KEY_PARMS, could handle TPM_SYMMETRIC_KEY_PARMS */ + case TPM_ALG_AES128: + case TPM_ALG_AES192: + case TPM_ALG_AES256: + default: + printf("TPM_KeyParms_Store: Cannot handle algorithmID %08x\n", + tpm_key_parms->algorithmID); + rc = TPM_BAD_KEY_PROPERTY; + break; + } + } + /* store parms */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_key_parms->parms)); + } + return rc; +} + +/* TPM_KeyParms_Delete frees any member allocated memory */ + +void TPM_KeyParms_Delete(TPM_KEY_PARMS *tpm_key_parms) +{ + printf(" TPM_KeyParms_Delete:\n"); + if (tpm_key_parms != NULL) { + TPM_SizedBuffer_Delete(&(tpm_key_parms->parms)); + TPM_RSAKeyParms_Delete(tpm_key_parms->tpm_rsa_key_parms); + free(tpm_key_parms->tpm_rsa_key_parms); + TPM_KeyParms_Init(tpm_key_parms); + } + return; +} + +/* TPM_KeyParms_GetRSAKeyParms() gets the TPM_RSA_KEY_PARMS from a TPM_KEY_PARMS cache. + + Returns an error if the cache is NULL, since the cache should always be set when the + TPM_KEY_PARMS indicates an RSA key. +*/ + +TPM_RESULT TPM_KeyParms_GetRSAKeyParms(TPM_RSA_KEY_PARMS **tpm_rsa_key_parms, + TPM_KEY_PARMS *tpm_key_parms) +{ + TPM_RESULT rc = 0; + + printf(" TPM_KeyParms_GetRSAKeyParms:\n"); + /* algorithmID must be RSA */ + if (rc == 0) { + if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { + printf("TPM_KeyParms_GetRSAKeyParms: Error, incorrect algorithmID %08x\n", + tpm_key_parms->algorithmID); + rc = TPM_BAD_KEY_PROPERTY; + } + } + /* if the TPM_RSA_KEY_PARMS structure has not been cached, deserialize it */ + if (rc == 0) { + if (tpm_key_parms->tpm_rsa_key_parms == NULL) { + printf("TPM_KeyParms_GetRSAKeyParms: Error (fatal), cache is NULL\n"); + /* This should never occur. The cache is loaded when the TPM_KEY_PARMS is loaded. */ + rc = TPM_FAIL; + } + } + /* return the cached structure */ + if (rc == 0) { + *tpm_rsa_key_parms = tpm_key_parms->tpm_rsa_key_parms; + } + return rc; +} + +/* TPM_KeyParms_CheckProperties() checks that the TPM can generate a key of the type requested in + 'tpm_key_parms' + + if' keyLength' is non-zero, checks that the tpm_key specifies the correct key length. If + keyLength is 0, any tpm_key key length is accepted. +*/ + +TPM_RESULT TPM_KeyParms_CheckProperties(TPM_KEY_PARMS *tpm_key_parms, + TPM_KEY_USAGE tpm_key_usage, + uint32_t keyLength, /* in bits */ + TPM_BOOL FIPS) +{ + TPM_RESULT rc = 0; + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms = NULL;/* used if algorithmID indicates RSA */ + + printf(" TPM_KeyParms_CheckProperties: keyUsage %04hx\n", tpm_key_usage); + printf(" TPM_KeyParms_CheckProperties: sigScheme %04hx\n", tpm_key_parms->sigScheme); + printf(" TPM_KeyParms_CheckProperties: encScheme %04hx\n", tpm_key_parms->encScheme); + if (rc == 0) { + /* the code currently only supports RSA */ + if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { + printf("TPM_KeyParms_CheckProperties: Error, algorithmID not TPM_ALG_RSA\n"); + rc = TPM_BAD_KEY_PROPERTY; + } + } + /* get the TPM_RSA_KEY_PARMS structure from the TPM_KEY_PARMS structure */ + /* NOTE: for now only support RSA keys */ + if (rc == 0) { + rc = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, tpm_key_parms); + } + /* check key length if specified as input parameter */ + if ((rc == 0) && (keyLength != 0)) { + if (tpm_rsa_key_parms->keyLength != keyLength) { /* in bits */ + printf("TPM_KeyParms_CheckProperties: Error, Bad keyLength should be %u, was %u\n", + keyLength, tpm_rsa_key_parms->keyLength); + rc = TPM_BAD_KEY_PROPERTY; + } + } + if (rc == 0) { + if (tpm_rsa_key_parms->keyLength > TPM_RSA_KEY_LENGTH_MAX) { /* in bits */ + printf("TPM_KeyParms_CheckProperties: Error, Bad keyLength max %u, was %u\n", + TPM_RSA_KEY_LENGTH_MAX, tpm_rsa_key_parms->keyLength); + rc = TPM_BAD_KEY_PROPERTY; + } + + } + /* kgold - Support only 2 primes */ + if (rc == 0) { + if (tpm_rsa_key_parms->numPrimes != 2) { + printf("TPM_KeyParms_CheckProperties: Error, numPrimes %u should be 2\n", + tpm_rsa_key_parms->numPrimes); + rc = TPM_BAD_KEY_PROPERTY; + } + } + /* if FIPS */ + if ((rc == 0) && FIPS) { + /* a. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS */ + if (tpm_rsa_key_parms->keyLength < 1024) { + printf("TPM_KeyParms_CheckProperties: Error, Invalid FIPS key length %u\n", + tpm_rsa_key_parms->keyLength); + rc = TPM_NOTFIPS; + } + /* c. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return TPM_NOTFIPS */ + else if (tpm_key_usage == TPM_KEY_LEGACY) { + printf("TPM_KeyParms_CheckProperties: Error, FIPS authDataUsage TPM_AUTH_NEVER\n"); + rc = TPM_NOTFIPS; + } + } + /* From Part 2 5.7.1 Mandatory Key Usage Schemes and TPM_CreateWrapKey, TPM_LoadKey */ + if (rc == 0) { + switch (tpm_key_usage) { + case TPM_KEY_UNINITIALIZED: + printf("TPM_KeyParms_CheckProperties: Error, keyUsage TPM_KEY_UNINITIALIZED\n"); + rc = TPM_BAD_KEY_PROPERTY; + break; + case TPM_KEY_SIGNING: + if (tpm_key_parms->encScheme != TPM_ES_NONE) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Signing encScheme %04hx is not TPM_ES_NONE\n", + tpm_key_parms->encScheme); + rc = TPM_BAD_KEY_PROPERTY; + } +#ifdef TPM_V12 + else if ((tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_DER) && + (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { +#else /* TPM 1.1 */ + else if (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { + +#endif + printf("TPM_KeyParms_CheckProperties: Error, " + "Signing sigScheme %04hx is not DER, SHA1, INFO\n", + tpm_key_parms->sigScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + break; + case TPM_KEY_STORAGE: + if (tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Storage encScheme %04hx is not TPM_ES_RSAESOAEP_SHA1_MGF1\n", + tpm_key_parms->encScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_key_parms->sigScheme != TPM_SS_NONE) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Storage sigScheme %04hx is not TPM_SS_NONE\n", + tpm_key_parms->sigScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { /*constant condition*/ + printf("TPM_KeyParms_CheckProperties: Error, " + "Storage algorithmID %08x is not TPM_ALG_RSA\n", + tpm_key_parms->algorithmID); + rc = TPM_BAD_KEY_PROPERTY; + } + /* interoperable TPM only supports 2048 */ + else if (tpm_rsa_key_parms->keyLength < 2048) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Storage keyLength %d is less than 2048\n", + tpm_rsa_key_parms->keyLength); + rc = TPM_BAD_KEY_PROPERTY; + } + else { + rc = TPM_KeyParams_CheckDefaultExponent(&(tpm_rsa_key_parms->exponent)); + } + break; + case TPM_KEY_IDENTITY: + if (tpm_key_parms->encScheme != TPM_ES_NONE) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Identity encScheme %04hx is not TPM_ES_NONE\n", + tpm_key_parms->encScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Identity sigScheme %04hx is not %04x\n", + tpm_key_parms->sigScheme, TPM_SS_RSASSAPKCS1v15_SHA1); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { /*constant condition*/ + printf("TPM_KeyParms_CheckProperties: Error, " + "Identity algorithmID %08x is not TPM_ALG_RSA\n", + tpm_key_parms->algorithmID); + rc = TPM_BAD_KEY_PROPERTY; + } + /* interoperable TPM only supports 2048 */ + else if (tpm_rsa_key_parms->keyLength < 2048) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Identity keyLength %d is less than 2048\n", + tpm_rsa_key_parms->keyLength); + rc = TPM_BAD_KEY_PROPERTY; + } + else { + rc = TPM_KeyParams_CheckDefaultExponent(&(tpm_rsa_key_parms->exponent)); + } + break; + case TPM_KEY_AUTHCHANGE: + if (tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Authchange encScheme %04hx is not TPM_ES_RSAESOAEP_SHA1_MGF1\n", + tpm_key_parms->encScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_key_parms->sigScheme != TPM_SS_NONE) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Authchange sigScheme %04hx is not TPM_SS_NONE\n", + tpm_key_parms->sigScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_rsa_key_parms->keyLength < 512) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Authchange keyLength %d is less than 512\n", + tpm_rsa_key_parms->keyLength); + rc = TPM_BAD_KEY_PROPERTY; + } + break; + case TPM_KEY_BIND: + if ((tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) && + (tpm_key_parms->encScheme != TPM_ES_RSAESPKCSv15)) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Bind encScheme %04hx is not %04x or %04x\n", + tpm_key_parms->encScheme, + TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_ES_RSAESPKCSv15); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_key_parms->sigScheme != TPM_SS_NONE) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Bind sigScheme %04hx is not TPM_SS_NONE\n", + tpm_key_parms->sigScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + break; + case TPM_KEY_LEGACY: + if ((tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) && + (tpm_key_parms->encScheme != TPM_ES_RSAESPKCSv15)) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Legacy encScheme %04hx is not %04x or %04x\n", + tpm_key_parms->encScheme, + TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_ES_RSAESPKCSv15); + rc = TPM_BAD_KEY_PROPERTY; + } + else if ((tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_DER)) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Legacy sigScheme %04hx is not %04x or %04x\n", + tpm_key_parms->sigScheme, + TPM_SS_RSASSAPKCS1v15_SHA1, TPM_SS_RSASSAPKCS1v15_DER); + rc = TPM_BAD_KEY_PROPERTY; + } + break; + case TPM_KEY_MIGRATE: + if (tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Migrate encScheme %04hx is not TPM_ES_RSAESOAEP_SHA1_MGF1\n", + tpm_key_parms->encScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_key_parms->sigScheme != TPM_SS_NONE) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Migrate sigScheme %04hx is not TPM_SS_NONE\n", + tpm_key_parms->sigScheme); + rc = TPM_BAD_KEY_PROPERTY; + } + else if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { /*constant condition*/ + printf("TPM_KeyParms_CheckProperties: Error, " + "Migrate algorithmID %08x is not TPM_ALG_RSA\n", + tpm_key_parms->algorithmID); + rc = TPM_BAD_KEY_PROPERTY; + } + /* interoperable TPM only supports 2048 */ + else if (tpm_rsa_key_parms->keyLength < 2048) { + printf("TPM_KeyParms_CheckProperties: Error, " + "Migrate keyLength %d is less than 2048\n", + tpm_rsa_key_parms->keyLength); + rc = TPM_BAD_KEY_PROPERTY; + } + else { + rc = TPM_KeyParams_CheckDefaultExponent(&(tpm_rsa_key_parms->exponent)); + } + break; + default: + printf("TPM_KeyParms_CheckProperties: Error, Unknown keyUsage %04hx\n", tpm_key_usage); + rc = TPM_BAD_KEY_PROPERTY; + break; + } + } + return rc; +} + +TPM_RESULT TPM_KeyParams_CheckDefaultExponent(TPM_SIZED_BUFFER *exponent) +{ + TPM_RESULT rc = 0; + uint32_t i; + + if ((rc == 0) && (exponent->size != 0)) { /* 0 is the default */ + printf(" TPM_KeyParams_CheckDefaultExponent: exponent size %u\n", exponent->size); + if (rc == 0) { + if (exponent->size < 3) { + printf("TPM_KeyParams_CheckDefaultExponent: Error, exponent size is %u\n", + exponent->size); + rc = TPM_BAD_KEY_PROPERTY; + } + } + if (rc == 0) { + for (i = 3 ; i < exponent->size ; i++) { + if (exponent->buffer[i] != 0) { + printf("TPM_KeyParams_CheckDefaultExponent: Error, exponent[%u] is %02x\n", + i, exponent->buffer[i]); + rc = TPM_BAD_KEY_PROPERTY; + } + } + } + if (rc == 0) { + if ((exponent->buffer[0] != tpm_default_rsa_exponent[0]) || + (exponent->buffer[1] != tpm_default_rsa_exponent[1]) || + (exponent->buffer[2] != tpm_default_rsa_exponent[2])) { + printf("TPM_KeyParams_CheckDefaultExponent: Error, exponent is %02x %02x %02x\n", + exponent->buffer[2], exponent->buffer[1], exponent->buffer[0]); + rc = TPM_BAD_KEY_PROPERTY; + } + } + } + return rc; +} + +/* + TPM_STORE_ASYMKEY +*/ + +void TPM_StoreAsymkey_Init(TPM_STORE_ASYMKEY *tpm_store_asymkey) +{ + printf(" TPM_StoreAsymkey_Init:\n"); + tpm_store_asymkey->payload = TPM_PT_ASYM; + TPM_Secret_Init(tpm_store_asymkey->usageAuth); + TPM_Secret_Init(tpm_store_asymkey->migrationAuth); + TPM_Digest_Init(tpm_store_asymkey->pubDataDigest); + TPM_StorePrivkey_Init(&(tpm_store_asymkey->privKey)); + return; +} + +/* TPM_StoreAsymkey_Load() deserializes the TPM_STORE_ASYMKEY structure. + + The serialized structure contains the private factor p. Normally, 'tpm_key_parms' and + tpm_store_pubkey are not NULL and the private key d is derived from p and the public key n and + exponent e. + + In some cases, a TPM_STORE_ASYMKEY is being manipulated without the rest of the TPM_KEY + structure. When 'tpm_key' is NULL, p is left intact, and the resulting structure cannot be used + as a private key. +*/ + +TPM_RESULT TPM_StoreAsymkey_Load(TPM_STORE_ASYMKEY *tpm_store_asymkey, + TPM_BOOL isEK, + unsigned char **stream, + uint32_t *stream_size, + TPM_KEY_PARMS *tpm_key_parms, + TPM_SIZED_BUFFER *pubKey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StoreAsymkey_Load:\n"); + /* load payload */ + if ((rc == 0) && !isEK) { + rc = TPM_Load8(&(tpm_store_asymkey->payload), stream, stream_size); + } + /* check payload value to ease debugging */ + if ((rc == 0) && !isEK) { + if ( + /* normal key */ + (tpm_store_asymkey->payload != TPM_PT_ASYM) && + /* TPM_CMK_CreateKey payload */ + (tpm_store_asymkey->payload != TPM_PT_MIGRATE_RESTRICTED) && + /* TPM_CMK_ConvertMigration payload */ + (tpm_store_asymkey->payload != TPM_PT_MIGRATE_EXTERNAL) + ) { + printf("TPM_StoreAsymkey_Load: Error, invalid payload %02x\n", + tpm_store_asymkey->payload); + rc = TPM_INVALID_STRUCTURE; + } + } + /* load usageAuth */ + if ((rc == 0) && !isEK) { + rc = TPM_Secret_Load(tpm_store_asymkey->usageAuth, stream, stream_size); + } + /* load migrationAuth */ + if ((rc == 0) && !isEK) { + rc = TPM_Secret_Load(tpm_store_asymkey->migrationAuth, stream, stream_size); + } + /* load pubDataDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_store_asymkey->pubDataDigest, stream, stream_size); + } + /* load privKey - actually prime factor p */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load((&(tpm_store_asymkey->privKey.p_key)), + stream, stream_size); + } + /* convert prime factor p to the private key */ + if ((rc == 0) && (tpm_key_parms != NULL) && (pubKey != NULL)) { + rc = TPM_StorePrivkey_Convert(tpm_store_asymkey, + tpm_key_parms, pubKey); + } + return rc; +} + +#if 0 +static TPM_RESULT TPM_StoreAsymkey_LoadTest(TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + int irc; + + /* actual */ + unsigned char *narr; + unsigned char *earr; + unsigned char *parr; + unsigned char *qarr; + unsigned char *darr; + + uint32_t nbytes; + uint32_t ebytes; + uint32_t pbytes; + uint32_t qbytes; + uint32_t dbytes; + + /* computed */ + unsigned char *q1arr = NULL; + unsigned char *d1arr = NULL; + + uint32_t q1bytes; + uint32_t d1bytes; + + printf(" TPM_StoreAsymkey_LoadTest:\n"); + /* actual data */ + if (rc == 0) { + narr = tpm_key->pubKey.key; + darr = tpm_key->tpm_store_asymkey->privKey.d_key; + parr = tpm_key->tpm_store_asymkey->privKey.p_key; + qarr = tpm_key->tpm_store_asymkey->privKey.q_key; + + nbytes = tpm_key->pubKey.keyLength; + dbytes = tpm_key->tpm_store_asymkey->privKey.d_keyLength; + pbytes = tpm_key->tpm_store_asymkey->privKey.p_keyLength; + qbytes = tpm_key->tpm_store_asymkey->privKey.q_keyLength; + + rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); + } + if (rc == 0) { + rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); + } + if (rc == 0) { + rc = TPM_Key_GetPrimeFactorP(&pbytes, &parr, tpm_key); + } + /* computed data */ + if (rc == 0) { + rc = TPM_RSAGetPrivateKey(&q1bytes, &q1arr, /* freed @1 */ + &d1bytes, &d1arr, /* freed @2 */ + nbytes, narr, + ebytes, earr, + pbytes, parr); + } + /* compare q */ + if (rc == 0) { + if (qbytes != q1bytes) { + printf("TPM_StoreAsymkey_LoadTest: Error (fatal), qbytes %u q1bytes %u\n", + qbytes, q1bytes); + rc = TPM_FAIL; + } + } + if (rc == 0) { + irc = memcmp(qarr, q1arr, qbytes); + if (irc != 0) { + printf("TPM_StoreAsymkey_LoadTest: Error (fatal), qarr mismatch\n"); + rc = TPM_FAIL; + } + } + /* compare d */ + if (rc == 0) { + if (dbytes != d1bytes) { + printf("TPM_StoreAsymkey_LoadTest: Error (fatal), dbytes %u d1bytes %u\n", + dbytes, d1bytes); + rc = TPM_FAIL; + } + } + if (rc == 0) { + irc = memcmp(darr, d1arr, dbytes); + if (irc != 0) { + printf("TPM_StoreAsymkey_LoadTest: Error (fatal), darr mismatch\n"); + rc = TPM_FAIL; + } + } + free(q1arr); /* @1 */ + free(d1arr); /* @2 */ + return rc; +} +#endif + +TPM_RESULT TPM_StoreAsymkey_Store(TPM_STORE_BUFFER *sbuffer, + TPM_BOOL isEK, + const TPM_STORE_ASYMKEY *tpm_store_asymkey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StoreAsymkey_Store:\n"); + /* store payload */ + if ((rc == 0) && !isEK) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_store_asymkey->payload), sizeof(TPM_PAYLOAD_TYPE)); + } + /* store usageAuth */ + if ((rc == 0) && !isEK) { + rc = TPM_Secret_Store(sbuffer, tpm_store_asymkey->usageAuth); + } + /* store migrationAuth */ + if ((rc == 0) && !isEK) { + rc = TPM_Secret_Store(sbuffer, tpm_store_asymkey->migrationAuth); + } + /* store pubDataDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_store_asymkey->pubDataDigest); + } + /* store privKey */ + if (rc == 0) { + rc = TPM_StorePrivkey_Store(sbuffer, &(tpm_store_asymkey->privKey)); + } + return rc; +} + +void TPM_StoreAsymkey_Delete(TPM_STORE_ASYMKEY *tpm_store_asymkey) +{ + printf(" TPM_StoreAsymkey_Delete:\n"); + if (tpm_store_asymkey != NULL) { + TPM_Secret_Delete(tpm_store_asymkey->usageAuth); + TPM_Secret_Delete(tpm_store_asymkey->migrationAuth); + TPM_StorePrivkey_Delete(&(tpm_store_asymkey->privKey)); + TPM_StoreAsymkey_Init(tpm_store_asymkey); + } + return; +} + +TPM_RESULT TPM_StoreAsymkey_GenerateEncData(TPM_SIZED_BUFFER *encData, + TPM_STORE_ASYMKEY *tpm_store_asymkey, + TPM_KEY *parent_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* TPM_STORE_ASYMKEY serialization */ + + printf(" TPM_StoreAsymkey_GenerateEncData;\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize the TPM_STORE_ASYMKEY member */ + if (rc == 0) { + rc = TPM_StoreAsymkey_Store(&sbuffer, FALSE, tpm_store_asymkey); + } + if (rc == 0) { + rc = TPM_RSAPublicEncryptSbuffer_Key(encData, &sbuffer, parent_key); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_StoreAsymkey_GetPrimeFactorP() gets the prime factor p from the TPM_STORE_ASYMKEY +*/ + +TPM_RESULT TPM_StoreAsymkey_GetPrimeFactorP(uint32_t *pbytes, + unsigned char **parr, + TPM_STORE_ASYMKEY *tpm_store_asymkey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StoreAsymkey_GetPrimeFactorP:\n"); + if (rc == 0) { + *pbytes = tpm_store_asymkey->privKey.p_key.size; + *parr = tpm_store_asymkey->privKey.p_key.buffer; + TPM_PrintFour(" TPM_StoreAsymkey_GetPrimeFactorP:", *parr); + } + return rc; +} + +/* TPM_StoreAsymkey_GetO1Size() calculates the destination o1 size for a TPM_STORE_ASYMKEY + + Used for creating a migration blob, TPM_STORE_ASYMKEY -> TPM_MIGRATE_ASYMKEY. + */ + +void TPM_StoreAsymkey_GetO1Size(uint32_t *o1_size, + TPM_STORE_ASYMKEY *tpm_store_asymkey) +{ + *o1_size = tpm_store_asymkey->privKey.p_key.size + /* private key */ + sizeof(uint32_t) - /* private key length */ + TPM_DIGEST_SIZE + /* - k1 -> k2 TPM_MIGRATE_ASYMKEY -> partPrivKey */ + sizeof(uint32_t) + /* TPM_MIGRATE_ASYMKEY -> partPrivKeyLen */ + sizeof(TPM_PAYLOAD_TYPE) + /* TPM_MIGRATE_ASYMKEY -> payload */ + TPM_SECRET_SIZE + /* TPM_MIGRATE_ASYMKEY -> usageAuth */ + TPM_DIGEST_SIZE + /* TPM_MIGRATE_ASYMKEY -> pubDataDigest */ + TPM_DIGEST_SIZE + /* OAEP pHash */ + TPM_DIGEST_SIZE + /* OAEP seed */ + 1; /* OAEP 0x01 byte */ + printf(" TPM_StoreAsymkey_GetO1Size: key size %u o1 size %u\n", + tpm_store_asymkey->privKey.p_key.size, *o1_size); +} + +/* TPM_StoreAsymkey_CheckO1Size() verifies the destination o1_size against the source k1k2 array + length + + This is a currently just a sanity check on the TPM_StoreAsymkey_GetO1Size() function. +*/ + +TPM_RESULT TPM_StoreAsymkey_CheckO1Size(uint32_t o1_size, + uint32_t k1k2_length) +{ + TPM_RESULT rc = 0; + + /* sanity check the TPM_MIGRATE_ASYMKEY size against the requested o1 size */ + /* K1 K2 are the length and value of the private key, 4 + 128 bytes for a 2048-bit key */ + if (o1_size < + (k1k2_length - TPM_DIGEST_SIZE + /* k1 k2, the first 20 bytes are used as the OAEP seed */ + sizeof(TPM_PAYLOAD_TYPE) + /* TPM_MIGRATE_ASYMKEY -> payload */ + TPM_SECRET_SIZE + /* TPM_MIGRATE_ASYMKEY -> usageAuth */ + TPM_DIGEST_SIZE + /* TPM_MIGRATE_ASYMKEY -> pubDataDigest */ + sizeof(uint32_t) + /* TPM_MIGRATE_ASYMKEY -> partPrivKeyLen */ + TPM_DIGEST_SIZE + /* OAEP pHash */ + TPM_DIGEST_SIZE + /* OAEP seed */ + 1)) { /* OAEP 0x01 byte */ + printf(" TPM_StoreAsymkey_CheckO1Size: Error (fatal) k1k2_length %d too large for o1 %u\n", + k1k2_length, o1_size); + rc = TPM_FAIL; + } + return rc; +} + +/* TPM_StoreAsymkey_StoreO1() creates an OAEP encoded TPM_MIGRATE_ASYMKEY from a + TPM_STORE_ASYMKEY. + + It does the common steps of constructing the TPM_MIGRATE_ASYMKEY, serializing it, and OAEP + padding. +*/ + +TPM_RESULT TPM_StoreAsymkey_StoreO1(BYTE *o1, + uint32_t o1_size, + TPM_STORE_ASYMKEY *tpm_store_asymkey, + TPM_DIGEST pHash, + TPM_PAYLOAD_TYPE payload_type, + TPM_SECRET usageAuth) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER k1k2_sbuffer; /* serialization of TPM_STORE_ASYMKEY -> privKey -> key */ + const unsigned char *k1k2; /* serialization results */ + uint32_t k1k2_length; + TPM_MIGRATE_ASYMKEY tpm_migrate_asymkey; + TPM_STORE_BUFFER tpm_migrate_asymkey_sbuffer; /* serialized tpm_migrate_asymkey */ + const unsigned char *tpm_migrate_asymkey_buffer; + uint32_t tpm_migrate_asymkey_length; + + printf(" TPM_StoreAsymkey_StoreO1:\n"); + TPM_Sbuffer_Init(&k1k2_sbuffer); /* freed @1 */ + TPM_MigrateAsymkey_Init(&tpm_migrate_asymkey); /* freed @2 */ + TPM_Sbuffer_Init(&tpm_migrate_asymkey_sbuffer); /* freed @3 */ + + /* NOTE Comments from TPM_CreateMigrationBlob rev 81 */ + /* a. Build two byte arrays, K1 and K2: */ + /* i. K1 = TPM_STORE_ASYMKEY.privKey[0..19] (TPM_STORE_ASYMKEY.privKey.keyLength + 16 bytes of + TPM_STORE_ASYMKEY.privKey.key), sizeof(K1) = 20 */ + /* ii. K2 = TPM_STORE_ASYMKEY.privKey[20..131] (position 16-127 of + TPM_STORE_ASYMKEY. privKey.key), sizeof(K2) = 112 */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(&k1k2_sbuffer, &(tpm_store_asymkey->privKey.p_key)); + } + if (rc == 0) { + TPM_Sbuffer_Get(&k1k2_sbuffer, &k1k2, &k1k2_length); + /* sanity check the TPM_STORE_ASYMKEY -> privKey -> key size against the requested o1 + size */ + rc = TPM_StoreAsymkey_CheckO1Size(o1_size, k1k2_length); + } + /* b. Build M1 a TPM_MIGRATE_ASYMKEY structure */ + /* i. TPM_MIGRATE_ASYMKEY.payload = TPM_PT_MIGRATE */ + /* ii. TPM_MIGRATE_ASYMKEY.usageAuth = TPM_STORE_ASYMKEY.usageAuth */ + /* iii. TPM_MIGRATE_ASYMKEY.pubDataDigest = TPM_STORE_ASYMKEY. pubDataDigest */ + /* iv. TPM_MIGRATE_ASYMKEY.partPrivKeyLen = 112 - 127. */ + /* v. TPM_MIGRATE_ASYMKEY.partPrivKey = K2 */ + if (rc == 0) { + tpm_migrate_asymkey.payload = payload_type; + TPM_Secret_Copy(tpm_migrate_asymkey.usageAuth, usageAuth); + TPM_Digest_Copy(tpm_migrate_asymkey.pubDataDigest, tpm_store_asymkey->pubDataDigest); + TPM_PrintFour(" TPM_StoreAsymkey_StoreO1: k1 -", k1k2); + TPM_PrintFour(" TPM_StoreAsymkey_StoreO1: k2 -", k1k2 + TPM_DIGEST_SIZE); + rc = TPM_SizedBuffer_Set(&(tpm_migrate_asymkey.partPrivKey), + k1k2_length - TPM_DIGEST_SIZE, /* k2 length 112 for 2048 bit key */ + k1k2 + TPM_DIGEST_SIZE); /* k2 */ + } + /* c. Create o1 (which SHALL be 198 bytes for a 2048 bit RSA key) by performing the OAEP + encoding of m using OAEP parameters of */ + /* i. m = M1 the TPM_MIGRATE_ASYMKEY structure */ + /* ii. pHash = d1->migrationAuth */ + /* iii. seed = s1 = K1 */ + if (rc == 0) { + /* serialize TPM_MIGRATE_ASYMKEY m */ + rc = TPM_MigrateAsymkey_Store(&tpm_migrate_asymkey_sbuffer, &tpm_migrate_asymkey); + } + if (rc == 0) { + /* get the serialization result */ + TPM_Sbuffer_Get(&tpm_migrate_asymkey_sbuffer, + &tpm_migrate_asymkey_buffer, &tpm_migrate_asymkey_length); + TPM_PrintFour(" TPM_StoreAsymkey_StoreO1: pHash -", pHash); + rc = TPM_RSA_padding_add_PKCS1_OAEP(o1, /* output */ + o1_size, + tpm_migrate_asymkey_buffer, /* message */ + tpm_migrate_asymkey_length, + pHash, + k1k2); /* k1, seed */ + TPM_PrintFour(" TPM_StoreAsymkey_StoreO1: o1 -", o1); + } + TPM_Sbuffer_Delete(&k1k2_sbuffer); /* @1 */ + TPM_MigrateAsymkey_Delete(&tpm_migrate_asymkey); /* @2 */ + TPM_Sbuffer_Delete(&tpm_migrate_asymkey_sbuffer); /* @3 */ + return rc; +} + +/* TPM_StoreAsymkey_LoadO1() extracts TPM_STORE_ASYMKEY from the OAEP encoded TPM_MIGRATE_ASYMKEY. + + It does the common steps OAEP depadding, deserializing the TPM_MIGRATE_ASYMKEY, and + reconstructing the TPM_STORE_ASYMKEY. + + It sets these, which may or may not be correct at a higher level + + TPM_STORE_ASYMKEY -> payload = TPM_MIGRATE_ASYMKEY -> payload + TPM_STORE_ASYMKEY -> usageAuth = TPM_MIGRATE_ASYMKEY -> usageAuth + TPM_STORE_ASYMKEY -> migrationAuth = pHash + TPM_STORE_ASYMKEY -> pubDataDigest = TPM_MIGRATE_ASYMKEY -> pubDataDigest + TPM_STORE_ASYMKEY -> privKey = seed + TPM_MIGRATE_ASYMKEY -> partPrivKey +*/ + +TPM_RESULT TPM_StoreAsymkey_LoadO1(TPM_STORE_ASYMKEY *tpm_store_asymkey, /* output */ + BYTE *o1, /* input */ + uint32_t o1_size) /* input */ +{ + TPM_RESULT rc = 0; + BYTE *tpm_migrate_asymkey_buffer; + uint32_t tpm_migrate_asymkey_length; + TPM_DIGEST seed; + TPM_DIGEST pHash; + unsigned char *stream; /* for deserializing structures */ + uint32_t stream_size; + TPM_MIGRATE_ASYMKEY tpm_migrate_asymkey; + TPM_STORE_BUFFER k1k2_sbuffer; + const unsigned char *k1k2_buffer; + uint32_t k1k2_length; + + printf(" TPM_StoreAsymkey_LoadO1:\n"); + TPM_MigrateAsymkey_Init(&tpm_migrate_asymkey); /* freed @1 */ + TPM_Sbuffer_Init(&k1k2_sbuffer); /* freed @2 */ + tpm_migrate_asymkey_buffer = NULL; /* freed @3 */ + /* allocate memory for TPM_MIGRATE_ASYMKEY after removing OAEP pad from o1 */ + if (rc == 0) { + rc = TPM_Malloc(&tpm_migrate_asymkey_buffer, o1_size); + } + if (rc == 0) { + TPM_PrintFour(" TPM_StoreAsymkey_LoadO1: o1 -", o1); + /* 5. Create m1, seed and pHash by OAEP decoding o1 */ + printf(" TPM_StoreAsymkey_LoadO1: Depadding\n"); + rc = TPM_RSA_padding_check_PKCS1_OAEP(tpm_migrate_asymkey_buffer, /* out: to */ + &tpm_migrate_asymkey_length, /* out: to length */ + o1_size, /* to size */ + o1, o1_size, /* from, from length */ + pHash, + seed); + TPM_PrintFour(" TPM_StoreAsymkey_LoadO1: tpm_migrate_asymkey_buffer -", + tpm_migrate_asymkey_buffer); + printf(" TPM_StoreAsymkey_LoadO1: tpm_migrate_asymkey_length %u\n", + tpm_migrate_asymkey_length); + TPM_PrintFour(" TPM_StoreAsymkey_LoadO1: - pHash", pHash); + TPM_PrintFour(" TPM_StoreAsymkey_LoadO1: - seed", seed); + } + /* deserialize the buffer back to a TPM_MIGRATE_ASYMKEY */ + if (rc == 0) { + stream = tpm_migrate_asymkey_buffer; + stream_size = tpm_migrate_asymkey_length; + rc = TPM_MigrateAsymkey_Load(&tpm_migrate_asymkey, &stream, &stream_size); + printf(" TPM_StoreAsymkey_LoadO1: partPrivKey length %u\n", + tpm_migrate_asymkey.partPrivKey.size); + TPM_PrintFourLimit(" TPM_StoreAsymkey_LoadO1: partPrivKey -", + tpm_migrate_asymkey.partPrivKey.buffer, + tpm_migrate_asymkey.partPrivKey.size); + } + /* create k1k2 by combining seed (k1) and TPM_MIGRATE_ASYMKEY.partPrivKey (k2) field */ + if (rc == 0) { + rc = TPM_Digest_Store(&k1k2_sbuffer, seed); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(&k1k2_sbuffer, + tpm_migrate_asymkey.partPrivKey.buffer, + tpm_migrate_asymkey.partPrivKey.size); + } + /* assemble the TPM_STORE_ASYMKEY structure */ + if (rc == 0) { + tpm_store_asymkey->payload = tpm_migrate_asymkey.payload; + TPM_Digest_Copy(tpm_store_asymkey->usageAuth, tpm_migrate_asymkey.usageAuth); + TPM_Digest_Copy(tpm_store_asymkey->migrationAuth, pHash); + TPM_Digest_Copy(tpm_store_asymkey->pubDataDigest, tpm_migrate_asymkey.pubDataDigest); + TPM_Sbuffer_Get(&k1k2_sbuffer, &k1k2_buffer, &k1k2_length); + printf(" TPM_StoreAsymkey_LoadO1: k1k2 length %u\n", k1k2_length); + TPM_PrintFourLimit(" TPM_StoreAsymkey_LoadO1: k1k2", k1k2_buffer, k1k2_length); + rc = TPM_SizedBuffer_Load(&(tpm_store_asymkey->privKey.p_key), + (unsigned char **)&k1k2_buffer, &k1k2_length); + } + TPM_MigrateAsymkey_Delete(&tpm_migrate_asymkey); /* @1 */ + TPM_Sbuffer_Delete(&k1k2_sbuffer); /* @2 */ + free(tpm_migrate_asymkey_buffer); /* @3 */ + return rc; +} + + +/* + TPM_MIGRATE_ASYMKEY +*/ + +/* TPM_MigrateAsymkey_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_MigrateAsymkey_Init(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey) +{ + printf(" TPM_MigrateAsymkey_Init:\n"); + tpm_migrate_asymkey->payload = TPM_PT_MIGRATE; + TPM_Secret_Init(tpm_migrate_asymkey->usageAuth); + TPM_Digest_Init(tpm_migrate_asymkey->pubDataDigest); + TPM_SizedBuffer_Init(&(tpm_migrate_asymkey->partPrivKey)); + return; +} + +/* TPM_MigrateAsymkey_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_MigrateAsymkey_Init() + After use, call TPM_MigrateAsymkey_Delete() to free memory +*/ + +TPM_RESULT TPM_MigrateAsymkey_Load(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_MigrateAsymkey_Load:\n"); + /* load payload */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_migrate_asymkey->payload), stream, stream_size); + } + /* check payload value to ease debugging */ + if (rc == 0) { + if ((tpm_migrate_asymkey->payload != TPM_PT_MIGRATE) && + (tpm_migrate_asymkey->payload != TPM_PT_MAINT) && + (tpm_migrate_asymkey->payload != TPM_PT_CMK_MIGRATE)) { + printf("TPM_MigrateAsymkey_Load: Error illegal payload %02x\n", + tpm_migrate_asymkey->payload); + rc = TPM_INVALID_STRUCTURE; + } + } + /* load usageAuth */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_migrate_asymkey->usageAuth, stream, stream_size); + } + /* load pubDataDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_migrate_asymkey->pubDataDigest, stream, stream_size); + } + /* load partPrivKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_migrate_asymkey->partPrivKey), stream, stream_size); + } + return rc; +} + +/* TPM_MigrateAsymkey_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_MigrateAsymkey_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_MigrateAsymkey_Store:\n"); + /* store payload */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_migrate_asymkey->payload), sizeof(TPM_PAYLOAD_TYPE)); + } + /* store usageAuth */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_migrate_asymkey->usageAuth); + } + /* store pubDataDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_migrate_asymkey->pubDataDigest); + } + /* store partPrivKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_migrate_asymkey->partPrivKey)); + } + return rc; +} + +/* TPM_MigrateAsymkey_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_MigrateAsymkey_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_MigrateAsymkey_Delete(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey) +{ + printf(" TPM_MigrateAsymkey_Delete:\n"); + if (tpm_migrate_asymkey != NULL) { + TPM_Secret_Delete(tpm_migrate_asymkey->usageAuth); + TPM_SizedBuffer_Zero(&(tpm_migrate_asymkey->partPrivKey)); + TPM_SizedBuffer_Delete(&(tpm_migrate_asymkey->partPrivKey)); + TPM_MigrateAsymkey_Init(tpm_migrate_asymkey); + } + return; +} + +/* + TPM_STORE_PRIVKEY +*/ + +void TPM_StorePrivkey_Init(TPM_STORE_PRIVKEY *tpm_store_privkey) +{ + printf(" TPM_StorePrivkey_Init:\n"); + TPM_SizedBuffer_Init(&(tpm_store_privkey->d_key)); + TPM_SizedBuffer_Init(&(tpm_store_privkey->p_key)); + TPM_SizedBuffer_Init(&(tpm_store_privkey->q_key)); + return; +} + +/* TPM_StorePrivkey_Convert() sets the prime factor q and private key d based on the prime factor p + and the public key and exponent. +*/ + +TPM_RESULT TPM_StorePrivkey_Convert(TPM_STORE_ASYMKEY *tpm_store_asymkey, /* I/O result */ + TPM_KEY_PARMS *tpm_key_parms, /* to get exponent */ + TPM_SIZED_BUFFER *pubKey) /* to get public key */ +{ + TPM_RESULT rc = 0; + /* computed data */ + unsigned char *narr; + unsigned char *earr; + unsigned char *parr; + unsigned char *qarr = NULL; + unsigned char *darr = NULL; + uint32_t nbytes; + uint32_t ebytes; + uint32_t pbytes; + uint32_t qbytes; + uint32_t dbytes; + + + printf(" TPM_StorePrivkey_Convert:\n"); + if (rc == 0) { + TPM_PrintFour(" TPM_StorePrivkey_Convert: p", tpm_store_asymkey->privKey.p_key.buffer); + nbytes = pubKey->size; + narr = pubKey->buffer; + rc = TPM_KeyParms_GetExponent(&ebytes, &earr, tpm_key_parms); + } + if (rc == 0) { + rc = TPM_StoreAsymkey_GetPrimeFactorP(&pbytes, &parr, tpm_store_asymkey); + } + if (rc == 0) { + rc = TPM_RSAGetPrivateKey(&qbytes, &qarr, /* freed @1 */ + &dbytes, &darr, /* freed @2 */ + nbytes, narr, + ebytes, earr, + pbytes, parr); + } + if (rc == 0) { + TPM_PrintFour(" TPM_StorePrivkey_Convert: q", qarr); + TPM_PrintFour(" TPM_StorePrivkey_Convert: d", darr); + rc = TPM_SizedBuffer_Set((&(tpm_store_asymkey->privKey.q_key)), qbytes, qarr); + } + if (rc == 0) { + rc = TPM_SizedBuffer_Set((&(tpm_store_asymkey->privKey.d_key)), dbytes, darr); + } + free(qarr); /* @1 */ + free(darr); /* @2 */ + return rc; +} + +/* TPM_StorePrivkey_Store serializes a TPM_STORE_PRIVKEY structure, appending results to 'sbuffer' + + Only the prime factor p is stored. The other prime factor q and the private key d are + recalculated after a load. + */ + +TPM_RESULT TPM_StorePrivkey_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_STORE_PRIVKEY *tpm_store_privkey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StorePrivkey_Store:\n"); + if (rc == 0) { + TPM_PrintFour(" TPM_StorePrivkey_Store: p", tpm_store_privkey->p_key.buffer); + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_store_privkey->p_key)); + } + return rc; +} + +void TPM_StorePrivkey_Delete(TPM_STORE_PRIVKEY *tpm_store_privkey) +{ + printf(" TPM_StorePrivkey_Delete:\n"); + if (tpm_store_privkey != NULL) { + TPM_SizedBuffer_Zero(&(tpm_store_privkey->d_key)); + TPM_SizedBuffer_Zero(&(tpm_store_privkey->p_key)); + TPM_SizedBuffer_Zero(&(tpm_store_privkey->q_key)); + + TPM_SizedBuffer_Delete(&(tpm_store_privkey->d_key)); + TPM_SizedBuffer_Delete(&(tpm_store_privkey->p_key)); + TPM_SizedBuffer_Delete(&(tpm_store_privkey->q_key)); + TPM_StorePrivkey_Init(tpm_store_privkey); + } + return; +} + +/* + TPM_PUBKEY +*/ + +void TPM_Pubkey_Init(TPM_PUBKEY *tpm_pubkey) +{ + printf(" TPM_Pubkey_Init:\n"); + TPM_KeyParms_Init(&(tpm_pubkey->algorithmParms)); + TPM_SizedBuffer_Init(&(tpm_pubkey->pubKey)); + return; +} + +TPM_RESULT TPM_Pubkey_Load(TPM_PUBKEY *tpm_pubkey, /* result */ + unsigned char **stream, /* pointer to next parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_Pubkey_Load:\n"); + /* load algorithmParms */ + if (rc == 0) { + rc = TPM_KeyParms_Load(&(tpm_pubkey->algorithmParms), stream, stream_size); + } + /* load pubKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_pubkey->pubKey), stream, stream_size); + } + return rc; +} + +/* TPM_Pubkey_Store serializes a TPM_PUBKEY structure, appending results to 'sbuffer' +*/ + +TPM_RESULT TPM_Pubkey_Store(TPM_STORE_BUFFER *sbuffer, + TPM_PUBKEY *tpm_pubkey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Pubkey_Store:\n"); + if (rc == 0) { + rc = TPM_KeyParms_Store(sbuffer, &(tpm_pubkey->algorithmParms)); + } + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_pubkey->pubKey)); + } + return rc; +} + +void TPM_Pubkey_Delete(TPM_PUBKEY *tpm_pubkey) +{ + printf(" TPM_Pubkey_Delete:\n"); + if (tpm_pubkey != NULL) { + TPM_KeyParms_Delete(&(tpm_pubkey->algorithmParms)); + TPM_SizedBuffer_Delete(&(tpm_pubkey->pubKey)); + TPM_Pubkey_Init(tpm_pubkey); + } + return; +} + +TPM_RESULT TPM_Pubkey_Set(TPM_PUBKEY *tpm_pubkey, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Pubkey_Set:\n"); + if (rc == 0) { + /* add TPM_KEY_PARMS algorithmParms */ + rc = TPM_KeyParms_Copy(&(tpm_pubkey->algorithmParms), + &(tpm_key->algorithmParms)); + } + if (rc == 0) { + /* add TPM_SIZED_BUFFER pubKey */ + rc = TPM_SizedBuffer_Copy(&(tpm_pubkey->pubKey), + &(tpm_key->pubKey)); + } + return rc; +} + +TPM_RESULT TPM_Pubkey_Copy(TPM_PUBKEY *dest_tpm_pubkey, + TPM_PUBKEY *src_tpm_pubkey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Pubkey_Copy:\n"); + /* copy TPM_KEY_PARMS algorithmParms */ + if (rc == 0) { + rc = TPM_KeyParms_Copy(&(dest_tpm_pubkey->algorithmParms), + &(src_tpm_pubkey->algorithmParms)); + } + /* copy TPM_SIZED_BUFFER pubKey */ + if (rc == 0) { + rc = TPM_SizedBuffer_Copy(&(dest_tpm_pubkey->pubKey), + &(src_tpm_pubkey->pubKey)); + } + return rc; + +} + +/* TPM_Pubkey_GetExponent() gets the exponent key from the TPM_RSA_KEY_PARMS contained in a + TPM_PUBKEY +*/ + +TPM_RESULT TPM_Pubkey_GetExponent(uint32_t *ebytes, + unsigned char **earr, + TPM_PUBKEY *tpm_pubkey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Pubkey_GetExponent:\n"); + if (rc == 0) { + rc = TPM_KeyParms_GetExponent(ebytes, earr, &(tpm_pubkey->algorithmParms)); + } + return rc; +} + +/* TPM_Pubkey_GetPublicKey() gets the public key from the TPM_PUBKEY + */ + +TPM_RESULT TPM_Pubkey_GetPublicKey(uint32_t *nbytes, + unsigned char **narr, + TPM_PUBKEY *tpm_pubkey) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Pubkey_GetPublicKey:\n"); + if (rc == 0) { + *nbytes = tpm_pubkey->pubKey.size; + *narr = tpm_pubkey->pubKey.buffer; + } + return rc; +} + +/* + TPM_RSA_KEY_PARMS +*/ + + +/* Allocates and loads a TPM_RSA_KEY_PARMS structure + + Must be delete'd and freed by the caller. +*/ + +void TPM_RSAKeyParms_Init(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms) +{ + printf(" TPM_RSAKeyParms_Init:\n"); + tpm_rsa_key_parms->keyLength = 0; + tpm_rsa_key_parms->numPrimes = 0; + TPM_SizedBuffer_Init(&(tpm_rsa_key_parms->exponent)); + return; +} + +/* TPM_RSAKeyParms_Load() sets members from stream, and shifts the stream past the bytes consumed. + + Must call TPM_RSAKeyParms_Delete() to free +*/ + +TPM_RESULT TPM_RSAKeyParms_Load(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms, /* result */ + unsigned char **stream, /* pointer to next parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_RSAKeyParms_Load:\n"); + /* load keyLength */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_rsa_key_parms->keyLength), stream, stream_size); + } + /* load numPrimes */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_rsa_key_parms->numPrimes), stream, stream_size); + } + /* load exponent */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_rsa_key_parms->exponent), stream, stream_size); + } + return rc; +} + +/* TPM_RSAKeyParms_Store serializes a TPM_RSA_KEY_PARMS structure, appending results to 'sbuffer' +*/ + +TPM_RESULT TPM_RSAKeyParms_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_RSA_KEY_PARMS *tpm_rsa_key_parms) +{ + TPM_RESULT rc = 0; + + printf(" TPM_RSAKeyParms_Store:\n"); + /* store keyLength */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_rsa_key_parms->keyLength); + } + /* store numPrimes */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_rsa_key_parms->numPrimes); + } + /* store exponent */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_rsa_key_parms->exponent)); + } + return rc; +} + +/* TPM_RSAKeyParms_Delete frees any member allocated memory + + If 'tpm_rsa_key_parms' is NULL, this is a no-op. + */ + +void TPM_RSAKeyParms_Delete(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms) +{ + printf(" TPM_RSAKeyParms_Delete:\n"); + if (tpm_rsa_key_parms != NULL) { + TPM_SizedBuffer_Delete(&(tpm_rsa_key_parms->exponent)); + TPM_RSAKeyParms_Init(tpm_rsa_key_parms); + } + return; +} + +/* TPM_RSAKeyParms_Copy() does a copy of the source to the destination. + + The destination must be initialized first. +*/ + +TPM_RESULT TPM_RSAKeyParms_Copy(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms_dest, + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms_src) +{ + TPM_RESULT rc = 0; + + printf(" TPM_RSAKeyParms_Copy:\n"); + if (rc == 0) { + tpm_rsa_key_parms_dest->keyLength = tpm_rsa_key_parms_src->keyLength; + tpm_rsa_key_parms_dest->numPrimes = tpm_rsa_key_parms_src->numPrimes; + rc = TPM_SizedBuffer_Copy(&(tpm_rsa_key_parms_dest->exponent), + &(tpm_rsa_key_parms_src->exponent)); + } + return rc; +} + +/* TPM_RSAKeyParms_New() allocates memory for a TPM_RSA_KEY_PARMS and initializes the structure */ + +TPM_RESULT TPM_RSAKeyParms_New(TPM_RSA_KEY_PARMS **tpm_rsa_key_parms) +{ + TPM_RESULT rc = 0; + + printf(" TPM_RSAKeyParms_New:\n"); + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)tpm_rsa_key_parms, sizeof(TPM_RSA_KEY_PARMS)); + } + if (rc == 0) { + TPM_RSAKeyParms_Init(*tpm_rsa_key_parms); + } + return rc; +} + +/* TPM_RSAKeyParms_GetExponent() gets the exponent array and size from tpm_rsa_key_parms. + + If the structure exponent.size is zero, the default RSA exponent is returned. +*/ + +TPM_RESULT TPM_RSAKeyParms_GetExponent(uint32_t *ebytes, + unsigned char **earr, + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms) +{ + TPM_RESULT rc = 0; + + printf(" TPM_RSAKeyParms_GetExponent:\n"); + if (tpm_rsa_key_parms->exponent.size != 0) { + *ebytes = tpm_rsa_key_parms->exponent.size; + *earr = tpm_rsa_key_parms->exponent.buffer; + } + else { + *ebytes = 3; + *earr = tpm_default_rsa_exponent; + } + return rc; +} + +/* + A Key Handle Entry +*/ + +/* TPM_KeyHandleEntry_Init() removes an entry from the list. It DOES NOT delete the + TPM_KEY object. */ + +void TPM_KeyHandleEntry_Init(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) +{ + tpm_key_handle_entry->handle = 0; + tpm_key_handle_entry->key = NULL; + tpm_key_handle_entry->parentPCRStatus = TRUE; + tpm_key_handle_entry->keyControl = 0; + return; +} + +/* TPM_KeyHandleEntry_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_KeyHandleEntry_Init() + After use, call TPM_KeyHandleEntry_Delete() to free memory +*/ + +TPM_RESULT TPM_KeyHandleEntry_Load(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_KeyHandleEntry_Load:\n"); + /* load handle */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_key_handle_entry->handle), stream, stream_size); + } + /* malloc space for the key member */ + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)&(tpm_key_handle_entry->key), sizeof(TPM_KEY)); + } + /* load key */ + if (rc == 0) { + TPM_Key_Init(tpm_key_handle_entry->key); + rc = TPM_Key_LoadClear(tpm_key_handle_entry->key, + FALSE, /* not EK */ + stream, stream_size); + } + /* load parentPCRStatus */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_key_handle_entry->parentPCRStatus), stream, stream_size); + } + /* load keyControl */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_key_handle_entry->keyControl), stream, stream_size); + } + return rc; +} + +/* TPM_KeyHandleEntry_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_KeyHandleEntry_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) +{ + TPM_RESULT rc = 0; + + printf(" TPM_KeyHandleEntry_Store:\n"); + /* store handle */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_key_handle_entry->handle); + } + /* store key with private data appended in clear text */ + if (rc == 0) { + rc = TPM_Key_StoreClear(sbuffer, + FALSE, /* not EK */ + tpm_key_handle_entry->key); + } + /* store parentPCRStatus */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + &(tpm_key_handle_entry->parentPCRStatus), sizeof(TPM_BOOL)); + } + /* store keyControl */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_key_handle_entry->keyControl); + } + return rc; +} + +/* TPM_KeyHandleEntry_Delete() deletes an entry from the list, deletes the TPM_KEY object, and + free's the TPM_KEY. +*/ + +void TPM_KeyHandleEntry_Delete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) +{ + if (tpm_key_handle_entry != NULL) { + if (tpm_key_handle_entry->handle != 0) { + printf(" TPM_KeyHandleEntry_Delete: Deleting %08x\n", tpm_key_handle_entry->handle); + TPM_Key_Delete(tpm_key_handle_entry->key); + free(tpm_key_handle_entry->key); + } + TPM_KeyHandleEntry_Init(tpm_key_handle_entry); + } + return; +} + +/* TPM_KeyHandleEntry_FlushSpecific() flushes a key handle according to the rules of + TPM_FlushSpecific() +*/ + +TPM_RESULT TPM_KeyHandleEntry_FlushSpecific(tpm_state_t *tpm_state, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) +{ + TPM_RESULT rc = 0; + TPM_AUTHHANDLE authHandle = 0; /* dummy parameter */ + TPM_BOOL continueAuthSession; /* dummy parameter */ + + printf(" TPM_KeyHandleEntry_FlushSpecific:\n"); + if (rc == 0) { + /* Internal error, should never happen */ + if (tpm_key_handle_entry->key == NULL) { + printf("TPM_KeyHandleEntry_FlushSpecific: Error (fatal), key is NULL\n"); + rc = TPM_FAIL; + } + } + /* terminate OSAP and DSAP sessions associated with the key */ + if (rc == 0) { + /* The dummy parameters are not used. The session, if any, associated with this function + is handled elsewhere. */ + TPM_AuthSessions_TerminateEntity(&continueAuthSession, + authHandle, + tpm_state->tpm_stclear_data.authSessions, + TPM_ET_KEYHANDLE, /* TPM_ENTITY_TYPE */ + &(tpm_key_handle_entry->key-> + tpm_store_asymkey->pubDataDigest)); /* entityDigest */ + printf(" TPM_KeyHandleEntry_FlushSpecific: Flushing key handle %08x\n", + tpm_key_handle_entry->handle); + /* free the TPM_KEY resources, free the key itself, and remove entry from the key handle + entries list */ + TPM_KeyHandleEntry_Delete(tpm_key_handle_entry); + } + return rc; +} + +/* + Key Handle Entries +*/ + +/* TPM_KeyHandleEntries_Init() initializes the fixed TPM_KEY_HANDLE_ENTRY array. All entries are + emptied. The keys are not deleted. +*/ + +void TPM_KeyHandleEntries_Init(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + size_t i; + + printf(" TPM_KeyHandleEntries_Init:\n"); + for (i = 0 ; i < TPM_KEY_HANDLES ; i++) { + TPM_KeyHandleEntry_Init(&(tpm_key_handle_entries[i])); + } + return; +} + +/* TPM_KeyHandleEntries_Delete() deletes and freed all TPM_KEY's stored in entries, and the entry + +*/ + +void TPM_KeyHandleEntries_Delete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + size_t i; + + printf(" TPM_KeyHandleEntries_Delete:\n"); + for (i = 0 ; i < TPM_KEY_HANDLES ; i++) { + TPM_KeyHandleEntry_Delete(&(tpm_key_handle_entries[i])); + } + return; +} + +/* TPM_KeyHandleEntries_Load() loads the key handle entries from a stream created by + TPM_KeyHandleEntries_Store() + + The two functions must be kept in sync. +*/ + +TPM_RESULT TPM_KeyHandleEntries_Load(tpm_state_t *tpm_state, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t keyCount = 0; /* keys to be saved */ + size_t i; + TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; + + /* check format tag */ + /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' + on the tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_KEY_HANDLE_ENTRIES_V1, stream, stream_size); + } + /* get the count of keys in the stream */ + if (rc == 0) { + rc = TPM_Load32(&keyCount, stream, stream_size); + printf(" TPM_KeyHandleEntries_Load: %u keys to be loaded\n", keyCount); + } + /* sanity check that keyCount not greater than key slots */ + if (rc == 0) { + if (keyCount > TPM_KEY_HANDLES) { + printf("TPM_KeyHandleEntries_Load: Error (fatal)" + " key handles in stream %u greater than %d\n", + keyCount, TPM_KEY_HANDLES); + rc = TPM_FAIL; + } + } + /* for each key handle entry */ + for (i = 0 ; (rc == 0) && (i < keyCount) ; i++) { + /* deserialize the key handle entry and its key member */ + if (rc == 0) { + TPM_KeyHandleEntry_Init(&tpm_key_handle_entry); /* freed @2 on error */ + rc = TPM_KeyHandleEntry_Load(&tpm_key_handle_entry, stream, stream_size); + } + if (rc == 0) { + printf(" TPM_KeyHandleEntries_Load: Loading key handle %08x\n", + tpm_key_handle_entry.handle); + /* Add the entry to the list. Keep the handle. If the suggested value could not be + accepted, this is a "should never happen" fatal error. It means that the save key + handle was saved twice. */ + rc = TPM_KeyHandleEntries_AddEntry(&(tpm_key_handle_entry.handle), /* suggested */ + TRUE, /* keep handle */ + tpm_state->tpm_key_handle_entries, + &tpm_key_handle_entry); + } + /* if there was an error copying the entry to the array, the entry must be delete'd to + prevent a memory leak, since a key has been loaded to the entry */ + if (rc != 0) { + TPM_KeyHandleEntry_Delete(&tpm_key_handle_entry); /* @2 on error */ + } + } + return rc; +} + +/* TPM_KeyHandleEntries_Store() stores the key handle entries to a stream that can be restored + through TPM_KeyHandleEntries_Load(). + + The two functions must be kept in sync. +*/ + +TPM_RESULT TPM_KeyHandleEntries_Store(TPM_STORE_BUFFER *sbuffer, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + size_t start; /* iterator though key handle entries */ + size_t current; /* iterator though key handle entries */ + uint32_t keyCount; /* keys to be saved */ + TPM_BOOL save; /* should key be saved */ + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; + + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_KEY_HANDLE_ENTRIES_V1); + } + /* first count up the keys */ + if (rc == 0) { + start = 0; + keyCount = 0; + printf(" TPM_KeyHandleEntries_Store: Counting keys to be stored\n"); + } + while ((rc == 0) && + /* returns TPM_RETRY when at the end of the table, terminates loop */ + (TPM_KeyHandleEntries_GetNextEntry(&tpm_key_handle_entry, + ¤t, + tpm_state->tpm_key_handle_entries, + start)) == 0) { + TPM_SaveState_IsSaveKey(&save, tpm_key_handle_entry); + if (save) { + keyCount++; + } + start = current + 1; + } + /* store the number of entries to save */ + if (rc == 0) { + printf(" TPM_KeyHandleEntries_Store: %u keys to be stored\n", keyCount); + rc = TPM_Sbuffer_Append32(sbuffer, keyCount); + } + /* for each key handle entry */ + if (rc == 0) { + printf(" TPM_KeyHandleEntries_Store: Storing keys\n"); + start = 0; + } + while ((rc == 0) && + /* returns TPM_RETRY when at the end of the table, terminates loop */ + (TPM_KeyHandleEntries_GetNextEntry(&tpm_key_handle_entry, + ¤t, + tpm_state->tpm_key_handle_entries, + start)) == 0) { + TPM_SaveState_IsSaveKey(&save, tpm_key_handle_entry); + if (save) { + /* store the key handle entry and its associated key */ + rc = TPM_KeyHandleEntry_Store(sbuffer, tpm_key_handle_entry); + } + start = current + 1; + } + return rc; +} + + + +/* TPM_KeyHandleEntries_StoreHandles() stores only the two members which are part of the + specification. + + - the number of loaded keys + - a list of key handles + + A TPM_KEY_HANDLE_LIST structure that enumerates all key handles loaded on the TPM. The list only + contains the number of handles that an external manager can operate with and does not include the + EK or SRK. This is command is available for backwards compatibility. It is the same as + TPM_CAP_HANDLE with a resource type of keys. +*/ + +TPM_RESULT TPM_KeyHandleEntries_StoreHandles(TPM_STORE_BUFFER *sbuffer, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + TPM_RESULT rc = 0; + uint16_t i, loadedCount; + + printf(" TPM_KeyHandleEntries_StoreHandles:\n"); + if (rc == 0) { + loadedCount = 0; + /* count the number of loaded handles */ + for (i = 0 ; i < TPM_KEY_HANDLES ; i++) { + if (tpm_key_handle_entries[i].key != NULL) { + loadedCount++; + } + } + /* store 'loaded' handle count */ + rc = TPM_Sbuffer_Append16(sbuffer, loadedCount); + } + for (i = 0 ; (rc == 0) && (i < TPM_KEY_HANDLES) ; i++) { + if (tpm_key_handle_entries[i].key != NULL) { /* if the index is loaded */ + rc = TPM_Sbuffer_Append32(sbuffer, tpm_key_handle_entries[i].handle); /* store it */ + } + } + return rc; +} + +/* TPM_KeyHandleEntries_DeleteHandle() removes a handle from the list. + + The TPM_KEY object must be _Delete'd and possibly free'd separately, because it might not be in + the table. +*/ + +TPM_RESULT TPM_KeyHandleEntries_DeleteHandle(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + TPM_KEY_HANDLE tpm_key_handle) +{ + TPM_RESULT rc = 0; + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; + + printf(" TPM_KeyHandleEntries_DeleteHandle: %08x\n", tpm_key_handle); + /* search for the handle */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_key_handle_entries, + tpm_key_handle); + if (rc != 0) { + printf("TPM_KeyHandleEntries_DeleteHandle: Error, key handle %08x not found\n", + tpm_key_handle); + } + } + /* delete the entry */ + if (rc == 0) { + TPM_KeyHandleEntry_Init(tpm_key_handle_entry); + } + return rc; +} + +/* TPM_KeyHandleEntries_IsSpace() returns 'isSpace' TRUE if an entry is available, FALSE if not. + + If TRUE, 'index' holds the first free position. +*/ + +void TPM_KeyHandleEntries_IsSpace(TPM_BOOL *isSpace, + uint32_t *index, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + printf(" TPM_KeyHandleEntries_IsSpace:\n"); + for (*index = 0, *isSpace = FALSE ; *index < TPM_KEY_HANDLES ; (*index)++) { + if (tpm_key_handle_entries[*index].key == NULL) { /* if the index is empty */ + printf(" TPM_KeyHandleEntries_IsSpace: Found space at %u\n", *index); + *isSpace = TRUE; + break; + } + } + return; +} + +/* TPM_KeyHandleEntries_GetSpace() returns the number of unused key handle entries. + +*/ + +void TPM_KeyHandleEntries_GetSpace(uint32_t *space, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + uint32_t i; + + printf(" TPM_KeyHandleEntries_GetSpace:\n"); + for (*space = 0 , i = 0 ; i < TPM_KEY_HANDLES ; i++) { + if (tpm_key_handle_entries[i].key == NULL) { /* if the index is empty */ + (*space)++; + } + } + return; +} + +/* TPM_KeyHandleEntries_IsEvictSpace() returns 'isSpace' TRUE if there are at least 'minSpace' + entries that do not have the ownerEvict bit set, FALSE if not. +*/ + +void TPM_KeyHandleEntries_IsEvictSpace(TPM_BOOL *isSpace, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + uint32_t minSpace) +{ + uint32_t evictSpace; + uint32_t i; + + for (i = 0, evictSpace = 0 ; i < TPM_KEY_HANDLES ; i++) { + if (tpm_key_handle_entries[i].key == NULL) { /* if the index is empty */ + evictSpace++; + } + else { /* is index is used */ + if (!(tpm_key_handle_entries[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { + evictSpace++; /* space that can be evicted */ + } + } + } + printf(" TPM_KeyHandleEntries_IsEvictSpace: evictable space, minimum %u free %u\n", + minSpace, evictSpace); + if (evictSpace >= minSpace) { + *isSpace = TRUE; + } + else { + *isSpace = FALSE; + } + return; +} + +/* TPM_KeyHandleEntries_AddKeyEntry() adds a TPM_KEY object to the list. + + If *tpm_key_handle == 0, a value is assigned. If *tpm_key_handle != 0, + that value is used if it it not currently in use. + + The handle is returned in tpm_key_handle. +*/ + +TPM_RESULT TPM_KeyHandleEntries_AddKeyEntry(TPM_KEY_HANDLE *tpm_key_handle, /* i/o */ + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, /* in */ + TPM_KEY *tpm_key, + TPM_BOOL parentPCRStatus, + TPM_KEY_CONTROL keyControl) +{ + TPM_RESULT rc = 0; + TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; + + printf(" TPM_KeyHandleEntries_AddKeyEntry:\n"); + tpm_key_handle_entry.key = tpm_key; + tpm_key_handle_entry.parentPCRStatus = parentPCRStatus; + tpm_key_handle_entry.keyControl = keyControl; + rc = TPM_KeyHandleEntries_AddEntry(tpm_key_handle, + FALSE, /* don't have to keep handle */ + tpm_key_handle_entries, + &tpm_key_handle_entry); + return rc; +} + +/* TPM_KeyHandleEntries_AddEntry() adds (copies) the TPM_KEY_HANDLE_ENTRY object to the list. + + If *tpm_key_handle == 0: + a value is assigned. + + If *tpm_key_handle != 0: + + If keepHandle is TRUE, the handle must be used. An error is returned if the handle is + already in use. + + If keepHandle is FALSE, if the handle is already in use, a new value is assigned. + + The handle is returned in tpm_key_handle. +*/ + +TPM_RESULT TPM_KeyHandleEntries_AddEntry(TPM_KEY_HANDLE *tpm_key_handle, /* i/o */ + TPM_BOOL keepHandle, /* input */ + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, /* input */ + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) /* input */ + +{ + TPM_RESULT rc = 0; + uint32_t index; + TPM_BOOL isSpace; + + printf(" TPM_KeyHandleEntries_AddEntry: handle %08x, keepHandle %u\n", + *tpm_key_handle, keepHandle); + /* check for valid TPM_KEY */ + if (rc == 0) { + if (tpm_key_handle_entry->key == NULL) { /* should never occur */ + printf("TPM_KeyHandleEntries_AddEntry: Error (fatal), NULL TPM_KEY\n"); + rc = TPM_FAIL; + } + } + /* is there an empty entry, get the location index */ + if (rc == 0) { + TPM_KeyHandleEntries_IsSpace(&isSpace, &index, tpm_key_handle_entries); + if (!isSpace) { + printf("TPM_KeyHandleEntries_AddEntry: Error, key handle entries full\n"); + rc = TPM_NOSPACE; + } + } + if (rc == 0) { + rc = TPM_Handle_GenerateHandle(tpm_key_handle, /* I/O */ + tpm_key_handle_entries, /* handle array */ + keepHandle, + TRUE, /* isKeyHandle */ + (TPM_GETENTRY_FUNCTION_T)TPM_KeyHandleEntries_GetEntry); + } + if (rc == 0) { + tpm_key_handle_entries[index].handle = *tpm_key_handle; + tpm_key_handle_entries[index].key = tpm_key_handle_entry->key; + tpm_key_handle_entries[index].keyControl = tpm_key_handle_entry->keyControl; + tpm_key_handle_entries[index].parentPCRStatus = tpm_key_handle_entry->parentPCRStatus; + printf(" TPM_KeyHandleEntries_AddEntry: Index %u key handle %08x key pointer %p\n", + index, tpm_key_handle_entries[index].handle, tpm_key_handle_entries[index].key); + } + return rc; +} + +/* TPM_KeyHandleEntries_GetEntry() searches all entries for the entry matching the handle, and + returns that entry */ + +TPM_RESULT TPM_KeyHandleEntries_GetEntry(TPM_KEY_HANDLE_ENTRY **tpm_key_handle_entry, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + TPM_KEY_HANDLE tpm_key_handle) +{ + TPM_RESULT rc = 0; + size_t i; + TPM_BOOL found; + + printf(" TPM_KeyHandleEntries_GetEntry: Get entry for handle %08x\n", tpm_key_handle); + for (i = 0, found = FALSE ; (i < TPM_KEY_HANDLES) && !found ; i++) { + /* first test for matching handle. Then check for non-NULL to insure that entry is valid */ + if ((tpm_key_handle_entries[i].handle == tpm_key_handle) && + tpm_key_handle_entries[i].key != NULL) { /* found */ + found = TRUE; + *tpm_key_handle_entry = &(tpm_key_handle_entries[i]); + } + } + if (!found) { + printf(" TPM_KeyHandleEntries_GetEntry: key handle %08x not found\n", tpm_key_handle); + rc = TPM_INVALID_KEYHANDLE; + } + else { + printf(" TPM_KeyHandleEntries_GetEntry: key handle %08x found\n", tpm_key_handle); + } + return rc; +} + +/* TPM_KeyHandleEntries_GetNextEntry() gets the next valid TPM_KEY_HANDLE_ENTRY at or after the + 'start' index. + + The current position is returned in 'current'. For iteration, the next 'start' should be + 'current' + 1. + + Returns + + 0 on success. + Returns TPM_RETRY when no more valid entries are found. + */ + +TPM_RESULT TPM_KeyHandleEntries_GetNextEntry(TPM_KEY_HANDLE_ENTRY **tpm_key_handle_entry, + size_t *current, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + size_t start) +{ + TPM_RESULT rc = TPM_RETRY; + + printf(" TPM_KeyHandleEntries_GetNextEntry: Start %lu\n", (unsigned long)start); + for (*current = start ; *current < TPM_KEY_HANDLES ; (*current)++) { + if (tpm_key_handle_entries[*current].key != NULL) { + *tpm_key_handle_entry = &(tpm_key_handle_entries[*current]); + rc = 0; /* found an entry */ + break; + } + } + return rc; +} + +/* TPM_KeyHandleEntries_GetKey() gets the TPM_KEY associated with the handle. + + If the key has PCR usage (size is non-zero and one or more mask bits are set), PCR's have been + specified. It computes a PCR digest based on the TPM PCR's and verifies it against the key + digestAtRelease. + + Exceptions: readOnly is TRUE when the caller is indicating that only the public key is being read + (e.g. TPM_GetPubKey). In this case, if keyFlags TPM_PCRIGNOREDONREAD is also TRUE, the PCR + digest and locality must not be checked. + + If ignorePCRs is TRUE, the PCR digest is also ignored. A typical case is during OSAP and DSAP + session setup. + */ + +TPM_RESULT TPM_KeyHandleEntries_GetKey(TPM_KEY **tpm_key, + TPM_BOOL *parentPCRStatus, + tpm_state_t *tpm_state, + TPM_KEY_HANDLE tpm_key_handle, + TPM_BOOL readOnly, + TPM_BOOL ignorePCRs, + TPM_BOOL allowEK) +{ + TPM_RESULT rc = 0; + TPM_BOOL found = FALSE; /* found a special handle key */ + TPM_BOOL validatePcrs = TRUE; + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; + + printf(" TPM_KeyHandleEntries_GetKey: For handle %08x\n", tpm_key_handle); + /* If it's one of the special handles, return the TPM_KEY */ + if (rc == 0) { + switch (tpm_key_handle) { + case TPM_KH_SRK: /* The handle points to the SRK */ + if (tpm_state->tpm_permanent_data.ownerInstalled) { + *tpm_key = &(tpm_state->tpm_permanent_data.srk); + *parentPCRStatus = FALSE; /* storage root key (SRK) has no parent */ + found = TRUE; + } + else { + printf(" TPM_KeyHandleEntries_GetKey: Error, SRK handle with no owner\n"); + rc = TPM_KEYNOTFOUND; + } + break; + case TPM_KH_EK: /* The handle points to the PUBEK, only usable with + TPM_OwnerReadInternalPub */ + if (rc == 0) { + if (!allowEK) { + printf(" TPM_KeyHandleEntries_GetKey: Error, EK handle not allowed\n"); + rc = TPM_KEYNOTFOUND; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_data.endorsementKey.keyUsage == + TPM_KEY_UNINITIALIZED) { + printf(" TPM_KeyHandleEntries_GetKey: Error, EK handle but no EK\n"); + rc = TPM_KEYNOTFOUND; + } + } + if (rc == 0) { + *tpm_key = &(tpm_state->tpm_permanent_data.endorsementKey); + *parentPCRStatus = FALSE; /* endorsement key (EK) has no parent */ + found = TRUE; + } + break; + case TPM_KH_OWNER: /* handle points to the TPM Owner */ + case TPM_KH_REVOKE: /* handle points to the RevokeTrust value */ + case TPM_KH_TRANSPORT: /* handle points to the EstablishTransport static authorization */ + case TPM_KH_OPERATOR: /* handle points to the Operator auth */ + case TPM_KH_ADMIN: /* handle points to the delegation administration auth */ + printf("TPM_KeyHandleEntries_GetKey: Error, Unsupported key handle %08x\n", + tpm_key_handle); + rc = TPM_INVALID_RESOURCE; + break; + default: + /* continue searching */ + break; + } + } + /* If not one of the special key handles, search for the handle in the list */ + if ((rc == 0) && !found) { + rc = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_state->tpm_key_handle_entries, + tpm_key_handle); + if (rc != 0) { + printf("TPM_KeyHandleEntries_GetKey: Error, key handle %08x not found\n", + tpm_key_handle); + } + } + /* Part 1 25.1 Validate Key for use + 2. Set LK to the loaded key that is being used */ + /* NOTE: For special handle keys, this was already done. Just do here for keys in table */ + if ((rc == 0) && !found) { + *tpm_key = tpm_key_handle_entry->key; + *parentPCRStatus = tpm_key_handle_entry->parentPCRStatus; + } + /* 3. If LK -> pcrInfoSize is not 0 - if the key specifies PCR's */ + /* NOTE Done by TPM_Key_CheckPCRDigest() */ + /* a. If LK -> pcrInfo -> releasePCRSelection identifies the use of one or more PCR */ + if (rc == 0) { +#ifdef TPM_V12 + validatePcrs = !ignorePCRs && + !(readOnly && ((*tpm_key)->keyFlags & TPM_PCRIGNOREDONREAD)); +#else + validatePcrs = !ignorePCRs && !readOnly; +#endif + } + if ((rc == 0) && validatePcrs) { + if (rc == 0) { + rc = TPM_Key_CheckPCRDigest(*tpm_key, tpm_state); + } + } + return rc; +} + +/* TPM_KeyHandleEntries_SetParentPCRStatus() updates the parentPCRStatus member of the + TPM_KEY_HANDLE_ENTRY */ + +TPM_RESULT TPM_KeyHandleEntries_SetParentPCRStatus(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + TPM_KEY_HANDLE tpm_key_handle, + TPM_BOOL parentPCRStatus) +{ + TPM_RESULT rc = 0; + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; + + printf(" TPM_KeyHandleEntries_SetParentPCRStatus: Handle %08x\n", tpm_key_handle); + /* get the entry for the handle from the table */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_key_handle_entries, + tpm_key_handle); + if (rc != 0) { + printf("TPM_KeyHandleEntries_SetParentPCRStatus: Error, key handle %08x not found\n", + tpm_key_handle); + } + } + if (rc == 0) { + tpm_key_handle_entry->parentPCRStatus = parentPCRStatus; + } + return rc; +} + +/* TPM_KeyHandleEntries_OwnerEvictLoad() loads all owner evict keys from the stream into the key + handle entries table. +*/ + +TPM_RESULT TPM_KeyHandleEntries_OwnerEvictLoad(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint16_t keyCount; + uint16_t i; /* the uint16_t corresponds to the standard getcap */ + TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; /* each entry as read from the stream */ + TPM_TAG ownerEvictVersion; + + printf(" TPM_KeyHandleEntries_OwnerEvictLoad:\n"); + /* get the owner evict version number */ + if (rc == 0) { + rc = TPM_Load16(&ownerEvictVersion, stream, stream_size); + } + if (rc == 0) { + if (ownerEvictVersion != TPM_TAG_NVSTATE_OE_V1) { + printf("TPM_KeyHandleEntries_OwnerEvictLoad: " + "Error (fatal) unsupported version tag %04x\n", + ownerEvictVersion); + rc = TPM_FAIL; + } + } + /* get the count of owner evict keys in the stream */ + if (rc == 0) { + rc = TPM_Load16(&keyCount, stream, stream_size); + } + /* sanity check that keyCount not greater than key slots */ + if (rc == 0) { + if (keyCount > TPM_OWNER_EVICT_KEY_HANDLES) { + printf("TPM_KeyHandleEntries_OwnerEvictLoad: Error (fatal)" + " key handles in stream %u greater than %d\n", + keyCount, TPM_OWNER_EVICT_KEY_HANDLES); + rc = TPM_FAIL; + } + } + if (rc == 0) { + printf(" TPM_KeyHandleEntries_OwnerEvictLoad: Count %hu\n", keyCount); + } + for (i = 0 ; (rc == 0) && (i < keyCount) ; i++) { + /* Must init each time through. This just resets the structure members. It does not free + the key that is in the structure after the first time through. That key has been added + (copied) to the key handle entries array. */ + printf(" TPM_KeyHandleEntries_OwnerEvictLoad: Loading key %hu\n", i); + TPM_KeyHandleEntry_Init(&tpm_key_handle_entry); /* freed @2 on error */ + if (rc == 0) { + rc = TPM_KeyHandleEntry_Load(&tpm_key_handle_entry, stream, stream_size); + } + /* add the entry to the list */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_AddEntry(&(tpm_key_handle_entry.handle), /* suggested */ + TRUE, /* keep handle */ + tpm_key_handle_entries, + &tpm_key_handle_entry); + } + /* if there was an error copying the entry to the array, the entry must be delete'd to + prevent a memory leak, since a key has been loaded to the entry */ + if (rc != 0) { + TPM_KeyHandleEntry_Delete(&tpm_key_handle_entry); /* @2 on error */ + } + } + return rc; +} + +/* TPM_KeyHandleEntries_OwnerEvictStore() stores all owner evict keys from the key handle entries + table to the stream. + + It is used to serialize to NVRAM. +*/ + +TPM_RESULT TPM_KeyHandleEntries_OwnerEvictStore(TPM_STORE_BUFFER *sbuffer, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + TPM_RESULT rc = 0; + uint16_t count; + uint16_t i; /* the uint16_t corresponds to the standard getcap */ + + printf(" TPM_KeyHandleEntries_OwnerEvictStore:\n"); + /* append the owner evict version number to the stream */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_OE_V1); + } + /* count the number of owner evict keys */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_OwnerEvictGetCount(&count, tpm_key_handle_entries); + } + /* append the count to the stream */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, count); + } + for (i = 0 ; (rc == 0) && (i < TPM_KEY_HANDLES) ; i++) { + /* if the slot is occupied */ + if (tpm_key_handle_entries[i].key != NULL) { + /* if the key is owner evict */ + if ((tpm_key_handle_entries[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { + /* store it */ + rc = TPM_KeyHandleEntry_Store(sbuffer, &(tpm_key_handle_entries[i])); + } + } + } + return rc; +} + +/* TPM_KeyHandleEntries_OwnerEvictGetCount returns the number of owner evict key entries + */ + +TPM_RESULT +TPM_KeyHandleEntries_OwnerEvictGetCount(uint16_t *count, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + TPM_RESULT rc = 0; + uint16_t i; /* the uint16_t corresponds to the standard getcap */ + + printf(" TPM_KeyHandleEntries_OwnerEvictGetCount:\n"); + /* count the number of loaded owner evict handles */ + if (rc == 0) { + for (i = 0 , *count = 0 ; i < TPM_KEY_HANDLES ; i++) { + /* if the slot is occupied */ + if (tpm_key_handle_entries[i].key != NULL) { + /* if the key is owner evict */ + if ((tpm_key_handle_entries[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { + (*count)++; /* count it */ + } + } + } + printf(" TPM_KeyHandleEntries_OwnerEvictGetCount: Count %hu\n", *count); + } + /* sanity check */ + if (rc == 0) { + if (*count > TPM_OWNER_EVICT_KEY_HANDLES) { + printf("TPM_KeyHandleEntries_OwnerEvictGetCount: Error (fatal), " + "count greater that max %u\n", TPM_OWNER_EVICT_KEY_HANDLES); + rc = TPM_FAIL; /* should never occur */ + } + } + return rc; +} + +/* TPM_KeyHandleEntries_OwnerEvictDelete() flushes owner evict keys. It does NOT write to NV. + +*/ + +void TPM_KeyHandleEntries_OwnerEvictDelete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + uint16_t i; /* the uint16_t corresponds to the standard getcap */ + + for (i = 0 ; i < TPM_KEY_HANDLES ; i++) { + /* if the slot is occupied */ + if (tpm_key_handle_entries[i].key != NULL) { + /* if the key is owner evict */ + if ((tpm_key_handle_entries[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { + TPM_KeyHandleEntry_Delete(&(tpm_key_handle_entries[i])); + } + } + } + return; +} + +/* + Processing Functions +*/ + +/* 14.4 TPM_ReadPubek rev 99 + + Return the endorsement key public portion. This value should have controls placed upon access as + it is a privacy sensitive value + + The readPubek flag is set to FALSE by TPM_TakeOwnership and set to TRUE by TPM_OwnerClear, thus + mirroring if a TPM Owner is present. +*/ + +TPM_RESULT TPM_Process_ReadPubek(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters*/ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NONCE antiReplay; + + /* processing */ + const unsigned char *pubEndorsementKeyStreamBuffer; + uint32_t pubEndorsementKeyStreamLength; + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORE_BUFFER pubEndorsementKeyStream; + TPM_DIGEST checksum; + + printf("TPM_Process_ReadPubek: Ordinal Entry\n"); + TPM_Sbuffer_Init(&pubEndorsementKeyStream); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour(" TPM_Process_ReadPubek: antiReplay", antiReplay); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ReadPubek: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. If TPM_PERMANENT_FLAGS -> readPubek is FALSE return TPM_DISABLED_CMD. */ + if (returnCode == TPM_SUCCESS) { + printf(" TPM_Process_ReadPubek: readPubek %02x\n", + tpm_state->tpm_permanent_flags.readPubek); + if (!tpm_state->tpm_permanent_flags.readPubek) { + printf("TPM_Process_ReadPubek: Error, readPubek is FALSE\n"); + returnCode = TPM_DISABLED_CMD; + } + } + /* 2. If no EK is present the TPM MUST return TPM_NO_ENDORSEMENT */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_permanent_data.endorsementKey.keyUsage == TPM_KEY_UNINITIALIZED) { + printf("TPM_Process_ReadPubek: Error, no EK is present\n"); + returnCode = TPM_NO_ENDORSEMENT; + } + } + /* 3. Create checksum by performing SHA-1 on the concatenation of (pubEndorsementKey || + antiReplay). */ + if (returnCode == TPM_SUCCESS) { + /* serialize the TPM_PUBKEY components of the EK */ + returnCode = + TPM_Key_StorePubkey(&pubEndorsementKeyStream, /* output */ + &pubEndorsementKeyStreamBuffer, /* output */ + &pubEndorsementKeyStreamLength, /* output */ + &(tpm_state->tpm_permanent_data.endorsementKey)); /* input */ + } + if (returnCode == TPM_SUCCESS) { + printf(" TPM_Process_ReadPubek: pubEndorsementKey length %u\n", + pubEndorsementKeyStreamLength); + /* create the checksum */ + returnCode = TPM_SHA1(checksum, +#if 0 /* The old Atmel chip and the LTC test code assume this, but it is incorrect */ + tpm_state->tpm_permanent_data.endorsementKey.pubKey.keyLength, + tpm_state->tpm_permanent_data.endorsementKey.pubKey.key, +#else /* this meets the TPM 1.2 standard */ + pubEndorsementKeyStreamLength, pubEndorsementKeyStreamBuffer, +#endif + sizeof(TPM_NONCE), antiReplay, + 0, NULL); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ReadPubek: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + /* 4. Export the PUBEK and checksum. */ + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append pubEndorsementKey */ + returnCode = TPM_Sbuffer_Append(response, + pubEndorsementKeyStreamBuffer, + pubEndorsementKeyStreamLength); + } + /* append checksum */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Store(response, checksum); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&pubEndorsementKeyStream); /* @1 */ + return rcf; +} + +/* 14.2 TPM_CreateRevocableEK rev 98 + + This command creates the TPM endorsement key. It returns a failure code if an endorsement key + already exists. The TPM vendor may have a separate mechanism to create the EK and "squirt" the + value into the TPM. +*/ + +TPM_RESULT TPM_Process_CreateRevocableEK(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NONCE antiReplay; /* Arbitrary data */ + TPM_KEY_PARMS keyInfo; /* Information about key to be created, this includes all + algorithm parameters */ + TPM_BOOL generateReset = FALSE; /* If TRUE use TPM RNG to generate EKreset. If FALSE + use the passed value inputEKreset */ + TPM_NONCE inputEKreset; /* The authorization value to be used with TPM_RevokeTrust + if generateReset==FALSE, else the parameter is present + but unused */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_KEY *endorsementKey; /* EK object from permanent store */ + TPM_BOOL writeAllNV1 = FALSE; /* flags to write back NV */ + TPM_BOOL writeAllNV2 = FALSE; /* flags to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_PUBKEY pubEndorsementKey; /* The public endorsement key */ + TPM_DIGEST checksum; /* Hash of pubEndorsementKey and antiReplay */ + + printf("TPM_Process_CreateRevocableEK: Ordinal Entry\n"); + /* get pointers */ + endorsementKey = &(tpm_state->tpm_permanent_data.endorsementKey); + /* so that Delete's are safe */ + TPM_KeyParms_Init(&keyInfo); /* freed @1 */ + TPM_Pubkey_Init(&pubEndorsementKey); /* freed @2 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* get keyInfo parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_Load(&keyInfo, &command, ¶mSize); /* freed @1 */ + } + /* get generateReset parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadBool(&generateReset, &command, ¶mSize); + } + /* get inputEKreset parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateRevocableEK: generateReset %02x\n", generateReset); + /* an email clarification says that this parameter is still present (but ignored) if + generateReset is TRUE */ + returnCode = TPM_Nonce_Load(inputEKreset, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_CreateRevocableEK: inputEKreset", inputEKreset); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CreateRevocableEK: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. If an EK already exists, return TPM_DISABLED_CMD */ + /* 2. Perform the actions of TPM_CreateEndorsementKeyPair, if any errors return with error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CreateEndorsementKeyPair_Common(endorsementKey, + &pubEndorsementKey, + checksum, + &writeAllNV1, + tpm_state, + &keyInfo, + antiReplay); + } + if (returnCode == TPM_SUCCESS) { + /* 3. Set TPM_PERMANENT_FLAGS -> enableRevokeEK to TRUE */ + TPM_SetCapability_Flag(&writeAllNV1, /* altered */ + &(tpm_state->tpm_permanent_flags.enableRevokeEK), /* flag */ + TRUE); /* value */ + /* a. If generateReset is TRUE then */ + if (generateReset) { + /* i. Set TPM_PERMANENT_DATA -> EKreset to the next value from the TPM RNG */ + returnCode = TPM_Nonce_Generate(tpm_state->tpm_permanent_data.EKReset); + } + /* b. Else */ + else { + /* i. Set TPM_PERMANENT_DATA -> EKreset to inputEkreset */ + TPM_Nonce_Copy(tpm_state->tpm_permanent_data.EKReset, inputEKreset); + } + } + /* save the permanent data and flags structure sto NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + (TPM_BOOL)(writeAllNV1 || writeAllNV2), + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CreateRevocableEK: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 4. Return PUBEK, checksum and Ekreset */ + /* append pubEndorsementKey. */ + returnCode = TPM_Pubkey_Store(response, &pubEndorsementKey); + } + /* append checksum */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Store(response, checksum); + } + /* append outputEKreset */ + /* 5. The outputEKreset authorization is sent in the clear. There is no uniqueness on the + TPM available to actually perform encryption or use an encrypted channel. The assumption + is that this operation is occurring in a controlled environment and sending the value in + the clear is acceptable. + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Store(response, tpm_state->tpm_permanent_data.EKReset); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_KeyParms_Delete(&keyInfo); /* @1 */ + TPM_Pubkey_Delete(&pubEndorsementKey); /* @2 */ + return rcf; +} + +/* 14.1 TPM_CreateEndorsementKeyPair rev 104 + + This command creates the TPM endorsement key. It returns a failure code if an endorsement key + already exists. +*/ + +TPM_RESULT TPM_Process_CreateEndorsementKeyPair(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters*/ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NONCE antiReplay; /* Arbitrary data */ + TPM_KEY_PARMS keyInfo; /* Information about key to be created, this includes all + algorithm parameters */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ + TPM_KEY *endorsementKey = FALSE; /* EK object from permanent store */ + TPM_BOOL writeAllNV1 = FALSE; /* flags to write back data */ + TPM_BOOL writeAllNV2 = FALSE; /* flags to write back flags */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_PUBKEY pubEndorsementKey; /* The public endorsement key */ + TPM_DIGEST checksum; /* Hash of pubEndorsementKey and antiReplay */ + + printf("TPM_Process_CreateEndorsementKeyPair: Ordinal Entry\n"); + /* get pointers */ + endorsementKey = &(tpm_state->tpm_permanent_data.endorsementKey); + /* so that Delete's are safe */ + TPM_KeyParms_Init(&keyInfo); /* freed @1 */ + TPM_Pubkey_Init(&pubEndorsementKey); /* freed @2 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* get keyInfo parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_Load(&keyInfo, &command, ¶mSize); /* freed @1 */ + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CreateEndorsementKeyPair: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CreateEndorsementKeyPair_Common(endorsementKey, + &pubEndorsementKey, + checksum, + &writeAllNV1, + tpm_state, + &keyInfo, + antiReplay); + } + /* 10. Set TPM_PERMANENT_FLAGS -> enableRevokeEK to FALSE */ + if (returnCode == TPM_SUCCESS) { + TPM_SetCapability_Flag(&writeAllNV2, /* altered */ + &(tpm_state->tpm_permanent_flags.enableRevokeEK), /* flag */ + FALSE); /* value */ + } + /* save the permanent data and flags structures to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + (TPM_BOOL)(writeAllNV1 || writeAllNV2), + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CreateEndorsementKeyPair: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + /* append pubEndorsementKey. */ + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + returnCode = TPM_Pubkey_Store(response, &pubEndorsementKey); + } + /* append checksum */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Store(response, checksum); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_KeyParms_Delete(&keyInfo); /* @1 */ + TPM_Pubkey_Delete(&pubEndorsementKey); /* @2 */ + return rcf; +} + +/* TPM_CreateEndorsementKeyPair_Common rev 104 + + Actions common to TPM_CreateEndorsementKeyPair and TPM_CreateRevocableEK + + 'endorsementKey' points to TPM_PERMANENT_DATA -> endorsementKey +*/ + +TPM_RESULT TPM_CreateEndorsementKeyPair_Common(TPM_KEY *endorsementKey, /* output */ + TPM_PUBKEY *pubEndorsementKey, /* output */ + TPM_DIGEST checksum, /* output */ + TPM_BOOL *writePermanentData, /* output */ + tpm_state_t *tpm_state, /* input */ + TPM_KEY_PARMS *keyInfo, /* input */ + TPM_NONCE antiReplay) /* input */ +{ + TPM_RESULT returnCode = TPM_SUCCESS; + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; /* from keyInfo */ + TPM_STORE_BUFFER pubEndorsementKeySerial; /* serialization for checksum calculation */ + const unsigned char *pubEndorsementKeyBuffer; + uint32_t pubEndorsementKeyLength; + + printf("TPM_CreateEndorsementKeyPair_Common:\n"); + TPM_Sbuffer_Init(&pubEndorsementKeySerial); /* freed @1 */ + /* 1. If an EK already exists, return TPM_DISABLED_CMD */ + if (returnCode == TPM_SUCCESS) { + if (endorsementKey->keyUsage != TPM_KEY_UNINITIALIZED) { + printf("TPM_CreateEndorsementKeyPair_Common: Error, key already initialized\n"); + returnCode = TPM_DISABLED_CMD; + } + } + /* 2. Validate the keyInfo parameters for the key description */ + if (returnCode == TPM_SUCCESS) { + /* + RSA + */ + /* a. If the algorithm type is RSA the key length MUST be a minimum of + 2048. For interoperability the key length SHOULD be 2048 */ + if (keyInfo->algorithmID == TPM_ALG_RSA) { + if (returnCode == TPM_SUCCESS) { + /* get the keyInfo TPM_RSA_KEY_PARMS structure */ + returnCode = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, + keyInfo); + } + if (returnCode == TPM_SUCCESS) { + if (tpm_rsa_key_parms->keyLength != TPM_KEY_RSA_NUMBITS) { /* in bits */ + printf("TPM_CreateEndorsementKeyPair_Common: Error, " + "Bad keyLength should be %u, was %u\n", + TPM_KEY_RSA_NUMBITS, tpm_rsa_key_parms->keyLength); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* kgold - Support only 2 primes */ + if (returnCode == TPM_SUCCESS) { + if (tpm_rsa_key_parms->numPrimes != 2) { + printf("TPM_CreateEndorsementKeyPair_Common: Error, " + "Bad numPrimes should be 2, was %u\n", + tpm_rsa_key_parms->numPrimes); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + } + /* + not RSA + */ + /* b. If the algorithm type is other than RSA the strength provided by + the key MUST be comparable to RSA 2048 */ + else { + if (returnCode == TPM_SUCCESS) { + printf("TPM_CreateEndorsementKeyPair_Common: Error, " + "algorithmID %08x not supported\n", + keyInfo->algorithmID); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + } + /* c. The other parameters of keyInfo (encScheme, sigScheme, etc.) are ignored. + */ + /* 3. Create a key pair called the "endorsement key pair" using a TPM-protected capability. The + type and size of key are that indicated by keyInfo. Set encScheme to + TPM_ES_RSAESOAEP_SHA1_MGF1. + + Save the endorsement key in permanent structure. Save the endorsement private key 'd' in the + TPM_KEY structure as encData */ + /* Certain HW TPMs do not ignore the encScheme parameter, and expect it to be + TPM_ES_RSAESOAEP_SHA1_MGF1. Test the value here to detect an application program that will + fail with that TPM. */ + + if (returnCode == TPM_SUCCESS) { + if (keyInfo->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { + returnCode = TPM_BAD_KEY_PROPERTY; + printf("TPM_CreateEndorsementKeyPair_Common: Error, " + "encScheme %08x must be TPM_ES_RSAESOAEP_SHA1_MGF1\n", + keyInfo->encScheme); + } + } + if (returnCode == TPM_SUCCESS) { + keyInfo->sigScheme = TPM_ES_NONE; + returnCode = TPM_Key_GenerateRSA(endorsementKey, + tpm_state, + NULL, /* parent key, indicate root key */ + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + 1, /* TPM_KEY */ + TPM_KEY_STORAGE, /* keyUsage */ + 0, /* keyFlags */ + TPM_AUTH_ALWAYS, /* authDataUsage */ + keyInfo, + NULL, /* no PCR's */ + NULL); /* no PCR's */ + *writePermanentData = TRUE; + } + /* Assemble the TPM_PUBKEY pubEndorsementKey for the response */ + if (returnCode == TPM_SUCCESS) { + /* add TPM_KEY_PARMS algorithmParms */ + returnCode = TPM_KeyParms_Copy(&(pubEndorsementKey->algorithmParms), + keyInfo); + } + if (returnCode == TPM_SUCCESS) { + /* add TPM_SIZED_BUFFER pubKey */ + returnCode = TPM_SizedBuffer_Set(&(pubEndorsementKey->pubKey), + endorsementKey->pubKey.size, + endorsementKey->pubKey.buffer); + } + /* 4. Create checksum by performing SHA-1 on the concatenation of (PUBEK + || antiReplay) */ + if (returnCode == TPM_SUCCESS) { + /* serialize the pubEndorsementKey */ + returnCode = TPM_Pubkey_Store(&pubEndorsementKeySerial, + pubEndorsementKey); + } + if (returnCode == TPM_SUCCESS) { + TPM_Sbuffer_Get(&pubEndorsementKeySerial, + &pubEndorsementKeyBuffer, &pubEndorsementKeyLength); + /* create the checksum */ + returnCode = TPM_SHA1(checksum, + pubEndorsementKeyLength, pubEndorsementKeyBuffer, + sizeof(TPM_NONCE), antiReplay, + 0, NULL); + } + /* 5. Store the PRIVEK */ + /* NOTE Created in TPM_PERMANENT_DATA, call should save to NVRAM */ + /* 6. Create TPM_PERMANENT_DATA -> tpmDAASeed from the TPM RNG */ + /* 7. Create TPM_PERMANENT_DATA -> daaProof from the TPM RNG */ + /* 8. Create TPM_PERMANENT_DATA -> daaBlobKey from the TPM RNG */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PermanentData_InitDaa(&(tpm_state->tpm_permanent_data)); + } + /* 9. Set TPM_PERMANENT_FLAGS -> CEKPUsed to TRUE */ + if (returnCode == TPM_SUCCESS) { + tpm_state->tpm_permanent_flags.CEKPUsed = TRUE; + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&pubEndorsementKeySerial); /* @1 */ + return returnCode; +} + +/* 14.3 TPM_RevokeTrust rev 98 + + This command clears the EK and sets the TPM back to a pure default state. The generation of the + AuthData value occurs during the generation of the EK. It is the responsibility of the EK + generator to properly protect and disseminate the RevokeTrust AuthData. +*/ + +TPM_RESULT TPM_Process_RevokeTrust(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters*/ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NONCE EKReset; /* The value that will be matched to EK Reset */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL writeAllNV1 = FALSE; /* flags to write back data */ + TPM_BOOL writeAllNV2 = FALSE; /* flags to write back flags */ + TPM_BOOL writeAllNV3 = FALSE; /* flags to write back flags */ + TPM_BOOL physicalPresence; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_RevokeTrust: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get EKReset parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Load(EKReset, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour(" TPM_Process_RevokeTrust: EKReset", EKReset); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_RevokeTrust: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM MUST validate that TPM_PERMANENT_FLAGS -> enableRevokeEK is TRUE, return + TPM_PERMANENTEK on error */ + if (returnCode == TPM_SUCCESS) { + if (!tpm_state->tpm_permanent_flags.enableRevokeEK) { + printf("TPM_Process_RevokeTrust: Error, enableRevokeEK is FALSE\n"); + returnCode = TPM_PERMANENTEK; + } + } + /* 2. The TPM MUST validate that the EKReset matches TPM_PERMANENT_DATA -> EKReset, return + TPM_AUTHFAIL on error. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Compare(tpm_state->tpm_permanent_data.EKReset, EKReset); + if (returnCode != 0) { + printf("TPM_Process_RevokeTrust: Error, EKReset mismatch\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* 3. Ensure that physical presence is being asserted */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_RevokeTrust: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + /* 4. Perform the actions of TPM_OwnerClear (excepting the command authentication) */ + /* a. NV items with the pubInfo -> nvIndex D value set MUST be deleted. This changes the + TPM_OwnerClear handling of the same NV areas */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_OwnerClearCommon(tpm_state, + TRUE); /* delete all NVRAM */ + writeAllNV1 = TRUE; + } + if (returnCode == TPM_SUCCESS) { + /* b. Set TPM_PERMANENT_FLAGS -> nvLocked to FALSE */ + TPM_SetCapability_Flag(&writeAllNV2, /* altered (dummy) */ + &(tpm_state->tpm_permanent_flags.nvLocked), /* flag */ + FALSE); /* value */ + /* 5. Invalidate TPM_PERMANENT_DATA -> tpmDAASeed */ + /* 6. Invalidate TPM_PERMANENT_DATA -> daaProof */ + /* 7. Invalidate TPM_PERMANENT_DATA -> daaBlobKey */ + returnCode = TPM_PermanentData_InitDaa(&(tpm_state->tpm_permanent_data)); + } + if (returnCode == TPM_SUCCESS) { + /* 8. Invalidate the EK and any internal state associated with the EK */ + printf("TPM_Process_RevokeTrust: Deleting endorsement key\n"); + TPM_Key_Delete(&(tpm_state->tpm_permanent_data.endorsementKey)); + TPM_SetCapability_Flag(&writeAllNV3, /* altered (dummy) */ + &(tpm_state->tpm_permanent_flags.CEKPUsed), /* flag */ + FALSE); /* value */ + } + /* Store the permanent data and flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV1, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_RevokeTrust: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + return rcf; +} + +/* 27.7 TPM_DisablePubekRead rev 94 + + The TPM Owner may wish to prevent any entity from reading the PUBEK. This command sets the + non-volatile flag so that the TPM_ReadPubek command always returns TPM_DISABLED_CMD. + + This commands has in essence been deprecated as TPM_TakeOwnership now sets the value to false. + The commands remains at this time for backward compatibility. +*/ + +TPM_RESULT TPM_Process_DisablePubekRead(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters*/ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner + authorization. HMAC key: ownerAuth. */ + + /* processing */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_DisablePubekRead: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DisablePubekRead: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* Verify that the TPM Owner authorizes the command and all of the input, on error return + TPM_AUTHFAIL. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 1. This capability sets the TPM_PERMANENT_FLAGS -> readPubek flag to FALSE. */ + if (returnCode == TPM_SUCCESS) { + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.readPubek), /* flag */ + FALSE); /* value */ + printf("TPM_Process_DisablePubekRead: readPubek now %02x\n", + tpm_state->tpm_permanent_flags.readPubek); + /* save the permanent flags structure to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DisablePubekRead: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + /* no outParam's, set authorization response data */ + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + return rcf; +} + +/* 27.6 TPM_OwnerReadPubek rev 94 + + Return the endorsement key public portion. This is authorized by the TPM Owner. +*/ + +TPM_RESULT TPM_Process_OwnerReadPubek(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters*/ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner + authorization. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + const unsigned char *pubEndorsementKeyStreamBuffer; + uint32_t pubEndorsementKeyStreamLength; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORE_BUFFER pubEndorsementKeyStream; /* The public endorsement key */ + + printf("TPM_Process_OwnerReadPubek: Ordinal Entry\n"); + TPM_Sbuffer_Init(&pubEndorsementKeyStream); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_OwnerReadPubek: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the TPM Owner authorization to execute this command */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* serialize the TPM_PUBKEY components of the EK */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_Key_StorePubkey(&pubEndorsementKeyStream, /* output */ + &pubEndorsementKeyStreamBuffer, /* output */ + &pubEndorsementKeyStreamLength, /* output */ + &(tpm_state->tpm_permanent_data.endorsementKey)); /* input */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_OwnerReadPubek: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 2. Export the PUBEK */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append(response, + pubEndorsementKeyStreamBuffer, + pubEndorsementKeyStreamLength); + } + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + /* no outParam's, set authorization response data */ + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&pubEndorsementKeyStream); /* @1 */ + return rcf; +} + +/* 27.1.1 TPM_EvictKey rev 87 + + The key commands are deprecated as the new way to handle keys is to use the standard context + commands. So TPM_EvictKey is now handled by TPM_FlushSpecific, TPM_TerminateHandle by + TPM_FlushSpecific. + + The TPM will invalidate the key stored in the specified handle and return the space to the + available internal pool for subsequent query by TPM_GetCapability and usage by TPM_LoadKey. If + the specified key handle does not correspond to a valid key, an error will be returned. +*/ + +TPM_RESULT TPM_Process_EvictKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters*/ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE evictHandle; /* The handle of the key to be evicted. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* table entry for the evictHandle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_EvictKey: Ordinal Entry\n"); + /* + get inputs + */ + /* get evictHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&evictHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_EvictKey: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* New 1.2 functionality + The command must check the status of the ownerEvict flag for the key and if the flag is TRUE + return TPM_KEY_CONTROL_OWNER + */ + /* evict the key stored in the specified handle */ + /* get the TPM_KEY_HANDLE_ENTRY */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_EvictKey: Evicting handle %08x\n", evictHandle); + returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_state->tpm_key_handle_entries, + evictHandle); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_EvictKey: Error, key handle %08x not found\n", + evictHandle); + } + } + /* If tpm_key_handle_entry -> ownerEvict is TRUE return TPM_KEY_OWNER_CONTROL */ + if (returnCode == TPM_SUCCESS) { + if (tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) { + printf("TPM_Process_EvictKey: Error, keyHandle specifies owner evict\n"); + returnCode = TPM_KEY_OWNER_CONTROL; + } + } + /* delete the entry, delete the key structure, and free the key */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntry_FlushSpecific(tpm_state, tpm_key_handle_entry); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_EvictKey: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 14.5 TPM_OwnerReadInternalPub rev 87 + + A TPM Owner authorized command that returns the public portion of the EK or SRK. + + The keyHandle parameter is included in the incoming session authorization to prevent + alteration of the value, causing a different key to be read. Unlike most key handles, which + can be mapped by higher layer software, this key handle has only two fixed values. + +*/ + +TPM_RESULT TPM_Process_OwnerReadInternalPub(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* of remaining parameters */ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* Handle for either PUBEK or SRK */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner + authentication. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_KEY *readKey = NULL; /* key to be read back */ + const unsigned char *stream; + uint32_t stream_size; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_OwnerReadInternalPub: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + /* NOTE: This is a special case, where the keyHandle is part of the HMAC calculation to + avoid a man-in-the-middle privacy attack that replaces the SRK handle with the EK + handle. */ + inParamStart = command; + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OwnerReadInternalPub: keyHandle %08x\n", keyHandle); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_OwnerReadInternalPub: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the parameters and TPM Owner AuthData for this command */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + if (returnCode == TPM_SUCCESS) { + /* 2. If keyHandle is TPM_KH_EK */ + if (keyHandle == TPM_KH_EK) { + /* a. Set publicPortion to PUBEK */ + printf("TPM_Process_OwnerReadInternalPub: Reading EK\n"); + readKey = &(tpm_state->tpm_permanent_data.endorsementKey); + } + /* 3. Else If keyHandle is TPM_KH_SRK */ + else if (keyHandle == TPM_KH_SRK) { + /* a. Set publicPortion to the TPM_PUBKEY of the SRK */ + printf("TPM_Process_OwnerReadInternalPub: Reading SRK\n"); + readKey = &(tpm_state->tpm_permanent_data.srk); + } + /* 4. Else return TPM_BAD_PARAMETER */ + else { + printf("TPM_Process_OwnerReadInternalPub: Error, invalid keyHandle %08x\n", + keyHandle); + returnCode = TPM_BAD_PARAMETER; + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_OwnerReadInternalPub: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 5. Export the public key of the referenced key */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_StorePubkey(response, &stream, &stream_size, readKey); + } + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + /* no outParam's, set authorization response data */ + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + + diff --git a/src/tpm12/tpm_key.h b/src/tpm12/tpm_key.h new file mode 100644 index 0000000..627233e --- /dev/null +++ b/src/tpm12/tpm_key.h @@ -0,0 +1,457 @@ +/********************************************************************************/ +/* */ +/* Key Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_key.h 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_KEY_H +#define TPM_KEY_H + +#include "tpm_global.h" +#include "tpm_store.h" +#include "tpm_structures.h" + +#define TPM_KEY_RSA_NUMBITS 2048 + +extern unsigned char tpm_default_rsa_exponent[]; + +/* TPM_KEY */ + +void TPM_Key_Init(TPM_KEY *tpm_key); +void TPM_Key_InitTag12(TPM_KEY *tpm_key); + +TPM_RESULT TPM_Key_Load(TPM_KEY *tpm_key, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Key_LoadPubData(TPM_KEY *tpm_key, + TPM_BOOL isEK, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Key_LoadClear(TPM_KEY *tpm_key, + TPM_BOOL isEK, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Key_Store(TPM_STORE_BUFFER *sbuffer, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_StorePubData(TPM_STORE_BUFFER *sbuffer, + TPM_BOOL isEK, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_StoreClear(TPM_STORE_BUFFER *sbuffer, + TPM_BOOL isEK, + TPM_KEY *tpm_key); + +void TPM_Key_Delete(TPM_KEY *tpm_key); + +TPM_RESULT TPM_Key_CheckStruct(int *ver, TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_Set(TPM_KEY *tpm_key, + tpm_state_t *tpm_state, + TPM_KEY *parent_key, + TPM_DIGEST *tpm_pcrs, + int ver, + TPM_KEY_USAGE keyUsage, + TPM_KEY_FLAGS keyFlags, + TPM_AUTH_DATA_USAGE authDataUsage, + TPM_KEY_PARMS *tpm_key_parms, + TPM_PCR_INFO *tpm_pcr_info, + TPM_PCR_INFO_LONG *tpm_pcr_info_long, + uint32_t keyLength, + BYTE* publicKey, + TPM_STORE_ASYMKEY *tpm_store_asymkey, + TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey); +TPM_RESULT TPM_Key_Copy(TPM_KEY *tpm_key_dest, + TPM_KEY *tpm_key_src, + TPM_BOOL copyEncData); +TPM_RESULT TPM_Key_LoadStoreAsymKey(TPM_KEY *tpm_key, + TPM_BOOL isEK, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Key_StorePubkey(TPM_STORE_BUFFER *pubkeyStream, + const unsigned char **pubkKeyStreamBuffer, + uint32_t *pubkeyStreamLength, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_GenerateRSA(TPM_KEY *tpm_key, + tpm_state_t *tpm_state, + TPM_KEY *parent_key, + TPM_DIGEST *tpm_pcrs, + int ver, + TPM_KEY_USAGE keyUsage, + TPM_KEY_FLAGS keyFlags, + TPM_AUTH_DATA_USAGE authDataUsage, + TPM_KEY_PARMS *tpm_key_parms, + TPM_PCR_INFO *tpm_pcr_info, + TPM_PCR_INFO_LONG *tpm_pcr_info_long); + +TPM_RESULT TPM_Key_GeneratePubDataDigest(TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_GeneratePubkeyDigest(TPM_DIGEST tpm_digest, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_ComparePubkey(TPM_KEY *tpm_key, + TPM_PUBKEY *tpm_pubkey); + +TPM_RESULT TPM_Key_CheckPubDataDigest(TPM_KEY *tpm_key); + +TPM_RESULT TPM_Key_GenerateEncData(TPM_KEY *tpm_key, + TPM_KEY *parent_key); +TPM_RESULT TPM_Key_DecryptEncData(TPM_KEY *tpm_key, + TPM_KEY *parent_key); + +TPM_RESULT TPM_Key_GetStoreAsymkey(TPM_STORE_ASYMKEY **tpm_store_asymkey, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_GetMigrateAsymkey(TPM_MIGRATE_ASYMKEY **tpm_migrate_asymkey, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_GetUsageAuth(TPM_SECRET **usageAuth, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_GetPublicKey(uint32_t *nbytes, + unsigned char **narr, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_GetPrimeFactorP(uint32_t *pbytes, + unsigned char **parr, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_GetPrivateKey(uint32_t *dbytes, + unsigned char **darr, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_GetExponent(uint32_t *ebytes, + unsigned char **earr, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_CheckProperties(int *ver, + TPM_KEY *tpm_key, + uint32_t keyLength, + TPM_BOOL FIPS); +TPM_RESULT TPM_Key_GetPCRUsage(TPM_BOOL *pcrUsage, + TPM_KEY *tpm_key, + size_t start_index); +TPM_RESULT TPM_Key_GetLocalityAtRelease(TPM_LOCALITY_SELECTION *localityAtRelease, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Key_CheckPCRDigest(TPM_KEY *tpm_key, + tpm_state_t *tpm_state); +TPM_RESULT TPM_Key_CheckRestrictDelegate(TPM_KEY *tpm_key, + TPM_CMK_DELEGATE restrictDelegate); + +/* + TPM_KEY_FLAGS +*/ + +TPM_RESULT TPM_KeyFlags_Load(TPM_KEY_FLAGS *tpm_key_flags, + unsigned char **stream, + uint32_t *stream_size); + +/* + TPM_KEY_PARMS +*/ + +void TPM_KeyParms_Init(TPM_KEY_PARMS *tpm_key_parms); +TPM_RESULT TPM_KeyParms_Set(TPM_KEY_PARMS *tpm_key_parms, + TPM_ALGORITHM_ID algorithmID, + TPM_ENC_SCHEME encScheme, + TPM_SIG_SCHEME sigScheme, + uint32_t parmSize, + BYTE* parms); +#if 0 +TPM_RESULT TPM_KeyParms_SetRSA(TPM_KEY_PARMS *tpm_key_parms, + TPM_ALGORITHM_ID algorithmID, + TPM_ENC_SCHEME encScheme, + TPM_SIG_SCHEME sigScheme, + uint32_t keyLength, + TPM_SIZED_BUFFER *exponent); +#endif +TPM_RESULT TPM_KeyParms_Copy(TPM_KEY_PARMS *tpm_key_parms_dest, + TPM_KEY_PARMS *tpm_key_parms_src); +TPM_RESULT TPM_KeyParms_Load(TPM_KEY_PARMS *tpm_key_parms, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_KeyParms_Store(TPM_STORE_BUFFER *sbuffer, + TPM_KEY_PARMS *tpm_key_parms); +void TPM_KeyParms_Delete(TPM_KEY_PARMS *tpm_key_parms); +TPM_RESULT TPM_KeyParms_GetRSAKeyParms(TPM_RSA_KEY_PARMS **tpm_rsa_key_parms, + TPM_KEY_PARMS *tpm_key_parms); +TPM_RESULT TPM_KeyParms_GetExponent(uint32_t *ebytes, + unsigned char **earr, + TPM_KEY_PARMS *tpm_key_parms); +TPM_RESULT TPM_KeyParms_CheckProperties(TPM_KEY_PARMS *tpm_key_parms, + TPM_KEY_USAGE tpm_key_usage, + uint32_t keyLength, + TPM_BOOL FIPS); +TPM_RESULT TPM_KeyParams_CheckDefaultExponent(TPM_SIZED_BUFFER *exponent); + +/* + TPM_PUBKEY +*/ + +void TPM_Pubkey_Init(TPM_PUBKEY *tpm_pubkey); +TPM_RESULT TPM_Pubkey_Load(TPM_PUBKEY *tpm_pubkey, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Pubkey_Store(TPM_STORE_BUFFER *sbuffer, + TPM_PUBKEY *tpm_pubkey); +void TPM_Pubkey_Delete(TPM_PUBKEY *tpm_pubkey); + +TPM_RESULT TPM_Pubkey_Set(TPM_PUBKEY *tpm_pubkey, + TPM_KEY *tpm_key); +TPM_RESULT TPM_Pubkey_Copy(TPM_PUBKEY *dest_tpm_pubkey, + TPM_PUBKEY *src_tpm_pubkey); +TPM_RESULT TPM_Pubkey_GetExponent(uint32_t *ebytes, + unsigned char **earr, + TPM_PUBKEY *tpm_pubkey); +TPM_RESULT TPM_Pubkey_GetPublicKey(uint32_t *nbytes, + unsigned char **narr, + TPM_PUBKEY *tpm_pubkey); + +/* + TPM_KEY_HANDLE_ENTRY +*/ + +void TPM_KeyHandleEntry_Init(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); +TPM_RESULT TPM_KeyHandleEntry_Load(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_KeyHandleEntry_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); +void TPM_KeyHandleEntry_Delete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); + +TPM_RESULT TPM_KeyHandleEntry_FlushSpecific(tpm_state_t *tpm_state, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); + +/* + TPM_KEY_HANDLE_ENTRY entries list +*/ + +void TPM_KeyHandleEntries_Init(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); +void TPM_KeyHandleEntries_Delete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); + +TPM_RESULT TPM_KeyHandleEntries_Load(tpm_state_t *tpm_state, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_KeyHandleEntries_Store(TPM_STORE_BUFFER *sbuffer, + tpm_state_t *tpm_state); + +TPM_RESULT TPM_KeyHandleEntries_StoreHandles(TPM_STORE_BUFFER *sbuffer, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); +TPM_RESULT TPM_KeyHandleEntries_DeleteHandle(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + TPM_KEY_HANDLE tpm_key_handle); + +void TPM_KeyHandleEntries_IsSpace(TPM_BOOL *isSpace, uint32_t *index, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); +void TPM_KeyHandleEntries_GetSpace(uint32_t *space, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); +void TPM_KeyHandleEntries_IsEvictSpace(TPM_BOOL *isSpace, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + uint32_t minSpace); +TPM_RESULT TPM_KeyHandleEntries_AddKeyEntry(TPM_KEY_HANDLE *tpm_key_handle, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + TPM_KEY *tpm_key, + TPM_BOOL parentPCRStatus, + TPM_KEY_CONTROL keyControl); +TPM_RESULT TPM_KeyHandleEntries_AddEntry(TPM_KEY_HANDLE *tpm_key_handle, + TPM_BOOL keepHandle, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); +TPM_RESULT TPM_KeyHandleEntries_GetEntry(TPM_KEY_HANDLE_ENTRY **tpm_key_handle_entry, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + TPM_KEY_HANDLE tpm_key_handle); +TPM_RESULT TPM_KeyHandleEntries_GetKey(TPM_KEY **tpm_key, + TPM_BOOL *parentPCRStatus, + tpm_state_t *tpm_state, + TPM_KEY_HANDLE tpm_key_handle, + TPM_BOOL readOnly, + TPM_BOOL ignorePCRs, + TPM_BOOL allowEK); +TPM_RESULT TPM_KeyHandleEntries_SetParentPCRStatus(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + TPM_KEY_HANDLE tpm_key_handle, + TPM_BOOL parentPCRStatus); +TPM_RESULT TPM_KeyHandleEntries_GetNextEntry(TPM_KEY_HANDLE_ENTRY **tpm_key_handle_entry, + size_t *current, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + size_t start); + +TPM_RESULT TPM_KeyHandleEntries_OwnerEvictLoad(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + unsigned char **stream, uint32_t *stream_size); +TPM_RESULT TPM_KeyHandleEntries_OwnerEvictStore(TPM_STORE_BUFFER *sbuffer, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); +TPM_RESULT TPM_KeyHandleEntries_OwnerEvictGetCount(uint16_t *count, + const TPM_KEY_HANDLE_ENTRY + *tpm_key_handle_entries); +void TPM_KeyHandleEntries_OwnerEvictDelete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); + +/* TPM_RSA_KEY_PARMS */ + +void TPM_RSAKeyParms_Init(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms); +TPM_RESULT TPM_RSAKeyParms_Load(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_RSAKeyParms_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_RSA_KEY_PARMS *tpm_rsa_key_parms); +void TPM_RSAKeyParms_Delete(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms); + +TPM_RESULT TPM_RSAKeyParms_Copy(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms_dest, + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms_src); +TPM_RESULT TPM_RSAKeyParms_New(TPM_RSA_KEY_PARMS **tpm_rsa_key_parms); +TPM_RESULT TPM_RSAKeyParms_GetExponent(uint32_t *ebytes, + unsigned char **earr, + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms); + +/* TPM_STORE_ASYMKEY */ + +void TPM_StoreAsymkey_Init(TPM_STORE_ASYMKEY *tpm_store_asymkey); +TPM_RESULT TPM_StoreAsymkey_Load(TPM_STORE_ASYMKEY *tpm_store_asymkey, + TPM_BOOL isEK, + unsigned char **stream, + uint32_t *stream_size, + TPM_KEY_PARMS *tpm_key_parms, + TPM_SIZED_BUFFER *tpm_store_pubkey); +TPM_RESULT TPM_StoreAsymkey_Store(TPM_STORE_BUFFER *sbuffer, + TPM_BOOL isEK, + const TPM_STORE_ASYMKEY *tpm_store_asymkey); +void TPM_StoreAsymkey_Delete(TPM_STORE_ASYMKEY *tpm_store_asymkey); + +TPM_RESULT TPM_StoreAsymkey_GenerateEncData(TPM_SIZED_BUFFER *encData, + TPM_STORE_ASYMKEY *tpm_store_asymkey, + TPM_KEY *parent_key); +TPM_RESULT TPM_StoreAsymkey_GetPrimeFactorP(uint32_t *pbytes, + unsigned char **parr, + TPM_STORE_ASYMKEY *tpm_store_asymkey); +void TPM_StoreAsymkey_GetO1Size(uint32_t *o1_size, + TPM_STORE_ASYMKEY *tpm_store_asymkey); +TPM_RESULT TPM_StoreAsymkey_CheckO1Size(uint32_t o1_size, + uint32_t k1k2_length); +TPM_RESULT TPM_StoreAsymkey_StoreO1(BYTE *o1, + uint32_t o1_size, + TPM_STORE_ASYMKEY *tpm_store_asymkey, + TPM_DIGEST pHash, + TPM_PAYLOAD_TYPE payload_type, + TPM_SECRET usageAuth); +TPM_RESULT TPM_StoreAsymkey_LoadO1(TPM_STORE_ASYMKEY *tpm_store_asymkey, + BYTE *o1, + uint32_t o1_size); + +/* TPM_MIGRATE_ASYMKEY */ + +void TPM_MigrateAsymkey_Init(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey); +TPM_RESULT TPM_MigrateAsymkey_Load(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_MigrateAsymkey_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey); +void TPM_MigrateAsymkey_Delete(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey); + +/* + TPM_STORE_PRIVKEY +*/ + +void TPM_StorePrivkey_Init(TPM_STORE_PRIVKEY *tpm_store_privkey); +TPM_RESULT TPM_StorePrivkey_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_STORE_PRIVKEY *tpm_store_privkey); +void TPM_StorePrivkey_Delete(TPM_STORE_PRIVKEY *tpm_store_privkey); + +TPM_RESULT TPM_StorePrivkey_Convert(TPM_STORE_ASYMKEY *tpm_store_asymkey, + TPM_KEY_PARMS *tpm_key_parms, + TPM_SIZED_BUFFER *pubKey); + + +/* Command Processing Functions */ + + +TPM_RESULT TPM_Process_ReadPubek(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_CreateRevocableEK(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_CreateEndorsementKeyPair(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_CreateEndorsementKeyPair_Common(TPM_KEY *endorsementKey, + TPM_PUBKEY *pubEndorsementKey, + TPM_DIGEST checksum, + TPM_BOOL *writePermanentData, + tpm_state_t *tpm_state, + TPM_KEY_PARMS *keyInfo, + TPM_NONCE antiReplay); + +TPM_RESULT TPM_Process_RevokeTrust(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_DisablePubekRead(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_OwnerReadPubek(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_EvictKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_OwnerReadInternalPub(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +#endif diff --git a/src/tpm12/tpm_libtpms_io.c b/src/tpm12/tpm_libtpms_io.c new file mode 100644 index 0000000..dfb5646 --- /dev/null +++ b/src/tpm12/tpm_libtpms_io.c @@ -0,0 +1,70 @@ +/********************************************************************************/ +/* */ +/* Libtpms IO Init */ +/* Written by Ken Goldman, Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_io.c 4564 2011-04-13 19:33:38Z stefanb $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_platform.h" +#include "tpm_types.h" + +#include "tpm_library_intern.h" + +/* header for this file */ +#include "tpm_io.h" + +/* TPM_IO_Init initializes the TPM to host interface. + + This is the Unix platform dependent socket version. +*/ + +TPM_RESULT TPM_IO_Init(void) +{ + TPM_RESULT rc = 0; + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + /* call user-provided function if available */ + if (cbs->tpm_io_init) { + rc = cbs->tpm_io_init(); + return rc; + } else { + /* Below code would start a TCP server socket; we don't want this + but rather expect all commands via TPMLIB_Process() to be sent + to the TPM. */ + return TPM_SUCCESS; + } +} diff --git a/src/tpm12/tpm_load.c b/src/tpm12/tpm_load.c new file mode 100644 index 0000000..b534eee --- /dev/null +++ b/src/tpm12/tpm_load.c @@ -0,0 +1,309 @@ +/********************************************************************************/ +/* */ +/* Load from Stream Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_load.c 4668 2012-01-25 21:16:48Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* Generally useful utilities to deserialize structures from a stream */ + +#include +#include +#include + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_sizedbuffer.h" +#include "tpm_types.h" + +#include "tpm_load.h" + +/* The LOADn() functions convert a big endian stream to integer types */ + +uint32_t LOAD32(const unsigned char *buffer, unsigned int offset) +{ + unsigned int i; + uint32_t result = 0; + + for (i = 0 ; i < 4 ; i++) { + result <<= 8; + result |= buffer[offset + i]; + } + return result; +} + +uint16_t LOAD16(const unsigned char *buffer, unsigned int offset) +{ + unsigned int i; + uint16_t result = 0; + + for (i = 0 ; i < 2 ; i++) { + result <<= 8; + result |= buffer[offset + i]; + } + return result; +} + +uint8_t LOAD8(const unsigned char *buffer, unsigned int offset) +{ + uint8_t result = 0; + + result |= buffer[offset]; + return result; +} + +/* TPM_Load32() loads 'tpm_uint32' from the stream. + + It checks that the stream has sufficient data, and adjusts 'stream' + and 'stream_size' past the data. +*/ + +TPM_RESULT TPM_Load32(uint32_t *tpm_uint32, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + /* check stream_size */ + if (rc == 0) { + if (*stream_size < sizeof(uint32_t)) { + printf("TPM_Load32: Error, stream_size %u less than %lu\n", + *stream_size, (unsigned long)sizeof(uint32_t)); + rc = TPM_BAD_PARAM_SIZE; + } + } + /* load the parameter */ + if (rc == 0) { + *tpm_uint32 = LOAD32(*stream, 0); + *stream += sizeof (uint32_t); + *stream_size -= sizeof (uint32_t); + } + return rc; +} + +/* TPM_Load16() loads 'tpm_uint16' from the stream. + + It checks that the stream has sufficient data, and adjusts 'stream' + and 'stream_size' past the data. +*/ + +TPM_RESULT TPM_Load16(uint16_t *tpm_uint16, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + /* check stream_size */ + if (rc == 0) { + if (*stream_size < sizeof(uint16_t)) { + printf("TPM_Load16: Error, stream_size %u less than %lu\n", + *stream_size, (unsigned long)sizeof(uint16_t)); + rc = TPM_BAD_PARAM_SIZE; + } + } + /* load the parameter */ + if (rc == 0) { + *tpm_uint16 = LOAD16(*stream, 0); + *stream += sizeof (uint16_t); + *stream_size -= sizeof (uint16_t); + } + return rc; +} + +TPM_RESULT TPM_Load8(uint8_t *tpm_uint8, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + /* check stream_size */ + if (rc == 0) { + if (*stream_size < sizeof(uint8_t)) { + printf("TPM_Load8: Error, stream_size %u less than %lu\n", + *stream_size, (unsigned long)sizeof(uint8_t)); + rc = TPM_BAD_PARAM_SIZE; + } + } + /* load the parameter */ + if (rc == 0) { + *tpm_uint8 = LOAD8(*stream, 0); + *stream += sizeof (uint8_t); + *stream_size -= sizeof (uint8_t); + } + return rc; +} + +/* Boolean incoming parameter values other than 0x00 and 0x01 have an implementation specific + interpretation. The TPM SHOULD return TPM_BAD_PARAMETER. +*/ + +TPM_RESULT TPM_LoadBool(TPM_BOOL *tpm_bool, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + /* check stream_size */ + if (rc == 0) { + if (*stream_size < sizeof(TPM_BOOL)) { + printf("TPM_LoadBool: Error, stream_size %u less than %lu\n", + *stream_size, (unsigned long)sizeof(TPM_BOOL)); + rc = TPM_BAD_PARAM_SIZE; + } + } + /* load the parameter */ + if (rc == 0) { + *tpm_bool = LOAD8(*stream, 0); + *stream += sizeof (uint8_t); + *stream_size -= sizeof (uint8_t); + } + if (rc == 0) { + if ((*tpm_bool != TRUE) && (*tpm_bool != FALSE)) { + printf("TPM_LoadBool: Error, illegal value %02x\n", *tpm_bool); + rc = TPM_BAD_PARAMETER; + } + } + return rc; +} + +/* TPM_Loadn() copies 'data_length' bytes from 'stream' to 'data' with + no endian adjustments. */ + +TPM_RESULT TPM_Loadn(BYTE *data, + size_t data_length, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + /* check stream_size */ + if (rc == 0) { + if (*stream_size < data_length) { + printf("TPM_Loadn: Error, stream_size %u less than %lu\n", + *stream_size, (unsigned long)data_length); + rc = TPM_BAD_PARAM_SIZE; + } + } + /* load the parameter */ + if (rc == 0) { + memcpy(data, *stream, data_length); + *stream += data_length; + *stream_size -= data_length; + } + return rc; +} + +/* TPM_LoadLong() creates a long from a stream in network byte order. + + The stream is not advanced. +*/ + +TPM_RESULT TPM_LoadLong(unsigned long *result, + const unsigned char *stream, + uint32_t stream_size) +{ + TPM_RESULT rc = 0; + size_t i; /* byte iterator */ + + printf(" TPM_LoadLong:\n"); + if (rc == 0) { + if (stream_size > sizeof(unsigned long)) { + printf(" TPM_LoadLong: Error, stream size %u too large\n", stream_size); + rc = TPM_BAD_PARAM_SIZE; + } + } + if (rc == 0) { + *result = 0; /* initialize all bytes to 0 in case buffer is less than sizeof(unsigned + long) bytes */ + for (i = 0 ; i < stream_size ; i++) { + /* copy big endian stream, put lowest address in an upper byte, highest address in byte + 0 */ + *result |= (unsigned long)(((unsigned long)stream[i]) << ((stream_size - 1 - i) * 8)); + } + printf(" TPM_LoadLong: Result %08lx\n", *result); + } + return rc; +} + +#if 0 +/* TPM_LoadString() returns a pointer to a C string. It does not copy the string. + + */ + +TPM_RESULT TPM_LoadString(const char **name, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + char *ptr; + + *name = NULL; + /* search for the first nul character */ + if (rc == 0) { + ptr = memchr(*stream, (int)'\0', *stream_size); + if (ptr == NULL) { + rc = TPM_BAD_PARAM_SIZE; + } + } + if (rc == 0) { + *name = (char *)*stream; /* cast because converting binary to string */ + *stream_size -= (ptr - *name) + 1; + *stream = (unsigned char *)ptr + 1; + } + return rc; +} +#endif + +/* TPM_CheckTag() loads a TPM_STRUCTURE_TAG from 'stream'. It check that the value is 'expectedTag' + and returns TPM_INVALID_STRUCTURE on error. + +*/ + +TPM_RESULT TPM_CheckTag(TPM_STRUCTURE_TAG expectedTag, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + TPM_STRUCTURE_TAG tag; + + if (rc == 0) { + rc = TPM_Load16(&tag, stream, stream_size); + } + if (rc == 0) { + if (tag != expectedTag) { + printf("TPM_CheckTag: Error, tag expected %04x found %04hx\n", expectedTag, tag); + rc = TPM_INVALID_STRUCTURE; + } + } + return rc; +} + diff --git a/src/tpm12/tpm_load.h b/src/tpm12/tpm_load.h new file mode 100644 index 0000000..08336cd --- /dev/null +++ b/src/tpm12/tpm_load.h @@ -0,0 +1,80 @@ +/********************************************************************************/ +/* */ +/* Load from Stream Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_load.h 4668 2012-01-25 21:16:48Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_LOAD_H +#define TPM_LOAD_H + +#include "tpm_types.h" + +TPM_RESULT TPM_Load32(uint32_t *tpm_uint32, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Load16(uint16_t *tpm_uint16, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Load8(uint8_t *tpm_uint8, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Loadn(BYTE *data, + size_t data_length, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_LoadBool(TPM_BOOL *tpm_bool, + unsigned char **stream, + uint32_t *stream_size); + +TPM_RESULT TPM_LoadLong(unsigned long *result, + const unsigned char *stream, + uint32_t stream_size); +#if 0 +TPM_RESULT TPM_LoadString(const char **name, + unsigned char **stream, + uint32_t *stream_size); +#endif +TPM_RESULT TPM_CheckTag(TPM_STRUCTURE_TAG expectedTag, + unsigned char **stream, + uint32_t *stream_size); + +/* byte stream to type */ + +uint32_t LOAD32(const unsigned char *buffer, unsigned int offset); +uint16_t LOAD16(const unsigned char *buffer, unsigned int offset); +uint8_t LOAD8(const unsigned char *buffer, unsigned int offset); + +#endif diff --git a/src/tpm12/tpm_maint.c b/src/tpm12/tpm_maint.c new file mode 100644 index 0000000..98753a2 --- /dev/null +++ b/src/tpm12/tpm_maint.c @@ -0,0 +1,1304 @@ +/********************************************************************************/ +/* */ +/* Maintenance Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_maint.c 4442 2011-02-14 20:20:01Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#if !defined(TPM_NOMAINTENANCE) && !defined(TPM_NOMAINTENANCE_COMMANDS) + +#include +#include + +#include "tpm_auth.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_owner.h" +#include "tpm_permanent.h" +#include "tpm_process.h" + +#include "tpm_maint.h" + +/* + Processing Functions +*/ + +/* 12. Maintenance Functions (optional) + + The maintenance mechanisms in the TPM MUST not require the TPM to hold a global secret. The + definition of global secret is a secret value shared by more than one TPM. + + The TPME is not allowed to pre-store or use unique identifiers in the TPM for the purpose of + maintenance. The TPM MUST NOT use the endorsement key for identification or encryption in the + maintenance process. The maintenance process MAY use a TPM Identity to deliver maintenance + information to specific TPM's. + + The maintenance process can only change the SRK, tpmProof and TPM Owner AuthData fields. + + The maintenance process can only access data in shielded locations where this data is necessary + to validate the TPM Owner, validate the TPME and manipulate the blob + + The TPM MUST be conformant to the TPM specification, protection profiles and security targets + after maintenance. The maintenance MAY NOT decrease the security values from the original + security target. + + The security target used to evaluate this TPM MUST include this command in the TOE. +*/ + +/* When a maintenance archive is created with generateRandom FALSE, the maintenance blob is XOR + encrypted with the owner authorization before encryption with the maintenance public key. This + prevents the manufacturer from obtaining plaintext data. The receiving TPM must have the same + owner authorization as the sending TPM in order to XOR decrypt the archive. + + When generateRandom is TRUE, the maintenance blob is XOR encrypted with random data, which is + also returned. This permits someone trusted by the Owner to load the maintenance archive into the + replacement platform in the absence of the Owner and manufacturer, without the Owner having to + reveal information about his auth value. The receiving and sending TPM's may have different owner + authorizations. The random data is transferred from the sending TPM owner to the receiving TPM + owner out of band, so the maintenance blob remains hidden from the manufacturer. + + This is a typical maintenance sequence: + 1. Manufacturer: + - generates maintenance key pair + - gives public key to TPM1 owner + 2. TPM1: TPM_LoadManuMaintPub + - load maintenance public key + 3. TPM1: TPM_CreateMaintenanceArchive + - XOR encrypt with owner auth or random + - encrypt with maintenance public key + 4. Manufacturer: + - decrypt with maintenance private key + - (still XOR encrypted with owner auth or random) + - encrypt with TPM2 SRK public key + 5. TPM2: TPM_LoadMaintenanceArchive + - decrypt with SRK private key + - XOR decrypt with owner auth or random +*/ + +/* 12.1 TPM_CreateMaintenanceArchive rev 101 + + This command creates the MaintenanceArchive. It can only be executed by the owner, and may be + shut off with the TPM_KillMaintenanceFeature command. +*/ + +TPM_RESULT TPM_Process_CreateMaintenanceArchive(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_BOOL generateRandom; /* Use RNG or Owner auth to generate 'random'. */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner + authentication. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey = NULL; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + uint32_t o1Oaep_size; + BYTE *o1Oaep; + BYTE *r1InnerWrapKey; + BYTE *x1InnerWrap; + TPM_KEY a1; /* SRK archive result */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER random; /* Random data to XOR with result. */ + TPM_STORE_BUFFER archive; /* Encrypted key archive. */ + + printf("TPM_Process_CreateMaintenanceArchive: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&random); /* freed @1 */ + TPM_Key_Init(&a1); /* freed @2 */ + TPM_Sbuffer_Init(&archive); /* freed @3 */ + o1Oaep = NULL; /* freed @4 */ + r1InnerWrapKey = NULL; /* freed @5 */ + x1InnerWrap = NULL; /* freed @6 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get generateRandom parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadBool(&generateRandom, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CreateMaintenanceArchive: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* Upon authorization being confirmed this command does the following: */ + /* 1. Validates that the TPM_PERMANENT_FLAGS -> AllowMaintenance is TRUE. If it is FALSE, the + TPM SHALL return TPM_DISABLED_CMD and exit this capability. */ + if (returnCode == TPM_SUCCESS) { + if (!tpm_state->tpm_permanent_flags.allowMaintenance) { + printf("TPM_Process_CreateMaintenanceArchive: Error allowMaintenance FALSE\n"); + returnCode = TPM_DISABLED_CMD; + } + } + /* 2. Validates the TPM Owner AuthData. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 3. If the value of TPM_PERMANENT_DATA -> ManuMaintPub is zero, the TPM MUST return the error + code TPM_KEYNOTFOUND */ + if (returnCode == TPM_SUCCESS) { + /* since there is no keyUsage, algorithmID seems like a way to check for an empty key */ + if (tpm_state->tpm_permanent_data.manuMaintPub.algorithmParms.algorithmID != TPM_ALG_RSA) { + printf("TPM_Process_CreateMaintenanceArchive: manuMaintPub key not found\n"); + returnCode = TPM_KEYNOTFOUND; + } + } + /* 4. Build a1 a TPM_KEY structure using the SRK. The encData field is not a normal + TPM_STORE_ASYMKEY structure but rather a TPM_MIGRATE_ASYMKEY structure built using the + following actions. */ + if (returnCode == TPM_SUCCESS) { + TPM_Key_Copy(&a1, + &(tpm_state->tpm_permanent_data.srk), + FALSE); /* don't copy encData */ + } + /* 5. Build a TPM_STORE_PRIVKEY structure from the SRK. This privKey element should be 132 bytes + long for a 2K RSA key. */ + /* 6. Create k1 and k2 by splitting the privKey element created in step 4 into 2 parts. k1 is + the first 20 bytes of privKey, k2 contains the remainder of privKey. */ + /* 7. Build m1 by creating and filling in a TPM_MIGRATE_ASYMKEY structure */ + /* a. m1 -> usageAuth is set to TPM_PERMANENT_DATA -> tpmProof */ + /* b. m1 -> pubDataDigest is set to the digest value of the SRK fields from step 4 */ + /* c. m1 -> payload is set to TPM_PT_MAINT */ + /* d. m1 -> partPrivKey is set to k2 */ + /* 8. Create o1 (which SHALL be 198 bytes for a 2048 bit RSA key) by performing the OAEP + encoding of m using OAEP parameters of */ + /* a. m = TPM_MIGRATE_ASYMKEY structure (step 7) */ + /* b. pHash = TPM_PERMANENT_DATA -> ownerAuth */ + /* c. seed = s1 = k1 (step 6) */ + if (returnCode == TPM_SUCCESS) { + TPM_StoreAsymkey_GetO1Size(&o1Oaep_size, + tpm_state->tpm_permanent_data.srk.tpm_store_asymkey); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc(&o1Oaep, o1Oaep_size); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc(&r1InnerWrapKey, o1Oaep_size); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc(&x1InnerWrap, o1Oaep_size); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_StoreAsymkey_StoreO1 + (o1Oaep, + o1Oaep_size, + tpm_state->tpm_permanent_data.srk.tpm_store_asymkey, + tpm_state->tpm_permanent_data.ownerAuth, /* pHash */ + TPM_PT_MAINT, /* TPM_PAYLOAD_TYPE */ + tpm_state->tpm_permanent_data.tpmProof); /* usageAuth */ + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_CreateMaintenanceArchive: o1 -", o1Oaep); + /* 9. If generateRandom = TRUE */ + if (generateRandom) { + /* a. Create r1 by obtaining values from the TPM RNG. The size of r1 MUST be the same + size as o1. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Random(r1InnerWrapKey, o1Oaep_size); + } + /* Set random parameter to r1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Set(&random, o1Oaep_size, r1InnerWrapKey); + } + } + /* 10. If generateRandom = FALSE */ + else { + /* a. Create r1 by applying MGF1 to the TPM Owner AuthData. The size of r1 MUST be the + same size as o1. */ + returnCode = TPM_MGF1(r1InnerWrapKey, /* unsigned char *mask */ + o1Oaep_size, /* long len */ + tpm_state->tpm_permanent_data.ownerAuth, /* const unsigned + char *seed */ + TPM_SECRET_SIZE); /* long seedlen */ + /* Set randomSize to 0. */ + /* NOTE Done by TPM_SizedBuffer_Init() */ + } + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_CreateMaintenanceArchive: r1 -", r1InnerWrapKey); + /* 11. Create x1 by XOR of o1 with r1 */ + TPM_XOR(x1InnerWrap, o1Oaep, r1InnerWrapKey, o1Oaep_size); + TPM_PrintFour("TPM_Process_CreateMaintenanceArchive: x1", x1InnerWrap); + /* 12. Encrypt x1 with the manuMaintPub key using the TPM_ES_RSAESOAEP_SHA1_MGF1 + encryption scheme. NOTE The check for OAEP is done by TPM_LoadManuMaintPub */ + /* 13. Set a1 -> encData to the encryption of x1 */ + returnCode = TPM_RSAPublicEncrypt_Pubkey(&(a1.encData), + x1InnerWrap, + o1Oaep_size, + &(tpm_state->tpm_permanent_data.manuMaintPub)); + TPM_PrintFour("TPM_Process_CreateMaintenanceArchive: encData", a1.encData.buffer); + } + /* 14. Set TPM_PERMANENT_FLAGS -> maintenanceDone to TRUE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateMaintenanceArchive: Set maintenanceDone\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.maintenanceDone), /* flag */ + TRUE); /* value */ + } + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* 15. Return a1 in the archive parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_Store(&archive, &a1); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CreateMaintenanceArchive: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return randomSize and random */ + returnCode = TPM_SizedBuffer_Store(response, &random); + } + if (returnCode == TPM_SUCCESS) { + /* return archiveSize and archive */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &archive); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&random); /* @1 */ + TPM_Key_Delete(&a1); /* @2 */ + TPM_Sbuffer_Delete(&archive); /* @3 */ + free(o1Oaep); /* @4 */ + free(r1InnerWrapKey); /* @5 */ + free(x1InnerWrap); /* @6 */ + return rcf; +} + +/* 12.2 TPM_LoadMaintenanceArchive rev 98 + + This command loads in a Maintenance archive that has been massaged by the manufacturer to load + into another TPM + + If the maintenance archive was created using the owner authorization for XOR encryption, the + current owner authorization must be used for decryption. The owner authorization does not change. + + If the maintenance archive was created using random data for the XOR encryption, the vendor + specific arguments must include the random data. The owner authorization may change. +*/ + +TPM_RESULT TPM_Process_LoadMaintenanceArchive(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + + TPM_SIZED_BUFFER archive; /* Vendor specific arguments, from + TPM_CreateMaintenanceArchive */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner + authentication. HMAC key: ownerAuth.*/ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_SECRET saveKey; /* copy of HMAC key, since key changes */ + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + unsigned char *stream; /* the input archive stream */ + uint32_t stream_size; + BYTE *x1InnerWrap; + uint32_t x1InnerWrap_size; + BYTE *r1InnerWrapKey; /* for XOR decryption */ + BYTE *o1Oaep; + TPM_KEY newSrk; + TPM_STORE_ASYMKEY srk_store_asymkey; + TPM_STORE_BUFFER asym_sbuffer; + TPM_BOOL writeAllNV1 = FALSE; /* flags to write back data */ + TPM_BOOL writeAllNV2 = FALSE; /* flags to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + /* Vendor specific arguments */ + + printf("TPM_Process_LoadMaintenanceArchive: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&archive); /* freed @1 */ + TPM_Key_Init(&newSrk); /* freed @2 */ + x1InnerWrap = NULL; /* freed @3 */ + r1InnerWrapKey = NULL; /* freed @4 */ + o1Oaep = NULL; /* freed @5 */ + TPM_StoreAsymkey_Init(&srk_store_asymkey); /* freed @6 */ + TPM_Sbuffer_Init(&asym_sbuffer); /* freed @7 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get Vendor specific arguments */ + if (returnCode == TPM_SUCCESS) { + /* NOTE TPM_CreateMaintenanceArchive sends a TPM_SIZED_BUFFER archive. */ + returnCode = TPM_SizedBuffer_Load(&archive, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_LoadMaintenanceArchive: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the TPM Owner's AuthData */ + /* Upon authorization being confirmed this command does the following: */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Validate that the maintenance information was sent by the TPME. The validation mechanism + MUST use a strength of function that is at least the same strength of function as a digital + signature performed using a 2048 bit RSA key. */ + /* NOTE SRK is 2048 bits minimum */ + /* 3. The packet MUST contain m2 as defined in Section 12.1 */ + /* The TPM_SIZED_BUFFER archive contains a TPM_KEY with a TPM_MIGRATE_ASYMKEY that will become + the new SRK */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadMaintenanceArchive: Deserializing TPM_KEY parameter\n"); + stream = archive.buffer; + stream_size = archive.size; + returnCode = TPM_Key_Load(&newSrk, &stream, &stream_size); + } + /* decrypt the TPM_KEY -> encData to x1 using the current SRK */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadMaintenanceArchive: Decrypting TPM_KEY -> encData with SRK\n"); + returnCode = TPM_RSAPrivateDecryptMalloc(&x1InnerWrap, + &x1InnerWrap_size, + newSrk.encData.buffer, + newSrk.encData.size, + &(tpm_state->tpm_permanent_data.srk)); + } + /* allocate memory for r1 based on x1 XOR encrypted data */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_LoadMaintenanceArchive: x1", x1InnerWrap); + printf("TPM_Process_LoadMaintenanceArchive: x1 size %u\n", x1InnerWrap_size); + returnCode = TPM_Malloc(&r1InnerWrapKey, x1InnerWrap_size); + } + /* allocate memory for o1 based on x1 XOR encrypted data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc(&o1Oaep, x1InnerWrap_size); + } + /* generate the XOR encryption secret from the ownerAuth */ + /* NOTE: This does not yet support a supplied random number as the inner wrapper key */ + if (returnCode == TPM_SUCCESS) { + TPM_MGF1(r1InnerWrapKey, /* unsigned char *mask */ + x1InnerWrap_size, /* long len */ + tpm_state->tpm_permanent_data.ownerAuth, /* const unsigned char *seed */ + TPM_SECRET_SIZE); /* long seedlen */ + TPM_PrintFour("TPM_Process_LoadMaintenanceArchive: r1 -", r1InnerWrapKey); + /* decrypt x1 to o1 using XOR encryption secret */ + printf("TPM_Process_LoadMaintenanceArchive: XOR Decrypting TPM_KEY SRK parameter\n"); + TPM_XOR(o1Oaep, x1InnerWrap, r1InnerWrapKey, x1InnerWrap_size); + TPM_PrintFour("TPM_Process_LoadMaintenanceArchive: o1 -", o1Oaep); + } + /* convert o1 to TPM_STORE_ASYMKEY */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_StoreAsymkey_LoadO1(&srk_store_asymkey, o1Oaep, x1InnerWrap_size); + } + /* TPM1 tpmProof comes in as TPM_STORE_ASYMKEY -> usageAuth */ + /* TPM1 ownerAuth comes in as TPM_STORE_ASYMKEY -> migrationAuth (from pHash) */ + /* 4. Ensure that only the target TPM can interpret the maintenance packet. The protection + mechanism MUST use a strength of function that is at least the same strength of function as a + digital signature performed using a 2048 bit RSA key. */ + /* 5. Execute the actions of TPM_OwnerClear. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_OwnerClearCommon(tpm_state, + FALSE); /* don't erase NVRAM with D bit set */ + writeAllNV1 = TRUE; + } + if (returnCode == TPM_SUCCESS) { + /* 6. Process the maintenance information */ + /* a. Update the SRK */ + /* i. Set the SRK usageAuth to be the same as the TPM source owner's AuthData */ + /* NOTE The source srk.usageAuth was lost, as usageAuth is used to transfer the tpmProof */ + TPM_Secret_Copy(srk_store_asymkey.usageAuth, srk_store_asymkey.migrationAuth); + /* b. Update TPM_PERMANENT_DATA -> tpmProof */ + TPM_Secret_Copy(tpm_state->tpm_permanent_data.tpmProof, srk_store_asymkey.usageAuth); + /* save a copy of the HMAC key for the response before invalidating */ + TPM_Secret_Copy(saveKey, *hmacKey); + /* c. Update TPM_PERMANENT_DATA -> ownerAuth */ + TPM_Secret_Copy(tpm_state->tpm_permanent_data.ownerAuth, srk_store_asymkey.migrationAuth); + /* serialize the TPM_STORE_ASYMKEY object */ + returnCode = TPM_StoreAsymkey_Store(&asym_sbuffer, FALSE, &srk_store_asymkey); + } + /* copy back to the new srk encData (clear text for SRK) */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_SetFromStore(&(newSrk.encData), &asym_sbuffer); + } + if (returnCode == TPM_SUCCESS) { + /* free old SRK resources */ + TPM_Key_Delete(&(tpm_state->tpm_permanent_data.srk)); + /* Copy new SRK to TPM_PERMANENT_DATA -> srk */ + /* This copies the basic TPM_KEY, but not the TPM_STORE_ASYMKEY cache */ + returnCode = TPM_Key_Copy(&(tpm_state->tpm_permanent_data.srk), &newSrk, + TRUE); /* copy encData */ + } + /* Recreate the TPM_STORE_ASYMKEY cache */ + if (returnCode == TPM_SUCCESS) { + stream = newSrk.encData.buffer; + stream_size = newSrk.encData.size; + returnCode = TPM_Key_LoadStoreAsymKey(&(tpm_state->tpm_permanent_data.srk), FALSE, + &stream, &stream_size); + } + /* 7. Set TPM_PERMANENT_FLAGS -> maintenanceDone to TRUE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadMaintenanceArchive: Set maintenanceDone\n"); + TPM_SetCapability_Flag(&writeAllNV2, /* altered */ + &(tpm_state->tpm_permanent_flags.maintenanceDone), /* flag */ + TRUE); /* value */ + } + /* Store the permanent data and flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + (TPM_BOOL)(writeAllNV1 || writeAllNV2), + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_LoadMaintenanceArchive: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + saveKey, /* the original owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&archive); /* @1 */ + TPM_Key_Delete(&newSrk); /* @2 */ + free(x1InnerWrap); /* @3 */ + free(r1InnerWrapKey); /* @4 */ + free(o1Oaep); /* @5 */ + TPM_StoreAsymkey_Delete(&srk_store_asymkey); /* @6 */ + TPM_Sbuffer_Delete(&asym_sbuffer); /* @7 */ + return rcf; +} + +/* 12.3 TPM_KillMaintenanceFeature rev 87 + + The KillMaintencanceFeature is a permanent action that prevents ANYONE from creating a + maintenance archive. This action, once taken, is permanent until a new TPM Owner is set. + + This action is to allow those customers who do not want the maintenance feature to not allow the + use of the maintenance feature. + + At the discretion of the Owner, it should be possible to kill the maintenance feature in such a + way that the only way to recover maintainability of the platform would be to wipe out the root + keys. This feature is mandatory in any TPM that implements the maintenance feature. +*/ + +TPM_RESULT TPM_Process_KillMaintenanceFeature(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner + authentication. HMAC key: ownerAuth.*/ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_KillMaintenanceFeature: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_KillMaintenanceFeature: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the TPM Owner AuthData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Set the TPM_PERMANENT_FLAGS.allowMaintenance flag to FALSE. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_KillMaintenanceFeature: Clear allowMaintenance\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.allowMaintenance), /* flag */ + FALSE); /* value */ + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_KillMaintenanceFeature: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 12.4 TPM_LoadManuMaintPub rev 96 + + The LoadManuMaintPub command loads the manufacturer's public key for use in the maintenance + process. The command installs ManuMaintPub in PERMANENT data storage inside a TPM. Maintenance + enables duplication of non-migratory data in protected storage. There is therefore a security + hole if a platform is shipped before the maintenance public key has been installed in a TPM. + + The command is expected to be used before installation of a TPM Owner or any key in TPM protected + storage. It therefore does not use authorization. + + The pubKey MUST specify an algorithm whose strength is not less than the RSA algorithm with 2048 + bit keys. + + pubKey SHOULD unambiguously identify the entity that will perform the maintenance process with + the TPM Owner. + + TPM_PERMANENT_DATA -> manuMaintPub SHALL exist in a TPM-shielded location, only. + + If an entity (Platform Entity) does not support the maintenance process but issues a platform + credential for a platform containing a TPM that supports the maintenance process, the value of + TPM_PERMANENT_DATA -> manuMaintPub MUST be set to zero before the platform leaves the entity's + control. +*/ + +TPM_RESULT TPM_Process_LoadManuMaintPub(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NONCE antiReplay; /* AntiReplay and validation nonce */ + TPM_PUBKEY pubKey; /* The public key of the manufacturer to be in use for maintenance + */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ + TPM_STORE_BUFFER pubKeySerial; /* serialization for checksum calculation */ + const unsigned char *pubKeyBuffer; + uint32_t pubKeyLength; + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_DIGEST checksum; /* Digest of pubKey and antiReplay */ + + printf("TPM_Process_LoadManuMaintPub: Ordinal Entry\n"); + TPM_Pubkey_Init(&pubKey); /* freed @1 */ + TPM_Sbuffer_Init(&pubKeySerial); /* freed @2 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* get pubKey parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Pubkey_Load(&pubKey, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_LoadManuMaintPub: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* The first valid TPM_LoadManuMaintPub command received by a TPM SHALL */ + if (returnCode == TPM_SUCCESS) { + if (!tpm_state->tpm_permanent_data.allowLoadMaintPub) { + printf("TPM_Process_LoadManuMaintPub: Error, command already run\n"); + returnCode = TPM_DISABLED_CMD; + } + } + /* The pubKey MUST specify an algorithm whose strength is not less than the RSA algorithm with + 2048 bit keys. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_CheckProperties(&(pubKey.algorithmParms), /* TPM_KEY_PARMS */ + TPM_KEY_STORAGE, /* TPM_KEY_USAGE */ + 2048, /* required, in bits */ + TRUE); /* FIPS */ + } + /* 1. Store the parameter pubKey as TPM_PERMANENT_DATA -> manuMaintPub. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Pubkey_Copy(&(tpm_state->tpm_permanent_data.manuMaintPub), + &pubKey); + writeAllNV = TRUE; + } + /* 2. Set checksum to SHA-1 of (pubkey || antiReplay) */ + if (returnCode == TPM_SUCCESS) { + /* serialize pubkey */ + returnCode = TPM_Pubkey_Store(&pubKeySerial, &pubKey); + } + if (returnCode == TPM_SUCCESS) { + TPM_Sbuffer_Get(&pubKeySerial, &pubKeyBuffer, &pubKeyLength); + /* create the checksum */ + returnCode = TPM_SHA1(checksum, + pubKeyLength, pubKeyBuffer, + sizeof(TPM_NONCE), antiReplay, + 0, NULL); + } + /* 4. Subsequent calls to TPM_LoadManuMaintPub SHALL return code TPM_DISABLED_CMD. */ + if (returnCode == TPM_SUCCESS) { + tpm_state->tpm_permanent_data.allowLoadMaintPub = FALSE; + } + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_LoadManuMaintPub: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 3. Export the checksum */ + returnCode = TPM_Digest_Store(response, checksum); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_Pubkey_Delete(&pubKey); /* @1 */ + TPM_Sbuffer_Delete(&pubKeySerial); /* @2 */ + return rcf; +} + +/* 12.5 TPM_ReadManuMaintPub rev 99 + + The ReadManuMaintPub command is used to check whether the manufacturer's public maintenance key + in a TPM has the expected value. This may be useful during the manufacture process. The command + returns a digest of the installed key, rather than the key itself. This hinders discovery of the + maintenance key, which may (or may not) be useful for manufacturer privacy. + + The command is expected to be used before installation of a TPM Owner or any key in TPM protected + storage. It therefore does not use authorization. + + This command returns the hash of the antiReplay nonce and the previously loaded manufacturer's + maintenance public key. +*/ + +TPM_RESULT TPM_Process_ReadManuMaintPub(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NONCE antiReplay; /* AntiReplay and validation nonce */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_STORE_BUFFER pubKeySerial; /* serialization for checksum calculation */ + const unsigned char *pubKeyBuffer; + uint32_t pubKeyLength; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_DIGEST checksum; /* Digest of pubKey and antiReplay */ + + printf("TPM_Process_ReadManuMaintPub: Ordinal Entry\n"); + TPM_Sbuffer_Init(&pubKeySerial); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ReadManuMaintPub: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Create "checksum" by concatenating data to form (TPM_PERMANENT_DATA -> manuMaintPub + || antiReplay) and passing the concatenated data through SHA-1. */ + if (returnCode == TPM_SUCCESS) { + /* serialize pubkey */ + returnCode = TPM_Pubkey_Store(&pubKeySerial, &(tpm_state->tpm_permanent_data.manuMaintPub)); + } + if (returnCode == TPM_SUCCESS) { + TPM_Sbuffer_Get(&pubKeySerial, &pubKeyBuffer, &pubKeyLength); + /* create the checksum */ + returnCode = TPM_SHA1(checksum, + pubKeyLength, pubKeyBuffer, + sizeof(TPM_NONCE), antiReplay, + 0, NULL); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ReadManuMaintPub: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 2. Export the checksum */ + returnCode = TPM_Digest_Store(response, checksum); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&pubKeySerial); /* @1 */ + return rcf; +} + +#endif diff --git a/src/tpm12/tpm_maint.h b/src/tpm12/tpm_maint.h new file mode 100644 index 0000000..f26f084 --- /dev/null +++ b/src/tpm12/tpm_maint.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* Maintenance Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_maint.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_MAINT_H +#define TPM_MAINT_H + +#include "tpm_types.h" +#include "tpm_global.h" + + + +/* + Processing Functions +*/ + +TPM_RESULT TPM_Process_CreateMaintenanceArchive(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_LoadMaintenanceArchive(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_KillMaintenanceFeature(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_LoadManuMaintPub(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ReadManuMaintPub(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +#endif diff --git a/src/tpm12/tpm_migration.c b/src/tpm12/tpm_migration.c new file mode 100644 index 0000000..62c59b6 --- /dev/null +++ b/src/tpm12/tpm_migration.c @@ -0,0 +1,4287 @@ +/********************************************************************************/ +/* */ +/* TPM Migration */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_migration.c 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_auth.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_permanent.h" +#include "tpm_process.h" +#include "tpm_secret.h" + +#include "tpm_migration.h" + +/* + TPM_MIGRATIONKEYAUTH +*/ + +/* TPM_Migrationkeyauth_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_Migrationkeyauth_Init(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth) +{ + printf(" TPM_Migrationkeyauth_Init:\n"); + TPM_Pubkey_Init(&(tpm_migrationkeyauth->migrationKey)); + tpm_migrationkeyauth->migrationScheme = 0; + TPM_Digest_Init(tpm_migrationkeyauth->digest); + return; +} + +/* TPM_Migrationkeyauth_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_Migrationkeyauth_Init() + After use, call TPM_Migrationkeyauth_Delete() to free memory +*/ + +TPM_RESULT TPM_Migrationkeyauth_Load(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Migrationkeyauth_Load:\n"); + /* load migrationKey */ + if (rc == 0) { + rc = TPM_Pubkey_Load(&(tpm_migrationkeyauth->migrationKey), stream, stream_size); + } + /* load migrationScheme */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_migrationkeyauth->migrationScheme), stream, stream_size); + } + /* load digest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_migrationkeyauth->digest, stream, stream_size); + } + return rc; +} + +/* TPM_Migrationkeyauth_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_Migrationkeyauth_Store(TPM_STORE_BUFFER *sbuffer, + TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Migrationkeyauth_Store:\n"); + /* store migrationKey */ + if (rc == 0) { + rc = TPM_Pubkey_Store(sbuffer, &(tpm_migrationkeyauth->migrationKey)); + } + /* store migrationScheme */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_migrationkeyauth->migrationScheme); + } + /* store digest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_migrationkeyauth->digest); + } + return rc; +} + +/* TPM_Migrationkeyauth_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_Migrationkeyauth_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_Migrationkeyauth_Delete(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth) +{ + printf(" TPM_Migrationkeyauth_Delete:\n"); + if (tpm_migrationkeyauth != NULL) { + TPM_Pubkey_Delete(&(tpm_migrationkeyauth->migrationKey)); + TPM_Migrationkeyauth_Init(tpm_migrationkeyauth); + } + return; +} + +/* + TPM_MSA_COMPOSITE +*/ + +/* TPM_MsaComposite_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_MsaComposite_Init(TPM_MSA_COMPOSITE *tpm_msa_composite) +{ + printf(" TPM_MsaComposite_Init:\n"); + tpm_msa_composite->MSAlist = 0; + tpm_msa_composite->migAuthDigest = NULL; + return; +} + +/* TPM_MsaComposite_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_MsaComposite_Init() + After use, call TPM_MsaComposite_Delete() to free memory +*/ + +TPM_RESULT TPM_MsaComposite_Load(TPM_MSA_COMPOSITE *tpm_msa_composite, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t i; + + printf(" TPM_MsaComposite_Load:\n"); + /* load MSAlist */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_msa_composite->MSAlist), stream, stream_size); + } + /* MSAlist MUST be one (1) or greater. */ + if (rc == 0) { + if (tpm_msa_composite->MSAlist == 0) { + printf("TPM_MsaComposite_Load: Error, MSAlist is zero\n"); + rc = TPM_INVALID_STRUCTURE; + } + } + /* FIXME add MSAlist limit */ + /* allocate memory for the migAuthDigest array */ + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)&(tpm_msa_composite->migAuthDigest), + (tpm_msa_composite->MSAlist) * TPM_DIGEST_SIZE); + } + /* load migAuthDigest array */ + for (i = 0 ; (rc == 0) && (i < tpm_msa_composite->MSAlist) ; i++) { + rc = TPM_Digest_Load(tpm_msa_composite->migAuthDigest[i], stream, stream_size); + } + return rc; +} + +/* TPM_MsaComposite_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_MsaComposite_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_MSA_COMPOSITE *tpm_msa_composite) +{ + TPM_RESULT rc = 0; + uint32_t i; + + printf(" TPM_MsaComposite_Store:\n"); + /* store MSAlist */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_msa_composite->MSAlist); + } + /* store migAuthDigest array */ + for (i = 0 ; (rc == 0) && (i < tpm_msa_composite->MSAlist) ; i++) { + rc = TPM_Digest_Store(sbuffer, tpm_msa_composite->migAuthDigest[i]); + } + return rc; +} + +/* TPM_MsaComposite_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_MsaComposite_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_MsaComposite_Delete(TPM_MSA_COMPOSITE *tpm_msa_composite) +{ + printf(" TPM_MsaComposite_Delete:\n"); + if (tpm_msa_composite != NULL) { + free(tpm_msa_composite->migAuthDigest); + TPM_MsaComposite_Init(tpm_msa_composite); + } + return; +} + +TPM_RESULT TPM_MsaComposite_CheckMigAuthDigest(TPM_DIGEST tpm_digest, /* value to check vs list */ + TPM_MSA_COMPOSITE *tpm_msa_composite) +{ + TPM_RESULT rc = 0; + uint32_t n; /* count through msaList */ + TPM_BOOL match; + + printf(" TPM_MsaComposite_CheckMigAuthDigest:\n"); + for (n = 0 , match = FALSE ; (n < tpm_msa_composite->MSAlist) && !match ; n++) { + rc = TPM_Digest_Compare(tpm_digest, tpm_msa_composite->migAuthDigest[n]); + if (rc == 0) { + match = TRUE; + } + } + if (match) { + rc = TPM_SUCCESS; + } + else { + printf("TPM_MsaComposite_CheckMigAuthDigest: Error, no match to msaList\n"); + rc = TPM_MA_TICKET_SIGNATURE; + } + return rc; +} + +/* TPM_MsaComposite_CheckSigTicket() + + i. Verify that for one of the n=1 to n=(msaList -> MSAlist) values of msaList -> + migAuthDigest[n], sigTicket == HMAC (V1) using tpmProof as the secret where V1 is a + TPM_CMK_SIGTICKET structure such that: + + (1) V1 -> verKeyDigest = msaList -> migAuthDigest[n] + (2) V1 -> signedData = SHA1[restrictTicket] +*/ + +TPM_RESULT TPM_MsaComposite_CheckSigTicket(TPM_DIGEST sigTicket, /* expected HMAC */ + TPM_SECRET tpmProof, /* HMAC key */ + TPM_MSA_COMPOSITE *tpm_msa_composite, + TPM_CMK_SIGTICKET *tpm_cmk_sigticket) +{ + TPM_RESULT rc = 0; + uint32_t n; /* count through msaList */ + TPM_BOOL match; + TPM_STORE_BUFFER sbuffer; + const unsigned char *buffer; + uint32_t length; + + printf(" TPM_MsaComposite_CheckSigTicket: TPM_MSA_COMPOSITE length %u\n", + tpm_msa_composite->MSAlist); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + for (n = 0 , match = FALSE ; + (rc == 0) && (n < tpm_msa_composite->MSAlist) && !match ; n++) { + + if (rc == 0) { + /* verKeyDigest = msaList -> migAuthDigest[n]. The rest of the structure is initialized + by the caller */ + TPM_PrintFour(" TPM_MsaComposite_CheckSigTicket: Checking migAuthDigest: ", + tpm_msa_composite->migAuthDigest[n]); + TPM_Digest_Copy(tpm_cmk_sigticket->verKeyDigest, tpm_msa_composite->migAuthDigest[n]); + /* serialize the TPM_CMK_SIGTICKET structure */ + TPM_Sbuffer_Clear(&sbuffer); /* reset pointers without free */ + rc = TPM_CmkSigticket_Store(&sbuffer, tpm_cmk_sigticket); + TPM_Sbuffer_Get(&sbuffer, &buffer, &length); + } + if (rc == 0) { + rc = TPM_HMAC_Check(&match, + sigTicket, /* expected */ + tpmProof, /* HMAC key*/ + length, buffer, /* TPM_CMK_SIGTICKET */ + 0, NULL); + } + } + if (rc == 0) { + if (!match) { + printf("TPM_MsaComposite_CheckSigTicket: Error, no match to msaList\n"); + rc = TPM_MA_TICKET_SIGNATURE; + } + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* + TPM_CMK_AUTH +*/ + +/* TPM_CmkAuth_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_CmkAuth_Init(TPM_CMK_AUTH *tpm_cmk_auth) +{ + printf(" TPM_CmkAuth_Init:\n"); + TPM_Digest_Init(tpm_cmk_auth->migrationAuthorityDigest); + TPM_Digest_Init(tpm_cmk_auth->destinationKeyDigest); + TPM_Digest_Init(tpm_cmk_auth->sourceKeyDigest); + return; +} + +/* TPM_CmkAuth_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_CmkAuth_Init() + After use, call TPM_CmkAuth_Delete() to free memory +*/ + +TPM_RESULT TPM_CmkAuth_Load(TPM_CMK_AUTH *tpm_cmk_auth, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CmkAuth_Load:\n"); + /* load migrationAuthorityDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_cmk_auth->migrationAuthorityDigest, stream, stream_size); + } + /* load destinationKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_cmk_auth->destinationKeyDigest, stream, stream_size); + } + /* load sourceKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_cmk_auth->sourceKeyDigest, stream, stream_size); + } + return rc; +} + +/* TPM_CmkAuth_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CmkAuth_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CMK_AUTH *tpm_cmk_auth) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CmkAuth_Store:\n"); + /* store migrationAuthorityDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_cmk_auth->migrationAuthorityDigest); + } + /* store destinationKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_cmk_auth->destinationKeyDigest); + } + /* store sourceKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_cmk_auth->sourceKeyDigest); + } + return rc; +} + +/* TPM_CmkAuth_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_CmkAuth_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_CmkAuth_Delete(TPM_CMK_AUTH *tpm_cmk_auth) +{ + printf(" TPM_CmkAuth_Delete:\n"); + if (tpm_cmk_auth != NULL) { + TPM_CmkAuth_Init(tpm_cmk_auth); + } + return; +} + +/* + TPM_CMK_MIGAUTH +*/ + +/* TPM_CmkMigauth_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_CmkMigauth_Init(TPM_CMK_MIGAUTH *tpm_cmk_migauth) +{ + printf(" TPM_CmkMigauth_Init:\n"); + TPM_Digest_Init(tpm_cmk_migauth->msaDigest); + TPM_Digest_Init(tpm_cmk_migauth->pubKeyDigest); + return; +} + +/* TPM_CmkMigauth_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_CmkMigauth_Init() + After use, call TPM_CmkMigauth_Delete() to free memory +*/ + +TPM_RESULT TPM_CmkMigauth_Load(TPM_CMK_MIGAUTH *tpm_cmk_migauth, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CmkMigauth_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_CMK_MIGAUTH, stream, stream_size); + } + /* load msaDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_cmk_migauth->msaDigest , stream, stream_size); + } + /* load pubKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_cmk_migauth->pubKeyDigest , stream, stream_size); + } + return rc; +} + +/* TPM_CmkMigauth_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CmkMigauth_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CMK_MIGAUTH *tpm_cmk_migauth) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CmkMigauth_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CMK_MIGAUTH); + } + /* store msaDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_cmk_migauth->msaDigest); + } + /* store pubKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_cmk_migauth->pubKeyDigest); + } + return rc; +} + +/* TPM_CmkMigauth_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_CmkMigauth_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_CmkMigauth_Delete(TPM_CMK_MIGAUTH *tpm_cmk_migauth) +{ + printf(" TPM_CmkMigauth_Delete:\n"); + if (tpm_cmk_migauth != NULL) { + TPM_CmkMigauth_Init(tpm_cmk_migauth); + } + return; +} + +/* TPM_CmkMigauth_CheckHMAC() checks an HMAC of a TPM_CMK_MIGAUTH object. + + It serializes the structure and HMAC's the result. The common function cannot be used because + 'tpm_hmac' is not part of the structure and cannot be NULL'ed. +*/ + +TPM_RESULT TPM_CmkMigauth_CheckHMAC(TPM_BOOL *valid, /* result */ + TPM_HMAC tpm_hmac, /* expected */ + TPM_SECRET tpm_hmac_key, /* key */ + TPM_CMK_MIGAUTH *tpm_cmk_migauth) /* data */ +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* serialized TPM_CMK_MIGAUTH */ + + printf(" TPM_CmkMigauth_CheckHMAC:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* Serialize the TPM_CMK_MIGAUTH structure */ + if (rc == 0) { + rc = TPM_CmkMigauth_Store(&sbuffer, tpm_cmk_migauth); + } + /* verify the HMAC of the serialized structure */ + if (rc == 0) { + rc = TPM_HMAC_CheckSbuffer(valid, /* result */ + tpm_hmac, /* expected */ + tpm_hmac_key, /* key */ + &sbuffer); /* data stream */ + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* + TPM_CMK_SIGTICKET +*/ + +/* TPM_CmkSigticket_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_CmkSigticket_Init(TPM_CMK_SIGTICKET *tpm_cmk_sigticket) +{ + printf(" TPM_CmkSigticket_Init:\n"); + TPM_Digest_Init(tpm_cmk_sigticket->verKeyDigest); + TPM_Digest_Init(tpm_cmk_sigticket->signedData); + return; +} + +/* TPM_CmkSigticket_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_CmkSigticket_Init() + After use, call TPM_CmkSigticket_Delete() to free memory +*/ + +TPM_RESULT TPM_CmkSigticket_Load(TPM_CMK_SIGTICKET *tpm_cmk_sigticket, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CmkSigticket_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_CMK_SIGTICKET, stream, stream_size); + } + /* load verKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_cmk_sigticket->verKeyDigest , stream, stream_size); + } + /* load signedData */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_cmk_sigticket->signedData , stream, stream_size); + } + return rc; +} + +/* TPM_CmkSigticket_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CmkSigticket_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CMK_SIGTICKET *tpm_cmk_sigticket) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CmkSigticket_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CMK_SIGTICKET); + } + /* store verKeyDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_cmk_sigticket->verKeyDigest); + } + /* store signedData */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_cmk_sigticket->signedData); + } + return rc; +} + +/* TPM_CmkSigticket_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_CmkSigticket_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_CmkSigticket_Delete(TPM_CMK_SIGTICKET *tpm_cmk_sigticket) +{ + printf(" TPM_CmkSigticket_Delete:\n"); + if (tpm_cmk_sigticket != NULL) { + TPM_CmkSigticket_Init(tpm_cmk_sigticket); + } + return; +} + +/* + TPM_CMK_MA_APPROVAL +*/ + +/* TPM_CmkMaApproval_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_CmkMaApproval_Init(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval) +{ + printf(" TPM_CmkMaApproval_Init:\n"); + TPM_Digest_Init(tpm_cmk_ma_approval->migrationAuthorityDigest); + return; +} + +/* TPM_CmkMaApproval_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_CmkMaApproval_Init() + After use, call TPM_CmkMaApproval_Delete() to free memory +*/ + +TPM_RESULT TPM_CmkMaApproval_Load(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CmkMaApproval_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_CMK_MA_APPROVAL, stream, stream_size); + } + /* load migrationAuthorityDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_cmk_ma_approval->migrationAuthorityDigest, stream, stream_size); + } + return rc; +} + +/* TPM_CmkMaApproval_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CmkMaApproval_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CmkMaApproval_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CMK_MA_APPROVAL); + } + /* store migrationAuthorityDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_cmk_ma_approval->migrationAuthorityDigest); + } + return rc; +} + +/* TPM_CmkMaApproval_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_CmkMaApproval_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_CmkMaApproval_Delete(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval) +{ + printf(" TPM_CmkMaApproval_Delete:\n"); + if (tpm_cmk_ma_approval != NULL) { + TPM_CmkMaApproval_Init(tpm_cmk_ma_approval); + } + return; +} + +/* TPM_CmkMaApproval_CheckHMAC() generates an HMAC of a TPM_CMK_MIGAUTH object + + It serializes the structure and HMAC's the result.The common function cannot be used because + 'tpm_hmac' is not part of the structure and cannot be NULL'ed. +*/ + +TPM_RESULT TPM_CmkMaApproval_CheckHMAC(TPM_BOOL *valid, /* result */ + TPM_HMAC tpm_hmac, /* expected */ + TPM_SECRET tpm_hmac_key, /* key */ + TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval) /* data */ +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* serialized TPM_CMK_MA_APPROVAL */ + + printf(" TPM_CmkMaApproval_CheckHMAC:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* Serialize the TPM_CMK_MA_APPROVAL structure */ + if (rc == 0) { + rc = TPM_CmkMaApproval_Store(&sbuffer, tpm_cmk_ma_approval); + } + /* verify the HMAC of the serialized structure */ + if (rc == 0) { + rc = TPM_HMAC_CheckSbuffer(valid, /* result */ + tpm_hmac, /* expected */ + tpm_hmac_key, /* key */ + &sbuffer); /* data stream */ + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* + Processing functions +*/ + +/* TPM_CreateBlobCommon() does the steps common to TPM_CreateMigrationBlob and + TPM_CMK_CreateBlob + + It takes a TPM_STORE_ASYMKEY, and + - splits the TPM_STORE_PRIVKEY into k1 (20) and k2 (112) + - builds a TPM_MIGRATE_ASYMKEY using + 'payload_type' + TPM_STORE_ASYMKEY usageAuth, pubDataDigest + k2 as partPrivKey + - serializes the TPM_MIGRATE_ASYMKEY + - OAEP encode using + 'phash' + k1 as seed +*/ + +TPM_RESULT TPM_CreateBlobCommon(TPM_SIZED_BUFFER *outData, /* The modified, encrypted + entity. */ + TPM_STORE_ASYMKEY *d1AsymKey, + TPM_DIGEST pHash, /* for OAEP padding */ + TPM_PAYLOAD_TYPE payload_type, + TPM_SIZED_BUFFER *random, /* String used for xor encryption */ + TPM_PUBKEY *migrationKey) /* public key of the migration + facility */ +{ + TPM_RESULT rc = 0; + uint32_t o1_size; + BYTE *o1; + BYTE *r1; + BYTE *x1; + + printf("TPM_CreateBlobCommon:\n"); + o1 = NULL; /* freed @1 */ + r1 = NULL; /* freed @2 */ + x1 = NULL; /* freed @3 */ + if (rc == 0) { + TPM_StoreAsymkey_GetO1Size(&o1_size, d1AsymKey); + } + if (rc == 0) { + rc = TPM_Malloc(&o1, o1_size); + } + if (rc == 0) { + rc = TPM_Malloc(&r1, o1_size); + } + if (rc == 0) { + rc = TPM_Malloc(&x1, o1_size); + } + if (rc == 0) { + rc = TPM_StoreAsymkey_StoreO1(o1, + o1_size, + d1AsymKey, + pHash, + payload_type, + d1AsymKey->usageAuth); + } + /* NOTE Comments from TPM_CreateMigrationBlob rev 81 */ + /* d. Create r1 a random value from the TPM RNG. The size of r1 MUST be the size of o1. Return + r1 in the Random parameter. */ + if (rc == 0) { + rc = TPM_Random(r1, o1_size); + } + /* e. Create x1 by XOR of o1 with r1 */ + if (rc == 0) { + TPM_PrintFourLimit("TPM_CreateBlobCommon: r1 -", r1, o1_size); + TPM_XOR(x1, o1, r1, o1_size); + TPM_PrintFourLimit("TPM_CreateBlobCommon: x1 -", x1, o1_size); + /* f. Copy r1 into the output field "random".*/ + rc = TPM_SizedBuffer_Set(random, o1_size, r1); + } + /* g. Encrypt x1 with the migration public key included in migrationKeyAuth. */ + if (rc == 0) { + rc = TPM_RSAPublicEncrypt_Pubkey(outData, + x1, + o1_size, + migrationKey); + TPM_PrintFour("TPM_CreateBlobCommon: outData", outData->buffer); + } + free(o1); /* @1 */ + free(r1); /* @2 */ + free(x1); /* @3 */ + return rc; +} + +/* 11.1 TPM_CreateMigrationBlob rev 109 + + The TPM_CreateMigrationBlob command implements the first step in the process of moving a + migratable key to a new parent or platform. Execution of this command requires knowledge of the + migrationAuth field of the key to be migrated. + + Migrate mode is generally used to migrate keys from one TPM to another for backup, upgrade or to + clone a key on another platform. To do this, the TPM needs to create a data blob that another TPM + can deal with. This is done by loading in a backup public key that will be used by the TPM to + create a new data blob for a migratable key. + + The TPM Owner does the selection and authorization of migration public keys at any time prior to + the execution of TPM_CreateMigrationBlob by performing the TPM_AuthorizeMigrationKey command. + + IReWrap mode is used to directly move the key to a new parent (either on this platform or + another). The TPM simply re-encrypts the key using a new parent, and outputs a normal encrypted + element that can be subsequently used by a TPM_LoadKey command. + + TPM_CreateMigrationBlob implicitly cannot be used to migrate a non-migratory key. No explicit + check is required. Only the TPM knows tpmProof. Therefore it is impossible for the caller to + submit an authorization value equal to tpmProof and migrate a non-migratory key. +*/ + +TPM_RESULT TPM_Process_CreateMigrationBlob(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* Handle of the parent key that can decrypt encData. */ + TPM_MIGRATE_SCHEME migrationType; /* The migration type, either MIGRATE or REWRAP */ + TPM_MIGRATIONKEYAUTH migrationKeyAuth; /* Migration public key and its authorization + digest. */ + TPM_SIZED_BUFFER encData; /* The encrypted entity that is to be modified. */ + TPM_AUTHHANDLE parentAuthHandle; /* The authorization handle used for the parent key. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with + parentAuthHandle */ + TPM_BOOL continueAuthSession; /* Continue use flag for parent session */ + TPM_AUTHDATA parentAuth; /* Authorization HMAC key: parentKey.usageAuth. */ + TPM_AUTHHANDLE entityAuthHandle; /* The authorization handle used for the encrypted + entity. */ + TPM_NONCE entitynonceOdd; /* Nonce generated by system associated with + entityAuthHandle */ + TPM_BOOL continueEntitySession = TRUE; /* Continue use flag for entity session */ + TPM_AUTHDATA entityAuth; /* Authorization HMAC key: entity.migrationAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL parentAuthHandleValid = FALSE; + TPM_BOOL entityAuthHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *parent_auth_session_data = NULL; /* session data for + parentAuthHandle */ + TPM_AUTH_SESSION_DATA *entity_auth_session_data = NULL; /* session data for + entityAuthHandle */ + TPM_SECRET *hmacKey; + TPM_SECRET *entityHmacKey; + TPM_KEY *parentKey; + TPM_BOOL parentPCRStatus; + TPM_SECRET *parentUsageAuth; + unsigned char *d1Decrypt; /* decryption of encData */ + uint32_t d1DecryptLength = 0; /* actual valid data */ + unsigned char *stream; /* for deserializing decrypted encData */ + uint32_t stream_size; + TPM_STORE_ASYMKEY d1AsymKey; /* structure from decrypted encData */ + TPM_STORE_BUFFER mka_sbuffer; /* serialized migrationKeyAuth */ + const unsigned char *mka_buffer; + uint32_t mka_length; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER random; /* String used for xor encryption */ + TPM_SIZED_BUFFER outData; /* The modified, encrypted entity. */ + + printf("TPM_Process_CreateMigrationBlob: Ordinal Entry\n"); + TPM_Migrationkeyauth_Init(&migrationKeyAuth); /* freed @1 */ + TPM_SizedBuffer_Init(&encData); /* freed @2 */ + TPM_SizedBuffer_Init(&random); /* freed @3 */ + TPM_SizedBuffer_Init(&outData); /* freed @4 */ + d1Decrypt = NULL; /* freed @5 */ + TPM_StoreAsymkey_Init(&d1AsymKey); /* freed @6 */ + TPM_Sbuffer_Init(&mka_sbuffer); /* freed @7 */ + /* + get inputs + */ + /* get parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get migrationType */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateMigrationBlob: parentHandle %08x\n", parentHandle); + returnCode = TPM_Load16(&migrationType, &command, ¶mSize); + } + /* get migrationKeyAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Migrationkeyauth_Load(&migrationKeyAuth, &command, ¶mSize); + } + /* get encData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&encData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag21(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Get(&parentAuthHandle, + &parentAuthHandleValid, + nonceOdd, + &continueAuthSession, + parentAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + printf("TPM_Process_CreateMigrationBlob: parentAuthHandle %08x\n", parentAuthHandle); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&entityAuthHandle, + &entityAuthHandleValid, + entitynonceOdd, + &continueEntitySession, + entityAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateMigrationBlob: entityAuthHandle %08x\n", entityAuthHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CreateMigrationBlob: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + parentAuthHandleValid = FALSE; + entityAuthHandleValid = FALSE; + } + /* + Processing + */ + /* The TPM does not check the PCR values when migrating values locked to a PCR. */ + /* get the key associated with parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* read-only, do not check PCR's */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get parentHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&parent_auth_session_data, + &hmacKey, + tpm_state, + parentAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + parentUsageAuth, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* 1. Validate that parentAuth authorizes the use of the key pointed to by parentHandle. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + parent_auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + parentAuth); /* Authorization digest for input */ + } + /* if there is no parent authorization, check that the parent authDataUsage is TPM_AUTH_NEVER */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { + if (parentKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_CreateMigrationBlob: Error, parent key authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* 2. Validate that parentHandle -> keyUsage is TPM_KEY_STORAGE, if not return + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_CreateMigrationBlob: Error, keyUsage %04hx is invalid\n", + parentKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. Create d1 a TPM_STORE_ASYMKEY structure by decrypting encData using the key pointed to by + parentHandle. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateMigrationBlob: Decrypting encData\n"); + /* decrypt with the parent key to a stream */ + returnCode = TPM_RSAPrivateDecryptMalloc(&d1Decrypt, /* decrypted data */ + &d1DecryptLength, /* actual size of d1 data */ + encData.buffer,/* encrypted data */ + encData.size, /* encrypted data size */ + parentKey); + } + /* deserialize the stream to a TPM_STORE_ASYMKEY d1AsymKey */ + if (returnCode == TPM_SUCCESS) { + stream = d1Decrypt; + stream_size = d1DecryptLength; + returnCode = TPM_StoreAsymkey_Load(&d1AsymKey, FALSE, + &stream, &stream_size, + NULL, /* TPM_KEY_PARMS */ + NULL); /* TPM_SIZED_BUFFER pubKey */ + } + /* a. Verify that d1 -> payload is TPM_PT_ASYM. */ + if (returnCode == TPM_SUCCESS) { + if (d1AsymKey.payload != TPM_PT_ASYM) { + printf("TPM_Process_CreateMigrationBlob: Error, bad payload %02x\n", + d1AsymKey.payload); + returnCode = TPM_BAD_MIGRATION; + } + } + /* 4. Validate that entityAuth authorizes the migration of d1. The validation MUST use d1 -> + migrationAuth as the secret. */ + /* get the second session data */ + /* The second authorisation session (using entityAuth) MUST be OIAP because OSAP does not have a + suitable entityType */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&entity_auth_session_data, + &entityHmacKey, + tpm_state, + entityAuthHandle, + TPM_PID_OIAP, + TPM_ET_KEYHANDLE, + ordinal, + NULL, + &(d1AsymKey.migrationAuth), + NULL); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Auth2data_Check(tpm_state, + *entityHmacKey, /* HMAC key */ + inParamDigest, + entity_auth_session_data, /* authorization session */ + entitynonceOdd, /* Nonce generated by system + associated with authHandle */ + continueEntitySession, + entityAuth); /* Authorization digest for input */ + } + /* 5. Validate that migrationKeyAuth -> digest is the SHA-1 hash of (migrationKeyAuth -> + migrationKey || migrationKeyAuth -> migrationScheme || TPM_PERMANENT_DATA -> tpmProof). */ + /* first serialize the TPM_PUBKEY migrationKeyAuth -> migrationKey */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateMigrationBlob: Verifying migrationKeyAuth\n"); + returnCode = TPM_Pubkey_Store(&mka_sbuffer, &(migrationKeyAuth.migrationKey)); + } + if (returnCode == TPM_SUCCESS) { + /* get the serialization result */ + TPM_Sbuffer_Get(&mka_sbuffer, &mka_buffer, &mka_length); + /* compare to migrationKeyAuth -> digest */ + returnCode = TPM_SHA1_Check(migrationKeyAuth.digest, + mka_length, mka_buffer, /* serialized migrationKey */ + sizeof(TPM_MIGRATE_SCHEME), &(migrationKeyAuth.migrationScheme), + TPM_SECRET_SIZE, tpm_state->tpm_permanent_data.tpmProof, + 0, NULL); + } + /* 6. If migrationType == TPM_MS_MIGRATE the TPM SHALL perform the following actions: */ + if ((returnCode == TPM_SUCCESS) && (migrationType == TPM_MS_MIGRATE)) { + printf("TPM_Process_CreateMigrationBlob: migrationType TPM_MS_MIGRATE\n"); + /* a. Build two byte arrays, K1 and K2: */ + /* i. K1 = d1.privKey[0..19] (d1.privKey.keyLength + 16 bytes of d1.privKey.key), sizeof(K1) + = 20 */ + /* ii. K2 = d1.privKey[20..131] (position 16-127 of TPM_STORE_ASYMKEY. privKey.key) + (position 16-127 of d1 . privKey.key), sizeof(K2) = 112 */ + /* b. Build M1 a TPM_MIGRATE_ASYMKEY structure */ + /* i. TPM_MIGRATE_ASYMKEY.payload = TPM_PT_MIGRATE */ + /* ii. TPM_MIGRATE_ASYMKEY.usageAuth = d1.usageAuth */ + /* iii. TPM_MIGRATE_ASYMKEY.pubDataDigest = d1.pubDataDigest */ + /* iv. TPM_MIGRATE_ASYMKEY.partPrivKeyLen = 112 - 127. */ + /* v. TPM_MIGRATE_ASYMKEY.partPrivKey = K2 */ + /* c. Create o1 (which SHALL be 198 bytes for a 2048 bit RSA key) by performing the OAEP + encoding of m using OAEP parameters of */ + /* i. m = M1 the TPM_MIGRATE_ASYMKEY structure */ + /* ii. pHash = d1->migrationAuth */ + /* iii. seed = s1 = K1 */ + /* d. Create r1 a random value from the TPM RNG. The size of r1 MUST be the size of + o1. Return r1 in the Random parameter. */ + /* e. Create x1 by XOR of o1 with r1*/ + /* f. Copy r1 into the output field "random".*/ + /* g. Encrypt x1 with the migration public key included in migrationKeyAuth.*/ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CreateBlobCommon(&outData, /* output */ + &d1AsymKey, /* TPM_STORE_ASYMKEY */ + d1AsymKey.migrationAuth, /* pHash */ + TPM_PT_MIGRATE, /* payload type */ + &random, /* string for XOR encryption */ + &(migrationKeyAuth.migrationKey)); /* TPM_PUBKEY */ + } + } + /* 7. If migrationType == TPM_MS_REWRAP the TPM SHALL perform the following actions: */ + else if ((returnCode == TPM_SUCCESS) && (migrationType == TPM_MS_REWRAP)) { + printf("TPM_Process_CreateMigrationBlob: migrationType TPM_MS_REWRAP\n"); + /* a. Rewrap the key using the public key in migrationKeyAuth, keeping the existing contents + of that key. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPublicEncrypt_Pubkey(&outData, + d1Decrypt, /* decrypted encData parameter */ + d1DecryptLength, + &(migrationKeyAuth.migrationKey)); + } + /* b. Set randomSize to 0 in the output parameter array */ + /* NOTE Done by TPM_SizedBuffer_Init() */ + } + /* 8. Else */ + /* a. Return TPM_BAD_PARAMETER */ + else if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateMigrationBlob: Error, illegal migrationType %04hx\n", + migrationType); + returnCode = TPM_BAD_PARAMETER; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CreateMigrationBlob: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return random */ + returnCode = TPM_SizedBuffer_Store(response, &random); + } + if (returnCode == TPM_SUCCESS) { + /* return outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + parent_auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *entityHmacKey, /* HMAC key */ + entity_auth_session_data, + outParamDigest, + entitynonceOdd, + continueEntitySession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) + && parentAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, + parentAuthHandle); + } + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueEntitySession) && + entityAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, + entityAuthHandle); + } + /* + cleanup + */ + TPM_Migrationkeyauth_Delete(&migrationKeyAuth); /* @1 */ + TPM_SizedBuffer_Delete(&encData); /* @2 */ + TPM_SizedBuffer_Delete(&random); /* @3 */ + TPM_SizedBuffer_Delete(&outData); /* @4 */ + free(d1Decrypt); /* @5 */ + TPM_StoreAsymkey_Delete(&d1AsymKey); /* @6 */ + TPM_Sbuffer_Delete(&mka_sbuffer); /* @7 */ + return rcf; +} + + + +/* 11.2 TPM_ConvertMigrationBlob rev 87 + + This command takes a migration blob and creates a normal wrapped blob. The migrated blob must be + loaded into the TPM using the normal TPM_LoadKey function. + + Note that the command migrates private keys, only. The migration of the associated public keys is + not specified by TPM because they are not security sensitive. Migration of the associated public + keys may be specified in a platform specific specification. A TPM_KEY structure must be recreated + before the migrated key can be used by the target TPM in a LoadKey command. +*/ + +/* The relationship between Create and Convert parameters are: + + Create: k1 || k2 = privKey + m = TPM_MIGRATE_ASYMKEY, partPrivKey = k2 + o1 = OAEP (m), seed = k1 + x1 = o1 ^ r1 + out = pub (x1) + Convert: + d1 = priv (in) + o1 = d1 ^ r1 + m1, seed = OAEP (o1) + k1 = seed || partPrivKey +*/ + +TPM_RESULT TPM_Process_ConvertMigrationBlob(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can decrypt keys. */ + TPM_SIZED_BUFFER inData; /* The XOR'd and encrypted key */ + TPM_SIZED_BUFFER random; /* Random value used to hide key data. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA parentAuth; /* The authorization digest that authorizes the inputs and + the migration of the key in parentHandle. HMAC key: + parentKey.usageAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_KEY *parentKey = NULL; /* the key specified by parentHandle */ + TPM_BOOL parentPCRStatus; + TPM_SECRET *parentUsageAuth; + unsigned char *d1Decrypt; + uint32_t d1DecryptLength = 0; /* actual valid data */ + BYTE *o1Oaep; + TPM_STORE_ASYMKEY d2AsymKey; + TPM_STORE_BUFFER d2_sbuffer; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER outData; /* The encrypted private key that can be loaded with + TPM_LoadKey */ + + printf("TPM_Process_ConvertMigrationBlob: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&inData); /* freed @1 */ + TPM_SizedBuffer_Init(&random); /* freed @2 */ + TPM_SizedBuffer_Init(&outData); /* freed @3 */ + d1Decrypt = NULL; /* freed @4 */ + o1Oaep = NULL; /* freed @5 */ + TPM_StoreAsymkey_Init(&d2AsymKey); /* freed @6 */ + TPM_Sbuffer_Init(&d2_sbuffer); /* freed @7 */ + /* + get inputs + */ + /* get parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get inData */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ConvertMigrationBlob: parentHandle %08x\n", parentHandle); + returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); + } + /* get random */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&random, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + parentAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ConvertMigrationBlob: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* Verify that parentHandle points to a valid key. Get the TPM_KEY associated with parentHandle + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* not r/o, using to decrypt */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* check TPM_AUTH_DATA_USAGE authDataUsage */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (parentKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_ConvertMigrationBlob: Error, parent key authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get parentHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + parentUsageAuth, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* 1. Validate the authorization to use the key in parentHandle */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + parentAuth); /* Authorization digest for input */ + } + /* 2. If the keyUsage field of the key referenced by parentHandle does not have the value + TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_ConvertMigrationBlob: Error, " + "parentHandle -> keyUsage should be TPM_KEY_STORAGE, is %04x\n", + parentKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. Create d1 by decrypting the inData area using the key in parentHandle */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ConvertMigrationBlob: Decrypting inData\n"); + TPM_PrintFourLimit("TPM_Process_ConvertMigrationBlob: inData", inData.buffer, inData.size); + returnCode = TPM_RSAPrivateDecryptMalloc(&d1Decrypt, /* decrypted data */ + &d1DecryptLength, /* actual size of d1 data */ + inData.buffer, /* encrypted data */ + inData.size, + parentKey); + } + /* the random input parameter must be the same length as the decrypted data */ + if (returnCode == TPM_SUCCESS) { + if (d1DecryptLength != random.size) { + printf("TPM_Process_ConvertMigrationBlob: Error " + "decrypt data length %u random size %u\n", + d1DecryptLength, random.size); + returnCode = TPM_BAD_PARAMETER; + } + } + /* allocate memory for o1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc(&o1Oaep, d1DecryptLength); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ConvertMigrationBlob: d1 length %u\n", d1DecryptLength); + TPM_PrintFourLimit("TPM_Process_ConvertMigrationBlob: d1 -", d1Decrypt, d1DecryptLength); + /* 4. Create o1 by XOR d1 and random parameter */ + TPM_XOR(o1Oaep, d1Decrypt, random.buffer, d1DecryptLength); + /* 5. Create m1 a TPM_MIGRATE_ASYMKEY structure, seed and pHash by OAEP decoding o1 */ + /* NOTE TPM_StoreAsymkey_LoadO1() extracts TPM_STORE_ASYMKEY from the OAEP encoded + TPM_MIGRATE_ASYMKEY. */ + returnCode = TPM_StoreAsymkey_LoadO1(&d2AsymKey, o1Oaep, d1DecryptLength); + } + /* 6. Create k1 by combining seed and the TPM_MIGRATE_ASYMKEY -> partPrivKey field */ + /* NOTE Done by TPM_StoreAsymkey_LoadO1 () */ + /* 7. Create d2 a TPM_STORE_ASYMKEY structure */ + if (returnCode == TPM_SUCCESS) { + /* a. Verify that m1 -> payload == TPM_PT_MIGRATE */ + /* NOTE TPM_StoreAsymkey_LoadO1() copied TPM_MIGRATE_ASYMKEY -> payload to TPM_STORE_ASYMKEY + -> payload */ + if (d2AsymKey.payload != TPM_PT_MIGRATE) { + printf("TPM_Process_ConvertMigrationBlob: Error, invalid payload %02x\n", + d2AsymKey.payload); + returnCode = TPM_BAD_MIGRATION; + } + } + if (returnCode == TPM_SUCCESS) { + /* b. Set d2 -> payload = TPM_PT_ASYM */ + d2AsymKey.payload = TPM_PT_ASYM; + /* c. Set d2 -> usageAuth to m1 -> usageAuth */ + /* d. Set d2 -> migrationAuth to pHash */ + /* e. Set d2 -> pubDataDigest to m1 -> pubDataDigest */ + /* f. Set d2 -> privKey field to k1 */ + /* NOTE Done by TPM_StoreAsymkey_LoadO1() */ + /* 9. Create outData using the key in parentHandle to perform the encryption */ + /* serialize d2key to d2 */ + returnCode = TPM_StoreAsymkey_Store(&d2_sbuffer, FALSE, &d2AsymKey); + } + /* encrypt d2 with parentKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPublicEncryptSbuffer_Key(&outData, &d2_sbuffer, parentKey); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ConvertMigrationBlob: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&inData); /* @1 */ + TPM_SizedBuffer_Delete(&random); /* @2 */ + TPM_SizedBuffer_Delete(&outData); /* @3 */ + free(d1Decrypt); /* @4 */ + free(o1Oaep); /* @5 */ + TPM_StoreAsymkey_Delete(&d2AsymKey); /* @6 */ + TPM_Sbuffer_Delete(&d2_sbuffer); /* @7 */ + return rcf; +} + +/* 11.3 TPM_AuthorizeMigrationKey rev 114 + + This command creates an authorization blob, to allow the TPM owner to specify which migration + facility they will use and allow users to migrate information without further involvement with + the TPM owner. + + It is the responsibility of the TPM Owner to determine whether migrationKey is appropriate for + migration. The TPM checks just the cryptographic strength of migrationKey. +*/ + +TPM_RESULT TPM_Process_AuthorizeMigrationKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_MIGRATE_SCHEME migrationScheme; /* Type of migration operation that is to be permitted for + this key. */ + TPM_PUBKEY migrationKey; /* The public key to be authorized. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner + authorization. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_RSA_KEY_PARMS *rsa_key_parms; /* for migrationKey */ + TPM_STORE_BUFFER sbuffer; + const unsigned char *buffer; + uint32_t length; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_MIGRATIONKEYAUTH outData; /* (f1) Returned public key and authorization digest. */ + + printf("TPM_Process_AuthorizeMigrationKey: Ordinal Entry\n"); + TPM_Pubkey_Init(&migrationKey); /* freed @1 */ + TPM_Migrationkeyauth_Init(&outData); /* freed @2 */ + TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get migrationScheme */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&migrationScheme, &command, ¶mSize); + } + /* get migrationKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Pubkey_Load(&migrationKey, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_AuthorizeMigrationKey: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Check that the cryptographic strength of migrationKey is at least that of a 2048 bit RSA + key. If migrationKey is an RSA key, this means that migrationKey MUST be 2048 bits or greater + and MUST use the default exponent. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms, + &(migrationKey.algorithmParms)); + } + if (returnCode == TPM_SUCCESS) { + if (rsa_key_parms->keyLength < 2048) { + printf("TPM_Process_AuthorizeMigrationKey: Error, " + "migrationKey length %u less than 2048\n", + rsa_key_parms->keyLength); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParams_CheckDefaultExponent(&(rsa_key_parms->exponent)); + } + /* 2. Validate the AuthData to use the TPM by the TPM Owner */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 3. Create a f1 a TPM_MIGRATIONKEYAUTH structure */ + /* NOTE: This is outData */ + /* 4. Verify that migrationKey-> algorithmParms -> encScheme is TPM_ES_RSAESOAEP_SHA1_MGF1, and + return the error code TPM_INAPPROPRIATE_ENC if it is not */ + if (returnCode == TPM_SUCCESS) { + if (migrationKey.algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { + printf("TPM_Process_AuthorizeMigrationKey: Error, " + "migrationKey encScheme %04hx must be TPM_ES_RSAESOAEP_SHA1_MGF1\n", + migrationKey.algorithmParms.encScheme); + returnCode = TPM_INAPPROPRIATE_ENC; + } + } + /* 5. Set f1 -> migrationKey to the input migrationKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Pubkey_Copy(&(outData.migrationKey), &(migrationKey)); + } + if (returnCode == TPM_SUCCESS) { + /* 6. Set f1 -> migrationScheme to the input migrationScheme */ + outData.migrationScheme = migrationScheme; + /* 7. Create v1 by concatenating (migrationKey || migrationScheme || TPM_PERMANENT_DATA -> + tpmProof) */ + /* 8. Create h1 by performing a SHA-1 hash of v1 */ + /* first serialize the TPM_PUBKEY migrationKey */ + returnCode = TPM_Pubkey_Store(&sbuffer, &migrationKey); + } + if (returnCode == TPM_SUCCESS) { + TPM_Sbuffer_Get(&sbuffer, &buffer, &length); + /* 9. Set f1 -> digest to h1 */ + returnCode = TPM_SHA1(outData.digest, + length, buffer, /* serialized migrationKey */ + sizeof(TPM_MIGRATE_SCHEME), &(migrationScheme), + TPM_SECRET_SIZE, tpm_state->tpm_permanent_data.tpmProof, + 0, NULL); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_AuthorizeMigrationKey: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 10. Return f1 as outData */ + returnCode = TPM_Migrationkeyauth_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_Pubkey_Delete(&migrationKey); /* @1 */ + TPM_Migrationkeyauth_Delete(&outData); /* @2 */ + TPM_Sbuffer_Delete(&sbuffer); /* @3 */ + return rcf; +} + +/* 11.4 TPM_MigrateKey rev 87 + + The TPM_MigrateKey command performs the function of a migration authority. + + The command is relatively simple; it just decrypts the input packet (coming from + TPM_CreateMigrationBlob or TPM_CMK_CreateBlob) and then re-encrypts it with the input public + key. The output of this command would then be sent to TPM_ConvertMigrationBlob or + TPM_CMK_ConvertMigration on the target TPM. + + TPM_MigrateKey does not make ANY assumptions about the contents of the encrypted blob. Since it + does not have the XOR string, it cannot actually determine much about the key that is being + migrated. + + This command exists to permit the TPM to be a migration authority. If used in this way, it is + expected that the physical security of the system containing the TPM and the AuthData value for + the MA key would be tightly controlled. + + To prevent the execution of this command using any other key as a parent key, this command works + only if keyUsage for maKeyHandle is TPM_KEY_MIGRATE. +*/ + +TPM_RESULT TPM_Process_MigrateKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE maKeyHandle; /* Handle of the key to be used to migrate the key. */ + TPM_PUBKEY pubKey; /* Public key to which the blob is to be migrated */ + TPM_SIZED_BUFFER inData; /* The input blob */ + + TPM_AUTHHANDLE maAuthHandle; /* The authorization session handle used for maKeyHandle. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with certAuthHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA keyAuth; /* The authorization session digest for the inputs and key to be + signed. HMAC key: maKeyHandle.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL maAuthHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_KEY *maKey = NULL; /* the key specified by maKeyHandle */ + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; /* for maKey */ + TPM_SECRET *maKeyUsageAuth; + TPM_BOOL maPCRStatus; + uint32_t decrypt_data_size; /* resulting decrypted data size */ + BYTE *decrypt_data = NULL; /* The resulting decrypted data. */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER outData; /* The re-encrypted blob */ + + printf("TPM_Process_MigrateKey: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&inData); /* freed @1 */ + TPM_SizedBuffer_Init(&outData); /* freed @2 */ + TPM_Pubkey_Init(&pubKey); /* freed @4 */ + /* + get inputs + */ + /* get maKeyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&maKeyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get pubKey */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_MigrateKey: maKeyHandle %08x\n", maKeyHandle); + returnCode = TPM_Pubkey_Load(&pubKey, &command, ¶mSize); + } + /* get encData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&maAuthHandle, + &maAuthHandleValid, + nonceOdd, + &continueAuthSession, + keyAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_MigrateKey: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + maAuthHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate that keyAuth authorizes the use of the key pointed to by maKeyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&maKey, &maPCRStatus, tpm_state, maKeyHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get maKeyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&maKeyUsageAuth, maKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + printf("TPM_Process_MigrateKey: maAuthHandle %08x\n", maAuthHandle); + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + maAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + maKey, + maKeyUsageAuth, /* OIAP */ + maKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + keyAuth); /* Authorization digest for input */ + } + /* check TPM_AUTH_DATA_USAGE authDataUsage */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (maKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_MigrateKey: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* 2. The TPM validates that the key pointed to by maKeyHandle has a key usage value of + TPM_KEY_MIGRATE, and that the allowed encryption scheme is TPM_ES_RSAESOAEP_SHA1_MGF1. */ + if (returnCode == TPM_SUCCESS) { + if (maKey->keyUsage != TPM_KEY_MIGRATE) { + printf("TPM_Process_MigrateKey: Error, keyUsage %04hx not TPM_KEY_MIGRATE\n", + maKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + else if (maKey->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { + printf("TPM_Process_MigrateKey: Error, encScheme %04hx not TPM_ES_RSAESOAEP_SHA_MGF1\n", + maKey->algorithmParms.encScheme); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* 3. The TPM validates that pubKey is of a size supported by the TPM and that its size is + consistent with the input blob and maKeyHandle. */ + /* NOTE: Let the encryption step do this step */ + /* 4. The TPM decrypts inData and re-encrypts it using pubKey. */ + /* get the TPM_RSA_KEY_PARMS associated with maKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, &(maKey->algorithmParms)); + } + /* decrypt using maKey */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_MigrateKey: Decrypt using maKey\n"); + returnCode = + TPM_RSAPrivateDecryptMalloc(&decrypt_data, /* decrypted data, freed @3 */ + &decrypt_data_size, /* actual size of decrypt data */ + inData.buffer, + inData.size, + maKey); + + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_MigrateKey: Encrypt using pubKey\n"); + returnCode = TPM_RSAPublicEncrypt_Pubkey(&outData, /* encrypted data */ + decrypt_data, + decrypt_data_size, + &pubKey); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_MigrateKey: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + maAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, maAuthHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&inData); /* @1 */ + TPM_SizedBuffer_Delete(&outData); /* @2 */ + free(decrypt_data); /* @3 */ + TPM_Pubkey_Delete(&pubKey); /* @4 */ + return rcf; +} + +/* 11.7 TPM_CMK_CreateKey rev 114 + + The TPM_CMK_CreateKey command both generates and creates a secure storage bundle for asymmetric + keys whose migration is controlled by a migration authority. + + TPM_CMK_CreateKey is very similar to TPM_CreateWrapKey, but: (1) the resultant key must be a + migratable key and can be migrated only by TPM_CMK_CreateBlob; (2) the command is Owner + authorized via a ticket. + + TPM_CMK_CreateKey creates an otherwise normal migratable key except that (1) migrationAuth is an + HMAC of the migration authority and the new key's public key, signed by tpmProof (instead of + being tpmProof); (2) the migrationAuthority bit is set TRUE; (3) the payload type is + TPM_PT_MIGRATE_RESTRICTED. + + The migration-selection/migration authority is specified by passing in a public key (actually the + digests of one or more public keys, so more than one migration authority can be specified). +*/ + +TPM_RESULT TPM_Process_CMK_CreateKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can perform key wrapping. */ + TPM_ENCAUTH dataUsageAuth; /* Encrypted usage authorization data for the key. */ + TPM_KEY keyInfo; /* Information about key to be created, pubkey.keyLength and + keyInfo.encData elements are 0. MUST be TPM_KEY12 */ + TPM_HMAC migrationAuthorityApproval;/* A ticket, created by the TPM Owner using + TPM_CMK_ApproveMA, approving a TPM_MSA_COMPOSITE + structure */ + TPM_DIGEST migrationAuthorityDigest;/* The digest of a TPM_MSA_COMPOSITE structure */ + + TPM_AUTHHANDLE authHandle; /* The authorization handle used for parent key + authorization. Must be an OSAP session. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA pubAuth; /* The authorization session digest that authorizes the use + of the public key in parentHandle. HMAC key: + parentKey.usageAuth.*/ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for entityAuthHandle + */ + TPM_SECRET *hmacKey; + TPM_KEY *parentKey = NULL; /* the key specified by parentHandle */ + TPM_BOOL parentPCRStatus; + TPM_BOOL hmacValid; /* for migrationAuthorityApproval */ + TPM_SECRET du1DecryptAuth; + TPM_STORE_ASYMKEY *wrappedStoreAsymkey; /* substructure of wrappedKey */ + TPM_CMK_MA_APPROVAL m1CmkMaApproval; + TPM_CMK_MIGAUTH m2CmkMigauth; + int ver; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_KEY wrappedKey; /* The TPM_KEY structure which includes the public and + encrypted private key. MUST be TPM_KEY12 */ + + printf("TPM_Process_CMK_CreateKey: Ordinal Entry\n"); + TPM_Key_Init(&keyInfo); /* freed @1 */ + TPM_Key_Init(&wrappedKey); /* freed @2 */ + TPM_CmkMaApproval_Init(&m1CmkMaApproval); /* freed @3 */ + TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @4 */ + /* + get inputs + */ + /* get parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get dataUsageAuth */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateKey: parentHandle %08x\n", parentHandle); + returnCode = TPM_Authdata_Load(dataUsageAuth, &command, ¶mSize); + } + /* get keyInfo */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_Load(&keyInfo, &command, ¶mSize); + } + /* get migrationAuthorityApproval */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(migrationAuthorityApproval, &command, ¶mSize); + } + /* get migrationAuthorityDigest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(migrationAuthorityDigest, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + pubAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateKey: authHandle %08x\n", authHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CMK_CreateKey: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the authorization to use the key pointed to by parentHandle. Return TPM_AUTHFAIL + on any error. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* not r/o, using to encrypt */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get the session data */ + /* 2. Validate the session type for parentHandle is OSAP. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + NULL, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + pubAuth); /* Authorization digest for input */ + } + /* 3. If the TPM is not designed to create a key of the type requested in keyInfo, return the + error code TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_CheckProperties(&ver, &keyInfo, 0, + tpm_state->tpm_permanent_flags.FIPS); + printf("TPM_Process_CMK_CreateKey: key parameters v = %d\n", ver); + } + /* 4. Verify that parentHandle->keyUsage equals TPM_KEY_STORAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateKey: Checking parent key\n"); + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_CMK_CreateKey: Error, parent keyUsage not TPM_KEY_STORAGE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 5. Verify that parentHandle-> keyFlags-> migratable == FALSE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_CMK_CreateKey: Error, parent migratable\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 6. If keyInfo -> keyFlags -> migratable is FALSE then return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateKey: Checking key flags\n"); + if (!(keyInfo.keyFlags & TPM_MIGRATABLE)) { + printf("TPM_Process_CMK_CreateKey: Error, keyInfo migratable is FALSE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 7. If keyInfo -> keyFlags -> migrateAuthority is FALSE , return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (!(keyInfo.keyFlags & TPM_MIGRATEAUTHORITY)) { + printf("TPM_Process_CMK_CreateKey: Error, keyInfo migrateauthority is FALSE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 8. Verify that the migration authority is authorized */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateKey: Checking migration authority authorization\n"); + /* a. Create M1 a TPM_CMK_MA_APPROVAL structure */ + /* NOTE Done by TPM_CmkMaApproval_Init() */ + /* i. Set M1 ->migrationAuthorityDigest to migrationAuthorityDigest */ + TPM_Digest_Copy(m1CmkMaApproval.migrationAuthorityDigest, migrationAuthorityDigest); + /* b. Verify that migrationAuthorityApproval == HMAC(M1) using tpmProof as the secret and + return error TPM_MA_AUTHORITY on mismatch */ + returnCode = + TPM_CmkMaApproval_CheckHMAC(&hmacValid, + migrationAuthorityApproval, /* expect */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &m1CmkMaApproval); + if (!hmacValid) { + printf("TPM_Process_CMK_CreateKey: Error, Invalid migrationAuthorityApproval\n"); + returnCode = TPM_MA_AUTHORITY; + } + } + /* 9. Validate key parameters */ + /* a. keyInfo -> keyUsage MUST NOT be TPM_KEY_IDENTITY or TPM_KEY_AUTHCHANGE. If it is, return + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateKey: Checking key usage\n"); + if ((keyInfo.keyUsage == TPM_KEY_IDENTITY) || + (keyInfo.keyUsage == TPM_KEY_AUTHCHANGE)) { + printf("TPM_Process_CMK_CreateKey: Error, invalid keyInfo -> keyUsage %04hx\n", + keyInfo.keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 10. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then */ + /* a. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS */ + /* b. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ + /* c. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return TPM_NOTFIPS */ + /* NOTE Done by TPM_Key_CheckProperties() */ + /* 11. If keyInfo -> keyUsage equals TPM_KEY_STORAGE or TPM_KEY_MIGRATE */ + /* a. algorithmID MUST be TPM_ALG_RSA */ + /* b. encScheme MUST be TPM_ES_RSAESOAEP_SHA1_MGF1 */ + /* c. sigScheme MUST be TPM_SS_NONE */ + /* d. key size MUST be 2048 */ + /* e. exponentSize MUST be 0 */ + /* NOTE Done by TPM_Key_CheckProperties() */ + /* 12. If keyInfo -> tag is NOT TPM_TAG_KEY12 return TPM_INVALID_STRUCTURE */ + if (returnCode == TPM_SUCCESS) { + if (ver != 2) { + printf("TPM_Process_CMK_CreateKey: Error, keyInfo must be TPM_TAG_KEY12\n"); + returnCode = TPM_INVALID_STRUCTURE; + } + } + /* 13. Map wrappedKey to a TPM_KEY12 structure */ + /* NOTE: Not required. TPM_KEY functions handle TPM_KEY12 subclass */ + /* 14. Create DU1 by decrypting dataUsageAuth according to the ADIP indicated by authHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_Decrypt(du1DecryptAuth, + NULL, + dataUsageAuth, + auth_session_data, + NULL, + NULL, + FALSE); /* even and odd */ + } + if (returnCode == TPM_SUCCESS) { + /* 15. Set continueAuthSession to FALSE */ + continueAuthSession = FALSE; + /* 16. Generate asymmetric key according to algorithm information in keyInfo */ + /* 17. Fill in the wrappedKey structure with information from the newly generated key. */ + printf("TPM_Process_CMK_CreateKey: Generating key\n"); + returnCode = TPM_Key_GenerateRSA(&wrappedKey, + tpm_state, + parentKey, + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + ver, /* TPM_KEY12 */ + keyInfo.keyUsage, + keyInfo.keyFlags, + keyInfo.authDataUsage, /* TPM_AUTH_DATA_USAGE */ + &(keyInfo.algorithmParms), /* TPM_KEY_PARMS */ + keyInfo.tpm_pcr_info, /* TPM_PCR_INFO */ + keyInfo.tpm_pcr_info_long); /* TPM_PCR_INFO_LONG */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetStoreAsymkey(&wrappedStoreAsymkey, + &wrappedKey); + } + if (returnCode == TPM_SUCCESS) { + /* a. Set wrappedKey -> encData -> usageAuth to DU1 */ + TPM_Secret_Copy(wrappedStoreAsymkey->usageAuth, du1DecryptAuth); + /* b. Set wrappedKey -> encData -> payload to TPM_PT_MIGRATE_RESTRICTED */ + wrappedStoreAsymkey->payload = TPM_PT_MIGRATE_RESTRICTED; + /* c. Create thisPubKey, a TPM_PUBKEY structure containing wrappedKey's public key. */ + /* NOTE All that is really needed is its digest, which is calculated directly */ + } + if (returnCode == TPM_SUCCESS) { + /* d. Create M2 a TPM_CMK_MIGAUTH structure */ + /* NOTE Done by TPM_CmkMigauth_Init() */ + /* i. Set M2 -> msaDigest to migrationAuthorityDigest */ + TPM_Digest_Copy(m2CmkMigauth.msaDigest, migrationAuthorityDigest); + /* ii. Set M2 -> pubKeyDigest to SHA-1 (thisPubKey) */ + returnCode = TPM_Key_GeneratePubkeyDigest(m2CmkMigauth.pubKeyDigest, &wrappedKey); + /* e. Set wrappedKey -> encData -> migrationAuth equal to HMAC(M2), using tpmProof as the + shared secret */ + returnCode = TPM_HMAC_GenerateStructure + (wrappedStoreAsymkey->migrationAuth, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &m2CmkMigauth, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_CmkMigauth_Store); /* store function */ + } + /* 18. If keyInfo->PCRInfoSize is non-zero */ + /* a. Set wrappedKey -> pcrInfo to a TPM_PCR_INFO_LONG structure */ + /* b. Set wrappedKey -> pcrInfo to keyInfo -> pcrInfo */ + /* b. Set wrappedKey -> digestAtCreation to the TPM_COMPOSITE_HASH indicated by + creationPCRSelection */ + /* c. Set wrappedKey -> localityAtCreation to TPM_STANY_FLAGS -> localityModifier */ + /* NOTE This is done during TPM_Key_GenerateRSA() */ + /* 19. Encrypt the private portions of the wrappedKey structure using the key in parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GenerateEncData(&wrappedKey, parentKey); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CMK_CreateKey: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 20. Return the newly generated key in the wrappedKey parameter */ + returnCode = TPM_Key_Store(response, &wrappedKey); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_Key_Delete(&keyInfo); /* @1 */ + TPM_Key_Delete(&wrappedKey); /* @2 */ + TPM_CmkMaApproval_Delete(&m1CmkMaApproval); /* @3 */ + TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @4 */ + return rcf; +} + + +/* 11.5 TPM_CMK_CreateTicket rev 101 + + The TPM_verifySignature command uses a public key to verify the signature over a digest. + + TPM_verifySignature returns a ticket that can be used to prove to the same TPM that signature + verification with a particular public key was successful. +*/ + +TPM_RESULT TPM_Process_CMK_CreateTicket(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_PUBKEY verificationKey; /* The public key to be used to check signatureValue */ + TPM_DIGEST signedData; /* The data to be verified */ + TPM_SIZED_BUFFER signatureValue; /* The signatureValue to be verified */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA pubAuth; /* The authorization digest for inputs and owner. HMAC key: + ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_CMK_SIGTICKET m2CmkSigticket; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_HMAC sigTicket; /* Ticket that proves digest created on this TPM */ + + printf("TPM_Process_CMK_CreateTicket: Ordinal Entry\n"); + TPM_Pubkey_Init(&verificationKey); /* freed @1 */ + TPM_SizedBuffer_Init(&signatureValue); /* freed @2 */ + TPM_CmkSigticket_Init(&m2CmkSigticket); /* freed @3 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get verificationKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Pubkey_Load(&verificationKey, &command, ¶mSize); + } + /* get signedData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(signedData, &command, ¶mSize); + } + /* get signatureValue */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&signatureValue, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + pubAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CMK_CreateTicket: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the TPM Owner authorization to use the command */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + pubAuth); /* Authorization digest for input */ + } + /* 2. Validate that the key type and algorithm are correct */ + /* a. Validate that verificationKey -> algorithmParms -> algorithmID == TPM_ALG_RSA */ + if (returnCode == TPM_SUCCESS) { + if (verificationKey.algorithmParms.algorithmID != TPM_ALG_RSA) { + printf("TPM_Process_CMK_CreateTicket: Error, incorrect algorithmID %08x\n", + verificationKey.algorithmParms.algorithmID); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* b. Validate that verificationKey -> algorithmParms ->encScheme == TPM_ES_NONE */ + if (returnCode == TPM_SUCCESS) { + if (verificationKey.algorithmParms.encScheme != TPM_ES_NONE) { + printf("TPM_Process_CMK_CreateTicket: Error, incorrect encScheme %04hx\n", + verificationKey.algorithmParms.encScheme); + returnCode = TPM_INAPPROPRIATE_ENC; + } + } + /* c. Validate that verificationKey ->algorithmParms ->sigScheme is + TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */ + if (returnCode == TPM_SUCCESS) { + if ((verificationKey.algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (verificationKey.algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { + printf("TPM_Process_CMK_CreateTicket: Error, incorrect sigScheme %04hx\n", + verificationKey.algorithmParms.sigScheme); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. Use verificationKey to verify that signatureValue is a valid signature on signedData, and + return error TPM_BAD_SIGNATURE on mismatch */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateTicket: Verifying signature\n"); + returnCode = TPM_RSAVerifyH(&signatureValue, /* signature */ + signedData, /* data that was signed */ + TPM_DIGEST_SIZE, /* size of signed data */ + &verificationKey); /* TPM_PUBKEY public key */ + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateTicket: Error verifying signature\n"); + } + } + /* 4. Create M2 a TPM_CMK_SIGTICKET */ + /* NOTE Done by TPM_CmkSigticket_Init() */ + /* a. Set M2 -> verKeyDigest to the SHA-1 (verificationKey) */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(m2CmkSigticket.verKeyDigest, &verificationKey, + (TPM_STORE_FUNCTION_T)TPM_Pubkey_Store); + } + if (returnCode == TPM_SUCCESS) { + /* b. Set M2 -> signedData to signedData */ + TPM_Digest_Copy(m2CmkSigticket.signedData, signedData); + /* 5. Set sigTicket = HMAC(M2) signed by using tpmProof as the secret */ + returnCode = TPM_HMAC_GenerateStructure + (sigTicket, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &m2CmkSigticket, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_CmkSigticket_Store); /* store function */ + } + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CMK_CreateTicket: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return sigTicket */ + returnCode = TPM_Digest_Store(response, sigTicket); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_Pubkey_Delete(&verificationKey); /* @1 */ + TPM_SizedBuffer_Delete(&signatureValue); /* @2 */ + TPM_CmkSigticket_Delete(&m2CmkSigticket); /* @3 */ + return rcf; +} + + +/* 11.9 TPM_CMK_CreateBlob rev 114 + + TPM_CMK_CreateBlob command is very similar to TPM_CreateMigrationBlob, except that it: (1) uses + an extra ticket (restrictedKeyAuth) instead of a migrationAuth authorization session; (2) uses + the migration options TPM_MS_RESTRICT_MIGRATE or TPM_MS_RESTRICT_APPROVE; (3) produces a wrapped + key blob whose migrationAuth is independent of tpmProof. + + If the destination (parent) public key is the MA, migration is implicitly permitted. Further + checks are required if the MA is not the destination (parent) public key, and merely selects a + migration destination: (1) sigTicket must prove that restrictTicket was signed by the MA; (2) + restrictTicket must vouch that the target public key is approved for migration to the destination + (parent) public key. (Obviously, this more complex method may also be used by an MA to approve + migration to that MA.) In both cases, the MA must be one of the MAs implicitly listed in the + migrationAuth of the target key-to-be-migrated. + + When the migrationType is TPM_MS_RESTRICT_MIGRATE, restrictTicket and sigTicket are unused. The + TPM may test that the corresponding sizes are zero, so the caller should set them to zero for + interoperability. +*/ + +TPM_RESULT TPM_Process_CMK_CreateBlob(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* Handle of the parent key that can decrypt encData. */ + TPM_MIGRATE_SCHEME migrationType; /* The migration type, either TPM_MS_RESTRICT_MIGRATE or + TPM_MS_RESTRICT_APPROVE + NOTE Never used */ + TPM_MIGRATIONKEYAUTH migrationKeyAuth; /* Migration public key and its authorization + session digest. */ + TPM_DIGEST pubSourceKeyDigest; /* The digest of the TPM_PUBKEY of the entity to be migrated + */ + TPM_SIZED_BUFFER msaListBuffer; /* One or more digests of public keys belonging to migration + authorities */ + TPM_SIZED_BUFFER restrictTicketBuffer; /* If migrationType is TPM_MS_RESTRICT_APPROVE, a + TPM_CMK_AUTH structure, containing the digests of + the public keys belonging to the Migration + Authority, the destination parent key and the + key-to-be-migrated. */ + TPM_SIZED_BUFFER sigTicketBuffer; /* If migrationType is TPM_MS_RESTRICT_APPROVE, a TPM_HMAC + structure, generated by the TPM, signaling a valid + signature over restrictTicket */ + TPM_SIZED_BUFFER encData; /* The encrypted entity that is to be modified. */ + TPM_AUTHHANDLE parentAuthHandle; /* The authorization handle used for the parent key. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with + parentAuthHandle */ + TPM_BOOL continueAuthSession; /* Continue use flag for parent session */ + TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and + parentHandle. HMAC key: parentKey.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_KEY *parentKey; + TPM_BOOL parentPCRStatus; + TPM_SECRET *parentUsageAuth; + unsigned char *d1Decrypt; /* decryption of encData */ + uint32_t d1DecryptLength = 0; /* actual valid data */ + TPM_STORE_ASYMKEY d1AsymKey; /* structure from decrypted encData */ + unsigned char *stream; /* for deserializing structures */ + uint32_t stream_size; + TPM_STORE_BUFFER mka_sbuffer; /* serialized migrationKeyAuth.migrationKey */ + const unsigned char *mka_buffer; + uint32_t mka_length; + TPM_DIGEST migrationKeyDigest; /* digest of migrationKeyAuth.migrationKey */ + TPM_DIGEST pHash; + TPM_CMK_MIGAUTH m2CmkMigauth; + TPM_BOOL valid; + TPM_MSA_COMPOSITE msaList; + TPM_DIGEST sigTicket; + TPM_CMK_AUTH restrictTicket; + TPM_CMK_SIGTICKET v1CmkSigticket; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER random; /* String used for xor encryption */ + TPM_SIZED_BUFFER outData; /* The modified, encrypted entity. */ + + printf("TPM_Process_CMK_CreateBlob: Ordinal Entry\n"); + d1Decrypt = NULL; /* freed @1 */ + TPM_Migrationkeyauth_Init(&migrationKeyAuth); /* freed @2 */ + TPM_SizedBuffer_Init(&msaListBuffer); /* freed @3 */ + TPM_SizedBuffer_Init(&restrictTicketBuffer); /* freed @4 */ + TPM_SizedBuffer_Init(&sigTicketBuffer); /* freed @5 */ + TPM_SizedBuffer_Init(&encData); /* freed @6 */ + TPM_SizedBuffer_Init(&random); /* freed @7 */ + TPM_SizedBuffer_Init(&outData); /* freed @8 */ + TPM_Sbuffer_Init(&mka_sbuffer); /* freed @9 */ + TPM_StoreAsymkey_Init(&d1AsymKey); /* freed @10 */ + TPM_MsaComposite_Init(&msaList); /* freed @11 */ + TPM_CmkAuth_Init(&restrictTicket); /* freed @12 */ + TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @13 */ + TPM_CmkSigticket_Init(&v1CmkSigticket); /* freed @14 */ + /* + get inputs + */ + /* get parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get migrationType */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&migrationType, &command, ¶mSize); + } + /* get migrationKeyAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Migrationkeyauth_Load(&migrationKeyAuth, &command, ¶mSize); + } + /* get pubSourceKeyDigest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(pubSourceKeyDigest, &command, ¶mSize); + } + /* get msaListBuffer */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&msaListBuffer, &command, ¶mSize); + } + /* deserialize to msaList */ + if (returnCode == TPM_SUCCESS) { + stream = msaListBuffer.buffer; + stream_size = msaListBuffer.size; + returnCode = TPM_MsaComposite_Load(&msaList, &stream, &stream_size); + } + /* get restrictTicket */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&restrictTicketBuffer, &command, ¶mSize); + } + /* get sigTicket */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&sigTicketBuffer, &command, ¶mSize); + } + /* get encData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&encData, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&parentAuthHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + parentAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CMK_CreateBlob: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* + The TPM does not check the PCR values when migrating values locked to a PCR. */ + /* get the key associated with parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* do not check PCR's */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get parentHandle -> usageAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); + } + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + parentAuthHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + parentUsageAuth, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* 1. Validate that parentAuth authorizes the use of the key pointed to by parentHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + parentAuth); /* Authorization digest for input */ + } + /* 2.The TPM MAY verify that migrationType == migrationKeyAuth -> migrationScheme and return + TPM_BAD_MODE on error. + a.The TPM MAY ignore migrationType. */ + /* 3. Verify that parentHandle-> keyFlags-> migratable == FALSE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_CMK_CreateBlob: Error, parent migratable\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* Validate that parentHandle -> keyUsage is TPM_KEY_STORAGE, if not return the error code + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_CMK_CreateBlob: Error, keyUsage %04hx is invalid\n", + parentKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. Create d1 by decrypting encData using the key pointed to by parentHandle. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateBlob: Decrypting encData\n"); + /* decrypt with the parent key to a stream */ + returnCode = TPM_RSAPrivateDecryptMalloc(&d1Decrypt, /* decrypted data, freed @1 */ + &d1DecryptLength, /* actual size of d1 data */ + encData.buffer,/* encrypted data */ + encData.size, /* encrypted data size */ + parentKey); + } + /* deserialize the stream to a TPM_STORE_ASYMKEY d1AsymKey */ + if (returnCode == TPM_SUCCESS) { + stream = d1Decrypt; + stream_size = d1DecryptLength; + returnCode = TPM_StoreAsymkey_Load(&d1AsymKey, FALSE, + &stream, &stream_size, + NULL, /* TPM_KEY_PARMS */ + NULL); /* TPM_SIZED_BUFFER pubKey */ + } + /* 5. Verify that the digest within migrationKeyAuth is legal for this TPM and public key */ + /* NOTE Presumably, this reverses the steps from TPM_AuthorizeMigrationKey */ + /* create h1 by concatenating (migrationKey || migrationScheme || TPM_PERMANENT_DATA -> + tpmProof) */ + /* first serialize the TPM_PUBKEY migrationKeyAuth -> migrationKey */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateBlob: Verifying migrationKeyAuth\n"); + returnCode = TPM_Pubkey_Store(&mka_sbuffer, &(migrationKeyAuth.migrationKey)); + } + if (returnCode == TPM_SUCCESS) { + /* get the serialization result */ + TPM_Sbuffer_Get(&mka_sbuffer, &mka_buffer, &mka_length); + /* then create the hash. tpmProof indicates that the input knew ownerAuth in + TPM_AuthorizeMigrationKey */ + /* compare to migrationKeyAuth -> digest */ + returnCode = TPM_SHA1_Check(migrationKeyAuth.digest, + mka_length, mka_buffer, /* serialized migrationKey */ + sizeof(TPM_MIGRATE_SCHEME), &(migrationKeyAuth.migrationScheme), + TPM_SECRET_SIZE, tpm_state->tpm_permanent_data.tpmProof, + 0, NULL); + } + /* 6. Verify that d1 -> payload == TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_EXTERNAL */ + if (returnCode == TPM_SUCCESS) { + if ((d1AsymKey.payload != TPM_PT_MIGRATE_RESTRICTED) && + (d1AsymKey.payload != TPM_PT_MIGRATE_EXTERNAL)) { + printf("TPM_Process_CMK_CreateBlob: Error, invalid payload %02x\n", d1AsymKey.payload); + returnCode = TPM_INVALID_STRUCTURE; + } + } + /* 7. Verify that the migration authorities in msaList are authorized to migrate this key */ + /* a. Create M2 a TPM_CMK_MIGAUTH structure */ + /* NOTE Done by TPM_CmkMigauth_Init() */ + /* i. Set M2 -> msaDigest to SHA-1[msaList] */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(m2CmkMigauth.msaDigest, &msaList, + (TPM_STORE_FUNCTION_T)TPM_MsaComposite_Store); + } + if (returnCode == TPM_SUCCESS) { + /* ii. Set M2 -> pubKeyDigest to pubSourceKeyDigest */ + TPM_Digest_Copy(m2CmkMigauth.pubKeyDigest, pubSourceKeyDigest); + /* b. Verify that d1 -> migrationAuth == HMAC(M2) using tpmProof as the secret and return + error TPM_MA_AUTHORITY on mismatch */ + returnCode = TPM_CmkMigauth_CheckHMAC(&valid, + d1AsymKey.migrationAuth, /* expected */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key*/ + &m2CmkMigauth); + if (!valid) { + printf("TPM_Process_CMK_CreateBlob: Error validating migrationAuth\n"); + returnCode = TPM_MA_AUTHORITY; + } + } + /* SHA-1[migrationKeyAuth -> migrationKey] is required below */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1(migrationKeyDigest, + mka_length, mka_buffer, /* serialized migrationKey */ + 0, NULL); + } + /* 8. If migrationKeyAuth -> migrationScheme == TPM_MS_RESTRICT_MIGRATE */ + if ((returnCode == TPM_SUCCESS) && + (migrationKeyAuth.migrationScheme == TPM_MS_RESTRICT_MIGRATE)) { + /* a. Verify that intended migration destination is an MA: */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateBlob: migrationScheme is TPM_MS_RESTRICT_MIGRATE\n"); + /* i. For one of n=1 to n=(msaList -> MSAlist), verify that SHA-1[migrationKeyAuth -> + migrationKey] == msaList -> migAuthDigest[n] */ + returnCode = TPM_MsaComposite_CheckMigAuthDigest(migrationKeyDigest, &msaList); + } + /* b. Validate that the MA key is the correct type */ + /* i. Validate that migrationKeyAuth -> migrationKey -> algorithmParms -> algorithmID == + TPM_ALG_RSA */ + if (returnCode == TPM_SUCCESS) { + if (migrationKeyAuth.migrationKey.algorithmParms.algorithmID != TPM_ALG_RSA) { + printf("TPM_Process_CMK_CreateBlob: Error, algorithmID %08x not TPM_ALG_RSA\n", + migrationKeyAuth.migrationKey.algorithmParms.algorithmID); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* ii. Validate that migrationKeyAuth -> migrationKey -> algorithmParms -> encScheme is an + encryption scheme supported by the TPM */ + if (returnCode == TPM_SUCCESS) { + if (migrationKeyAuth.migrationKey.algorithmParms.encScheme != + TPM_ES_RSAESOAEP_SHA1_MGF1) { + + printf("TPM_Process_CMK_CreateBlob: Error, " + "encScheme %04hx not TPM_ES_RSAESOAEP_SHA1_MGF1\n", + migrationKeyAuth.migrationKey.algorithmParms.encScheme ); + returnCode = TPM_INAPPROPRIATE_ENC; + } + } + /* iii. Validate that migrationKeyAuth -> migrationKey ->algorithmParms -> sigScheme is + TPM_SS_NONE */ + if (returnCode == TPM_SUCCESS) { + if (migrationKeyAuth.migrationKey.algorithmParms.sigScheme != TPM_SS_NONE) { + printf("TPM_Process_CMK_CreateBlob: Error, sigScheme %04hx not TPM_SS_NONE\n", + migrationKeyAuth.migrationKey.algorithmParms.sigScheme); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* c. The TPM MAY validate that restrictTicketSize is zero. */ + if (returnCode == TPM_SUCCESS) { + if (restrictTicketBuffer.size != 0) { + printf("TPM_Process_CMK_CreateBlob: Error, " + "TPM_MS_RESTRICT_MIGRATE and restrictTicketSize %u not zero\n", + restrictTicketBuffer.size); + returnCode = TPM_BAD_PARAMETER; + } + } + /* d. The TPM MAY validate that sigTicketSize is zero. */ + if (returnCode == TPM_SUCCESS) { + if (sigTicketBuffer.size != 0) { + printf("TPM_Process_CMK_CreateBlob: Error, " + "TPM_MS_RESTRICT_MIGRATE and sigTicketSize %u not zero\n", + sigTicketBuffer.size); + returnCode = TPM_BAD_PARAMETER; + } + } + } + /* 9. If migrationKeyAuth -> migrationScheme == TPM_MS_RESTRICT_APPROVE */ + else if ((returnCode == TPM_SUCCESS) && + (migrationKeyAuth.migrationScheme == TPM_MS_RESTRICT_APPROVE)) { + /* a. Verify that the intended migration destination has been approved by the MSA: */ + /* i. Verify that for one of the n=1 to n=(msaList -> MSAlist) values of msaList -> + migAuthDigest[n], sigTicket == HMAC (V1) using tpmProof as the secret where V1 is a + TPM_CMK_SIGTICKET structure such that: */ + /* (1) V1 -> verKeyDigest = msaList -> migAuthDigest[n] */ + /* (2) V1 -> signedData = SHA-1[restrictTicket] */ + printf("TPM_Process_CMK_CreateBlob: migrationScheme is TPM_MS_RESTRICT_APPROVE_DOUBLE\n"); + /* deserialize the sigTicket TPM_HMAC */ + if (returnCode == TPM_SUCCESS) { + stream = sigTicketBuffer.buffer; + stream_size = sigTicketBuffer.size; + returnCode = TPM_Digest_Load(sigTicket, &stream, &stream_size); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1(v1CmkSigticket.signedData, + restrictTicketBuffer.size, restrictTicketBuffer.buffer, + 0, NULL); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_MsaComposite_CheckSigTicket(sigTicket, + tpm_state->tpm_permanent_data.tpmProof, + &msaList, + &v1CmkSigticket); + } + /* ii. If [restrictTicket -> destinationKeyDigest] != SHA-1[migrationKeyAuth -> + migrationKey], return error TPM_MA_DESTINATION */ + /* deserialize the restrictTicket structure */ + if (returnCode == TPM_SUCCESS) { + stream = restrictTicketBuffer.buffer; + stream_size = restrictTicketBuffer.size; + returnCode = TPM_CmkAuth_Load(&restrictTicket, &stream, &stream_size); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Compare(migrationKeyDigest, + restrictTicket.destinationKeyDigest); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateBlob: Error, no match to destinationKeyDigest\n"); + returnCode = TPM_MA_DESTINATION; + } + } + /* iii. If [restrictTicket -> sourceKeyDigest] != pubSourceKeyDigest, return error + TPM_MA_SOURCE */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Compare(pubSourceKeyDigest, restrictTicket.sourceKeyDigest); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateBlob: Error, no match to sourceKeyDigest\n"); + returnCode = TPM_MA_SOURCE; + } + } + } + /* 10. Else return with error TPM_BAD_PARAMETER. */ + else if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_CreateBlob: Error, Illegal migrationScheme %04hx\n", + migrationKeyAuth.migrationScheme); + returnCode = TPM_BAD_PARAMETER; + } + /* 11. Build two bytes array, K1 and K2, using d1: */ + /* a. K1 = TPM_STORE_ASYMKEY.privKey[0..19] (TPM_STORE_ASYMKEY.privKey.keyLength + 16 bytes of + TPM_STORE_ASYMKEY.privKey.key), sizeof(K1) = 20 */ + /* b. K2 = TPM_STORE_ASYMKEY.privKey[20..131] (position 16-127 of + TPM_STORE_ASYMKEY.privKey.key), sizeof(K2) = 112 */ + /* 12. Build M1 a TPM_MIGRATE_ASYMKEY structure */ + /* a. TPM_MIGRATE_ASYMKEY.payload = TPM_PT_CMK_MIGRATE */ + /* b. TPM_MIGRATE_ASYMKEY.usageAuth = TPM_STORE_ASYMKEY.usageAuth */ + /* c. TPM_MIGRATE_ASYMKEY.pubDataDigest = TPM_STORE_ASYMKEY.pubDataDigest */ + /* d. TPM_MIGRATE_ASYMKEY.partPrivKeyLen = 112 - 127. */ + /* e. TPM_MIGRATE_ASYMKEY.partPrivKey = K2 */ + /* 13. Create o1 (which SHALL be 198 bytes for a 2048 bit RSA key) by performing the OAEP + encoding of m using OAEP parameters m, pHash, and seed */ + /* a. m is the previously created M1 */ + /* b. pHash = SHA-1( SHA-1[msaList] || pubSourceKeyDigest) */ + /* c. seed = s1 = the previously created K1 */ + /* 14. Create r1 a random value from the TPM RNG. The size of r1 MUST be the size of o1. Return + r1 in the */ + /* random parameter */ + /* 15. Create x1 by XOR of o1 with r1 */ + /* 16. Copy r1 into the output field "random" */ + /* 17. Encrypt x1 with the migrationKeyAuth-> migrationKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1(pHash, + TPM_DIGEST_SIZE, m2CmkMigauth.msaDigest, + TPM_DIGEST_SIZE, pubSourceKeyDigest, + 0, NULL); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CreateBlobCommon(&outData, + &d1AsymKey, + pHash, + TPM_PT_CMK_MIGRATE, + &random, + &(migrationKeyAuth.migrationKey)); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CMK_CreateBlob: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return random */ + returnCode = TPM_SizedBuffer_Store(response, &random); + } + if (returnCode == TPM_SUCCESS) { + /* return outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, + parentAuthHandle); + } + /* + cleanup + */ + free(d1Decrypt); /* @1 */ + TPM_Migrationkeyauth_Delete(&migrationKeyAuth); /* @2 */ + TPM_SizedBuffer_Delete(&msaListBuffer); /* @3 */ + TPM_SizedBuffer_Delete(&restrictTicketBuffer); /* @4 */ + TPM_SizedBuffer_Delete(&sigTicketBuffer); /* @5 */ + TPM_SizedBuffer_Delete(&encData); /* @6 */ + TPM_SizedBuffer_Delete(&random); /* @7 */ + TPM_SizedBuffer_Delete(&outData); /* @8 */ + TPM_Sbuffer_Delete(&mka_sbuffer); /* @9 */ + TPM_StoreAsymkey_Delete(&d1AsymKey); /* @10 */ + TPM_MsaComposite_Delete(&msaList); /* @11 */ + TPM_CmkAuth_Delete(&restrictTicket); /* @12 */ + TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @13 */ + TPM_CmkSigticket_Delete(&v1CmkSigticket); /* @14 */ + return rcf; +} + +/* 11.7 TPM_CMK_SetRestrictions rev 96 + + This command is used by the Owner to dictate the usage of a certified-migration key with + delegated authorisation (authorisation other than actual Owner authorisation). + + This command is provided for privacy reasons and must not itself be delegated, because a + certified-migration-key may involve a contractual relationship between the Owner and an external + entity. + + Since restrictions are validated at DSAP session use, there is no need to invalidate DSAP + sessions when the restriction value changes. +*/ + +TPM_RESULT TPM_Process_CMK_SetRestrictions(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_CMK_DELEGATE restriction; /* The bit mask of how to set the restrictions on CMK keys + */ + TPM_AUTHHANDLE authHandle; /* The authorization handle TPM Owner authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA ownerAuth; /* The authorization digest. HMAC key: TPM Owner Auth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_CMK_SetRestrictions: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get restriction */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&restriction, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_SetRestrictions: restriction %08x\n", restriction); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CMK_SetRestrictions: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the ordinal and parameters using TPM Owner authorization, return TPM_AUTHFAIL on + error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_CMK_SetRestrictions: ownerAuth secret", *hmacKey); + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Set TPM_PERMANENT_DATA -> TPM_CMK_DELEGATE -> restrictDelegate = restriction */ + if (returnCode == TPM_SUCCESS) { + /* only update NVRAM if the value is changing */ + if (tpm_state->tpm_permanent_data.restrictDelegate != restriction) { + tpm_state->tpm_permanent_data.restrictDelegate = restriction; + /* Store the permanent data back to NVRAM */ + printf("TPM_Process_CMK_SetRestrictions: Storing permanent data\n"); + returnCode = TPM_PermanentAll_NVStore(tpm_state, + TRUE, /* write NV */ + 0); /* no roll back */ + } + else { + printf("TPM_Process_CMK_SetRestrictions: No change to value\n"); + } + } + /* 3. Return TPM_SUCCESS */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CMK_SetRestrictions: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 11.6 TPM_CMK_ApproveMA 87 + + This command creates an authorization ticket, to allow the TPM owner to specify which Migration + Authorities they approve and allow users to create certified-migration-keys without further + involvement with the TPM owner. + + It is the responsibility of the TPM Owner to determine whether a particular Migration Authority is + suitable to control migration. +*/ + +TPM_RESULT TPM_Process_CMK_ApproveMA(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_DIGEST migrationAuthorityDigest; /* A digest of a TPM_MSA_COMPOSITE structure (itself + one or more digests of public keys belonging to + migration authorities) */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* Authorization HMAC, key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_CMK_MA_APPROVAL m2CmkMaApproval; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_HMAC outData; /* HMAC of migrationAuthorityDigest */ + + printf("TPM_Process_CMK_ApproveMA: Ordinal Entry\n"); + TPM_CmkMaApproval_Init(&m2CmkMaApproval); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get migrationAuthorityDigest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(migrationAuthorityDigest, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CMK_ApproveMA: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the AuthData to use the TPM by the TPM Owner */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + if (returnCode == TPM_SUCCESS) { + /* 2. Create M2 a TPM_CMK_MA_APPROVAL structure */ + /* NOTE Done by TPM_CmkMaApproval_Init() */ + /* a. Set M2 ->migrationAuthorityDigest to migrationAuthorityDigest */ + TPM_Digest_Copy(m2CmkMaApproval.migrationAuthorityDigest, migrationAuthorityDigest); + /* 3. Set outData = HMAC(M2) using tpmProof as the secret */ + returnCode = TPM_HMAC_GenerateStructure + (outData, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &m2CmkMaApproval, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_CmkMaApproval_Store); /* store function */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CMK_ApproveMA: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the outData */ + returnCode = TPM_Digest_Store(response, outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_CmkMaApproval_Delete(&m2CmkMaApproval); /* @1 */ + return rcf; +} + +/* 11.10 TPM_CMK_ConvertMigration rev 106 + + TPM_CMK_ConvertMigration completes the migration of certified migration blobs. + + This command takes a certified migration blob and creates a normal wrapped blob with payload type + TPM_PT_MIGRATE_EXTERNAL. The migrated blob must be loaded into the TPM using the normal + TPM_LoadKey function. + + Note that the command migrates private keys, only. The migration of the associated public keys is + not specified by TPM because they are not security sensitive. Migration of the associated public + keys may be specified in a platform specific specification. A TPM_KEY structure must be recreated + before the migrated key can be used by the target TPM in a LoadKey command. + + TPM_CMK_ConvertMigration checks that one of the MAs implicitly listed in the migrationAuth of the + target key has approved migration of the target key to the destination (parent) key, and that the + settings (flags etc.) in the target key are those of a CMK. +*/ + +TPM_RESULT TPM_Process_CMK_ConvertMigration(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can decrypt keys. */ + TPM_CMK_AUTH restrictTicket; /* The digests of public keys belonging to the Migration + Authority, the destination parent key and the + key-to-be-migrated. */ + TPM_HMAC sigTicket; /* A signature ticket, generated by the TPM, signaling a + valid signature over restrictTicket */ + TPM_KEY migratedKey; /* The public key of the key-to-be-migrated. The private + portion MUST be TPM_MIGRATE_ASYMKEY properly XOR'd */ + TPM_SIZED_BUFFER msaListBuffer; /* One or more digests of public keys belonging to migration + authorities */ + TPM_SIZED_BUFFER random; /* Random value used to hide key data. */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA parentAuth; /* Authorization HMAC: parentKey.usageAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_KEY *parentKey; + TPM_BOOL parentPCRStatus; + TPM_SECRET *parentUsageAuth; + unsigned char *d1Decrypt; + uint32_t d1DecryptLength = 0; /* actual valid data */ + BYTE *o1Oaep; + unsigned char *stream; /* for deserializing structures */ + uint32_t stream_size; + TPM_MSA_COMPOSITE msaList; + TPM_DIGEST msaListDigest; + TPM_DIGEST migratedPubKeyDigest; + TPM_STORE_ASYMKEY d2AsymKey; + TPM_STORE_BUFFER d2_sbuffer; + TPM_DIGEST parentPubKeyDigest; + TPM_CMK_SIGTICKET v1CmkSigticket; + TPM_CMK_MIGAUTH m2CmkMigauth; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER outData; /* The encrypted private key that can be loaded with + TPM_LoadKey */ + + printf("TPM_Process_CMK_ConvertMigration: Ordinal Entry\n"); + TPM_CmkAuth_Init(&restrictTicket); /* freed @1 */ + TPM_Key_Init(&migratedKey); /* freed @2 */ + TPM_SizedBuffer_Init(&msaListBuffer); /* freed @3 */ + TPM_SizedBuffer_Init(&random); /* freed @4 */ + TPM_SizedBuffer_Init(&outData); /* freed @5 */ + d1Decrypt = NULL; /* freed @6 */ + TPM_MsaComposite_Init(&msaList); /* freed @7 */ + TPM_StoreAsymkey_Init(&d2AsymKey); /* freed @8 */ + TPM_Sbuffer_Init(&d2_sbuffer); /* freed @9 */ + TPM_CmkSigticket_Init(&v1CmkSigticket); /* freed @10 */ + o1Oaep = NULL; /* freed @11 */ + TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @12 */ + /* + get inputs + */ + /* get parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get restrictTicket */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_ConvertMigration: parentHandle %08x\n", parentHandle); + returnCode = TPM_CmkAuth_Load(&restrictTicket, &command, ¶mSize); + } + /* get sigTicket */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(sigTicket, &command, ¶mSize); + } + /* get migratedKey */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_Load(&migratedKey, &command, ¶mSize); + } + /* get msaListBuffer */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&msaListBuffer, &command, ¶mSize); + } + /* get random */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&random, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + parentAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CMK_ConvertMigration: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the AuthData to use the key in parentHandle */ + /* get the key associated with parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* not r/o, using private key */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get parentHandle -> usageAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); + } + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + parentUsageAuth, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* 1. Validate the authorization to use the key in parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + parentAuth); /* Authorization digest for input */ + } + /* 2. If the keyUsage field of the key referenced by parentHandle does not have the value + TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_CMK_ConvertMigration: Error, " + "parentHandle -> keyUsage should be TPM_KEY_STORAGE, is %04x\n", + parentKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. Create d1 by decrypting the migratedKey -> encData area using the key in parentHandle */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_ConvertMigration: Decrypting encData\n"); + TPM_PrintFour("TPM_Process_CMK_ConvertMigration: encData", migratedKey.encData.buffer); + returnCode = TPM_RSAPrivateDecryptMalloc(&d1Decrypt, /* decrypted data */ + &d1DecryptLength, /* actual size of d1 data */ + migratedKey.encData.buffer, /* encrypted data */ + migratedKey.encData.size, + parentKey); + } + /* the random input parameter must be the same length as the decrypted data */ + if (returnCode == TPM_SUCCESS) { + if (d1DecryptLength != random.size) { + printf("TPM_Process_CMK_ConvertMigration: Error " + "decrypt data length %u random size %u\n", + d1DecryptLength, random.size); + returnCode = TPM_BAD_PARAMETER; + } + } + /* allocate memory for o1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc(&o1Oaep, d1DecryptLength); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_ConvertMigration: d1 length %u\n", d1DecryptLength); + TPM_PrintFour("TPM_Process_CMK_ConvertMigration: d1 -", d1Decrypt); + /* 4. Create o1 by XOR d1 and random parameter */ + TPM_XOR(o1Oaep, d1Decrypt, random.buffer, d1DecryptLength); + /* 5. Create m1 a TPM_MIGRATE_ASYMKEY, seed and pHash by OAEP decoding o1 */ + /* 7. Create k1 by combining seed and the TPM_MIGRATE_ASYMKEY -> partPrivKey */ + /* 8. Create d2 a TPM_STORE_ASYMKEY structure */ + /* a. Set the TPM_STORE_ASYMKEY -> privKey field to k1 */ + /* b. Set d2 -> usageAuth to m1 -> usageAuth */ + /* c. Set d2 -> pubDataDigest to m1 -> pubDataDigest */ + returnCode = TPM_StoreAsymkey_LoadO1(&d2AsymKey, o1Oaep, d1DecryptLength); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_ConvertMigration: Checking pHash\n"); + /* 6. Create migratedPubKey a TPM_PUBKEY structure corresponding to migratedKey */ + /* NOTE this function goes directly to the SHA1 digest */ + returnCode = TPM_Key_GeneratePubkeyDigest(migratedPubKeyDigest, &migratedKey); + } + /* 6.a. Verify that pHash == SHA-1( SHA-1[msaList] || SHA-1(migratedPubKey ) */ + /* deserialize to msaListBuffer to msaList */ + if (returnCode == TPM_SUCCESS) { + stream = msaListBuffer.buffer; + stream_size = msaListBuffer.size; + returnCode = TPM_MsaComposite_Load(&msaList, &stream, &stream_size); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(msaListDigest, &msaList, + (TPM_STORE_FUNCTION_T)TPM_MsaComposite_Store); + } + /* pHash is returned in TPM_STORE_ASYMKEY -> migrationAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_Check(d2AsymKey.migrationAuth, + TPM_DIGEST_SIZE, msaListDigest, + TPM_DIGEST_SIZE, migratedPubKeyDigest, + 0, NULL); + } + /* 9. Verify that parentHandle-> keyFlags -> migratable == FALSE and parentHandle-> encData -> + migrationAuth == tpmProof */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_ConvertMigration: Checking parent key\n"); + if (parentKey->keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_CMK_ConvertMigration: Error, parent migratable\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 10. Verify that m1 -> payload == TPM_PT_CMK_MIGRATE, then set d2-> payload = + TPM_PT_MIGRATE_EXTERNAL */ + /* NOTE TPM_StoreAsymkey_LoadO1() copied TPM_MIGRATE_ASYMKEY -> payload to TPM_STORE_ASYMKEY -> + payload */ + if (returnCode == TPM_SUCCESS) { + if (d2AsymKey.payload != TPM_PT_CMK_MIGRATE) { + printf("TPM_Process_CMK_ConvertMigration: Error, invalid payload %02x\n", + d2AsymKey.payload); + returnCode = TPM_BAD_MIGRATION; + } + else { + d2AsymKey.payload = TPM_PT_MIGRATE_EXTERNAL; + } + } + /* 11. Verify that for one of the n=1 to n=(msaList -> MSAlist) values of msaList -> + migAuthDigest[n], sigTicket == HMAC (V1) using tpmProof as the secret where V1 is a + TPM_CMK_SIGTICKET structure such that: */ + /* a. V1 -> verKeyDigest = msaList -> migAuthDigest[n] */ + /* b. V1 -> signedData = SHA-1[restrictTicket] */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CMK_ConvertMigration: Checking sigTicket\n"); + /* generate SHA1[restrictTicket] */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(v1CmkSigticket.signedData, &restrictTicket, + (TPM_STORE_FUNCTION_T)TPM_CmkAuth_Store); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour(" TPM_Process_CMK_ConvertMigration: TPM_CMK_SIGTICKET -> sigTicket", + v1CmkSigticket.signedData); + returnCode = TPM_MsaComposite_CheckSigTicket(sigTicket, + tpm_state->tpm_permanent_data.tpmProof, + &msaList, + &v1CmkSigticket); + } + } + /* 12. Create parentPubKey, a TPM_PUBKEY structure corresponding to parenthandle */ + if (returnCode == TPM_SUCCESS) { + /* NOTE this function goes directly to the SHA1 digest */ + returnCode = TPM_Key_GeneratePubkeyDigest(parentPubKeyDigest, parentKey); + } + /* 13. If [restrictTicket -> destinationKeyDigest] != SHA-1(parentPubKey), return error + TPM_MA_DESTINATION */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Compare(restrictTicket.destinationKeyDigest, + parentPubKeyDigest); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_CMK_ConvertMigration: Error checking destinationKeyDigest\n"); + returnCode = TPM_MA_DESTINATION; + } + } + /* 14. Verify that migratedKey is corresponding to d2 */ + /* NOTE check the private key against the public key */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_StorePrivkey_Convert(&d2AsymKey, + &(migratedKey.algorithmParms), + &(migratedKey.pubKey)); + } + /* 15. If migratedKey -> keyFlags -> migratable is FALSE, and return error TPM_INVALID_KEYUSAGE + */ + if (returnCode == TPM_SUCCESS) { + if (!(migratedKey.keyFlags & TPM_MIGRATABLE)) { + printf("TPM_Process_CMK_ConvertMigration: Error, migratedKey migratable is FALSE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 16. If migratedKey -> keyFlags -> migrateAuthority is FALSE, return error + TPM_INVALID_KEYUSAGE + */ + if (returnCode == TPM_SUCCESS) { + if (!(migratedKey.keyFlags & TPM_MIGRATEAUTHORITY)) { + printf("TPM_Process_CMK_ConvertMigration: Error, " + "migratedKey migrateauthority is FALSE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 17. If [restrictTicket -> sourceKeyDigest] != SHA-1(migratedPubKey), return error + TPM_MA_SOURCE */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Compare(restrictTicket.sourceKeyDigest, migratedPubKeyDigest); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_CMK_ConvertMigration: Error checking sourceKeyDigest\n"); + returnCode = TPM_MA_SOURCE; + } + } + /* 18. Create M2 a TPM_CMK_MIGAUTH structure */ + /* NOTE Done by TPM_CmkMigauth_Init() */ + /* a. Set M2 -> msaDigest to SHA-1[msaList] */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(m2CmkMigauth.msaDigest, &msaList, + (TPM_STORE_FUNCTION_T)TPM_MsaComposite_Store); + } + if (returnCode == TPM_SUCCESS) { + /* b. Set M2 -> pubKeyDigest to SHA-1[migratedPubKey] */ + TPM_Digest_Copy(m2CmkMigauth.pubKeyDigest, migratedPubKeyDigest); + /* 19. Set d2 -> migrationAuth = HMAC(M2) using tpmProof as the secret */ + returnCode = TPM_HMAC_GenerateStructure + (d2AsymKey.migrationAuth, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &m2CmkMigauth, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_CmkMigauth_Store); /* store function */ + } + /* 21. Create outData using the key in parentHandle to perform the encryption */ + if (returnCode == TPM_SUCCESS) { + /* serialize d2Asymkey to d2_sbuffer */ + returnCode = TPM_StoreAsymkey_Store(&d2_sbuffer, FALSE, &d2AsymKey); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPublicEncryptSbuffer_Key(&outData, &d2_sbuffer, parentKey); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CMK_ConvertMigration: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the outData */ + returnCode = TPM_SizedBuffer_Store(response, &outData); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_CmkAuth_Delete(&restrictTicket); /* @1 */ + TPM_Key_Delete(&migratedKey); /* @2 */ + TPM_SizedBuffer_Delete(&msaListBuffer); /* @3 */ + TPM_SizedBuffer_Delete(&random); /* @4 */ + TPM_SizedBuffer_Delete(&outData); /* @5 */ + free(d1Decrypt); /* @6 */ + TPM_MsaComposite_Delete(&msaList); /* @7 */ + TPM_StoreAsymkey_Delete(&d2AsymKey); /* @8 */ + TPM_Sbuffer_Delete(&d2_sbuffer); /* @9 */ + TPM_CmkSigticket_Delete(&v1CmkSigticket); /* @10 */ + free(o1Oaep); /* @11 */ + TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @12 */ + return rcf; +} diff --git a/src/tpm12/tpm_migration.h b/src/tpm12/tpm_migration.h new file mode 100644 index 0000000..91f9fa3 --- /dev/null +++ b/src/tpm12/tpm_migration.h @@ -0,0 +1,218 @@ +/********************************************************************************/ +/* */ +/* Migration */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_migration.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_MIGRATION_H +#define TPM_MIGRATION_H + +#include "tpm_global.h" + +/* + TPM_MIGRATIONKEYAUTH +*/ + +void TPM_Migrationkeyauth_Init(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth); +TPM_RESULT TPM_Migrationkeyauth_Load(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Migrationkeyauth_Store(TPM_STORE_BUFFER *sbuffer, + TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth); +void TPM_Migrationkeyauth_Delete(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth); + +/* + TPM_MSA_COMPOSITE +*/ + +void TPM_MsaComposite_Init(TPM_MSA_COMPOSITE *tpm_msa_composite); +TPM_RESULT TPM_MsaComposite_Load(TPM_MSA_COMPOSITE *tpm_msa_composite, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_MsaComposite_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_MSA_COMPOSITE *tpm_msa_composite); +void TPM_MsaComposite_Delete(TPM_MSA_COMPOSITE *tpm_msa_composite); + +TPM_RESULT TPM_MsaComposite_CheckMigAuthDigest(TPM_DIGEST tpm_digest, + TPM_MSA_COMPOSITE *tpm_msa_composite); +TPM_RESULT TPM_MsaComposite_CheckSigTicket(TPM_DIGEST sigTicket, + TPM_SECRET tpmProof, + TPM_MSA_COMPOSITE *tpm_msa_composite, + TPM_CMK_SIGTICKET *tpm_cmk_sigticket); + +/* + TPM_CMK_AUTH +*/ + +void TPM_CmkAuth_Init(TPM_CMK_AUTH *tpm_cmk_auth); +TPM_RESULT TPM_CmkAuth_Load(TPM_CMK_AUTH *tpm_cmk_auth, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_CmkAuth_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CMK_AUTH *tpm_cmk_auth); +void TPM_CmkAuth_Delete(TPM_CMK_AUTH *tpm_cmk_auth); + +/* + TPM_CMK_MIGAUTH +*/ + +void TPM_CmkMigauth_Init(TPM_CMK_MIGAUTH *tpm_cmk_migauth); +TPM_RESULT TPM_CmkMigauth_Load(TPM_CMK_MIGAUTH *tpm_cmk_migauth, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_CmkMigauth_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CMK_MIGAUTH *tpm_cmk_migauth); +void TPM_CmkMigauth_Delete(TPM_CMK_MIGAUTH *tpm_cmk_migauth); + +TPM_RESULT TPM_CmkMigauth_CheckHMAC(TPM_BOOL *valid, + TPM_HMAC tpm_hmac, + TPM_SECRET tpm_hmac_key, + TPM_CMK_MIGAUTH *tpm_cmk_migauth); + +/* + TPM_CMK_SIGTICKET +*/ + +void TPM_CmkSigticket_Init(TPM_CMK_SIGTICKET *tpm_cmk_sigticket); +TPM_RESULT TPM_CmkSigticket_Load(TPM_CMK_SIGTICKET *tpm_cmk_sigticket, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_CmkSigticket_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CMK_SIGTICKET *tpm_cmk_sigticket); +void TPM_CmkSigticket_Delete(TPM_CMK_SIGTICKET *tpm_cmk_sigticket); + +/* + TPM_CMK_MA_APPROVAL +*/ + +void TPM_CmkMaApproval_Init(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval); +TPM_RESULT TPM_CmkMaApproval_Load(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_CmkMaApproval_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval); +void TPM_CmkMaApproval_Delete(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval); + +TPM_RESULT TPM_CmkMaApproval_CheckHMAC(TPM_BOOL *valid, + TPM_HMAC tpm_hmac, + TPM_SECRET tpm_hmac_key, + TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval); + +/* + Processing Functions +*/ + +TPM_RESULT TPM_CreateBlobCommon(TPM_SIZED_BUFFER *outData, + TPM_STORE_ASYMKEY *d1Key, + TPM_DIGEST pHash, + TPM_PAYLOAD_TYPE payload_type, + TPM_SIZED_BUFFER *random, + TPM_PUBKEY *migrationKey); + +TPM_RESULT TPM_Process_CreateMigrationBlob(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ConvertMigrationBlob(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_AuthorizeMigrationKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_MigrateKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CMK_CreateKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CMK_CreateTicket(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CMK_CreateBlob(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CMK_SetRestrictions(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CMK_ApproveMA(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CMK_ConvertMigration(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + + +#endif diff --git a/src/tpm12/tpm_nonce.c b/src/tpm12/tpm_nonce.c new file mode 100644 index 0000000..115bef6 --- /dev/null +++ b/src/tpm12/tpm_nonce.c @@ -0,0 +1,157 @@ +/********************************************************************************/ +/* */ +/* Nonce Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_nonce.c 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_crypto.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_structures.h" + +#include "tpm_nonce.h" + +/* TPM_Nonce_Init resets a nonce structure to zeros */ + +void TPM_Nonce_Init(TPM_NONCE tpm_nonce) +{ + size_t i; + + printf(" TPM_Nonce_Init:\n"); + for (i = 0 ; i < TPM_NONCE_SIZE ; i++) { + tpm_nonce[i] = 0; + } + return; +} + +/* TPM_Nonce_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes +*/ + + +TPM_RESULT TPM_Nonce_Load(TPM_NONCE tpm_nonce, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Nonce_Load:\n"); + rc = TPM_Loadn(tpm_nonce, TPM_NONCE_SIZE, stream, stream_size); + return rc; +} + +/* TPM_Nonce_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + After use, call TPM_Sbuffer_Delete() to free memory +*/ + +TPM_RESULT TPM_Nonce_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_NONCE tpm_nonce) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Nonce_Store:\n"); + rc = TPM_Sbuffer_Append(sbuffer, tpm_nonce, TPM_NONCE_SIZE); + return rc; +} + +/* TPM_Nonce_Copy() copies the source to the destination + */ + +void TPM_Nonce_Copy(TPM_NONCE destination, const TPM_NONCE source) +{ + printf(" TPM_Nonce_Copy:\n"); + memcpy(destination, source, TPM_NONCE_SIZE); + return; +} + +/* TPM_Nonce_Compare() compares the source to the destination. + + Returns TPM_AUTHFAIL if the nonces are not equal +*/ + +TPM_RESULT TPM_Nonce_Compare(TPM_NONCE expect, const TPM_NONCE actual) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Nonce_Compare:\n"); + rc = memcmp(expect, actual, TPM_NONCE_SIZE); + if (rc != 0) { + printf("TPM_Nonce_Compare: Error comparing nonce\n"); + TPM_PrintFour(" TPM_Nonce_Compare: Expect", expect); + TPM_PrintFour(" TPM_Nonce_Compare: Actual", actual); + rc = TPM_AUTHFAIL; + } + return rc; +} + +/* TPM_Nonce_Generate() generates a new nonce from the random number generator + */ + +TPM_RESULT TPM_Nonce_Generate(TPM_NONCE tpm_nonce) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Nonce_Generate:\n"); + rc = TPM_Random(tpm_nonce, TPM_NONCE_SIZE); + return rc; +} + +/* TPM_Nonce_IsZero() returns 'isZero' TRUE is all bytes 'tpm_nonce' are 0x00 + */ + +void TPM_Nonce_IsZero(TPM_BOOL *isZero, TPM_NONCE tpm_nonce) +{ + size_t i; + + printf(" TPM_Nonce_IsZero:\n"); + for (i = 0, *isZero = TRUE ; (i < TPM_NONCE_SIZE) && *isZero ; i++) { + if (tpm_nonce[i] != 0) { + *isZero = FALSE; + } + } + return; +} + diff --git a/src/tpm12/tpm_nonce.h b/src/tpm12/tpm_nonce.h new file mode 100644 index 0000000..a2113f8 --- /dev/null +++ b/src/tpm12/tpm_nonce.h @@ -0,0 +1,60 @@ +/********************************************************************************/ +/* */ +/* Nonce Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_nonce.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_NONCE_H +#define TPM_NONCE_H + +#include "tpm_store.h" +#include "tpm_structures.h" + +void TPM_Nonce_Init(TPM_NONCE tpm_nonce); + +TPM_RESULT TPM_Nonce_Generate(TPM_NONCE tpm_nonce); + +void TPM_Nonce_Copy(TPM_NONCE destination, + const TPM_NONCE source); +TPM_RESULT TPM_Nonce_Load(TPM_NONCE tpm_nonce, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Nonce_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_NONCE tpm_nonce); +TPM_RESULT TPM_Nonce_Compare(TPM_NONCE expect, const TPM_NONCE actual); +void TPM_Nonce_IsZero(TPM_BOOL *isZero, TPM_NONCE tpm_nonce); + +#endif diff --git a/src/tpm12/tpm_nvram.c b/src/tpm12/tpm_nvram.c new file mode 100644 index 0000000..1235973 --- /dev/null +++ b/src/tpm12/tpm_nvram.c @@ -0,0 +1,3747 @@ +/********************************************************************************/ +/* */ +/* NVRAM Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_nvram.c 4724 2014-08-11 20:33:23Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include +#include + +#include "tpm_auth.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_memory.h" +#include "tpm_nvfile.h" +#include "tpm_pcr.h" +#include "tpm_permanent.h" +#include "tpm_platform.h" +#include "tpm_process.h" +#include "tpm_secret.h" +#include "tpm_storage.h" +#include "tpm_structures.h" + +#include "tpm_nvram.h" + +/* + NV Defined Space Utilities +*/ + +/* + TPM_NV_ATTRIBUTES +*/ + +/* TPM_NVAttributes_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_NVAttributes_Init(TPM_NV_ATTRIBUTES *tpm_nv_attributes) +{ + printf(" TPM_NVAttributes_Init:\n"); + tpm_nv_attributes->attributes = 0; + return; +} + +/* TPM_NVAttributes_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_NVAttributes_Init() + After use, call TPM_NVAttributes_Delete() to free memory +*/ + +TPM_RESULT TPM_NVAttributes_Load(TPM_NV_ATTRIBUTES *tpm_nv_attributes, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_NVAttributes_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_NV_ATTRIBUTES, stream, stream_size); + } + /* load attributes */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_nv_attributes->attributes), stream, stream_size); + } + return rc; +} + +/* TPM_NVAttributes_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_NVAttributes_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_NV_ATTRIBUTES *tpm_nv_attributes) +{ + TPM_RESULT rc = 0; + + printf(" TPM_NVAttributes_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NV_ATTRIBUTES); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_nv_attributes->attributes); + } + return rc; +} + +/* TPM_NVAttributes_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the nv_attributes + sets pointers to NULL + calls TPM_NVAttributes_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_NVAttributes_Delete(TPM_NV_ATTRIBUTES *tpm_nv_attributes) +{ + printf(" TPM_NVAttributes_Delete:\n"); + if (tpm_nv_attributes != NULL) { + TPM_NVAttributes_Init(tpm_nv_attributes); + } + return; +} + +void TPM_NVAttributes_Copy(TPM_NV_ATTRIBUTES *tpm_nv_attributes_dest, + TPM_NV_ATTRIBUTES *tpm_nv_attributes_src) +{ + tpm_nv_attributes_dest->attributes = tpm_nv_attributes_src->attributes; + return; +} + +/* + TPM_NV_DATA_PUBLIC +*/ + +/* TPM_NVDataPublic_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_NVDataPublic_Init(TPM_NV_DATA_PUBLIC *tpm_nv_data_public) +{ + printf(" TPM_NVDataPublic_Init:\n"); + tpm_nv_data_public->nvIndex = TPM_NV_INDEX_LOCK; /* mark unused */ + TPM_PCRInfoShort_Init(&(tpm_nv_data_public->pcrInfoRead)); + TPM_PCRInfoShort_Init(&(tpm_nv_data_public->pcrInfoWrite)); + TPM_NVAttributes_Init(&(tpm_nv_data_public->permission)); + tpm_nv_data_public->bReadSTClear = FALSE; + tpm_nv_data_public->bWriteSTClear = FALSE; + tpm_nv_data_public->bWriteDefine = FALSE; + tpm_nv_data_public->dataSize = 0; + return; +} + +/* TPM_NVDataPublic_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_NVDataPublic_Init() + After use, call TPM_NVDataPublic_Delete() to free memory +*/ + +TPM_RESULT TPM_NVDataPublic_Load(TPM_NV_DATA_PUBLIC *tpm_nv_data_public, + unsigned char **stream, + uint32_t *stream_size, + TPM_BOOL optimize) +{ + TPM_RESULT rc = 0; + + printf(" TPM_NVDataPublic_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_NV_DATA_PUBLIC, stream, stream_size); + } + /* load nvIndex */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_nv_data_public->nvIndex), stream, stream_size); + } + /* load pcrInfoRead */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Load(&(tpm_nv_data_public->pcrInfoRead), stream, stream_size, optimize); + } + /* load pcrInfoWrite */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Load(&(tpm_nv_data_public->pcrInfoWrite), stream, stream_size, optimize); + } + /* load permission */ + if (rc == 0) { + rc = TPM_NVAttributes_Load(&(tpm_nv_data_public->permission), stream, stream_size); + } + /* load bReadSTClear */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_nv_data_public->bReadSTClear), stream, stream_size); + } + /* load bWriteSTClear */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_nv_data_public->bWriteSTClear), stream, stream_size); + } + /* load bWriteDefine */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_nv_data_public->bWriteDefine), stream, stream_size); + } + /* load dataSize */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_nv_data_public->dataSize), stream, stream_size); + } + return rc; +} + +/* TPM_NVDataPublic_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_NVDataPublic_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_NV_DATA_PUBLIC *tpm_nv_data_public, + TPM_BOOL optimize) +{ + TPM_RESULT rc = 0; + + printf(" TPM_NVDataPublic_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NV_DATA_PUBLIC); + } + /* store nvIndex */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_nv_data_public->nvIndex); + } + /* store pcrInfoRead */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_nv_data_public->pcrInfoRead), optimize); + } + /* store pcrInfoWrite */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_nv_data_public->pcrInfoWrite), optimize); + } + /* store permission */ + if (rc == 0) { + rc = TPM_NVAttributes_Store(sbuffer, &(tpm_nv_data_public->permission)); + } + /* store bReadSTClear */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_nv_data_public->bReadSTClear), sizeof(TPM_BOOL)); + } + /* store bWriteSTClear */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_nv_data_public->bWriteSTClear), sizeof(TPM_BOOL)); + } + /* store bWriteDefine */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_nv_data_public->bWriteDefine), sizeof(TPM_BOOL)); + } + /* store dataSize */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_nv_data_public->dataSize); + } + return rc; +} + +/* TPM_NVDataPublic_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_NVDataPublic_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_NVDataPublic_Delete(TPM_NV_DATA_PUBLIC *tpm_nv_data_public) +{ + printf(" TPM_NVDataPublic_Delete:\n"); + if (tpm_nv_data_public != NULL) { + TPM_PCRInfoShort_Delete(&(tpm_nv_data_public->pcrInfoRead)); + TPM_PCRInfoShort_Delete(&(tpm_nv_data_public->pcrInfoWrite)); + TPM_NVAttributes_Delete(&(tpm_nv_data_public->permission)); + TPM_NVDataPublic_Init(tpm_nv_data_public); + } + return; +} + +/* + TPM_NV_DATA_SENSITIVE +*/ + +/* TPM_NVDataSensitive_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_NVDataSensitive_Init(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive) +{ + printf(" TPM_NVDataSensitive_Init:\n"); + TPM_NVDataPublic_Init(&(tpm_nv_data_sensitive->pubInfo)); + TPM_Secret_Init(tpm_nv_data_sensitive->authValue); + tpm_nv_data_sensitive->data = NULL; + TPM_Digest_Init(tpm_nv_data_sensitive->digest); + return; +} + +/* TPM_NVDataSensitive_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_NVDataSensitive_Init() + After use, call TPM_NVDataSensitive_Delete() to free memory +*/ + +TPM_RESULT TPM_NVDataSensitive_Load(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive, + TPM_TAG nvEntriesVersion, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + TPM_BOOL optimize; + TPM_BOOL isGPIO; + + printf(" TPM_NVDataSensitive_Load: nvEntriesVersion %04hx\n", nvEntriesVersion); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_NV_DATA_SENSITIVE, stream, stream_size); + } + /* load pubInfo */ + if (rc == 0) { + /* versions after V1 optimise the serialization */ + optimize = (nvEntriesVersion != TPM_TAG_NVSTATE_NV_V1); + rc = TPM_NVDataPublic_Load(&(tpm_nv_data_sensitive->pubInfo), + stream, stream_size, + optimize); /* optimize digestAtRelease */ + } + /* load authValue */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_nv_data_sensitive->authValue, stream, stream_size); + } + /* is the nvIndex GPIO space */ + if (rc == 0) { + rc = TPM_NVDataSensitive_IsGPIO(&isGPIO, tpm_nv_data_sensitive->pubInfo.nvIndex); + } + /* allocate memory for data */ + if ((rc == 0) && !isGPIO) { + rc = TPM_Malloc(&(tpm_nv_data_sensitive->data), + tpm_nv_data_sensitive->pubInfo.dataSize); + } + /* load data */ + if ((rc == 0) && !isGPIO) { + rc = TPM_Loadn(tpm_nv_data_sensitive->data, tpm_nv_data_sensitive->pubInfo.dataSize, + stream, stream_size); + } + /* create digest. The digest is not stored to save NVRAM space */ + if (rc == 0) { + rc = TPM_SHA1(tpm_nv_data_sensitive->digest, + sizeof(TPM_NV_INDEX), + (unsigned char *)&tpm_nv_data_sensitive->pubInfo.nvIndex, + TPM_AUTHDATA_SIZE, tpm_nv_data_sensitive->authValue, + 0, NULL); + } + return rc; +} + +/* TPM_NVDataSensitive_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + nvWrite TRUE indicates a write command, not a command to define the space. +*/ + +TPM_RESULT TPM_NVDataSensitive_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive) +{ + TPM_RESULT rc = 0; + TPM_BOOL isGPIO; + + printf(" TPM_NVDataSensitive_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NV_DATA_SENSITIVE); + } + /* store pubInfo */ + if (rc == 0) { + rc = TPM_NVDataPublic_Store(sbuffer, &(tpm_nv_data_sensitive->pubInfo), + TRUE); /* optimize digestAtRelease */ + } + /* store authValue */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_nv_data_sensitive->authValue); + } + /* is the nvIndex GPIO space */ + if (rc == 0) { + rc = TPM_NVDataSensitive_IsGPIO(&isGPIO, tpm_nv_data_sensitive->pubInfo.nvIndex); + } + /* store data */ + if ((rc == 0) && !isGPIO) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_nv_data_sensitive->data, + tpm_nv_data_sensitive->pubInfo.dataSize); + } + return rc; +} + +/* TPM_NVDataSensitive_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_NVDataSensitive_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_NVDataSensitive_Delete(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive) +{ + printf(" TPM_NVDataSensitive_Delete:\n"); + if (tpm_nv_data_sensitive != NULL) { + /* zero any secrets in NV index data */ + if (tpm_nv_data_sensitive->data != NULL) { + memset(tpm_nv_data_sensitive->data, 0xff, tpm_nv_data_sensitive->pubInfo.dataSize); + } + TPM_NVDataPublic_Delete(&(tpm_nv_data_sensitive->pubInfo)); + TPM_Secret_Delete(tpm_nv_data_sensitive->authValue); + free(tpm_nv_data_sensitive->data); + TPM_NVDataSensitive_Init(tpm_nv_data_sensitive); + } + return; +} + +/* TPM_NVDataSensitive_IsValidIndex() determines if 'nvIndex' is permissible for an NV defined space + TPM_NV_DATA_SENSITIVE structure. + + Some values have special meaning, so they are allowed for the TPM_NV_DefineSpace command but will + not actually define a space. +*/ + +TPM_RESULT TPM_NVDataSensitive_IsValidIndex(TPM_NV_INDEX nvIndex) +{ + TPM_RESULT rc = 0; + TPM_BOOL isGPIO; + + printf(" TPM_NVDataSensitive_IsValidIndex: nvIndex %08x\n", nvIndex); + if (rc == 0) { + if ((nvIndex == TPM_NV_INDEX_LOCK) || + (nvIndex == TPM_NV_INDEX0) || + (nvIndex == TPM_NV_INDEX_DIR)) { + printf("TPM_NVDataSensitive_IsValidIndex: Error, illegal special index\n"); + rc = TPM_BADINDEX; + } + } + if (rc == 0) { + if ((nvIndex & TPM_NV_INDEX_RESVD) != 0) { + printf("TPM_NVDataSensitive_IsValidIndex: Error, illegal reserved index\n"); + rc = TPM_BADINDEX; + } + } + if (rc == 0) { + rc = TPM_NVDataSensitive_IsValidPlatformIndex(nvIndex); + } + /* The GPIO range validity is platform dependent */ + if (rc == 0) { + rc = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); + } + return rc; +} + +/* TPM_NVDataSensitive_IsGPIO() determines if 'nvIndex' is in the GPIO range and is valid. + + Returns: + + TPM_SUCCESS , FALSE if 'nvIndex' is not in the GPIO range + TPM_SUCCESS , TRUE if 'nvIndex' is in the GPIO range and the platform allows GPIO defined space + TPM_BADINDEX, FALSE if 'nvIndex' is in the GPIO range and the platform does not allow GPIO + defined space +*/ + +TPM_RESULT TPM_NVDataSensitive_IsGPIO(TPM_BOOL *isGPIO, TPM_NV_INDEX nvIndex) +{ + TPM_RESULT rc = 0; + + printf(" TPM_NVDataSensitive_IsGPIO: nvIndex %08x\n", nvIndex); + *isGPIO = FALSE; +#if defined TPM_PCCLIENT + if (rc == 0) { + /* GPIO space allowed for PC Client */ + if ((nvIndex >= TPM_NV_INDEX_GPIO_START) && + (nvIndex <= TPM_NV_INDEX_GPIO_END)) { + printf(" TPM_NVDataSensitive_IsGPIO: nvIndex is GPIO space\n"); + *isGPIO = TRUE; + } + } + /* #elif */ +#else + if (rc == 0) { + /* GPIO space cannot be defined in platforms with no GPIO */ + if ((nvIndex >= TPM_NV_INDEX_GPIO_START) && + (nvIndex <= TPM_NV_INDEX_GPIO_END)) { + printf("TPM_NVDataSensitive_IsGPIO: Error, illegal index\n"); + rc = TPM_BADINDEX; + } + } +#endif + return rc; +} + +TPM_RESULT TPM_NVDataSensitive_IsValidPlatformIndex(TPM_NV_INDEX nvIndex) +{ + TPM_RESULT rc = 0; + + printf(" TPM_NVDataSensitive_IsValidPlatformIndex: nvIndex %08x\n", nvIndex); +#ifndef TPM_PCCLIENT + if (rc == 0) { + if (((nvIndex & TPM_NV_INDEX_PURVIEW_MASK) >> TPM_NV_INDEX_PURVIEW_BIT) == TPM_PC) { + printf(" TPM_NVDataSensitive_IsValidPlatformIndex: Error, PC Client index\n"); + rc = TPM_BADINDEX; + } + } +#endif + return rc; +} + +/* + NV Index Entries + + This handles the in-memory copy of NV defined space +*/ + +/* + TPM_NVIndexEntries_Init() initializes the TPM_NV_INDEX_ENTRIES array +*/ + +void TPM_NVIndexEntries_Init(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + printf(" TPM_NVIndexEntries_Init:\n"); + tpm_nv_index_entries->nvIndexCount = 0; + tpm_nv_index_entries->tpm_nvindex_entry = NULL; + return; +} + +/* + TPM_NVIndexEntries_Delete() iterates through the entire TPM_NV_INDEX_ENTRIES array, deleting any + used entries. + + It then frees and reinitializes the array. +*/ + + +void TPM_NVIndexEntries_Delete(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + size_t i; + + printf(" TPM_NVIndexEntries_Delete: Deleting from %u slots\n", + tpm_nv_index_entries->nvIndexCount); + /* free the entries */ + for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { + TPM_NVDataSensitive_Delete(&(tpm_nv_index_entries->tpm_nvindex_entry[i])); + } + /* free the array */ + free(tpm_nv_index_entries->tpm_nvindex_entry); + TPM_NVIndexEntries_Init(tpm_nv_index_entries); + return; +} + +/* TPM_NVIndexEntries_Trace() traces the TPM_NV_INDEX_ENTRIES array. + + Edit and call as required for debugging. +*/ + +void TPM_NVIndexEntries_Trace(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + uint32_t i; + TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; + + printf("\tTPM_NVIndexEntries_Trace: %u slots\n", tpm_nv_index_entries->nvIndexCount); + for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { + tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); + printf("\tTPM_NVIndexEntries_Trace: TPM_NV_DATA_SENSITIVE.data %p\n", + tpm_nv_data_sensitive->data); + } + return; +} + +/* + TPM_NVIndexEntries_Load() loads the TPM_NV_INDEX_ENTRIES array from a stream. + + The first data in the stream must be a uint32_t count of the number of entries to follow. +*/ + +TPM_RESULT TPM_NVIndexEntries_Load(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t i; + TPM_TAG nvEntriesVersion; + + printf(" TPM_NVIndexEntries_Load:\n"); + /* get the NV entries version number */ + if (rc == 0) { + rc = TPM_Load16(&nvEntriesVersion, stream, stream_size); + } + /* check tag */ + if (rc == 0) { + switch (nvEntriesVersion) { + case TPM_TAG_NVSTATE_NV_V1: + case TPM_TAG_NVSTATE_NV_V2: + break; + default: + printf("TPM_NVIndexEntries_Load: Error (fatal), version %04x unsupported\n", + nvEntriesVersion); + rc = TPM_FAIL; + break; + } + } + /* nvIndexCount */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_nv_index_entries->nvIndexCount), stream, stream_size); + } + /* allocate memory for the array, nvIndexCount TPM_NV_DATA_SENSITIVE structures */ + if ((rc == 0) && (tpm_nv_index_entries->nvIndexCount > 0)) { + printf(" TPM_NVIndexEntries_Load: Loading %u slots\n", tpm_nv_index_entries->nvIndexCount); + rc = TPM_Malloc((unsigned char **)&(tpm_nv_index_entries->tpm_nvindex_entry), + sizeof(TPM_NV_DATA_SENSITIVE) * tpm_nv_index_entries->nvIndexCount); + } + /* immediately after allocating, initialize so that _Delete is safe even on a _Load error */ + for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { + TPM_NVDataSensitive_Init(&(tpm_nv_index_entries->tpm_nvindex_entry[i])); + } + /* tpm_nvindex_entry array */ + for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { + printf(" TPM_NVIndexEntries_Load: Loading slot %u\n", i); + if (rc == 0) { + rc = TPM_NVDataSensitive_Load(&(tpm_nv_index_entries->tpm_nvindex_entry[i]), + nvEntriesVersion, stream, stream_size); + } + /* should never load an unused entry */ + if (rc == 0) { + printf(" TPM_NVIndexEntries_Load: Loaded NV index %08x\n", + tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); + if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex == TPM_NV_INDEX_LOCK) { + printf("TPM_NVIndexEntries_Load: Error (fatal) Entry %u bad NV index %08x\n", + i, tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); + rc = TPM_FAIL; + } + } + } + return rc; +} + +/* + TPM_NVIndexEntries_Store() serializes the TPM_NV_INDEX_ENTRIES array into a stream. Only used + entries are serialized. + + The first data in the stream is the used count, obtained by iterating through the array. +*/ + +TPM_RESULT TPM_NVIndexEntries_Store(TPM_STORE_BUFFER *sbuffer, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + uint32_t count; /* number of used entries to store */ + size_t i; + + printf(" TPM_NVIndexEntries_Store: Storing from %u slots\n", + tpm_nv_index_entries->nvIndexCount); + /* append the NV entries version number to the stream */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_NV_V2); + } + /* count the number of used entries */ + if (rc == 0) { + rc = TPM_NVIndexEntries_GetUsedCount(&count, tpm_nv_index_entries); + } + /* store the actual used count, not the number of array entries */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, count); + } + /* tpm_nvindex_entry array */ + for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { + /* if the entry is used */ + if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { + printf(" TPM_NVIndexEntries_Store: Storing slot %lu NV index %08x\n", + (unsigned long)i, tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); + rc = TPM_NVDataSensitive_Store(sbuffer, &(tpm_nv_index_entries->tpm_nvindex_entry[i])); + } + else { + printf(" TPM_NVIndexEntries_Store: Skipping unused slot %lu\n", (unsigned long)i); + } + } + return rc; +} + +/* TPM_NVIndexEntries_StClear() steps through each entry in the NV TPM_NV_INDEX_ENTRIES array, + setting the volatile flags to FALSE. +*/ + +void TPM_NVIndexEntries_StClear(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + size_t i; + + printf(" TPM_NVIndexEntries_StClear: Clearing %u slots\n", tpm_nv_index_entries->nvIndexCount); + /* bReadSTClear and bWriteSTClear are volatile, in that they are set FALSE at + TPM_Startup(ST_Clear) */ + for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { + tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.bReadSTClear = FALSE; + tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.bWriteSTClear = FALSE; + } + return; +} + +/* TPM_NVIndexEntries_LoadVolatile() deserializes the stream into the volatile members of the + TPM_NV_INDEX_ENTRIES array. +*/ + +TPM_RESULT TPM_NVIndexEntries_LoadVolatile(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t usedCount; + uint32_t entryIndex; + TPM_NV_DATA_PUBLIC *tpm_nv_data_public; + + printf(" TPM_NVIndexEntries_LoadVolatile:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_NV_INDEX_ENTRIES_VOLATILE_V1, stream, stream_size); + } + /* Get the number of used slots. This should be equal to the total number of slots. */ + if (rc == 0) { + rc = TPM_Load32(&usedCount, stream, stream_size); + } + if (rc == 0) { + printf(" TPM_NVIndexEntries_LoadVolatile: usedCount %u\n", usedCount); + if (usedCount != tpm_nv_index_entries->nvIndexCount) { + printf("TPM_NVIndexEntries_LoadVolatile: Error (fatal), " + "usedCount %u does not equal slot count %u\n", + usedCount, tpm_nv_index_entries->nvIndexCount); + rc = TPM_FAIL; + } + } + /* deserialize the stream into the TPM_NV_INDEX_ENTRIES array */ + for (entryIndex = 0 ; + (rc == 0) && (entryIndex < tpm_nv_index_entries->nvIndexCount) ; + entryIndex++) { + + tpm_nv_data_public = &(tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo); + printf(" TPM_NVIndexEntries_LoadVolatile: Loading index %08x\n", + tpm_nv_data_public->nvIndex); + /* load bReadSTClear */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_nv_data_public->bReadSTClear), stream, stream_size); + } + /* load bWriteSTClear */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_nv_data_public->bWriteSTClear), stream, stream_size); + } + } + return rc; +} + +/* TPM_NVIndexEntries_StoreVolatile() serializes the volatile members of the + TPM_NV_INDEX_ENTRIES array into the TPM_STORE_BUFFER. +*/ + +TPM_RESULT TPM_NVIndexEntries_StoreVolatile(TPM_STORE_BUFFER *sbuffer, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + uint32_t usedCount; + uint32_t entryIndex; + TPM_NV_DATA_PUBLIC *tpm_nv_data_public; + + printf(" TPM_NVIndexEntries_StoreVolatile: %u slots\n", tpm_nv_index_entries->nvIndexCount); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NV_INDEX_ENTRIES_VOLATILE_V1); + } + /* Get the number of used slots. If indexes were deleted since the last TPM_Init, there can be + some unused slots. */ + if (rc == 0) { + rc = TPM_NVIndexEntries_GetUsedCount(&usedCount, tpm_nv_index_entries); + } + /* store usedCount */ + if (rc == 0) { + printf(" TPM_NVIndexEntries_StoreVolatile: usedCount %u\n", usedCount); + rc = TPM_Sbuffer_Append32(sbuffer, usedCount); + } + /* save entries into the array */ + for (entryIndex = 0 ; + (rc == 0) && (entryIndex < tpm_nv_index_entries->nvIndexCount) ; + entryIndex++) { + /* Only save used slots. During a rollback, slots are deleted and recreated. At that time, + unused slots will be reclaimed. */ + if (tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.nvIndex != + TPM_NV_INDEX_LOCK) { + + tpm_nv_data_public = &(tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo); + printf(" TPM_NVIndexEntries_StoreVolatile: Storing index %08x\n", + tpm_nv_data_public->nvIndex); + /* store bReadSTClear */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + &(tpm_nv_data_public->bReadSTClear), sizeof(TPM_BOOL)); + } + /* store bWriteSTClear */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + &(tpm_nv_data_public->bWriteSTClear), sizeof(TPM_BOOL)); + } + } + } + return rc; +} + +/* TPM_NVIndexEntries_GetVolatile() saves an array of the NV defined space volatile flags. + + The array is used during a rollback, since the volatile flags are not stored in NVRAM +*/ + +TPM_RESULT TPM_NVIndexEntries_GetVolatile(TPM_NV_DATA_ST **tpm_nv_data_st, /* freed by caller */ + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + uint32_t usedCount; + uint32_t entryIndex; + uint32_t usedIndex; + + printf(" TPM_NVIndexEntries_GetVolatile: %u slots\n", tpm_nv_index_entries->nvIndexCount); + /* Get the number of used slots. If indexes were deleted since the last TPM_Init, there can be + some unused slots. */ + if (rc == 0) { + rc = TPM_NVIndexEntries_GetUsedCount(&usedCount, tpm_nv_index_entries); + } + /* allocate memory for the array, nvIndexCount TPM_NV_DATA_SENSITIVE structures */ + if ((rc == 0) && (usedCount > 0)) { + printf(" TPM_NVIndexEntries_GetVolatile: Aloocating for %u used slots\n", usedCount); + rc = TPM_Malloc((unsigned char **)tpm_nv_data_st, + sizeof(TPM_NV_DATA_ST) * usedCount); + } + /* save entries into the array */ + for (entryIndex = 0 , usedIndex = 0 ; + (rc == 0) && (entryIndex < tpm_nv_index_entries->nvIndexCount) && (usedCount > 0) ; + entryIndex++) { + /* Only save used slots. During a rollback, slots are deleted and recreated. At that time, + unused slots will be reclaimed. */ + if (tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.nvIndex != + TPM_NV_INDEX_LOCK) { + + printf(" TPM_NVIndexEntries_GetVolatile: Saving slot %u at used %u NV index %08x\n", + entryIndex, usedIndex, + tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.nvIndex); + + printf(" TPM_NVIndexEntries_GetVolatile: bReadSTClear %u bWriteSTClear %u\n", + tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.bReadSTClear, + tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.bWriteSTClear); + (*tpm_nv_data_st)[usedIndex].nvIndex = + tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.nvIndex; + (*tpm_nv_data_st)[usedIndex].bReadSTClear = + tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.bReadSTClear; + (*tpm_nv_data_st)[usedIndex].bWriteSTClear = + tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.bWriteSTClear; + usedIndex++; + } + } + return rc; +} + +/* TPM_NVIndexEntries_SetVolatile() restores an array of the NV defined space volatile flags. + + The array is used during a rollback, since the volatile flags are not stored in NVRAM +*/ + +TPM_RESULT TPM_NVIndexEntries_SetVolatile(TPM_NV_DATA_ST *tpm_nv_data_st, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + uint32_t usedCount; + uint32_t i; + + printf(" TPM_NVIndexEntries_SetVolatile: %u slots\n", tpm_nv_index_entries->nvIndexCount); + /* Get the number of used slots. This should be equal to the total number of slots. */ + if (rc == 0) { + rc = TPM_NVIndexEntries_GetUsedCount(&usedCount, tpm_nv_index_entries); + } + if (rc == 0) { + if (usedCount != tpm_nv_index_entries->nvIndexCount) { + printf("TPM_NVIndexEntries_SetVolatile: Error (fatal), " + "usedCount %u does not equal slot count %u\n", + usedCount, tpm_nv_index_entries->nvIndexCount); + rc = TPM_FAIL; + } + } + /* if the used count is non-zero, the volatile array should not be NULL */ + if (rc == 0) { + if ((usedCount > 0) && (tpm_nv_data_st == NULL)) { + printf("TPM_NVIndexEntries_SetVolatile: Error (fatal), " + "usedCount %u unconsistant with volatile array NULL\n", usedCount); + rc = TPM_FAIL; + } + } + /* copy entries into the array */ + for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { + printf(" TPM_NVIndexEntries_SetVolatile: slot %u index %08x\n", + i, tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); + /* sanity check on a mismatch of entries between the save and restore */ + if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex != + tpm_nv_data_st[i].nvIndex) { + + printf("TPM_NVIndexEntries_SetVolatile: Error (fatal), " + "mismatch NV entry %08x, saved %08x\n", + tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex, + tpm_nv_data_st[i].nvIndex); + rc = TPM_FAIL; + } + /* restore entries from the array */ + else { + printf(" TPM_NVIndexEntries_SetVolatile: bReadSTClear %u bWriteSTClear %u\n", + tpm_nv_data_st[i].bReadSTClear, tpm_nv_data_st[i].bWriteSTClear); + tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.bReadSTClear = + tpm_nv_data_st[i].bReadSTClear; + tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.bWriteSTClear = + tpm_nv_data_st[i].bWriteSTClear; + } + } + return rc; +} + +/* TPM_NVIndexEntries_GetFreeEntry() gets a free entry in the TPM_NV_INDEX_ENTRIES array. + + If a free entry exists, it it returned. It should already be initialized. + + If a free entry does not exist, it it created and initialized. + + If a slot cannot be created, tpm_nv_data_sensitive returns NULL, so a subsequent free is safe. +*/ + +TPM_RESULT TPM_NVIndexEntries_GetFreeEntry(TPM_NV_DATA_SENSITIVE **tpm_nv_data_sensitive, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + size_t i; + + printf(" TPM_NVIndexEntries_GetFreeEntry: Searching %u slots\n", + tpm_nv_index_entries->nvIndexCount); + /* for debug - trace the entire TPM_NV_INDEX_ENTRIES array */ + for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { + *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); + printf(" TPM_NVIndexEntries_GetFreeEntry: slot %lu entry %08x\n", + (unsigned long)i, (*tpm_nv_data_sensitive)->pubInfo.nvIndex); + } + /* search the existing array for a free entry */ + for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) && !done ; i++) { + *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); + /* if the entry is not used */ + if ((*tpm_nv_data_sensitive)->pubInfo.nvIndex == TPM_NV_INDEX_LOCK) { + printf(" TPM_NVIndexEntries_GetFreeEntry: Found free slot %lu\n", (unsigned long)i); + done = TRUE; + } + } + /* need to expand the array */ + if ((rc == 0) && !done) { + *tpm_nv_data_sensitive = NULL; + rc = TPM_Realloc((unsigned char **)&(tpm_nv_index_entries->tpm_nvindex_entry), + sizeof(TPM_NV_DATA_SENSITIVE) * (i + 1)); + } + /* initialize the new entry in the array */ + if ((rc == 0) && !done) { + printf(" TPM_NVIndexEntries_GetFreeEntry: Created new slot at index %lu\n", + (unsigned long)i); + *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); + TPM_NVDataSensitive_Init(*tpm_nv_data_sensitive); + tpm_nv_index_entries->nvIndexCount++; + } + return rc; +} + +/* TPM_NVIndexEntries_GetEntry() gets the TPM_NV_DATA_SENSITIVE entry corresponding to nvIndex. + + Returns TPM_BADINDEX on non-existent nvIndex +*/ + +TPM_RESULT TPM_NVIndexEntries_GetEntry(TPM_NV_DATA_SENSITIVE **tpm_nv_data_sensitive, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + TPM_NV_INDEX nvIndex) +{ + TPM_RESULT rc = 0; + size_t i; + TPM_BOOL found; + + printf(" TPM_NVIndexEntries_GetEntry: Getting NV index %08x in %u slots\n", + nvIndex, tpm_nv_index_entries->nvIndexCount); + /* for debug tracing */ + for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { + *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); + printf(" TPM_NVIndexEntries_GetEntry: slot %lu entry %08x\n", + (unsigned long)i, (*tpm_nv_data_sensitive)->pubInfo.nvIndex); + } + /* check for the special index that indicates an empty entry */ + if (rc == 0) { + if (nvIndex == TPM_NV_INDEX_LOCK) { + rc = TPM_BADINDEX; + } + } + for (i = 0 , found = FALSE ; + (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) && !found ; + i++) { + + *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); + if ((*tpm_nv_data_sensitive)->pubInfo.nvIndex == nvIndex) { + printf(" TPM_NVIndexEntries_GetEntry: Found NV index at slot %lu\n", (unsigned long)i); + printf(" TPM_NVIndexEntries_GetEntry: permission %08x dataSize %u\n", + (*tpm_nv_data_sensitive)->pubInfo.permission.attributes, + (*tpm_nv_data_sensitive)->pubInfo.dataSize); + printf(" TPM_NVIndexEntries_GetEntry: " + "bReadSTClear %02x bWriteSTClear %02x bWriteDefine %02x\n", + (*tpm_nv_data_sensitive)->pubInfo.bReadSTClear, + (*tpm_nv_data_sensitive)->pubInfo.bWriteSTClear, + (*tpm_nv_data_sensitive)->pubInfo.bWriteDefine); + found = TRUE; + } + } + if (rc == 0) { + if (!found) { + printf(" TPM_NVIndexEntries_GetEntry: NV index not found\n"); + rc = TPM_BADINDEX; + } + } + return rc; +} + +/* TPM_NVIndexEntries_GetUsedCount() returns the number of used entries in the TPM_NV_INDEX_ENTRIES + array. + + At startup, all entries will be used. If an NV index is deleted, the entryis marked unused, but + the TPM_NV_INDEX_ENTRIES space is not reclaimed until the next startup. +*/ + +TPM_RESULT TPM_NVIndexEntries_GetUsedCount(uint32_t *count, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + size_t i; + + *count = 0; + for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { + /* if the entry is used */ + if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { + (*count)++; + } + } + printf(" TPM_NVIndexEntries_GetUsedCount: Used count %d in %u slots\n", + *count, tpm_nv_index_entries->nvIndexCount); + return rc; +} + +/* TPM_NVIndexEntries_GetNVList() serializes a list of the used NV indexes into the + TPM_STORE_BUFFER +*/ + +TPM_RESULT TPM_NVIndexEntries_GetNVList(TPM_STORE_BUFFER *sbuffer, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_NVIndexEntries_GetNVList: Creating list from %u slots\n", + tpm_nv_index_entries->nvIndexCount); + + for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { + /* if the entry is used */ + if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { + rc = TPM_Sbuffer_Append32(sbuffer, + tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); + } + } + return rc; +} + +/* TPM_NVIndexEntries_GetUsedSpace() gets the NV space consumed by NV defined space indexes. + + It does it inefficiently but reliably by serializing the structure with the same function used + when writing to NV storage. +*/ + +TPM_RESULT TPM_NVIndexEntries_GetUsedSpace(uint32_t *usedSpace, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; + const unsigned char *buffer; + + printf(" TPM_NVIndexEntries_GetUsedSpace:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize NV defined space */ + if (rc == 0) { + rc = TPM_NVIndexEntries_Store(&sbuffer, tpm_nv_index_entries); + } + /* get the serialized buffer and its length */ + if (rc == 0) { + TPM_Sbuffer_Get(&sbuffer, &buffer, usedSpace); + printf(" TPM_NVIndexEntries_GetUsedSpace: Used space %u\n", *usedSpace); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_NVIndexEntries_GetFreeSpace() gets the total free NV defined space. + + When defining an index, not all can be used for data, as some is consumed by metadata such as + authorization and the index number. +*/ + +TPM_RESULT TPM_NVIndexEntries_GetFreeSpace(uint32_t *freeSpace, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) +{ + TPM_RESULT rc = 0; + uint32_t usedSpace; + + printf(" TPM_NVIndexEntries_GetFreeSpace:\n"); + /* get the used space */ + if (rc == 0) { + rc = TPM_NVIndexEntries_GetUsedSpace(&usedSpace, tpm_nv_index_entries); + } + /* sanity check */ + if (rc == 0) { + if (usedSpace > TPM_MAX_NV_DEFINED_SIZE) { + printf("TPM_NVIndexEntries_GetFreeSpace: used %u greater than max %u\n", + usedSpace, TPM_MAX_NV_DEFINED_SIZE); + rc = TPM_NOSPACE; + } + } + /* calculate the free space */ + if (rc == 0) { + *freeSpace = TPM_MAX_NV_DEFINED_SIZE - usedSpace; + printf(" TPM_NVIndexEntries_GetFreeSpace: Free space %u\n", *freeSpace); + } + return rc; +} + +/* TPM_OwnerClear: rev 99 + 12. The TPM MUST deallocate all defined NV storage areas where + a. TPM_NV_PER_OWNERWRITE is TRUE if nvIndex does not have the "D" bit set + b. TPM_NV_PER_OWNERREAD is TRUE if nvIndex does not have the "D" bit set + c. The TPM MUST NOT deallocate any other currently defined NV storage areas. + + TPM_RevokeTrust: a. NV items with the pubInfo -> nvIndex D value set MUST be deleted. This + changes the TPM_OwnerClear handling of the same NV areas + + If deleteAllNvram is TRUE, all NVRAM is deleted. If it is FALSE, indexes with the D bit set are + not cleared. + + The write to NV space is done bu the caller. +*/ + +TPM_RESULT TPM_NVIndexEntries_DeleteOwnerAuthorized(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + TPM_BOOL deleteAllNvram) +{ + TPM_RESULT rc = 0; + size_t i; + TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; /* an entry in the array */ + + printf(" TPM_NVIndexEntries_DeleteOwnerAuthorized: Deleting from %u slots\n", + tpm_nv_index_entries->nvIndexCount); + for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { + /* get an entry in the array */ + tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); + + /* if the index is in use */ + if (tpm_nv_data_sensitive->pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { + /* if TPM_NV_PER_OWNERWRITE or TPM_NV_PER_OWNERREAD and nvIndex does not have the "D" + bit set */ + if ((tpm_nv_data_sensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE) || + (tpm_nv_data_sensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD)) { + if (!(tpm_nv_data_sensitive->pubInfo.nvIndex & TPM_NV_INDEX_D_BIT) || + deleteAllNvram) { + /* delete the index */ + printf(" TPM_NVIndexEntries_DeleteOwnerAuthorized: Deleting NV index %08x\n", + tpm_nv_data_sensitive->pubInfo.nvIndex); + TPM_NVDataSensitive_Delete(tpm_nv_data_sensitive); + } + } + } + } + return rc; +} + +/* TPM_NVIndexEntries_GetDataPublic() returns the TPM_NV_DATA_PUBLIC corresponding to the nvIndex + */ + +TPM_RESULT TPM_NVIndexEntries_GetDataPublic(TPM_NV_DATA_PUBLIC **tpm_nv_data_public, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + TPM_NV_INDEX nvIndex) +{ + TPM_RESULT rc = 0; + TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; + + printf(" TPM_NVIndexEntries_GetDataPublic: Getting data at NV index %08x\n", nvIndex); + if (rc == 0) { + rc = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, + tpm_nv_index_entries, + nvIndex); + } + if (rc == 0) { + *tpm_nv_data_public = &(tpm_nv_data_sensitive->pubInfo); + } + return rc; +} + +/* + Command Processing Functions +*/ + +/* 20.4 TPM_NV_ReadValue rev 114 + + Read a value from the NV store. This command uses optional owner authorization. + + Action 1 indicates that if the NV area is not locked then reading of the NV area continues + without ANY authorization. This is intentional, and allows a platform manufacturer to set the NV + areas, read them back, and then lock them all without having to install a TPM owner. +*/ + +TPM_RESULT TPM_Process_NVReadValue(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NV_INDEX nvIndex; /* The index of the area to set */ + uint32_t offset = 0; /* The offset into the area */ + uint32_t dataSize = 0; /* The size of the data area */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for TPM Owner + authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by caller */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA ownerAuth; /* HMAC key: TPM Owner authorization */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_BOOL ignore_auth = FALSE; + TPM_BOOL dir = FALSE; + TPM_BOOL physicalPresence; + TPM_BOOL isGPIO = FALSE; + BYTE *gpioData = NULL; + TPM_NV_DATA_SENSITIVE *d1NvdataSensitive; + uint32_t s1Last; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER data; /* The data to set the area to */ + + printf("TPM_Process_NVReadValue: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&data); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get nvIndex parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&nvIndex, &command, ¶mSize); + } + /* get offset parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&offset, &command, ¶mSize); + } + /* get dataSize parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&dataSize, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT | + TPM_CHECK_NV_NOAUTH)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_NVReadValue: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. If TPM_PERMANENT_FLAGS -> nvLocked is FALSE then all authorization checks are + ignored */ + /* a. Ignored checks include physical presence, owner authorization, PCR, bReadSTClear, + locality, TPM_NV_PER_OWNERREAD, disabled and deactivated */ + /* b. TPM_NV_PER_AUTHREAD is not ignored. */ + /* c. If ownerAuth is present, the TPM MAY check the authorization HMAC. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_NVReadValue: index %08x offset %u dataSize %u\n", + nvIndex, offset, dataSize); + if (!(tpm_state->tpm_permanent_flags.nvLocked)) { + printf("TPM_Process_NVReadValue: nvLocked FALSE, ignoring authorization\n"); + ignore_auth = TRUE; + } + /* determine whether the nvIndex is legal GPIO space */ + if (returnCode == 0) { + returnCode = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); + } + } + /* 2. Set D1 a TPM_NV_DATA_AREA structure to the area pointed to by nvIndex, if not found + return TPM_BADINDEX */ + if (returnCode == TPM_SUCCESS) { + /* a. If nvIndex = TPM_NV_INDEX_DIR, set D1 to TPM_PERMANENT_DATA -> authDir[0] */ + if (nvIndex == TPM_NV_INDEX_DIR) { + printf("TPM_Process_NVReadValue: Reading DIR\n"); + dir = TRUE; + } + else { + printf("TPM_Process_NVReadValue: Loading data from NVRAM\n"); + returnCode = TPM_NVIndexEntries_GetEntry(&d1NvdataSensitive, + &(tpm_state->tpm_nv_index_entries), + nvIndex); + if (returnCode != 0) { + printf("TPM_Process_NVReadValue: Error, NV index %08x not found\n", nvIndex); + } + } + } + /* Do not check permission for DIR, DIR is no-auth */ + if ((returnCode == TPM_SUCCESS) && !dir) { + /* 3. If TPM_PERMANENT_FLAGS -> nvLocked is TRUE */ + if (tpm_state->tpm_permanent_flags.nvLocked) { + /* a. If D1 -> permission -> TPM_NV_PER_OWNERREAD is TRUE */ + if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD) { + /* i. If TPM_PERMANENT_FLAGS -> disable is TRUE, return TPM_DISABLED */ + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_Process_NVReadValue: Error, disabled\n"); + return TPM_DISABLED; + } + /* ii. If TPM_STCLEAR_FLAGS -> deactivated is TRUE, return TPM_DEACTIVATED */ + else if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_Process_NVReadValue: Error, deactivated\n"); + return TPM_DEACTIVATED;; + } + } + /* NOTE: Intel software requires NV access disabled and deactivated */ + /* b. If D1 -> permission -> TPM_NV_PER_OWNERREAD is FALSE */ + /* i. If TPM_PERMANENT_FLAGS -> disable is TRUE, the TPM MAY return TPM_DISABLED */ + /* ii. If TPM_STCLEAR_FLAGS -> deactivated is TRUE, the TPM MAY return + TPM_DEACTIVATED */ + } + } + /* 4. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */ + /* NOTE: This is optional if ignore_auth is TRUE */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !dir) { + /* a. If D1 -> TPM_NV_PER_OWNERREAD is FALSE return TPM_AUTH_CONFLICT */ + if (!(d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD)) { + printf("TPM_Process_NVReadValue: Error, " + "owner authorization conflict, attributes %08x\n", + d1NvdataSensitive->pubInfo.permission.attributes); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* b. Validate command and parameters using TPM Owners authorization on error return + TPM_AUTHFAIL */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !ignore_auth) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 5. Else */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !dir) { + /* a. If D1 -> TPM_NV_PER_AUTHREAD is TRUE return TPM_AUTH_CONFLICT */ + if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_AUTHREAD) { + printf("TPM_Process_NVReadValue: Error, authorization conflict TPM_NV_PER_AUTHREAD\n"); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* b. If D1 -> TPM_NV_PER_OWNERREAD is TRUE return TPM_AUTH_CONFLICT */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !ignore_auth && !dir) { + if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD) { + printf("TPM_Process_NVReadValue: Error, authorization conflict TPM_NV_PER_OWNERREAD\n"); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* 6. Check that D1 -> pcrInfoRead -> localityAtRelease for TPM_STANY_DATA -> localityModifier + is TRUE */ + /* a. For example if TPM_STANY_DATA -> localityModifier was 2 then D1 -> pcrInfo -> + localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ + /* b. On error return TPM_BAD_LOCALITY */ + /* NOTE Done by TPM_PCRInfoShort_CheckDigest() */ + /* 7. If D1 -> attributes specifies TPM_NV_PER_PPREAD then validate physical presence is + asserted if not return TPM_BAD_PRESENCE */ + if ((returnCode == TPM_SUCCESS) && !ignore_auth && !dir) { + if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_PPREAD) { + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_NVReadValue: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + } + } + if ((returnCode == TPM_SUCCESS) && !ignore_auth && !dir) { + /* 8. If D1 -> TPM_NV_PER_READ_STCLEAR then */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_READ_STCLEAR) && + /* a. If D1 -> bReadSTClear is TRUE return TPM_DISABLED_CMD */ + (d1NvdataSensitive->pubInfo.bReadSTClear)) { + printf("TPM_Process_NVReadValue: Error, area locked by bReadSTClear\n"); + returnCode = TPM_DISABLED_CMD; + } + } + /* 9. If D1 -> pcrInfoRead -> pcrSelection specifies a selection of PCR */ + /* a. Create P1 a composite hash of the PCR specified by D1 -> pcrInfoRead */ + /* b. Compare P1 to D1 -> pcrInfoRead -> digestAtRelease return TPM_WRONGPCRVAL on + mismatch */ + if ((returnCode == TPM_SUCCESS) && !ignore_auth && !dir) { + returnCode = TPM_PCRInfoShort_CheckDigest(&(d1NvdataSensitive->pubInfo.pcrInfoRead), + tpm_state->tpm_stclear_data.PCRS, + tpm_state->tpm_stany_flags.localityModifier); + } + if (returnCode == TPM_SUCCESS && !dir) { + /* 10. If dataSize is 0 then */ + if (dataSize == 0) { + printf("TPM_Process_NVReadValue: dataSize 0, setting bReadSTClear\n"); + /* a. Set D1 -> bReadSTClear to TRUE */ + d1NvdataSensitive->pubInfo.bReadSTClear = TRUE; + /* b. Set data to NULL (output parameter dataSize to 0) */ + /* NOTE Done by TPM_SizedBuffer_Init */ + } + /* 11. Else (if dataSize is not 0) */ + else { + if (returnCode == TPM_SUCCESS) { + /* a. Set S1 to offset + dataSize */ + s1Last = offset + dataSize; /* set to last data point */ + /* b. If S1 > D1 -> dataSize return TPM_NOSPACE */ + if (s1Last > d1NvdataSensitive->pubInfo.dataSize) { + printf("TPM_Process_NVReadValue: Error, NVRAM dataSize %u\n", + d1NvdataSensitive->pubInfo.dataSize); + returnCode = TPM_NOSPACE; + } + } + /* c. Set data to area pointed to by offset */ + if ((returnCode == TPM_SUCCESS) && !isGPIO) { + TPM_PrintFourLimit("TPM_Process_NVReadValue: read data", + d1NvdataSensitive->data + offset, dataSize); + returnCode = TPM_SizedBuffer_Set(&data, + dataSize, d1NvdataSensitive->data + offset); + } + /* GPIO */ + if ((returnCode == TPM_SUCCESS) && isGPIO) { + returnCode = TPM_Malloc(&gpioData, dataSize); /* freed @2 */ + } + if ((returnCode == TPM_SUCCESS) && isGPIO) { + printf("TPM_Process_NVReadValue: Reading GPIO\n"); + returnCode = TPM_IO_GPIO_Read(nvIndex, + dataSize, + gpioData, + tpm_state->tpm_number); + } + if ((returnCode == TPM_SUCCESS) && isGPIO) { + returnCode = TPM_SizedBuffer_Set(&data, + dataSize, gpioData); + } + } + } + /* DIR read */ + if (returnCode == TPM_SUCCESS && dir) { + /* DIR is hard coded as a TPM_DIRVALUE array */ + if (returnCode == TPM_SUCCESS) { + s1Last = offset + dataSize; /* set to last data point */ + if (s1Last > TPM_DIGEST_SIZE) { + printf("TPM_Process_NVReadValue: Error, NVRAM dataSize %u too small\n", + TPM_DIGEST_SIZE); + returnCode = TPM_NOSPACE; + } + } + /* i.This includes partial reads of TPM_NV_INDEX_DIR. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_NVReadValue: Copying data\n"); + returnCode = TPM_SizedBuffer_Set(&data, dataSize, + tpm_state->tpm_permanent_data.authDIR + offset); + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_NVReadValue: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return data */ + returnCode = TPM_SizedBuffer_Store(response, &data); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&data); /* @1 */ + free(gpioData); /* @2 */ + return rcf; +} + +/* 20.5 TPM_NV_ReadValueAuth rev 87 + + This command requires that the read be authorized by a value set with the blob. +*/ + +TPM_RESULT TPM_Process_NVReadValueAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NV_INDEX nvIndex; /* The index of the area to set */ + uint32_t offset = 0; /* The offset from the data area */ + uint32_t dataSize = 0; /* The size of the data area */ + TPM_AUTHHANDLE authHandle; /* The auth handle for the NV element authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA authHmac; /* HMAC key: nv element authorization */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_NV_DATA_SENSITIVE *d1NvdataSensitive; + uint32_t s1Last; + TPM_BOOL physicalPresence; + TPM_BOOL isGPIO; + BYTE *gpioData = NULL; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_SIZED_BUFFER data; /* The data */ + + printf("TPM_Process_NVReadValueAuth: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&data); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get nvIndex parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&nvIndex, &command, ¶mSize); + } + /* get offset parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&offset, &command, ¶mSize); + } + /* get dataSize parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&dataSize, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + authHmac, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_NVReadValueAuth: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* determine whether the nvIndex is legal GPIO space */ + if (returnCode == 0) { + returnCode = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); + } + /* 1. Locate and set D1 to the TPM_NV_DATA_AREA that corresponds to nvIndex, on error return + TPM_BAD_INDEX */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_NVReadValueAuth: index %08x offset %u dataSize %u\n", + nvIndex, offset, dataSize); + printf("TPM_Process_NVReadValueAuth: Loading data from NVRAM\n"); + returnCode = TPM_NVIndexEntries_GetEntry(&d1NvdataSensitive, + &(tpm_state->tpm_nv_index_entries), + nvIndex); + if (returnCode != 0) { + printf("TPM_Process_NVReadValueAuth: Error, NV index %08x not found\n", nvIndex); + } + } + /* 2. If D1 -> TPM_NV_PER_AUTHREAD is FALSE return TPM_AUTH_CONFLICT */ + if (returnCode == TPM_SUCCESS) { + if (!(d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_AUTHREAD)) { + printf("TPM_Process_NVReadValueAuth: Error, authorization conflict\n"); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* 3. Validate authHmac using D1 -> authValue on error return TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_NV, + ordinal, + NULL, + &(d1NvdataSensitive->authValue), /* OIAP */ + d1NvdataSensitive->digest); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + authHmac); /* Authorization digest for input */ + } + /* 4. If D1 -> attributes specifies TPM_NV_PER_PPREAD then validate physical presence is + asserted if not return TPM_BAD_PRESENCE */ + if (returnCode == TPM_SUCCESS) { + if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_PPREAD) { + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_NVReadValueAuth: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + } + } + /* 5. Check that D1 -> pcrInfoRead -> localityAtRelease for TPM_STANY_DATA -> localityModifier + is TRUE */ + /* a. For example if TPM_STANY_DATA -> localityModifier was 2 then D1 -> pcrInfo -> + localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ + /* b. On error return TPM_BAD_LOCALITY */ + /* 6. If D1 -> pcrInfoRead -> pcrSelection specifies a selection of PCR */ + /* a. Create P1 a composite hash of the PCR specified by D1 -> pcrInfoRead */ + /* b. Compare P1 to D1 -> pcrInfoRead -> digestAtRelease return TPM_WRONGPCRVAL on + mismatch */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRInfoShort_CheckDigest(&(d1NvdataSensitive->pubInfo.pcrInfoRead), + tpm_state->tpm_stclear_data.PCRS, + tpm_state->tpm_stany_flags.localityModifier); + } + if (returnCode == TPM_SUCCESS) { + /* 7. If D1 specifies TPM_NV_PER_READ_STCLEAR then */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_READ_STCLEAR) && + /* a. If D1 -> bReadSTClear is TRUE return TPM_DISABLED_CMD */ + (d1NvdataSensitive->pubInfo.bReadSTClear)) { + printf("TPM_Process_NVReadValueAuth: Error, area locked by bReadSTClear\n"); + returnCode = TPM_DISABLED_CMD; + } + } + if (returnCode == TPM_SUCCESS) { + /* 8. If dataSize is 0 then */ + if (dataSize == 0) { + printf("TPM_Process_NVReadValueAuth: dataSize 0, setting bReadSTClear\n"); + /* a. Set D1 -> bReadSTClear to TRUE */ + d1NvdataSensitive->pubInfo.bReadSTClear = TRUE; + /* b. Set data to NULL */ + /* NOTE Done by TPM_SizedBuffer_Init */ + } + /* 9. Else (if dataSize is not 0) */ + else { + if (returnCode == TPM_SUCCESS) { + /* a. Set S1 to offset + dataSize */ + s1Last = offset + dataSize; /* set to last data point */ + /* b. If S1 > D1 -> dataSize return TPM_NOSPACE */ + if (s1Last > d1NvdataSensitive->pubInfo.dataSize) { + printf("TPM_Process_NVReadValueAuth: Error, NVRAM dataSize %u too small\n", + d1NvdataSensitive->pubInfo.dataSize); + returnCode = TPM_NOSPACE; + } + } + /* c. Set data to area pointed to by offset */ + if ((returnCode == TPM_SUCCESS) && !isGPIO) { + TPM_PrintFourLimit("TPM_Process_NVReadValueAuth: read data", + d1NvdataSensitive->data + offset, dataSize); + returnCode = TPM_SizedBuffer_Set(&data, dataSize, d1NvdataSensitive->data + offset); + } + /* GPIO */ + if ((returnCode == TPM_SUCCESS) && isGPIO) { + returnCode = TPM_Malloc(&gpioData, dataSize); /* freed @2 */ + } + if ((returnCode == TPM_SUCCESS) && isGPIO) { + printf("TPM_Process_NVReadValueAuth: Reading GPIO\n"); + returnCode = TPM_IO_GPIO_Read(nvIndex, + dataSize, + gpioData, + tpm_state->tpm_number); + } + if ((returnCode == TPM_SUCCESS) && isGPIO) { + returnCode = TPM_SizedBuffer_Set(&data, + dataSize, gpioData); + } + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_NVReadValueAuth: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return data */ + returnCode = TPM_SizedBuffer_Store(response, &data); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&data); /* @1 */ + return rcf; +} + +/* 20.2 TPM_NV_WriteValue rev 117 + + This command writes the value to a defined area. The write can be TPM Owner authorized or + unauthorized and protected by other attributes and will work when no TPM Owner is present. + + The action setting bGlobalLock to TRUE is intentionally before the action checking the + owner authorization. This allows code (e.g., a BIOS) to lock NVRAM without knowing the + owner authorization. + + The DIR (TPM_NV_INDEX_DIR) has the attributes TPM_NV_PER_OWNERWRITE and TPM_NV_WRITEALL. + + FIXME: A simpler way to do DIR might be to create the DIR as NV defined space at first + initialization and remove the special casing here. +*/ + +TPM_RESULT TPM_Process_NVWriteValue(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + int irc; + + /* input parameters */ + TPM_NV_INDEX nvIndex; /* The index of the area to set */ + uint32_t offset = 0; /* The offset into the NV Area */ + TPM_SIZED_BUFFER data; /* The data to set the area to */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for TPM Owner */ + TPM_NONCE nonceOdd; /* Nonce generated by caller */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA ownerAuth; /* The authorization digest HMAC key: TPM Owner auth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey = NULL; + TPM_BOOL ignore_auth = FALSE; + TPM_BOOL index0 = FALSE; + TPM_BOOL done = FALSE; + TPM_BOOL dir = FALSE; + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + TPM_NV_DATA_SENSITIVE *d1NvdataSensitive = NULL; + uint32_t s1Last; + TPM_BOOL physicalPresence; + TPM_BOOL isGPIO = FALSE; + uint32_t nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; + /* temp for noOwnerNVWrite, initialize to + silence compiler */ + TPM_BOOL nv1Incremented = FALSE; /* flag that nv1 was incremented */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_NVWriteValue: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&data); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get nvIndex parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&nvIndex, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&offset, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&data, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT | + TPM_CHECK_NV_NOAUTH)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_NVWriteValue: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_NVWriteValue: index %08x offset %u dataSize %u\n", + nvIndex, offset, data.size); + TPM_PrintFourLimit("TPM_Process_NVWriteValue: data", data.buffer, data.size); + /* 1. If TPM_PERMANENT_FLAGS -> nvLocked is FALSE then all authorization checks except for + the max NV writes are ignored */ + /* a. Ignored checks include physical presence, owner authorization, TPM_NV_PER_OWNERWRITE, + PCR, bWriteDefine, bGlobalLock, bWriteSTClear, locality, disabled and deactivated */ + /* b. TPM_NV_PER_AUTHWRITE is not ignored. */ + /* a.If ownerAuth is present, the TPM MAY check the authorization HMAC. */ + if (!(tpm_state->tpm_permanent_flags.nvLocked)) { + printf("TPM_Process_NVWriteValue: nvLocked FALSE, ignoring authorization\n"); + ignore_auth = TRUE; + } + if (nvIndex == TPM_NV_INDEX0) { + index0 = TRUE; + } + /* determine whether the nvIndex is legal GPIO space */ + if (returnCode == 0) { + returnCode = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); + } + } + /* 2. Locate and set D1 to the TPM_NV_DATA_AREA that corresponds to nvIndex, return TPM_BADINDEX + on error */ + if ((returnCode == TPM_SUCCESS) && !index0) { + /* a. If nvIndex = TPM_NV_INDEX_DIR, set D1 to TPM_PERMANENT_DATA -> authDir[0] */ + if (nvIndex == TPM_NV_INDEX_DIR) { + printf("TPM_Process_NVWriteValue: Writing DIR\n"); + dir = TRUE; + } + else { + printf("TPM_Process_NVWriteValue: Loading data space from NVRAM\n"); + returnCode = TPM_NVIndexEntries_GetEntry(&d1NvdataSensitive, + &(tpm_state->tpm_nv_index_entries), + nvIndex); + if (returnCode != 0) { + printf("TPM_Process_NVWriteValue: Error, NV index %08x not found\n", nvIndex); + } + } + } + if ((returnCode == TPM_SUCCESS) && !index0) { + /* 3. If TPM_PERMANENT_FLAGS -> nvLocked is TRUE */ + if (tpm_state->tpm_permanent_flags.nvLocked) { + /* a. If D1 -> permission -> TPM_NV_PER_OWNERWRITE is TRUE */ + if (dir || /* DIR always has TPM_NV_PER_OWNERWRITE */ + (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE)) { + /* i. If TPM_PERMANENT_FLAGS -> disable is TRUE, return TPM_DISABLED */ + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_Process_NVWriteValue: Error, disabled\n"); + return TPM_DISABLED; + } + /* ii.If TPM_STCLEAR_FLAGS -> deactivated is TRUE, return TPM_DEACTIVATED */ + else if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_Process_NVWriteValue: Error, deactivated\n"); + return TPM_DEACTIVATED;; + } + } + /* NOTE: Intel software requires NV access disabled and deactivated */ + /* b. If D1 -> permission -> TPM_NV_PER_OWNERWRITE is FALSE */ + /* i. If TPM_PERMANENT_FLAGS -> disable is TRUE, the TPM MAY return TPM_DISABLED */ + /* ii. If TPM_STCLEAR_FLAGS -> deactivated is TRUE, the TPM MAY return + TPM_DEACTIVATED */ + } + } + /* 4. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !dir && !index0) { + /* a. If D1 -> permission -> TPM_NV_PER_OWNERWRITE is FALSE return TPM_AUTH_CONFLICT */ + /* i. This check is ignored if nvIndex is TPM_NV_INDEX0. */ + if (!(d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE)) { + printf("TPM_Process_NVWriteValue: Error, owner authorization conflict\n"); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* b. Validate command and parameters using ownerAuth HMAC with TPM Owner authentication as the + secret, return TPM_AUTHFAIL on error */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + /* NOTE: This is optional if ignore_auth is TRUE */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 5. Else */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !ignore_auth && !index0) { + /* a. If D1 -> permission -> TPM_NV_PER_OWNERWRITE is TRUE return TPM_AUTH_CONFLICT */ + if (dir || /* DIR always has TPM_NV_PER_OWNERWRITE */ + (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE)) { + printf("TPM_Process_NVWriteValue: Error, no owner authorization conflict\n"); + returnCode = TPM_AUTH_CONFLICT; + } + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !index0) { + /* b. If no TPM Owner validate max NV writes without an owner */ + /* i. Set NV1 to TPM_PERMANENT_DATA -> noOwnerNVWrite */ + nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; + /* ii. Increment NV1 by 1 */ + nv1++; + /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */ + if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) { + printf("TPM_Process_NVWriteValue: Error, max NV writes %d w/o owner reached\n", + tpm_state->tpm_permanent_data.noOwnerNVWrite); + returnCode = TPM_MAXNVWRITES; + } + /* iv. Set NV1_INCREMENTED to TRUE */ + else { + nv1Incremented = TRUE; + } + } + if (returnCode == TPM_SUCCESS) { + /* 6. If nvIndex = 0 then */ + if (nvIndex == 0) { + /* a. If dataSize is not 0, the TPM MAY return TPM_BADINDEX. */ + if (data.size != 0) { + printf("TPM_Process_NVWriteValue: Error, index 0 size %u\n", data.size); + returnCode = TPM_BADINDEX; + } + else { + /* b. Set TPM_STCLEAR_FLAGS -> bGlobalLock to TRUE */ + printf("TPM_Process_NVWriteValue: nvIndex 0, setting bGlobalLock\n"); + tpm_state->tpm_stclear_flags.bGlobalLock = TRUE; + /* c. Return TPM_SUCCESS */ + done = TRUE; + } + } + } + /* 7. If D1 -> permission -> TPM_NV_PER_AUTHWRITE is TRUE return TPM_AUTH_CONFLICT */ + if ((returnCode == TPM_SUCCESS) && !done && !dir) { + if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_AUTHWRITE) { + printf("TPM_Process_NVWriteValue: Error, authorization conflict, attributes %08x \n", + d1NvdataSensitive->pubInfo.permission.attributes); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* 8. Check that D1 -> pcrInfoWrite -> localityAtRelease for TPM_STANY_DATA -> localityModifier + is TRUE */ + /* a. For example if TPM_STANY_DATA -> localityModifier was 2 then D1 -> pcrInfo -> + localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ + /* b. On error return TPM_BAD_LOCALITY */ + /* NOTE Done by TPM_PCRInfoShort_CheckDigest() */ + /* 9. If D1 -> attributes specifies TPM_NV_PER_PPWRITE then validate physical presence is + asserted if not return TPM_BAD_PRESENCE */ + if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { + if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_PPWRITE) { + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_NVWriteValue: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + } + } + if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { + /* 10. If D1 -> attributes specifies TPM_NV_PER_WRITEDEFINE */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEDEFINE) && + /* a. If D1 -> bWriteDefine is TRUE return TPM_AREA_LOCKED */ + (d1NvdataSensitive->pubInfo.bWriteDefine)) { + printf("TPM_Process_NVWriteValue: Error, area locked by bWriteDefine\n"); + returnCode = TPM_AREA_LOCKED; + } + } + if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { + /* 11. If D1 -> attributes specifies TPM_NV_PER_GLOBALLOCK */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_GLOBALLOCK) && + /* a. If TPM_STCLEAR_FLAGS -> bGlobalLock is TRUE return TPM_AREA_LOCKED */ + (tpm_state->tpm_stclear_flags.bGlobalLock)) { + printf("TPM_Process_NVWriteValue: Error, area locked by bGlobalLock\n"); + returnCode = TPM_AREA_LOCKED; + } + } + if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { + /* 12. If D1 -> attributes specifies TPM_NV_PER_WRITE_STCLEAR */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITE_STCLEAR) && + /* a. If D1 ->bWriteSTClear is TRUE return TPM_AREA_LOCKED */ + (d1NvdataSensitive->pubInfo.bWriteSTClear)) { + printf("TPM_Process_NVWriteValue: Error, area locked by bWriteSTClear\n"); + returnCode = TPM_AREA_LOCKED; + } + } + /* 13. If D1 -> pcrInfoWrite -> pcrSelection specifies a selection of PCR */ + /* a. Create P1 a composite hash of the PCR specified by D1 -> pcrInfoWrite */ + /* b. Compare P1 to D1 -> pcrInfoWrite -> digestAtRelease return TPM_WRONGPCRVAL on mismatch + */ + if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { + returnCode = TPM_PCRInfoShort_CheckDigest(&(d1NvdataSensitive->pubInfo.pcrInfoWrite), + tpm_state->tpm_stclear_data.PCRS, + tpm_state->tpm_stany_flags.localityModifier); + } + if ((returnCode == TPM_SUCCESS) && !done && !dir) { + /* 14. If dataSize = 0 then */ + if (data.size == 0) { + printf("TPM_Process_NVWriteValue: dataSize 0, setting bWriteSTClear, bWriteDefine\n"); + /* a. Set D1 -> bWriteSTClear to TRUE */ + d1NvdataSensitive->pubInfo.bWriteSTClear = TRUE; + /* b. Set D1 -> bWriteDefine */ + if (!d1NvdataSensitive->pubInfo.bWriteDefine) { /* save wearout, only write if + FALSE */ + d1NvdataSensitive->pubInfo.bWriteDefine = TRUE; + /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after structure is + written */ + writeAllNV = TRUE; + } + } + /* 15. Else (if dataSize is not 0) */ + else { + if (returnCode == TPM_SUCCESS) { + /* a. Set S1 to offset + dataSize */ + s1Last = offset + data.size; /* set to last data point */ + /* b. If S1 > D1 -> dataSize return TPM_NOSPACE */ + if (s1Last > d1NvdataSensitive->pubInfo.dataSize) { + printf("TPM_Process_NVWriteValue: Error, NVRAM dataSize %u too small\n", + d1NvdataSensitive->pubInfo.dataSize); + returnCode = TPM_NOSPACE; + } + } + if (returnCode == TPM_SUCCESS) { + /* c. If D1 -> attributes specifies TPM_NV_PER_WRITEALL */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEALL) && + /* i. If dataSize != D1 -> dataSize return TPM_NOT_FULLWRITE */ + (data.size != d1NvdataSensitive->pubInfo.dataSize)) { + printf("TPM_Process_NVWriteValue: Error, Must write full %u\n", + d1NvdataSensitive->pubInfo.dataSize); + returnCode = TPM_NOT_FULLWRITE; + } + } + if (returnCode == TPM_SUCCESS) { + /* not GPIO */ + if (!isGPIO) { + /* wearout optimization, don't write if the data is the same */ + irc = memcmp((d1NvdataSensitive->data) + offset, data.buffer, data.size); + if (irc != 0) { + printf("TPM_Process_NVWriteValue: Copying data\n"); + /* d. Write the new value into the NV storage area */ + memcpy((d1NvdataSensitive->data) + offset, data.buffer, data.size); + /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after + structure is written */ + writeAllNV = TRUE; + } + else { + printf("TPM_Process_NVWriteValue: Same data, no copy\n"); + } + } + /* GPIO */ + else { + printf("TPM_Process_NVWriteValue: Writing GPIO\n"); + returnCode = TPM_IO_GPIO_Write(nvIndex, + data.size, + data.buffer, + tpm_state->tpm_number); + } + } + } + } + /* DIR write */ + if ((returnCode == TPM_SUCCESS) && !done && dir) { + /* For TPM_NV_INDEX_DIR, the ordinal MUST NOT set an error code for the "if dataSize = 0" + action. However, the flags set in this case are not applicable to the DIR. */ + if (data.size != 0) { + /* DIR is hard coded as a TPM_DIRVALUE array, TPM_NV_WRITEALL is implied */ + if (returnCode == TPM_SUCCESS) { + if ((offset != 0) || (data.size != TPM_DIGEST_SIZE)) { + printf("TPM_Process_NVWriteValue: Error, Must write full DIR %u\n", + TPM_DIGEST_SIZE); + returnCode = TPM_NOT_FULLWRITE; + } + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_NVWriteValue: Copying data\n"); + memcpy(tpm_state->tpm_permanent_data.authDIR, data.buffer, TPM_DIGEST_SIZE); + writeAllNV = TRUE; + } + } + } + if ((returnCode == TPM_SUCCESS) && !done && !dir) { + /* 16. Set D1 -> bReadSTClear to FALSE (unlocked by a successful write) */ + d1NvdataSensitive->pubInfo.bReadSTClear = FALSE; + } + /* 15.d Write the new value into the NV storage area */ + if (writeAllNV) { + printf("TPM_Process_NVWriteValue: Writing data to NVRAM\n"); + /* NOTE Don't do this step until just before the serialization */ + /* e. If NV1_INCREMENTED is TRUE */ + if (nv1Incremented) { + /* i. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */ + tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1; + } + } + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_NVWriteValue: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&data); /* @1 */ + return rcf; +} + +/* 20.3 TPM_NV_WriteValueAuth rev 87 + + This command writes to a previously defined area. The area must require authorization to + write. This command is for using when authorization other than the owner authorization is to be + used. Otherwise, you should use TPM_NV_WriteValue +*/ + +TPM_RESULT TPM_Process_NVWriteValueAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + int irc; + + /* input parameters */ + TPM_NV_INDEX nvIndex; /* The index of the area to set */ + uint32_t offset = 0; /* The offset into the chunk */ + TPM_SIZED_BUFFER data; /* The data to set the area to */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for NV element + authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA authValue; /* HMAC key: NV element auth value */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey = NULL; + TPM_NV_DATA_SENSITIVE *d1NvdataSensitive; + uint32_t s1Last; + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + TPM_BOOL physicalPresence; + TPM_BOOL isGPIO; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_NVWriteValueAuth: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&data); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get nvIndex parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&nvIndex, &command, ¶mSize); + } + /* get offset parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&offset, &command, ¶mSize); + } + /* get data parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&data, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + authValue, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_NVWriteValueAuth: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* determine whether the nvIndex is legal GPIO space */ + if (returnCode == 0) { + returnCode = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); + } + /* 1. Locate and set D1 to the TPM_NV_DATA_AREA that corresponds to nvIndex, return TPM_BADINDEX + on error */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_NVWriteValueAuth: index %08x offset %u dataSize %u\n", + nvIndex, offset, data.size); + TPM_PrintFourLimit("TPM_Process_NVWriteValueAuth: data", data.buffer, data.size); + printf("TPM_Process_NVWriteValueAuth: Loading data from NVRAM\n"); + returnCode = TPM_NVIndexEntries_GetEntry(&d1NvdataSensitive, + &(tpm_state->tpm_nv_index_entries), + nvIndex); + if (returnCode != 0) { + printf("TPM_Process_NVWriteValueAuth: Error, NV index %08x not found\n", nvIndex); + } + } + /* 2. If D1 -> attributes does not specify TPM_NV_PER_AUTHWRITE then return TPM_AUTH_CONFLICT */ + if (returnCode == TPM_SUCCESS) { + if (!(d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_AUTHWRITE)) { + printf("TPM_Process_NVWriteValueAuth: Error, authorization conflict\n"); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* 3. Validate authValue using D1 -> authValue, return TPM_AUTHFAIL on error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_NV, + ordinal, + NULL, + &(d1NvdataSensitive->authValue), /* OIAP */ + d1NvdataSensitive->digest); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + authValue); /* Authorization digest for input */ + } + /* 4. Check that D1 -> pcrInfoWrite -> localityAtRelease for TPM_STANY_DATA -> localityModifier + is TRUE */ + /* a. For example if TPM_STANY_DATA -> localityModifier was 2 then D1 -> pcrInfo -> + localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ + /* b. On error return TPM_BAD_LOCALITY */ + /* NOTE Done by TPM_PCRInfoShort_CheckDigest() */ + /* 5. If D1 -> attributes specifies TPM_NV_PER_PPWRITE then validate physical presence is + asserted if not return TPM_BAD_PRESENCE */ + if (returnCode == TPM_SUCCESS) { + if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_PPWRITE) { + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_NVWriteValueAuth: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + } + } + /* 6. If D1 -> pcrInfoWrite -> pcrSelection specifies a selection of PCR */ + /* a. Create P1 a composite hash of the PCR specified by D1 -> pcrInfoWrite */ + /* b. Compare P1 to digestAtRelease return TPM_WRONGPCRVAL on mismatch */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRInfoShort_CheckDigest(&(d1NvdataSensitive->pubInfo.pcrInfoWrite), + tpm_state->tpm_stclear_data.PCRS, + tpm_state->tpm_stany_flags.localityModifier); + } + if (returnCode == TPM_SUCCESS) { + /* 7. If D1 -> attributes specifies TPM_NV_PER_WRITEDEFINE */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEDEFINE) && + /* a. If D1 -> bWriteDefine is TRUE return TPM_AREA_LOCKED */ + (d1NvdataSensitive->pubInfo.bWriteDefine)) { + printf("TPM_Process_NVWriteValueAuth: Error, area locked by bWriteDefine\n"); + returnCode = TPM_AREA_LOCKED; + } + } + if (returnCode == TPM_SUCCESS) { + /* 8. If D1 -> attributes specifies TPM_NV_PER_GLOBALLOCK */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_GLOBALLOCK) && + /* a. If TPM_STCLEAR_FLAGS -> bGlobalLock is TRUE return TPM_AREA_LOCKED */ + (tpm_state->tpm_stclear_flags.bGlobalLock)) { + printf("TPM_Process_NVWriteValueAuth: Error, area locked by bGlobalLock\n"); + returnCode = TPM_AREA_LOCKED; + } + } + if (returnCode == TPM_SUCCESS) { + /* 9. If D1 -> attributes specifies TPM_NV_PER_WRITE_STCLEAR */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITE_STCLEAR) && + /* a. If D1 -> bWriteSTClear is TRUE return TPM_AREA_LOCKED */ + (d1NvdataSensitive->pubInfo.bWriteSTClear)) { + printf("TPM_Process_NVWriteValueAuth: Error, area locked by bWriteSTClear\n"); + returnCode = TPM_AREA_LOCKED; + } + } + if (returnCode == TPM_SUCCESS) { + /* 10. If dataSize = 0 then */ + if (data.size == 0) { + printf("TPM_Process_NVWriteValueAuth: " + "dataSize 0, setting bWriteSTClear, bWriteDefine\n"); + /* a. Set D1 -> bWriteSTClear to TRUE */ + d1NvdataSensitive->pubInfo.bWriteSTClear = TRUE; + /* b. Set D1 -> bWriteDefine to TRUE */ + if (!d1NvdataSensitive->pubInfo.bWriteDefine) { /* save wearout, only write if + FALSE */ + d1NvdataSensitive->pubInfo.bWriteDefine = TRUE; + /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after structure is + written */ + writeAllNV = TRUE; + } + } + /* 11. Else (if dataSize is not 0) */ + else { + if (returnCode == TPM_SUCCESS) { + /* a. Set S1 to offset + dataSize */ + s1Last = offset + data.size; /* set to last data point */ + /* b. If S1 > D1 -> dataSize return TPM_NOSPACE */ + if (s1Last > d1NvdataSensitive->pubInfo.dataSize) { + printf("TPM_Process_NVWriteValueAuth: Error, NVRAM dataSize %u\n", + d1NvdataSensitive->pubInfo.dataSize); + returnCode = TPM_NOSPACE; + } + } + if (returnCode == TPM_SUCCESS) { + /* c. If D1 -> attributes specifies TPM_PER_WRITEALL */ + if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEALL) && + /* i. If dataSize != D1 -> dataSize return TPM_NOT_FULLWRITE */ + (data.size != d1NvdataSensitive->pubInfo.dataSize)) { + printf("TPM_Process_NVWriteValueAuth: Error, Must write all %u\n", + d1NvdataSensitive->pubInfo.dataSize); + returnCode = TPM_NOT_FULLWRITE; + } + } + if (returnCode == TPM_SUCCESS) { + /* not GPIO */ + if (!isGPIO) { + /* wearout optimization, don't write if the data is the same */ + irc = memcmp((d1NvdataSensitive->data) + offset, data.buffer, data.size); + if (irc != 0) { + /* d. Write the new value into the NV storage area */ + printf("TPM_Process_NVWriteValueAuth: Copying data\n"); + memcpy((d1NvdataSensitive->data) + offset, data.buffer, data.size); + /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after + structure is written */ + writeAllNV = TRUE; + } + else { + printf("TPM_Process_NVWriteValueAuth: Same data, no copy\n"); + } + } + /* GPIO */ + else { + printf("TPM_Process_NVWriteValueAuth: Writing GPIO\n"); + returnCode = TPM_IO_GPIO_Write(nvIndex, + data.size, + data.buffer, + tpm_state->tpm_number); + } + } + } + } + /* 12. Set D1 -> bReadSTClear to FALSE */ + if (returnCode == TPM_SUCCESS) { + d1NvdataSensitive->pubInfo.bReadSTClear = FALSE; + printf("TPM_Process_NVWriteValueAuth: Writing data to NVRAM\n"); + } + /* write back TPM_PERMANENT_DATA if required */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_NVWriteValueAuth: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&data); /* @1 */ + return rcf; +} + +/* 20.1 TPM_NV_DefineSpace rev 109 + + This establishes the space necessary for the indicated index. The definition will include the + access requirements for writing and reading the area. + + Previously defined space at the index and new size is non-zero (and space is available, + etc.) -> redefine the index + + No previous space at the index and new size is non-zero (and space is available, etc.)-> + define the index + + Previously defined space at the index and new size is 0 -> delete the index + + No previous space at the index and new size is 0 -> error + + The space definition size does not include the area needed to manage the space. + + Setting TPM_PERMANENT_FLAGS -> nvLocked TRUE when it is already TRUE is not an error. + + For the case where pubInfo -> dataSize is 0, pubInfo -> pcrInfoRead and pubInfo -> pcrInfoWrite + are not used. However, since the general principle is to validate parameters before changing + state, the TPM SHOULD parse pubInfo completely before invalidating the data area. +*/ + +TPM_RESULT TPM_Process_NVDefineSpace(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_NV_INDEX newNVIndex = TPM_NV_INDEX_LOCK; /* from input TPM_NV_DATA_PUBLIC, initialize + to silence compiler */ + TPM_ENCAUTH encAuth; /* The encrypted AuthData, only valid if the attributes + require subsequent authorization */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for ownerAuth */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest HMAC key: ownerAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey = NULL; + TPM_BOOL ignore_auth = FALSE; + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + TPM_BOOL done = FALSE; /* processing is done */ + TPM_DIGEST a1Auth; + TPM_NV_DATA_SENSITIVE *d1_old; /* possibly old data */ + TPM_NV_DATA_SENSITIVE *d1_new = NULL; /* new data */ + TPM_NV_DATA_PUBLIC *pubInfo = NULL; /* new, initialize to silence + compiler */ + uint32_t freeSpace; /* free space after allocating new + index */ + TPM_BOOL writeLocalities = FALSE; + TPM_BOOL physicalPresence; + TPM_BOOL foundOld = TRUE; /* index already exists, initialize + to silence compiler */ + uint32_t nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; + /* temp for noOwnerNVWrite, initialize to silence + compiler */ + TPM_BOOL nv1Incremented = FALSE; /* flag that nv1 was incremented */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_NVDefineSpace: Ordinal Entry\n"); + /* This design gets a slot in the TPM_NV_INDEX_ENTRIES array, either an existing empty one or a + newly re'allocated one. The incoming parameters are deserialized directly into the slot. + + On success, the slot remains. On failure, the slot is deleted. There is no need to remove + the slot from the array. It can remain for the next call. + */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get or create a free index in the TPM_NV_INDEX_ENTRIES array */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_NVIndexEntries_GetFreeEntry(&d1_new, &(tpm_state->tpm_nv_index_entries)); + } + /* get pubInfo parameter */ + if (returnCode == TPM_SUCCESS) { + pubInfo = &(d1_new->pubInfo); /* pubInfo is an input parameter */ + returnCode = TPM_NVDataPublic_Load(pubInfo, + &command, ¶mSize, + FALSE); /* not optimized for digestAtRelease */ + /* The NV index cannot be immediately deserialized in the slot, or the function will think + that the index already exists. Therefore, the nvIndex parameter is saved and temporarily + set to empty until the old slot is deleted. */ + newNVIndex = pubInfo->nvIndex; /* save the possibly new index */ + pubInfo->nvIndex = TPM_NV_INDEX_LOCK; /* temporarily mark unused */ + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_NVDefineSpace: index %08x permission %08x dataSize %08x\n", + newNVIndex, pubInfo->permission.attributes, pubInfo->dataSize); + TPM_PCRInfo_Trace("TPM_Process_NVDefineSpace: pcrInfoRead", + pubInfo->pcrInfoRead.pcrSelection, + pubInfo->pcrInfoRead.digestAtRelease); + TPM_PCRInfo_Trace("TPM_Process_NVDefineSpace: pcrInfoWrite", + pubInfo->pcrInfoWrite.pcrSelection, + pubInfo->pcrInfoWrite.digestAtRelease); + /* get encAuth parameter */ + returnCode = TPM_Secret_Load(encAuth, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER | TPM_CHECK_NV_NOAUTH); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_NVDefineSpace: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. If pubInfo -> nvIndex == TPM_NV_INDEX_LOCK and tag = TPM_TAG_RQU_COMMAND */ + if ((returnCode == TPM_SUCCESS) && + (newNVIndex == TPM_NV_INDEX_LOCK) && + (tag == TPM_TAG_RQU_COMMAND)) { + /* a. If pubInfo -> dataSize is not 0, the command MAY return TPM_BADINDEX. */ + if (pubInfo->dataSize != 0) { + printf("TPM_Process_NVDefineSpace: Error, TPM_NV_INDEX_LOCK dataSize %u\n", + pubInfo->dataSize); + returnCode = TPM_BADINDEX; + } + else { + /* b. Set TPM_PERMANENT_FLAGS -> nvLocked to TRUE */ + /* writeAllNV set to TRUE if nvLocked is being set, not if already set */ + printf("TPM_Process_NVDefineSpace: Setting nvLocked\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.nvLocked ), /* flag */ + TRUE); /* value */ + } + /* c. Return TPM_SUCCESS */ + done = TRUE; + } + /* 2. If TPM_PERMANENT_FLAGS -> nvLocked is FALSE then all authorization checks except for the + Max NV writes are ignored */ + /* a. Ignored checks include physical presence, owner authorization, 'D' bit check, bGlobalLock, + no authorization with a TPM owner present, bWriteSTClear, the check that pubInfo -> dataSize + is 0 in Action 5.c. (the no-authorization case), disabled and deactivated. */ + /* NOTE: The disabled and deactivated flags are conditionally checked by TPM_CheckState() using + the TPM_CHECK_NV_NOAUTH flag */ + /* ii. The check that pubInfo -> dataSize is 0 is still enforced in Action 6.f. (returning after + deleting a previously defined storage area) and Action 9.f. (not allowing a space of size 0 + to be defined). */ + /* i.If ownerAuth is present, the TPM MAY check the authorization HMAC. */ + if (returnCode == TPM_SUCCESS) { + if (!(tpm_state->tpm_permanent_flags.nvLocked)) { + printf("TPM_Process_NVDefineSpace: nvLocked FALSE, ignoring authorization\n"); + ignore_auth = TRUE; + } + } + /* b.The check for pubInfo -> nvIndex == 0 in Action 3. is not ignored. */ + if ((returnCode == TPM_SUCCESS) && !done) { + if (newNVIndex == TPM_NV_INDEX0) { + printf("TPM_Process_NVDefineSpace: Error, bad index %08x\n", newNVIndex); + returnCode = TPM_BADINDEX; + } + } + /* 3. If pubInfo -> nvIndex has the D bit (bit 28) set to a 1 or pubInfo -> nvIndex == 0 then */ + if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth) { + /* b. The D bit specifies an index value that is set in manufacturing and can never be + deleted or added to the TPM */ + if (newNVIndex & TPM_NV_INDEX_D_BIT) { + /* c. Index value of 0 is reserved and cannot be defined */ + /* a. Return TPM_BADINDEX */ + printf("TPM_Process_NVDefineSpace: Error, bad index %08x\n", newNVIndex); + returnCode = TPM_BADINDEX; + } + } + /* 4. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */ + /* b. authHandle session type MUST be OSAP */ + /* must get the HMAC key for the response even if ignore_auth is TRUE */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_OWNER, + ordinal, + NULL, + NULL, + tpm_state->tpm_permanent_data.ownerAuth); + } + /* a. The TPM MUST validate the command and parameters using the TPM Owner authentication and + ownerAuth, on error return TPM_AUTHFAIL */ + /* NOTE: This is optional if ignore_auth is TRUE */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !done) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* c. Create A1 by decrypting encAuth according to the ADIP indicated by authHandle. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !done) { + returnCode = TPM_AuthSessionData_Decrypt(a1Auth, + NULL, + encAuth, + auth_session_data, + NULL, + NULL, + FALSE); /* even and odd */ + } + /* 5. else (not auth1) */ + /* a. Validate the assertion of physical presence. Return TPM_BAD_PRESENCE on error. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done && !ignore_auth) { + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_NVDefineSpace: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + } + /* b. If TPM Owner is present then return TPM_OWNER_SET. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done && !ignore_auth) { + if (tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_Process_NVDefineSpace: Error, no authorization, but owner installed\n"); + returnCode = TPM_OWNER_SET; + } + } + /* c. If pubInfo -> dataSize is 0 then return TPM_BAD_DATASIZE. Setting the size to 0 represents + an attempt to delete the value without TPM Owner authentication. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done && !ignore_auth) { + if (pubInfo->dataSize == 0) { + printf("TPM_Process_NVDefineSpace: Error, no owner authorization and dataSize 0\n"); + returnCode = TPM_BAD_DATASIZE; + } + } + /* d. Validate max NV writes without an owner */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done) { + /* i. Set NV1 to TPM_PERMANENT_DATA -> noOwnerNVWrite */ + nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; + /* ii. Increment NV1 by 1 */ + nv1++; + /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */ + if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) { + printf("TPM_Process_NVDefineSpace: Error, max NV writes %d w/o owner reached\n", + tpm_state->tpm_permanent_data.noOwnerNVWrite); + returnCode = TPM_MAXNVWRITES; + } + else { + /* iv. Set NV1_INCREMENTED to TRUE */ + nv1Incremented = TRUE; + } + } + /* e. Set A1 to encAuth. There is no nonce or authorization to create the encryption string, + hence the AuthData value is passed in the clear */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done) { + TPM_Digest_Copy(a1Auth, encAuth); + } + /* 6. If pubInfo -> nvIndex points to a valid previously defined storage area then */ + /* 6.a. Map D1 a TPM_NV_DATA_SENSITIVE to the storage area */ + if ((returnCode == TPM_SUCCESS) && !done) { + printf("TPM_Process_NVDefineSpace: Loading existing NV index %08x\n", newNVIndex); + returnCode = TPM_NVIndexEntries_GetEntry(&d1_old, + &(tpm_state->tpm_nv_index_entries), + newNVIndex); + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_NVDefineSpace: NV index %08x exists\n", newNVIndex); + foundOld = TRUE; + } + else if (returnCode == TPM_BADINDEX) { + returnCode = TPM_SUCCESS; /* non-existent index is not an error */ + foundOld = FALSE; + printf("TPM_Process_NVDefineSpace: Index %08x is new\n", newNVIndex); + } + } + if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && foundOld) { + /* 6.b. If D1 -> attributes specifies TPM_NV_PER_GLOBALLOCK then */ + if (d1_old->pubInfo.permission.attributes & TPM_NV_PER_GLOBALLOCK) { + /* i. If TPM_STCLEAR_FLAGS -> bGlobalLock is TRUE then return TPM_AREA_LOCKED */ + if (tpm_state->tpm_stclear_flags.bGlobalLock) { + printf("TPM_Process_NVDefineSpace: Error, index %08x (bGlobalLock) locked\n", + newNVIndex); + returnCode = TPM_AREA_LOCKED; + } + } + } + if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && foundOld) { + /* 6.c. If D1 -> attributes specifies TPM_NV_PER_WRITE_STCLEAR */ + if (d1_old->pubInfo.permission.attributes & TPM_NV_PER_WRITE_STCLEAR) { + /* i. If D1 -> pubInfo -> bWriteSTClear is TRUE then return TPM_AREA_LOCKED */ + if (d1_old->pubInfo.bWriteSTClear) { + printf("TPM_Process_NVDefineSpace: Error, area locked by bWriteSTClear\n"); + returnCode = TPM_AREA_LOCKED; + } + } + } + /* NOTE Changed the Action order. Must terminate auth sessions while the old index digest + still exists. + */ + /* 6.f. The TPM invalidates authorization sessions */ + /* i. MUST invalidate all authorization sessions associated with D1 */ + /* ii. MAY invalidate any other authorization session */ + if ((returnCode == TPM_SUCCESS) && !done && foundOld) { + TPM_AuthSessions_TerminateEntity(&continueAuthSession, + authHandle, + tpm_state->tpm_stclear_data.authSessions, + TPM_ET_NV, + &(d1_old->digest)); + } + if ((returnCode == TPM_SUCCESS) && !done && foundOld) { + /* 6.d. Invalidate the data area currently pointed to by D1 and ensure that if the area is + reallocated no residual information is left */ + printf("TPM_Process_NVDefineSpace: Deleting index %08x\n", newNVIndex); + TPM_NVDataSensitive_Delete(d1_old); + /* must write deleted space back to NVRAM */ + writeAllNV = TRUE; + /* 6.e. If NV1_INCREMENTED is TRUE */ + /* i. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */ + /* NOTE Don't do this step until just before the serialization */ + } + /* g. If pubInfo -> dataSize is 0 then return TPM_SUCCESS */ + if ((returnCode == TPM_SUCCESS) && !done && foundOld) { + if (pubInfo->dataSize == 0) { + printf("TPM_Process_NVDefineSpace: Size 0, done\n"); + done = TRUE; + } + } + /* 7. Parse pubInfo -> pcrInfoRead */ + /* a. Validate pcrInfoRead structure on error return TPM_INVALID_STRUCTURE */ + /* i. Validation includes proper PCR selections and locality selections */ + /* NOTE: Done by TPM_NVDataPublic_Load() */ + /* 8. Parse pubInfo -> pcrInfoWrite */ + /* a. Validate pcrInfoWrite structure on error return TPM_INVALID_STRUCTURE */ + /* i. Validation includes proper PCR selections and locality selections */ + /* NOTE: Done by TPM_NVDataPublic_Load() */ + if ((returnCode == TPM_SUCCESS) && !done) { + /* b. If pcrInfoWrite -> localityAtRelease disallows some localities */ + if (pubInfo->pcrInfoRead.localityAtRelease != TPM_LOC_ALL) { + /* i. Set writeLocalities to TRUE */ + writeLocalities = TRUE; + } + /* c. Else */ + else { + /* i. Set writeLocalities to FALSE */ + writeLocalities = FALSE; + } + } + /* 9. Validate that the attributes are consistent */ + /* a. The TPM SHALL ignore the bReadSTClear, bWriteSTClear and bWriteDefine attributes during + the execution of this command */ + /* b. If TPM_NV_PER_OWNERWRITE is TRUE and TPM_NV_PER_AUTHWRITE is TRUE return TPM_AUTH_CONFLICT + */ + if ((returnCode == TPM_SUCCESS) && !done) { + if ((pubInfo->permission.attributes & TPM_NV_PER_OWNERWRITE) && + (pubInfo->permission.attributes & TPM_NV_PER_AUTHWRITE)) { + printf("TPM_Process_NVDefineSpace: Error, write authorization conflict\n"); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* c. If TPM_NV_PER_OWNERREAD is TRUE and TPM_NV_PER_AUTHREAD is TRUE return TPM_AUTH_CONFLICT + */ + if ((returnCode == TPM_SUCCESS) && !done) { + if ((pubInfo->permission.attributes & TPM_NV_PER_OWNERREAD) && + (pubInfo->permission.attributes & TPM_NV_PER_AUTHREAD)) { + printf("TPM_Process_NVDefineSpace: Error, read authorization conflict\n"); + returnCode = TPM_AUTH_CONFLICT; + } + } + /* d. If TPM_NV_PER_OWNERWRITE and TPM_NV_PER_AUTHWRITE and TPM_NV_PER_WRITEDEFINE and + TPM_NV_PER_PPWRITE and writeLocalities are all FALSE */ + if ((returnCode == TPM_SUCCESS) && !done) { + if (!(pubInfo->permission.attributes & TPM_NV_PER_OWNERWRITE) && + !(pubInfo->permission.attributes & TPM_NV_PER_AUTHWRITE) && + !(pubInfo->permission.attributes & TPM_NV_PER_WRITEDEFINE) && + !(pubInfo->permission.attributes & TPM_NV_PER_PPWRITE) && + !writeLocalities) { + /* i. Return TPM_PER_NOWRITE */ + printf("TPM_Process_NVDefineSpace: Error, no write\n"); + returnCode = TPM_PER_NOWRITE; + } + } + /* e. Validate pubInfo -> nvIndex */ + /* i. Make sure that the index is applicable for this TPM return TPM_BADINDEX on error */ + if ((returnCode == TPM_SUCCESS) && !done) { + returnCode = TPM_NVDataSensitive_IsValidIndex(newNVIndex); + } + /* f. If dataSize is 0 return TPM_BAD_PARAM_SIZE */ + if ((returnCode == TPM_SUCCESS) && !done) { + if (pubInfo->dataSize == 0) { + printf("TPM_Process_NVDefineSpace: Error, New index data size is zero\n"); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* 10. Create D1 a TPM_NV_DATA_SENSITIVE structure */ + /* NOTE Created and initialized d1_new directly in the TPM_NV_INDEX_ENTRIES array */ + /* a. Set D1 -> pubInfo to pubInfo */ + /* NOTE deserialized in place */ + if ((returnCode == TPM_SUCCESS) && !done) { + /* b. Set D1 -> authValue to A1 */ + TPM_Digest_Copy(d1_new->authValue, a1Auth); + /* c. Set D1 -> pubInfo -> bReadSTClear to FALSE */ + /* d. Set D1 -> pubInfo -> bWriteSTClear to FALSE */ + /* e. Set D1 -> pubInfo -> bWriteDefine to FALSE */ + pubInfo->bReadSTClear = FALSE; + pubInfo->bWriteSTClear = FALSE; + pubInfo->bWriteDefine = FALSE; + } + if ((returnCode == TPM_SUCCESS) && !done) { + /* assign the empty slot to the index now so it will be counted as used space during the + serialization. */ + pubInfo->nvIndex = newNVIndex; + /* 12.a. Reserve NV space for pubInfo -> dataSize + + NOTE: Action is out or order. Must allocate data space now so that the serialization + inherent in TPM_NVIndexEntries_GetFreeSpace() is valid + */ + returnCode = TPM_Malloc(&(d1_new->data), pubInfo->dataSize); + } + /* 11. Validate that sufficient NV is available to store D1 and pubInfo -> dataSize bytes of + data*/ + /* a. return TPM_NOSPACE if pubInfo -> dataSize is not available in the TPM */ + if ((returnCode == TPM_SUCCESS) && !done) { + printf("TPM_Process_NVDefineSpace: Allocated %u data bytes at %p\n", + pubInfo->dataSize, d1_new->data); + printf("TPM_Process_NVDefineSpace: Checking for %u bytes free space\n", pubInfo->dataSize); + returnCode = TPM_NVIndexEntries_GetFreeSpace(&freeSpace, + &(tpm_state->tpm_nv_index_entries)); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_NVDefineSpace: Error: No space\n"); + } + } + /* if there is no free space, free the NV index in-memory structure. This implicitly removes + the entry from tpm_nv_index_entries. If pubInfo -> nvIndex is TPM_NV_INDEX_TRIAL, the entry + should also be removed. */ + if ((returnCode != TPM_SUCCESS) || + (newNVIndex == TPM_NV_INDEX_TRIAL)) { + if (newNVIndex == TPM_NV_INDEX_TRIAL) { + printf("TPM_Process_NVDefineSpace: nvIndex is TPM_NV_INDEX_TRIAL, done\n"); + /* don't actually write, just return success or failure */ + done = TRUE; + } + TPM_NVDataSensitive_Delete(d1_new); + } + /* 12. If pubInfo -> nvIndex is not TPM_NV_INDEX_TRIAL */ + if ((returnCode == TPM_SUCCESS) && !done) { + printf("TPM_Process_NVDefineSpace: Creating index %08x\n", newNVIndex); + /* b. Set all bytes in the newly defined area to 0xFF */ + memset(d1_new->data, 0xff, pubInfo->dataSize); + /* must write newly defined space back to NVRAM */ + writeAllNV = TRUE; + } + if (returnCode == TPM_SUCCESS) { + /* c. If NV1_INCREMENTED is TRUE */ + if (nv1Incremented) { + /* i. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */ + tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1; + } + /* 13. Ignore continueAuthSession on input and set to FALSE on output */ + continueAuthSession = FALSE; + } + /* write the file to NVRAM */ + /* write back TPM_PERMANENT_DATA and TPM_PERMANENT_FLAGS if required */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_NVDefineSpace: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 27.3 DIR commands rev 87 + + The DIR commands are replaced by the NV storage commands. + + The DIR [0] in 1.1 is now TPM_PERMANENT_DATA -> authDIR[0] and is always available for the TPM to + use. It is accessed by DIR commands using dirIndex 0 and by NV commands using nvIndex + TPM_NV_INDEX_DIR. + + If the TPM vendor supports additional DIR registers, the TPM vendor may return errors or provide + vendor specific mappings for those DIR registers to NV storage locations. + + 1. A dirIndex value of 0 MUST corresponds to an NV storage nvIndex value TPM_NV_INDEX_DIR. + + 2. The TPM vendor MAY return errors or MAY provide vendor specific mappings for DIR dirIndex + values greater than 0 to NV storage locations. +*/ + +/* 27.3.1 TPM_DirWriteAuth rev 87 + + The TPM_DirWriteAuth operation provides write access to the Data Integrity Registers. DIRs are + non-volatile memory registers held in a TPM-shielded location. Owner authentication is required + to authorize this action. + + Access is also provided through the NV commands with nvIndex TPM_NV_INDEX_DIR. Owner + authorization is not required when nvLocked is FALSE. + + Version 1.2 requires only one DIR. If the DIR named does not exist, the TPM_DirWriteAuth + operation returns TPM_BADINDEX. +*/ + +TPM_RESULT TPM_Process_DirWriteAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_DIRINDEX dirIndex; /* Index of the DIR */ + TPM_DIRVALUE newContents; /* New value to be stored in named DIR */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for command. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs. HMAC key: + ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_DirWriteAuth: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get dirIndex parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&dirIndex, &command, ¶mSize); + } + /* get newContents parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DirWriteAuth: dirIndex %08x\n", dirIndex); + returnCode = TPM_Digest_Load(newContents, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_DirWriteAuth: newContents", newContents); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DirWriteAuth: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate that authHandle contains a TPM Owner AuthData to execute the TPM_DirWriteAuth + command */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Validate that dirIndex points to a valid DIR on this TPM */ + if (returnCode == TPM_SUCCESS) { + if (dirIndex != 0) { /* only one TPM_PERMANENT_DATA -> authDIR */ + printf("TPM_Process_DirWriteAuth: Error, Invalid index %08x\n", dirIndex); + returnCode = TPM_BADINDEX; + } + } + /* 3. Write newContents into the DIR pointed to by dirIndex */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DirWriteAuth: Writing data\n"); + TPM_Digest_Copy(tpm_state->tpm_permanent_data.authDIR, newContents); + /* write back TPM_PERMANENT_DATA */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + TRUE, + returnCode); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DirWriteAuth: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 27.3.2 TPM_DirRead rev 87 + + The TPM_DirRead operation provides read access to the DIRs. No authentication is required to + perform this action because typically no cryptographically useful AuthData is available early in + boot. TSS implementors may choose to provide other means of authorizing this action. Version 1.2 + requires only one DIR. If the DIR named does not exist, the TPM_DirRead operation returns + TPM_BADINDEX. +*/ + +TPM_RESULT TPM_Process_DirRead(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_DIRINDEX dirIndex; /* Index of the DIR to be read */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_DirRead: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get dirIndex parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&dirIndex, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DirRead: dirIndex %08x\n", dirIndex); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DirRead: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Validate that dirIndex points to a valid DIR on this TPM */ + if (returnCode == TPM_SUCCESS) { + if (dirIndex != 0) { /* only one TPM_PERMANENT_DATA -> authDIR */ + printf("TPM_Process_DirRead: Error, Invalid index %08x\n", dirIndex); + returnCode = TPM_BADINDEX; + } + } + /* 2. Return the contents of the DIR in dirContents */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DirRead: Reading data\n"); + TPM_PrintFour("TPM_Process_DirRead:", tpm_state->tpm_permanent_data.authDIR); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DirRead: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append dirContents */ + returnCode = TPM_Digest_Store(response, tpm_state->tpm_permanent_data.authDIR); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + return rcf; +} diff --git a/src/tpm12/tpm_nvram.h b/src/tpm12/tpm_nvram.h new file mode 100644 index 0000000..4bea9ef --- /dev/null +++ b/src/tpm12/tpm_nvram.h @@ -0,0 +1,201 @@ +/********************************************************************************/ +/* */ +/* NVRAM Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_nvram.h 4528 2011-03-29 22:16:28Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_NVRAM_H +#define TPM_NVRAM_H + +#include + +#include "tpm_global.h" +#include "tpm_types.h" + +/* + NVRAM common functions +*/ + +/* + TPM_NV_ATTRIBUTES +*/ + +void TPM_NVAttributes_Init(TPM_NV_ATTRIBUTES *tpm_nv_attributes); +TPM_RESULT TPM_NVAttributes_Load(TPM_NV_ATTRIBUTES *tpm_nv_attributes, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_NVAttributes_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_NV_ATTRIBUTES *tpm_nv_attributes); +void TPM_NVAttributes_Delete(TPM_NV_ATTRIBUTES *tpm_nv_attributes); + +void TPM_NVAttributes_Copy(TPM_NV_ATTRIBUTES *tpm_nv_attributes_dest, + TPM_NV_ATTRIBUTES *tpm_nv_attributes_src); + +/* + TPM_NV_DATA_PUBLIC +*/ + +void TPM_NVDataPublic_Init(TPM_NV_DATA_PUBLIC *tpm_nv_data_public); +TPM_RESULT TPM_NVDataPublic_Load(TPM_NV_DATA_PUBLIC *tpm_nv_data_public, + unsigned char **stream, + uint32_t *stream_size, + TPM_BOOL optimize); +TPM_RESULT TPM_NVDataPublic_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_NV_DATA_PUBLIC *tpm_nv_data_public, + TPM_BOOL optimize); +void TPM_NVDataPublic_Delete(TPM_NV_DATA_PUBLIC *tpm_nv_data_public); + +/* + TPM_NV_DATA_SENSITIVE +*/ + +void TPM_NVDataSensitive_Init(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive); +TPM_RESULT TPM_NVDataSensitive_Load(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive, + TPM_TAG nvEntriesVersion, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_NVDataSensitive_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive); +void TPM_NVDataSensitive_Delete(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive); + +TPM_RESULT TPM_NVDataSensitive_IsValidIndex(TPM_NV_INDEX nvIndex); +TPM_RESULT TPM_NVDataSensitive_IsGPIO(TPM_BOOL *isGPIO, TPM_NV_INDEX nvIndex); +TPM_RESULT TPM_NVDataSensitive_IsValidPlatformIndex(TPM_NV_INDEX nvIndex); + +/* + NV Index Entries +*/ + +void TPM_NVIndexEntries_Init(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +void TPM_NVIndexEntries_Delete(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +void TPM_NVIndexEntries_Trace(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_Load(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_NVIndexEntries_Store(TPM_STORE_BUFFER *sbuffer, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +void TPM_NVIndexEntries_StClear(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_LoadVolatile(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_NVIndexEntries_StoreVolatile(TPM_STORE_BUFFER *sbuffer, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_GetVolatile(TPM_NV_DATA_ST **tpm_nv_data_st, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_SetVolatile(TPM_NV_DATA_ST *tpm_nv_data_st, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_GetFreeEntry(TPM_NV_DATA_SENSITIVE **tpm_nv_data_sensitive, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_GetEntry(TPM_NV_DATA_SENSITIVE **tpm_nv_data_sensitive, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + TPM_NV_INDEX nvIndex); +TPM_RESULT TPM_NVIndexEntries_GetUsedCount(uint32_t *count, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_GetNVList(TPM_STORE_BUFFER *sbuffer, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_GetUsedSpace(uint32_t *usedSpace, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_DeleteOwnerAuthorized(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + TPM_BOOL deleteAllNvram); +TPM_RESULT TPM_NVIndexEntries_GetUsedSpace(uint32_t *usedSpace, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_GetFreeSpace(uint32_t *freeSpace, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); +TPM_RESULT TPM_NVIndexEntries_GetDataPublic(TPM_NV_DATA_PUBLIC **tpm_nv_data_public, + TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, + TPM_NV_INDEX nvIndex); + +/* + Processing Functions +*/ + + +TPM_RESULT TPM_Process_NVReadValue(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_NVReadValueAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_NVWriteValue(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_NVWriteValueAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +TPM_RESULT TPM_Process_NVDefineSpace(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DirRead(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DirWriteAuth(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +#endif diff --git a/src/tpm12/tpm_nvram_const.h b/src/tpm12/tpm_nvram_const.h new file mode 100644 index 0000000..68ee97c --- /dev/null +++ b/src/tpm12/tpm_nvram_const.h @@ -0,0 +1,138 @@ +/********************************************************************************/ +/* */ +/* NVRAM Constants */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_nvram_const.h 4528 2011-03-29 22:16:28Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_NVRAM_CONST_H +#define TPM_NVRAM_CONST_H + +/* + These are implementation specific constants +*/ + +/* + TPMS_MAX defines the maximum number of TPM instances. +*/ + +#define TPMS_MAX 1 + +/* + NVRAM storage directory path +*/ + + +#ifdef TPM_NV_DISK +/* TPM_NV_DISK uses the TPM_PATH environment variable */ +#endif + +/* Defines the maximum size of the NV defined space, the NV indexes created by TPM_NV_DefineSpace. + + The PC Client requires 2048 bytes. There is at least (currently) 6 bytes of overhead, a tag and + a count. +*/ + +#ifndef TPM_MAX_NV_DEFINED_SIZE +#define TPM_MAX_NV_DEFINED_SIZE 2100 +#endif + +/* TPM_MAX_NV_SPACE defines the maximum NV space for non-volatile state. + + It does not include the area used for TPM_SaveState. + + See TPM_OWNER_EVICT_KEY_HANDLES, TPM_MIN_COUNTERS, TPM_NUM_FAMILY_TABLE_ENTRY_MIN, + TPM_NUM_DELEGATE_TABLE_ENTRY_MIN, etc. and the platform specific requirements for NV defined + space. +*/ + +#ifndef TPM_MAX_NV_SPACE + + + +#ifdef TPM_NV_DISK +#define TPM_MAX_NV_SPACE 100000 /* arbitrary value */ +#endif + +#endif /* TPM_MAX_NV_SPACE */ + +#ifndef TPM_MAX_NV_SPACE +#error "TPM_MAX_NV_SPACE is not defined" +#endif + +/* TPM_MAX_SAVESTATE_SPACE defines the maximum NV space for TPM saved state. + + It is used by TPM_SaveState + + NOTE This macro is based on the maximum number of loaded keys and session. For example, 3 loaded + keys, 3 OSAP sessions, and 1 transport session consumes about 2500 bytes. + + See TPM_KEY_HANDLES, TPM_NUM_PCR, TPM_MIN_AUTH_SESSIONS, TPM_MIN_TRANS_SESSIONS, + TPM_MIN_DAA_SESSIONS, TPM_MIN_SESSION_LIST, etc. +*/ + +#ifndef TPM_MAX_SAVESTATE_SPACE + + + +#ifdef TPM_NV_DISK +#define TPM_MAX_SAVESTATE_SPACE 100000 /* arbitrary value */ +#endif + +#endif /* TPM_MAX_SAVESTATE_SPACE */ + +#ifndef TPM_MAX_SAVESTATE_SPACE +#error "TPM_MAX_SAVESTATE_SPACE is not defined" +#endif + +/* TPM_MAX_VOLATILESTATE_SPACE defines the maximum NV space for TPM volatile state. + + It is used for applications that save and restore the entire TPM volatile is a non-standard way. +*/ + +#ifndef TPM_MAX_VOLATILESTATE_SPACE + + +#ifdef TPM_NV_DISK +#define TPM_MAX_VOLATILESTATE_SPACE 524288 /* arbitrary value */ +#endif + +#endif /* TPM_MAX_VOLATILESTATE_SPACE */ + +#ifndef TPM_MAX_VOLATILESTATE_SPACE +#error "TPM_MAX_VOLATILESTATE_SPACE is not defined" +#endif + +#endif diff --git a/src/tpm12/tpm_openssl_helpers.c b/src/tpm12/tpm_openssl_helpers.c new file mode 100644 index 0000000..c798acb --- /dev/null +++ b/src/tpm12/tpm_openssl_helpers.c @@ -0,0 +1,135 @@ +/********************************************************************************/ +/* */ +/* OpenSSL helper functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2020. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_openssl_helpers.h" + +#include "tpm_crypto.h" + +#if USE_OPENSSL_FUNCTIONS_RSA + +TPM_RESULT TPM_RSAGenerateEVP_PKEY(EVP_PKEY **pkey, /* out: pkey */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + int irc; + BIGNUM * n = NULL; + BIGNUM * e = NULL; + BIGNUM * d = NULL; + RSA * rsakey = NULL; + + /* sanity check for the free */ + if (rc == 0) { + if (*pkey != NULL) { + printf("TPM_RSAGeneratePrivateToken: Error (fatal), pkey %p should be NULL\n", + *pkey); + rc = TPM_FAIL; + } + } + /* construct the OpenSSL private key object */ + if (rc == 0) { + *pkey = EVP_PKEY_new(); /* freed by caller */ + if (*pkey == NULL) { + printf("TPM_RSAGeneratePrivateToken: Error in EVP_PKEY_new()\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ + } + if (rc == 0) { + if (darr != NULL) { + rc = TPM_bin2bn((TPM_BIGNUM *)&d, darr, dbytes); /* freed by caller */ + } + } + if (rc == 0) { + rsakey = RSA_new(); + if (rsakey == NULL) { + printf("TPM_RSAGeneratePrivateToken: Error in RSA_new()\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + irc = RSA_set0_key(rsakey, n, e, d); + if (irc != 1) { + printf("TPM_RSAGeneratePrivateToken: Error in RSA_set0_key()\n"); + rc = TPM_FAIL; + } else { + n = NULL; + e = NULL; + d = NULL; + } + } + if (rc == 0) { + RSA_set_flags(rsakey, RSA_FLAG_NO_BLINDING); + irc = EVP_PKEY_assign_RSA(*pkey, rsakey); + if (irc == 0) { + printf("TPM_RSAGeneratePrivateToken: Error in EVP_PKEY_assign_RSA()\n"); + rc = TPM_FAIL; + } else { + rsakey = NULL; + } + } + + if (rc != 0) { + EVP_PKEY_free(*pkey); + *pkey = NULL; + RSA_free(rsakey); + BN_free(n); + BN_free(e); + BN_clear_free(d); + } + + return rc; +} + +#endif + diff --git a/src/tpm12/tpm_openssl_helpers.h b/src/tpm12/tpm_openssl_helpers.h new file mode 100644 index 0000000..330fd98 --- /dev/null +++ b/src/tpm12/tpm_openssl_helpers.h @@ -0,0 +1,50 @@ +/********************************************************************************/ +/* */ +/* OpenSSL helper functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2020. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_OPENSSL_HELPERS_H +#define TPM_OPENSSL_HELPERS_H + +TPM_RESULT TPM_RSAGenerateEVP_PKEY(EVP_PKEY **pkey, /* out: pkey */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes); + +#endif diff --git a/src/tpm12/tpm_owner.c b/src/tpm12/tpm_owner.c new file mode 100644 index 0000000..4360505 --- /dev/null +++ b/src/tpm12/tpm_owner.c @@ -0,0 +1,1968 @@ +/********************************************************************************/ +/* */ +/* Ownership Processing */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_owner.c 4620 2011-09-07 21:43:19Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_audit.h" +#include "tpm_auth.h" +#include "tpm_counter.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_delegate.h" +#include "tpm_error.h" +#include "tpm_init.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_nonce.h" +#include "tpm_nvram.h" +#include "tpm_pcr.h" +#include "tpm_permanent.h" +#include "tpm_process.h" +#include "tpm_secret.h" +#include "tpm_session.h" +#include "tpm_sizedbuffer.h" +#include "tpm_transport.h" + +#include "tpm_owner.h" + +/* Flags involved with clearing an owner: + + pFlags.disableOwnerClear + set by TPM_DisableOwnerClear + clear by successful owner clear + vFlags.disableForceClear + set by TPM_DisableForceClear + clear by TPM_Init + + TPM_OwnerClear + requires ownerAuth + pFlags.disableOwnerClear == FALSE + TPM_ForceClear + requires physical presence + vFlags.disableForceClear == FALSE +*/ + +/* 6.1 TPM_TakeOwnership rev 114 + + This command inserts the TPM Ownership value into the TPM. +*/ + +TPM_RESULT TPM_Process_TakeOwnership(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* bytes left in command */ + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_PROTOCOL_ID protocolID; /* The ownership protocol in use */ + TPM_SIZED_BUFFER encOwnerAuth; /* The owner authorization data encrypted with PUBEK */ + TPM_SIZED_BUFFER encSrkAuth; /* The SRK authorization data encrypted with PUBEK */ + TPM_KEY srkParams; /* Structure containing all parameters of new SRK. + pubKey.keyLength & encSize are both 0. This structure + MAY be TPM_KEY12. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for this command */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession; /* The continue use flag for the authorization handle */ + TPM_AUTHDATA ownerAuth; /* Authorization digest for input params. HMAC key: the new + ownerAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_SECRET a1Auth; /* decrypt of encOwnerAuth */ + uint32_t a1Auth_length; /* length of decrypted A1 */ + TPM_SECRET a2SrkAuth; /* decrypt of encSrkAuth */ + uint32_t a2SrkAuth_length; /* length of decrypted A2 */ + TPM_RSA_KEY_PARMS *srkRSAKeyParms; + TPM_STORE_ASYMKEY *srkStoreAsymkey; + TPM_STORE_BUFFER asymKeySbuffer; /* serialized SRK asymkey */ + TPM_KEY *srk; /* pointer to SRK in permanent data */ + TPM_SIZED_BUFFER exponent; /* default exponent */ + TPM_BOOL writeAllNV1 = FALSE; /* flags to write back NV */ + TPM_BOOL writeAllNV2 = FALSE; /* flags to write back NV */ + int ver; /* TPM_KEY or TPM_KEY12 */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_KEY srkPub; /* Structure containing all parameters of new SRK, + srkPub.encData is set to 0. */ + + printf("TPM_Process_TakeOwnership: Ordinal Entry\n"); + srk = &(tpm_state->tpm_permanent_data.srk); /* get pointer to SRK in permanent data */ + + /* so that Delete's are safe */ + TPM_SizedBuffer_Init(&encOwnerAuth); /* freed @1 */ + TPM_SizedBuffer_Init(&encSrkAuth); /* freed @2 */ + TPM_Key_Init(&srkParams); /* freed @3 */ + TPM_Key_Init(&srkPub); /* freed @5 */ + TPM_SizedBuffer_Init(&exponent); /* freed @6 */ + TPM_Sbuffer_Init(&asymKeySbuffer); /* freed @7 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get protocolID parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&protocolID, &command, ¶mSize); + } + /* get encOwnerAuth parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: protocolID %04hx\n", protocolID); + returnCode = TPM_SizedBuffer_Load(&encOwnerAuth, &command, ¶mSize); + } + /* get encSrkAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&encSrkAuth, &command, ¶mSize); + } + /* get srkParams parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_Load(&srkParams, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_ENABLED | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_TakeOwnership: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. If TPM_PERMANENT_DATA -> ownerAuth is valid return TPM_OWNER_SET */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Checking TPM state\n"); + if (tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_Process_TakeOwnership: Error, owner already installed\n"); + returnCode = TPM_OWNER_SET; + } + } + /* 2. If TPM_PERMANENT_FLAGS -> ownership is FALSE return TPM_INSTALL_DISABLED */ + if (returnCode == TPM_SUCCESS) { + if (!(tpm_state->tpm_permanent_flags.ownership)) { + printf("TPM_Process_TakeOwnership: Error, ownership is false\n"); + returnCode = TPM_INSTALL_DISABLED; + } + } + /* 3. If TPM_PERMANENT_DATA -> endorsementKey is invalid return TPM_NO_ENDORSEMENT */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_permanent_data.endorsementKey.keyUsage == TPM_KEY_UNINITIALIZED) { + printf("TPM_Process_TakeOwnership: Error, endorsement key is invalid\n"); + returnCode = TPM_NO_ENDORSEMENT; + } + } + /* 4. Verify that authHandle is of type OIAP on error return TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OIAP, + 0, /* OSAP entity type */ + ordinal, + NULL, + NULL, /* no OIAP authorization */ + NULL); + } + /* 5. If protocolID is not TPM_PID_OWNER, the TPM MAY return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (protocolID != TPM_PID_OWNER) { + printf("TPM_Process_TakeOwnership: Error, bad protocolID\n"); + returnCode = TPM_BAD_PARAMETER; + + } + } + /* 6. Create A1 a TPM_SECRET by decrypting encOwnerAuth using PRIVEK as the key */ + /* a. This requires that A1 was encrypted using the PUBEK */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPrivateDecryptH(a1Auth, /* decrypted data */ + &a1Auth_length, /* actual size of A1 */ + TPM_SECRET_SIZE, /* size of A1 buffer */ + encOwnerAuth.buffer, /* encrypted data */ + encOwnerAuth.size, /* encrypted data size */ + &(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* b. Validate that A1 is a length of 20 bytes, on error return TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (a1Auth_length != TPM_SECRET_SIZE) { + printf("TPM_Process_TakeOwnership: Error, A1 length %u, should be %u\n", + a1Auth_length, TPM_SECRET_SIZE); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* 7. Validate the command and parameters using A1 and ownerAuth, on error return TPM_AUTHFAIL + */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_TakeOwnership: A1 secret", a1Auth); + returnCode = TPM_Authdata_Check(tpm_state, + a1Auth, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* + 8. Validate srkParams + */ + /* a. If srkParams -> keyUsage is not TPM_KEY_STORAGE return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Validating SRK parameters\n"); + if (srkParams.keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->keyUsage is not TPM_KEY_STORAGE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* b. If srkParams -> migratable is TRUE return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (srkParams.keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_TakeOwnership: Error, srkParams->keyFlags migratable is TRUE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* c. If srkParams -> algorithmParms -> algorithmID is NOT TPM_ALG_RSA return + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (srkParams.algorithmParms.algorithmID != TPM_ALG_RSA) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->algorithmID is NOT TPM_ALG_RSA\n"); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* d. If srkParams -> algorithmParms -> encScheme is NOT TPM_ES_RSAESOAEP_SHA1_MGF1 return + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (srkParams.algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->encScheme is NOT TPM_ES_RSAESOAEP_SHA1_MGF1\n"); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* e. If srkParams -> algorithmParms -> sigScheme is NOT TPM_SS_NONE return + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (srkParams.algorithmParms.sigScheme != TPM_SS_NONE) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->sigScheme is NOT TPM_SS_NONE\n"); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* f. srkParams -> algorithmParms -> parms -> keyLength MUST be greater than or equal to + 2048, on error return TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_GetRSAKeyParms(&srkRSAKeyParms, &(srkParams.algorithmParms)); + } + if (returnCode == TPM_SUCCESS) { + if (srkRSAKeyParms->keyLength < 2048) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->parms->keyLength " + "MUST be greater than or equal to 2048\n"); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* g .If srkParams -> algorithmParms -> parms -> exponentSize is not 0, return + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (srkRSAKeyParms->exponent.size != 0) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->parms->exponentSize %u is not zero\n", + srkRSAKeyParms->exponent.size); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* h. If TPM_PERMANENT_FLAGS -> FIPS is TRUE */ + /* i. If srkParams -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state -> tpm_permanent_flags.FIPS) { + if (srkParams.authDataUsage == TPM_AUTH_NEVER) { + printf("TPM_Process_TakeOwnership: Error, " + "FIPS and authDataUsage is TPM_AUTH_NEVER\n"); + returnCode = TPM_NOTFIPS; + } + } + } + /* check that srkParams is TPM_KEY or TPM_KEY12 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_CheckStruct(&ver, &srkParams); + } + /* 9. Generate K1 (SRK) according to the srkParams on error return TPM_BAD_KEY_PROPERTY */ + /* a.This includes copying PCRInfo from srkParams to K1 */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: SRK key length %u\n", srkRSAKeyParms->keyLength); + if (ver == 1) { + if (srkParams.tpm_pcr_info != NULL) { + TPM_PCRInfo_Trace("TPM_Process_TakeOwnership: SRK PCRs", + srkParams.tpm_pcr_info->pcrSelection, + srkParams.tpm_pcr_info->digestAtRelease); + } + else { + printf("TPM_Process_TakeOwnership: No SRK PCRs\n"); + } + } + else { + if (srkParams.tpm_pcr_info_long != NULL) { + TPM_PCRInfo_Trace("TPM_Process_TakeOwnership: SRK PCRs", + srkParams.tpm_pcr_info_long->releasePCRSelection, + srkParams.tpm_pcr_info_long->digestAtRelease); + } + else { + printf("TPM_Process_TakeOwnership: No SRK PCRs\n"); + } + } + printf("TPM_Process_TakeOwnership: Creating SRK, authDataUsage %u\n", + srkParams.authDataUsage); + /* The old keys should already be deleted from an OwnerClear, but it can't hurt to do it + again to prevent memory leaks on errors. */ + TPM_Key_Delete(srk); /* not freed, in permanent store */ + returnCode = TPM_Key_GenerateRSA(srk, + tpm_state, + NULL, /* parent key */ + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + ver, + TPM_KEY_STORAGE, /* keyUsage */ + srkParams.keyFlags, + srkParams.authDataUsage, + &(srkParams.algorithmParms), /* TPM_KEY_PARMS */ + srkParams.tpm_pcr_info, + srkParams.tpm_pcr_info_long); + writeAllNV1 = TRUE; + } + /* 15. Create TPM_PERMANENT_DATA -> tpmProof by using the TPM RNG */ + /* NOTE: Moved here so tpmProof can be inserted into SRK -> migrationAuth */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Creating tpmProof\n"); + returnCode = TPM_Secret_Generate(tpm_state->tpm_permanent_data.tpmProof); + } + /* 10. Create A2 a TPM_SECRET by decrypting encSrkAuth using the PRIVEK */ + /* a. This requires A2 to be encrypted using the PUBEK */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPrivateDecryptH(a2SrkAuth, /* decrypted data */ + &a2SrkAuth_length, /* actual size of A2 */ + TPM_SECRET_SIZE, /* size of A2 buffer */ + encSrkAuth.buffer, /* encrypted data */ + encSrkAuth.size, /* encrypted data size */ + &(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* b. Validate that A2 is a length of 20 bytes, on error return TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (a2SrkAuth_length != TPM_SECRET_SIZE) { + printf("TPM_Process_TakeOwnership: Error, A2 length %u, should be %u\n", + a2SrkAuth_length, TPM_SECRET_SIZE); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* c. Store A2 in K1 (SRK) -> usageAuth */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_TakeOwnership: Insert usageAuth into SRK", a2SrkAuth); + /* get the TPM_STORE_ASYMKEY from the TPM_KEY srk */ + returnCode = TPM_Key_GetStoreAsymkey(&srkStoreAsymkey, srk); + } + if (returnCode == TPM_SUCCESS) { + /* insert the authData into the TPM_STORE_ASYMKEY */ + TPM_Secret_Copy(srkStoreAsymkey->usageAuth, a2SrkAuth); + /* store tpmProof in migrationAuth to indicate that this is a non-migratable key */ + TPM_Secret_Copy(srkStoreAsymkey->migrationAuth, tpm_state->tpm_permanent_data.tpmProof); + /* serialize the TPM_STORE_ASYMKEY object */ + returnCode = TPM_StoreAsymkey_Store(&asymKeySbuffer, FALSE, srkStoreAsymkey); + } + /* store the serialized TPM_STORE_ASYMKEY as encData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_SetFromStore(&(srk->encData), &asymKeySbuffer); + } + /* 11. Store K1 in TPM_PERMANENT_DATA -> srk */ + /* NOTE Generated directly in srk */ + /* 12. Store A1 in TPM_PERMANENT_DATA -> ownerAuth */ + if (returnCode == TPM_SUCCESS) { + TPM_Secret_Copy(tpm_state->tpm_permanent_data.ownerAuth, a1Auth); + tpm_state->tpm_permanent_data.ownerInstalled = TRUE; + } + /* 13. Create TPM_PERMANENT_DATA -> contextKey according to the rules for the algorithm in use + by the TPM to save context blobs */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Creating contextKey\n"); + returnCode = TPM_SymmetricKeyData_GenerateKey(tpm_state->tpm_permanent_data.contextKey); + } + /* 14. Create TPM_PERMANENT_DATA -> delegateKey according to the rules for the algorithm in use + by the TPM to save delegate blobs */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Creating delegateKey\n"); + returnCode = TPM_SymmetricKeyData_GenerateKey(tpm_state->tpm_permanent_data.delegateKey); + } + /* 15. Create TPM_PERMANENT_DATA -> tpmProof by using the TPM RNG */ + /* NOTE: This Action done earlier */ + /* 16. Export TPM_PERMANENT_DATA -> srk as srkPub */ + if (returnCode == TPM_SUCCESS) { + /* copy the srk */ + printf("TPM_Process_TakeOwnership: Creating srkPub for response\n"); + returnCode = TPM_Key_Copy(&srkPub, srk, FALSE); /* don't copy encData */ + } + /* 17. Set TPM_PERMANENT_FLAGS -> readPubek to FALSE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Clear readPubek\n"); + TPM_SetCapability_Flag(&writeAllNV2, /* altered */ + &(tpm_state->tpm_permanent_flags.readPubek), /* flag */ + FALSE); /* value */ + } + /* Store the permanent data and flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + (TPM_BOOL)(writeAllNV1 || writeAllNV2), + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_TakeOwnership: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append srkPub */ + returnCode = TPM_Key_Store(response, &srkPub); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + /* 18. Calculate resAuth using the newly established TPM_PERMANENT_DATA -> ownerAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_AuthParams_Set(response, + tpm_state->tpm_permanent_data.ownerAuth, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + TPM_SizedBuffer_Delete(&encOwnerAuth); /* @1 */ + TPM_SizedBuffer_Delete(&encSrkAuth); /* @2 */ + TPM_Key_Delete(&srkParams); /* @3 */ + TPM_Key_Delete(&srkPub); /* @5 */ + TPM_SizedBuffer_Delete(&exponent); /* @6 */ + TPM_Sbuffer_Delete(&asymKeySbuffer); /* @7 */ + return rcf; +} + +/* 6.2 TPM_OwnerClear rev 101 + + The OwnerClear command performs the clear operation under authorization. This command is + available until the Owner executes the DisableOwnerClear, at which time any further invocation of + this command returns TPM_CLEAR_DISABLED. +*/ + +TPM_RESULT TPM_Process_OwnerClear(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner + authorization. HMAC key: permanent_data.ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_SECRET oldOwnerAuth; /* saved copy for response */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back permanent */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_OwnerClear: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_OwnerClear: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Verify that the TPM Owner authorizes the command and all of the input, on error return + TPM_AUTHFAIL. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + /* make a copy of the TPM_PERMANENT_DATA.ownerAuth for the response, since it gets + invalidated in step 5. */ + TPM_Secret_Copy(oldOwnerAuth, *hmacKey); + TPM_PrintFour("TPM_Process_OwnerClear: ownerAuth secret", *hmacKey); + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. If TPM_PERMANENT_FLAGS -> disableOwnerClear is TRUE then return TPM_CLEAR_DISABLED. */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_permanent_flags.disableOwnerClear) { + printf("TPM_Process_OwnerClear: Error, disableOwnerClear is TRUE\n"); + returnCode = TPM_CLEAR_DISABLED; + } + } + /* owner clear common code */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_OwnerClearCommon(tpm_state, + FALSE); /* don't delete if D bit set */ + continueAuthSession = FALSE; /* Fixed value FALSE */ + writeAllNV = TRUE; + } + /* Store the permanent data and flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_OwnerClear: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + oldOwnerAuth, /* old owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. NOTE: Normally this will fail because all + sessions have been closed. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + return rcf; +} + +/* 6.3 TPM_ForceClear rev 109 + + The ForceClear command performs the Clear operation under physical access. This command is + available until the execution of the DisableForceClear, at which time any further invocation of + this command returns TPM_CLEAR_DISABLED. + + TPM_ForceClear can succeed even if no owner is installed. In that case, it does whatever + TPM_OwnerClear actions that it can. +*/ + +TPM_RESULT TPM_Process_ForceClear(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back data */ + TPM_BOOL physicalPresence; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ForceClear: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ForceClear: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM SHALL check for the assertion of physical presence, if not present return + TPM_BAD_PRESENCE */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_ForceClear: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + /* 2. If TPM_STCLEAR_FLAGS -> disableForceClear is TRUE return TPM_CLEAR_DISABLED */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_stclear_flags.disableForceClear) { + printf("TPM_Process_ForceClear: Error, disableForceClear is TRUE\n"); + returnCode = TPM_CLEAR_DISABLED; + } + } + /* 3. The TPM SHALL execute the actions of TPM_OwnerClear (except for the TPM Owner + authentication check) */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_OwnerClearCommon(tpm_state, + FALSE); /* don't delete if D bit set */ + writeAllNV = TRUE; + } + /* Store the permanent data and flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ForceClear: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* TPM_OwnerClearCommon() rev 116 + + Performs owner clear operations common to TPM_OwnerClear, TPM_ForceClear, and TPM_RevokeTrust. + + It assumes that any required authorization is performed by the caller + + If deleteAllNvram is TRUE, all NVRAM is deleted. If it is FALSE, indexes with the D bit set are + not cleared. + + Data is not written back to NV space here. It is written by the caller. +*/ + +TPM_RESULT TPM_OwnerClearCommon(tpm_state_t *tpm_state, + TPM_BOOL deleteAllNvram) +{ + TPM_RESULT rc = 0; + size_t start; + size_t current; + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; + + /* 3. Unload all loaded keys. */ + /* a. If TPM_PERMANENT_FLAGS -> FIPS is TRUE, the memory locations containing secret or private + keys MUST be set to all zeros. */ + start = 0; + while ((rc == 0) && + /* returns TPM_RETRY when at the end of the table, terminates loop */ + (TPM_KeyHandleEntries_GetNextEntry(&tpm_key_handle_entry, + ¤t, + tpm_state->tpm_key_handle_entries, + start)) == 0) { + printf("TPM_OwnerClearCommon: Flushing key handle %08x\n", + tpm_key_handle_entry->handle); + rc = TPM_KeyHandleEntry_FlushSpecific(tpm_state, tpm_key_handle_entry); + start = current + 1; + } +#ifdef TPM_V11 + /* 5. The TPM sets all DIR registers to their default value. */ + if (rc == 0) { + TPM_Digest_Init(tpm_state->tpm_permanent_data.authDIR); + } +#endif + /* a.This includes owner evict keys */ + if (rc == 0) { + printf("TPM_OwnerClearCommon: Deleting owner evict keys\n"); + TPM_KeyHandleEntries_OwnerEvictDelete(tpm_state->tpm_key_handle_entries); + } + /* 4. The TPM MUST NOT modify the following TPM_PERMANENT_DATA items + a. endorsementKey + b. revMajor + c. revMinor + d. manuMaintPub + e. auditMonotonicCounter + NOTE: TPMWG email: Don't touch the base value. + f. monotonicCounter + g. pcrAttrib + h. rngState + i. EKReset + j. lastFamilyID + k. tpmDAASeed + l. DIR[1] + m. daaProof + n. daaBlobKey + */ + /* 5. The TPM MUST invalidate the following TPM_PERMANENT_DATA items and + any internal resources associated with these items */ + if (rc == 0) { + printf("TPM_OwnerClearCommon: Invalidate TPM_PERMANENT_DATA items\n"); + /* a. ownerAuth */ + TPM_Secret_Init(tpm_state->tpm_permanent_data.ownerAuth); + tpm_state->tpm_permanent_data.ownerInstalled = FALSE; + /* b. srk */ + TPM_Key_Delete(&(tpm_state->tpm_permanent_data.srk)); + /* c. delegateKey */ + printf("TPM_OwnerClearCommon: Invalidate delegateKey\n"); + TPM_SymmetricKeyData_Init(tpm_state->tpm_permanent_data.delegateKey); + /* d. delegateTable */ + TPM_DelegateTable_Delete(&(tpm_state->tpm_permanent_data.delegateTable)); + /* e. contextKey */ + printf("TPM_OwnerClearCommon: Invalidate contextKey\n"); + TPM_SymmetricKeyData_Init(tpm_state->tpm_permanent_data.contextKey); + /* f. tpmProof */ + TPM_Secret_Init(tpm_state->tpm_permanent_data.tpmProof); + /* g. operatorAuth */ + TPM_Secret_Init(tpm_state->tpm_permanent_data.operatorAuth); + /* 6. The TPM MUST reset to manufacturing defaults the following TPM_PERMANENT_DATA items */ + /* a. noOwnerNVWrite MUST be set to 0 */ + tpm_state->tpm_permanent_data.noOwnerNVWrite = 0; + /* b. ordinalAuditStatus */ + rc = TPM_OrdinalAuditStatus_Init(&(tpm_state->tpm_permanent_data)); + /* c. restrictDelegate */ + tpm_state->tpm_permanent_data.restrictDelegate = 0; + } + if (rc == 0) { + /* 7. The TPM MUST invalidate or reset all fields of TPM_STANY_DATA + a. Nonces SHALL be reset + b. Lists (e.g. contextList) SHALL be invalidated + NOTE This also terminates all sessions + */ + printf("TPM_OwnerClearCommon: Invalidate TPM_STANY_DATA\n"); + TPM_StanyData_Delete(&(tpm_state->tpm_stany_data)); + /* 8. The TPM MUST invalidate all fields of TPM_STCLEAR_DATA except the PCR's + a. Nonces SHALL be reset + b. Lists (e.g. contextList) SHALL be invalidated + c. deferredPhysicalPresence MUST be set to 0 + */ + printf("TPM_OwnerClearCommon: Invalidate TPM_STCLEAR_DATA\n"); + TPM_StclearData_Delete(&(tpm_state->tpm_stclear_data), + tpm_state->tpm_permanent_data.pcrAttrib, + FALSE); /* don't reset the PCR's */ + /* 9. The TPM MUST set the following TPM_PERMANENT_FLAGS to their default values */ + /* a. disable */ + printf("TPM_OwnerClearCommon: Set disable TRUE\n"); + tpm_state->tpm_permanent_flags.disable = TRUE; + /* b. deactivated */ + printf("TPM_OwnerClearCommon: Set deactivated TRUE\n"); + tpm_state->tpm_permanent_flags.deactivated = TRUE; + /* c. readPubek */ + printf("TPM_OwnerClearCommon: Set readPubek TRUE\n"); + tpm_state->tpm_permanent_flags.readPubek = TRUE; + /* d. disableOwnerClear */ + tpm_state->tpm_permanent_flags.disableOwnerClear = FALSE; +#if (TPM_REVISION >= 103) /* added for rev 103 */ + /* e. disableFullDALogicInfo */ + tpm_state->tpm_permanent_flags.disableFullDALogicInfo = FALSE; +#endif + /* f. allowMaintenance */ +#if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) + tpm_state->tpm_permanent_flags.allowMaintenance = FALSE; +#else + tpm_state->tpm_permanent_flags.allowMaintenance = TRUE; +#endif + + /* #if (TPM_REVISION >= 104) This was added in rev 104, but was implemented by vendors + earlier */ + /* g. readSRKPub */ + tpm_state->tpm_permanent_flags.readSRKPub = FALSE; + /* 10. The TPM MUST set the following TPM_PERMANENT_FLAGS */ + /* a. ownership to TRUE */ + tpm_state->tpm_permanent_flags.ownership = TRUE; + /* b. operator to FALSE */ + tpm_state->tpm_permanent_flags.tpmOperator = FALSE; + /* c. maintenanceDone to FALSE */ + tpm_state->tpm_permanent_flags.maintenanceDone = FALSE; + /* 11. The TPM releases all TPM_PERMANENT_DATA -> monotonicCounter settings + + a. This includes invalidating all currently allocated counters. The result will be no + currently allocated counters and the new owner will need to allocate counters. The actual + count value will continue to increase. + */ + rc = TPM_Counters_Release(tpm_state->tpm_permanent_data.monotonicCounter); + /* NOTE: v1.1 says to set all TPM_PERSISTENT_FLAGS to the default value, but I doubt this is + correct. I assume that physicalPresenceLifetimeLock which is a one-way flag, should not + be reset. A similar comment goes for tpmPost and tpmPostLock. */ + } + /* TPM_OwnerClear 12. The TPM MUST deallocate all defined NV storage areas where + a. TPM_NV_PER_OWNERWRITE is TRUE if nvIndex does not have the "D" bit set + b. TPM_NV_PER_OWNERREAD is TRUE if nvIndex does not have the "D" bit set + c. The TPM MUST NOT deallocate any other currently defined NV storage areas. + d.This default behavior MAY be superseded for GPIO indexes by the platform specific + specification. + + TPM_RevokeTrust: a. NV items with the pubInfo -> nvIndex D value set MUST be deleted. This + changes the TPM_OwnerClear handling of the same NV areas + */ + if (rc == 0) { + rc = TPM_NVIndexEntries_DeleteOwnerAuthorized(&(tpm_state->tpm_nv_index_entries), + deleteAllNvram); + } +#if defined TPM_PCCLIENT + /* From the PC Client TIS + + 1.When there is no TPM Owner, the TPM_NV_INDEX_GPIO_00 area MUST be deallocated (see main + specification part 3 on TPM_OwnerClear). + */ + if (rc == 0) { + TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; + rc = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, + &(tpm_state->tpm_nv_index_entries), + TPM_NV_INDEX_GPIO_00); + /* if found, delete */ + if (rc == 0) { + TPM_NVDataSensitive_Delete(tpm_nv_data_sensitive); + } + else if (rc == TPM_BADINDEX) { + rc = TPM_SUCCESS; /* non-existent index is not an error */ + } + } +#endif + /* 13. The TPM MUST invalidate all familyTable entries */ + if (rc == 0) { + TPM_FamilyTable_Delete(&(tpm_state->tpm_permanent_data.familyTable)); + } + /* 14. The TPM MUST terminate all sessions, active or saved. */ + /* NOTE: Done by TPM_StclearData_Delete() */ + /* NOTE The TPM_PERMANENT_DATA and TPM_PERMANENT_FLAGS NVRAM store cannot be factored out here, + since some callers do other functions before the store. */ + return rc; +} + +/* 6.6 TSC_PhysicalPresence rev 87 + + Some TPM operations require the indication of a human's physical presence at the platform. The + presence of the human either provides another indication of platform ownership or a mechanism to + ensure that the execution of the command is not the result of a remote software process. + + This command allows a process on the platform to indicate the assertion of physical presence. As + this command is executable by software there must be protections against the improper invocation + of this command. + + The physicalPresenceHWEnable and physicalPresenceCMDEnable indicate the ability for either SW or + HW to indicate physical presence. These flags can be reset until the physicalPresenceLifetimeLock + is set. The platform manufacturer should set these flags to indicate the capabilities of the + platform the TPM is bound to. The command provides two sets of functionality. The first is to + enable, permanently, either the HW or the SW ability to assert physical presence. The second is + to allow SW, if enabled, to assert physical presence. +*/ + +TPM_RESULT TPM_Process_PhysicalPresence(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_PHYSICAL_PRESENCE physicalPresence; /* The state to set the TPM's Physical Presence + flags */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ +#ifdef TPM_V12 + uint16_t a1 = TRUE; /* lifetime settings */ + uint16_t a2 = TRUE; /* assertion settings */ +#endif + TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_PhysicalPresence: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get physicalPresence parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&physicalPresence, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_PhysicalPresence: physicalPresence parameter %04x\n", physicalPresence); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_PhysicalPresence: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ +#ifdef TPM_V12 + if (returnCode == TPM_SUCCESS) { + if (physicalPresence & TPM_PHYSICAL_PRESENCE_MASK) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresence extra bits\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 1. For documentation ease, the bits break into two categories. The first is the lifetime + settings and the second is the assertion settings. */ + if (returnCode == TPM_SUCCESS) { + /* a. Define A1 to be the lifetime settings: TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK, + TPM_PHYSICAL_PRESENCE_HW_ENABLE, TPM_PHYSICAL_make contingent!!!PRESENCE_CMD_ENABLE, + TPM_PHYSICAL_PRESENCE_HW_DISABLE, and TPM_PHYSICAL_PRESENCE_CMD_DISABLE */ + a1 = physicalPresence & (TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK | + TPM_PHYSICAL_PRESENCE_HW_ENABLE | + TPM_PHYSICAL_PRESENCE_CMD_ENABLE | + TPM_PHYSICAL_PRESENCE_HW_DISABLE | + TPM_PHYSICAL_PRESENCE_CMD_DISABLE); + + /* b. Define A2 to be the assertion settings: TPM_PHYSICAL_PRESENCE_LOCK, + TPM_PHYSICAL_PRESENCE_PRESENT, and TPM_PHYSICAL_PRESENCE_NOTPRESENT */ + a2 = physicalPresence & (TPM_PHYSICAL_PRESENCE_LOCK | + TPM_PHYSICAL_PRESENCE_PRESENT | + TPM_PHYSICAL_PRESENCE_NOTPRESENT); + printf("TPM_Process_PhysicalPresence: a1 %04x a2 %04x\n", a1, a2); + } + /* + Lifetime lock settings + */ + /* 2. If any A1 setting is present */ + if ((returnCode == TPM_SUCCESS) && a1) { + if (returnCode == TPM_SUCCESS) { + /* a. If TPM_PERMANENT_FLAGS -> physicalPresenceLifetimeLock is TRUE, return + TPM_BAD_PARAMETER */ + if (tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock) { + printf("TPM_Process_PhysicalPresence: Error, " + "physicalPresenceLifetimeLock is TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* b. If any A2 setting is present return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (a2) { + printf("TPM_Process_PhysicalPresence: Error, a1 and a2 TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* c. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_ENABLE and physicalPresence -> + TPM_PHYSICAL_PRESENCE_HW_DISABLE are TRUE, return TPM_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_DISABLE)) { + printf("TPM_Process_PhysicalPresence: Error, HW enable and disable both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* d. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_ENABLE and physicalPresence + -> TPM_PHYSICAL_PRESENCE_CMD_DISABLE are TRUE, return TPM_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE ) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_DISABLE )) { + printf("TPM_Process_PhysicalPresence: Error, CMD enable and disable both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + /* e. If physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_ENABLE is TRUE Set + TPM_PERMANENT_FLAGS -> physicalPresenceHWEnable to TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), + TRUE); /* value */ + } + /* f. If physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_DISABLE is TRUE Set + TPM_PERMANENT_FLAGS -> physicalPresenceHWEnable to FALSE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_DISABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable FALSE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), + FALSE); /* value */ + } + /* g. If physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_ENABLE is TRUE, Set + TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable to TRUE. */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), + TRUE); /* value */ + } + /* h. If physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_DISABLE is TRUE, Set + TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable to FALSE. */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_DISABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable FALSE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), + FALSE); /* value */ + } + /* i. If physicalPresence -> TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK is TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK) { + /* i. Set TPM_PERMANENT_FLAGS -> physicalPresenceLifetimeLock to TRUE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLifetimeLock\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock), + TRUE); /* value */ + } + } + /* j. Return TPM_SUCCESS */ + } + /* + SW physical presence assertion + */ + /* 3. If any A2 setting is present */ + if ((returnCode == TPM_SUCCESS) && a2) { + /* a. If any A1 setting is present return TPM_BAD_PARAMETER */ + /* i. This check here just for consistency, the prior checks would have already ensured that + this was OK */ + if (returnCode == TPM_SUCCESS) { + if (a1) { + printf("TPM_Process_PhysicalPresence: Error, a1 and a2 TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* b. If TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable is FALSE, return TPM_BAD_PARAMETER + */ + if (returnCode == TPM_SUCCESS) { + if (!tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceCMDEnable is FALSE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* c. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_LOCK and physicalPresence -> + TPM_PHYSICAL_PRESENCE_PRESENT are TRUE, return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK ) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT)) { + printf("TPM_Process_PhysicalPresence: Error, LOCK and PRESENT both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* d. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_PRESENT and physicalPresence -> + TPM_PHYSICAL_PRESENCE_NOTPRESENT are TRUE, return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT)) { + printf("TPM_Process_PhysicalPresence: Error, PRESENT and NOT_PRESENT both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* e. If TPM_STCLEAR_FLAGS -> physicalPresenceLock is TRUE, return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_stclear_flags.physicalPresenceLock) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLock is TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + /* f. If physicalPresence -> TPM_PHYSICAL_PRESENCE_LOCK is TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK) { + /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to FALSE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = FALSE; + /* ii. Set TPM_STCLEAR_FLAGS -> physicalPresenceLock to TRUE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLock TRUE\n"); + tpm_state->tpm_stclear_flags.physicalPresenceLock = TRUE; + /* iii. Return TPM_SUCCESS */ + } + /* g. If physicalPresence -> TPM_PHYSICAL_PRESENCE_PRESENT is TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) { + /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to TRUE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresence TRUE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = TRUE; + } + /* h. If physicalPresence -> TPM_PHYSICAL_PRESENCE_NOTPRESENT is TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT) { + /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to FALSE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = FALSE; + } + /* i. Return TPM_SUCCESS */ + } + } + /* 4. Else There were no A1 or A2 parameters set */ + if (returnCode == TPM_SUCCESS) { + if (!a1 && !a2) { + /* a. Return TPM_BAD_PARAMETER */ + printf("TPM_Process_PhysicalPresence: Error, a1 and a2 FALSE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } +#else /* TPM v1.1 */ + /* 2. Once the PhysicalPresenceLock flag is set to TRUE, the TPM MUST not modify the + PhysicalPresence flag until a TPM_Init followed by TPM_Startup(stType = TCPA_ST_CLEAR). Upon + a TPM_Init and TPM_Startup(stType = TCPA_ST_STATE) the TPM MUST set the PhysicalPresenceLock + flag to FALSE. */ + /* NOTE: I assume this is a typo, that PhysicalPresenceLock is restored by TPM_ST_STATE and set + false on TPM_ST_CLEAR. Other places in the specification certainly say that. */ + /* 3.If the PhysicalPresenceLock flag is set to TRUE upon any call to this operation, the TPM + MUST cause no action and MUST return the error TCPA_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_stclear_flags.physicalPresenceLock) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLock is TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + /* NOTE: The specification doesn't say what to do if both flags are set. Following the 1.2 + specification seems reasonable. */ + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT)) { + printf("TPM_Process_PhysicalPresence: Error, PRESENT and NOT_PRESENT both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + if ((tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock) && + (physicalPresence & (TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK | + TPM_PHYSICAL_PRESENCE_HW_ENABLE | + TPM_PHYSICAL_PRESENCE_CMD_ENABLE))) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLifetimeLock is TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + if ((!tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable) && + (physicalPresence & (TPM_PHYSICAL_PRESENCE_LOCK | + TPM_PHYSICAL_PRESENCE_PRESENT | + TPM_PHYSICAL_PRESENCE_NOTPRESENT))) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceCMDEnable is FALSE\n"); + returnCode = TPM_BAD_PARAMETER; + } + + } + /* 1. This operation MUST be implemented to process the values in the following order: */ + if (returnCode == TPM_SUCCESS) { + /* a. physicalPresenceHWEnable and physicalPresenceCMDEnable */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), + TRUE); /* value */ + } + if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), + TRUE); /* value */ + } + /* b. physicalPresenceLifetimeLock */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLifetimeLock\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock), + TRUE); /* value */ + } + /* c. PhysicalPresence */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresence TRUE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = TRUE; + } + if (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = FALSE; + } + /* d. PhysicalPresenceLock */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLock TRUE\n"); + tpm_state->tpm_stclear_flags.physicalPresenceLock = TRUE; + } + } +#endif + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_PhysicalPresence: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 6.4 TPM_DisableOwnerClear rev 87 + + The DisableOwnerClear command disables the ability to execute the TPM_OwnerClear command + permanently. Once invoked the only method of clearing the TPM will require physical access to the + TPM. + + After the execution of TPM_ForceClear, ownerClear is re-enabled and must be explicitly disabled + again by the new TPM Owner. +*/ + +TPM_RESULT TPM_Process_DisableOwnerClear(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the + authorization handle */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner + authentication. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey = NULL; + TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_DisableOwnerClear: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DisableOwnerClear: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. The TPM verifies that the authHandle properly authorizes the owner. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. The TPM sets the TPM_PERMANENT_FLAGS -> disableOwnerClear flag to TRUE. */ + /* 3. When this flag is TRUE the only mechanism that can clear the TPM is the TPM_ForceClear + command. The TPM_ForceClear command requires physical access to the TPM to execute. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DisableOwnerClear: Set disableOwnerClear\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.disableOwnerClear), /* flag */ + TRUE); /* value */ + } + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DisableOwnerClear: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + return rcf; +} + +/* 6.5 TPM_DisableForceClear rev 97 + + The DisableForceClear command disables the execution of the ForceClear command until the next + startup cycle. Once this command is executed, the TPM_ForceClear is disabled until another + startup cycle is run. +*/ + +TPM_RESULT TPM_Process_DisableForceClear(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_DisableForceClear: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DisableForceClear: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM sets the TPM_STCLEAR_FLAGS.disableForceClear flag in the TPM that disables the + execution of the TPM_ForceClear command. */ + if (returnCode == TPM_SUCCESS) { + tpm_state->tpm_stclear_flags.disableForceClear = TRUE; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DisableForceClear: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 6.7 TSC_ResetEstablishmentBit rev 98 + + The PC TPM Interface Specification (TIS) specifies setting tpmEstablished to TRUE upon execution + of the HASH_START sequence. The setting implies the creation of a Trusted Operating System on the + platform. Platforms will use the value of tpmEstablished to determine if operations necessary to + maintain the security perimeter are necessary. + + The tpmEstablished bit provides a non-volatile, secure reporting that a HASH_START was previously + run on the platform. When a platform makes use of the tpmEstablished bit, the platform can reset + tpmEstablished as the operation is no longer necessary. + + For example, a platform could use tpmEstablished to ensure that, if HASH_START had ever been, + executed the platform could use the value to invoke special processing. Once the processing is + complete the platform will wish to reset tpmEstablished to avoid invoking the special process + again. + + The TPM_PERMANENT_FLAGS -> tpmEstablished bit described in the TPM specifications uses positive + logic. The TPM_ACCESS register uses negative logic, so that TRUE is reflected as a 0. +*/ + +TPM_RESULT TPM_Process_ResetEstablishmentBit(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ResetEstablishmentBit: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ResetEstablishmentBit: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Validate the assertion of locality 3 or locality 4 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, /* BYTE bitmap */ + tpm_state->tpm_stany_flags.localityModifier); + } + /* 2. Set TPM_PERMANENT_FLAGS -> tpmEstablished to FALSE */ + if (returnCode == TPM_SUCCESS) { + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.tpmEstablished), /* flag */ + FALSE); /* value */ + + } + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* 3. Return TPM_SUCCESS */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ResetEstablishmentBit: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + diff --git a/src/tpm12/tpm_owner.h b/src/tpm12/tpm_owner.h new file mode 100644 index 0000000..b96464f --- /dev/null +++ b/src/tpm12/tpm_owner.h @@ -0,0 +1,107 @@ +/********************************************************************************/ +/* */ +/* Ownership Processing */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_owner.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_OWNER_H +#define TPM_OWNER_H + +#include "tpm_global.h" +#include "tpm_secret.h" +#include "tpm_store.h" +#include "tpm_types.h" + +TPM_RESULT TPM_OwnerClearCommon(tpm_state_t *tpm_state, + TPM_BOOL deleteAllNvram); + +TPM_RESULT TPM_Process_TakeOwnership(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_OwnerClear(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_PhysicalPresence(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_DisableOwnerClear(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_ForceClear(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_DisableForceClear(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +TPM_RESULT TPM_Process_ResetEstablishmentBit(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +#endif diff --git a/src/tpm12/tpm_pcr.c b/src/tpm12/tpm_pcr.c new file mode 100644 index 0000000..b6998a7 --- /dev/null +++ b/src/tpm12/tpm_pcr.c @@ -0,0 +1,3800 @@ +/********************************************************************************/ +/* */ +/* PCR Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_pcr.c 4730 2014-09-08 22:02:18Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_auth.h" +#include "tpm_constants.h" +#include "tpm_cryptoh.h" +#include "tpm_digest.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_global.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_process.h" +#include "tpm_sizedbuffer.h" +#include "tpm_types.h" +#include "tpm_ver.h" + +#include "tpm_pcr.h" + + +/* + Locality Utilities +*/ + +/* TPM_Locality_Set() sets a bit in the TPM_LOCALITY_SELECTION (BYTE) bitmap based on the + TPM_STANY_FLAGS -> TPM_MODIFIER_INDICATOR (uint32_t) -> localityModifier +*/ + +TPM_RESULT TPM_Locality_Set(TPM_LOCALITY_SELECTION *tpm_locality_selection, /* BYTE bitmap */ + TPM_MODIFIER_INDICATOR tpm_modifier_indicator) /* uint32_t from + TPM_STANY_FLAGS + */ +{ + TPM_RESULT rc = 0; + printf(" TPM_Locality_Set:\n"); + switch (tpm_modifier_indicator) { + case 0: + *tpm_locality_selection = TPM_LOC_ZERO; + break; + case 1: + *tpm_locality_selection = TPM_LOC_ONE; + break; + case 2: + *tpm_locality_selection = TPM_LOC_TWO; + break; + case 3: + *tpm_locality_selection = TPM_LOC_THREE; + break; + case 4: + *tpm_locality_selection = TPM_LOC_FOUR; + break; + default: + /* This should never occur. The code that sets TPM_STANY_FLAGS should screen out bad values + */ + printf("TPM_Locality_Set: Error (fatal), tpm_modifier_indicator %u out of range\n", + tpm_modifier_indicator); + rc = TPM_FAIL; + } + return rc; +} + +/* TPM_Locality_Check() checks that a bit in the TPM_LOCALITY_SELECTION (BYTE) bitmap is set for bit + TPM_STANY_FLAGS -> TPM_MODIFIER_INDICATOR (uint32_t) -> localityModifier + + 'tpm_locality_selection' is typically localityAtRelease, pcrResetLocal, pcrExtendLocal + 'localityModifier' is TPM_STANY_FLAGS.localityModifier +*/ + +TPM_RESULT TPM_Locality_Check(TPM_LOCALITY_SELECTION tpm_locality_selection, /* BYTE bitmap */ + TPM_MODIFIER_INDICATOR localityModifier) /* uint32_t from + TPM_STANY_FLAGS */ +{ + + TPM_RESULT rc = 0; + printf(" TPM_Locality_Check:\n"); + switch (localityModifier) { + case 0: + if ((tpm_locality_selection & TPM_LOC_ZERO) == 0) { + rc = TPM_BAD_LOCALITY; + } + break; + case 1: + if ((tpm_locality_selection & TPM_LOC_ONE) == 0) { + rc = TPM_BAD_LOCALITY; + } + break; + case 2: + if ((tpm_locality_selection & TPM_LOC_TWO) == 0) { + rc = TPM_BAD_LOCALITY; + } + break; + case 3: + if ((tpm_locality_selection & TPM_LOC_THREE) == 0) { + rc = TPM_BAD_LOCALITY; + } + break; + case 4: + if ((tpm_locality_selection & TPM_LOC_FOUR) == 0) { + rc = TPM_BAD_LOCALITY; + } + break; + default: + /* This should never occur. The code that sets TPM_STANY_FLAGS should screen out bad values + */ + printf("TPM_Locality_Check: Error (fatal), localityModifier %u out of range\n", + localityModifier); + rc = TPM_FAIL; + } + if (rc != 0) { + printf("TPM_Locality_Check: Error, " + "localityModifier %u tpm_locality_selection %02x\n", + localityModifier, tpm_locality_selection); + } + return rc; +} + +TPM_RESULT TPM_LocalitySelection_CheckLegal(TPM_LOCALITY_SELECTION tpm_locality_selection) /* BYTE + bitmap */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_LocalitySelection_CheckLegal: TPM_LOCALITY_SELECTION %02x\n", + tpm_locality_selection); + /* if any extra bits are set, illegal value */ + if ((tpm_locality_selection & ~TPM_LOC_ALL) || + /* This value MUST not be zero (0). (can never be satisfied) */ + (tpm_locality_selection == 0)) { + printf("TPM_LocalitySelection_CheckLegal: Error, bad locality selection %02x\n", + tpm_locality_selection); + rc = TPM_INVALID_STRUCTURE; + } + return rc; +} + +TPM_RESULT TPM_LocalityModifier_CheckLegal(TPM_MODIFIER_INDICATOR localityModifier) +{ + TPM_RESULT rc = 0; + + printf(" TPM_LocalityModifier_CheckLegal: TPM_MODIFIER_INDICATOR %08x\n", localityModifier); + /* if past the maximum, illegal value */ + if (localityModifier > TPM_LOC_MAX) { + printf("TPM_LocalityModifier_CheckLegal: Error, bad locality modifier %u\n", + localityModifier); + rc = TPM_BAD_LOCALITY; + } + return rc; +} + +void TPM_PCRLocality_Compare(TPM_BOOL *match, + TPM_LOCALITY_SELECTION tpm_locality_selection1, + TPM_LOCALITY_SELECTION tpm_locality_selection2) +{ + if (tpm_locality_selection1 == tpm_locality_selection2) { + *match = TRUE; + } + else { + *match = FALSE; + } + return; +} + +/* + state PCR's +*/ + +TPM_RESULT TPM_PCR_CheckRange(TPM_PCRINDEX index) +{ + TPM_RESULT rc = 0; + + if (index >= TPM_NUM_PCR) { + printf("TPM_PCR_CheckRange: Error, PCR index was %u should be <= %u\n", + index, TPM_NUM_PCR); + rc = TPM_BADINDEX; + } + return rc; +} + +/* TPM_PCR_Init() initializes the PCR based on the platform specification. This should be called by + TPM_Init. + + The caller must check that the PCR index is in range! +*/ + +void TPM_PCR_Init(TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ + const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes, + size_t pcrIndex) +{ + printf(" TPM_PCR_Init: pcrIndex %lu\n", (unsigned long)pcrIndex); + +#if defined TPM_PCCLIENT /* These values are from the PC Client specification */ + tpm_pcr_attributes = tpm_pcr_attributes; + if ((pcrIndex >= 17) && (pcrIndex <= 22)) { + TPM_Digest_Set(tpm_pcrs[pcrIndex]); /* 17-22 init to ff */ + } + else { + TPM_Digest_Init(tpm_pcrs[pcrIndex]); /* 0-16,23 init to 0 */ + } + /* #elif Add other platform specific values here */ +#else /* This is the default case for the main specification */ + if (!(tpm_pcr_attributes[pcrIndex].pcrReset)) { + /* FALSE- Default value of the PCR MUST be 0x00..00 */ + TPM_Digest_Init(tpm_pcrs[pcrIndex]); + } + else { + /* TRUE - Default value of the PCR MUST be 0xFF..FF. */ + TPM_Digest_Set(tpm_pcrs[pcrIndex]); + } +#endif + return; +} + +/* TPM_PCR_Reset() resets the PCR based on the platform specification. This should be called by the + TPM_PCR_Reset ordinal. + + The caller must check that the PCR index is in range and that pcrReset is TRUE! +*/ + +void TPM_PCR_Reset(TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ + TPM_BOOL TOSPresent, + TPM_PCRINDEX pcrIndex) +{ + TPM_PCRVALUE zeroPCR; + TPM_PCRVALUE onesPCR; + + TPM_Digest_Init(zeroPCR); + TPM_Digest_Set(onesPCR); +#if defined TPM_PCCLIENT /* These values are from the PC Client specification */ + if (TOSPresent || /* TOSPresent -> 00 */ + (pcrIndex == 16) || /* PCR 16 -> 00 */ + (pcrIndex == 23)) { /* PCR 23 -> 00 */ + TPM_PCR_Store(tpm_pcrs, pcrIndex, zeroPCR); + } + else { + TPM_PCR_Store(tpm_pcrs, pcrIndex, onesPCR); /* PCR 17-22 -> ff */ + } + /* #elif Add other platform specific values here */ +#else /* This is the default case for the main specification */ + if (TOSPresent) { + TPM_PCR_Store(tpm_pcrs, pcrIndex, zeroPCR); + } + else { + TPM_PCR_Store(tpm_pcrs, pcrIndex, onesPCR); + } +#endif + return; +} + +/* TPM_PCR_Load() copies the PCR at 'index' to 'dest_pcr' + +*/ + +TPM_RESULT TPM_PCR_Load(TPM_PCRVALUE dest_pcr, + TPM_PCRVALUE *tpm_pcrs, + TPM_PCRINDEX index) +{ + TPM_RESULT rc = 0; + + /* range check pcrNum */ + if (rc == 0) { + rc = TPM_PCR_CheckRange(index); + } + if (rc == 0) { + TPM_Digest_Copy(dest_pcr, tpm_pcrs[index]); + } + return rc; +} + +/* TPM_PCR_Store() copies 'src_pcr' to the PCR at 'index' + +*/ + +TPM_RESULT TPM_PCR_Store(TPM_PCRVALUE *tpm_pcrs, + TPM_PCRINDEX index, + TPM_PCRVALUE src_pcr) +{ + TPM_RESULT rc = 0; + + /* range check pcrNum */ + if (rc == 0) { + rc = TPM_PCR_CheckRange(index); + } + if (rc == 0) { + TPM_Digest_Copy(tpm_pcrs[index], src_pcr); + } + return rc; +} + +/* + TPM_SELECT_SIZE +*/ + +/* TPM_SelectSize_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_SelectSize_Init(TPM_SELECT_SIZE *tpm_select_size) +{ + printf(" TPM_SelectSize_Init:\n"); + tpm_select_size->major = TPM_MAJOR; + tpm_select_size->minor = TPM_MINOR; + tpm_select_size->reqSize = TPM_NUM_PCR/CHAR_BIT; + return; +} + +/* TPM_SelectSize_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_SelectSize_Init() +*/ + +TPM_RESULT TPM_SelectSize_Load(TPM_SELECT_SIZE *tpm_select_size, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + printf(" TPM_SelectSize_Load:\n"); + /* load major */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_select_size->major), stream, stream_size); + } + /* This SHALL indicate the major version of the TPM. This MUST be 0x01 */ + if (rc == 0) { + if (tpm_select_size->major != 0x01) { + printf("TPM_SelectSize_Load: Error, major %02x should be 01\n", tpm_select_size->major); + rc = TPM_BAD_PARAMETER; + } + } + /* load minor */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_select_size->minor), stream, stream_size); + } + /* This SHALL indicate the minor version of the TPM. This MAY be 0x01 or 0x02 */ + if (rc == 0) { + if ((tpm_select_size->minor != 0x01) && + (tpm_select_size->minor != 0x02)) { + printf("TPM_SelectSize_Load: Error, minor %02x should be 01\n", tpm_select_size->minor); + rc = TPM_BAD_PARAMETER; + } + } + /* load reqSize */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_select_size->reqSize), stream, stream_size); + } + return rc; +} + +/* + TPM_PCR_ATTRIBUTES +*/ + +/* 8.9 Debug PCR register + + There is a need to define a PCR that allows for debugging. The attributes of the debug register + are such that it is easy to reset but the register provides no measurement value that can not be + spoofed. Production applications should not use the debug PCR for any SEAL or other + operations. The anticipation is that the debug PCR is set and used by application developers + during the application development cycle. Developers are responsible for ensuring that a conflict + between two programs does not invalidate the settings they are interested in. + + The specific register that is the debug PCR MUST be set by the platform specific specification. + + The attributes for the debug PCR SHALL be the following: + pcrReset = TRUE; + pcrResetLocal = 0x1f; + pcrExtendLocal = 0x1f; + pcrUseLocal = 0x1f + + These settings are to create a PCR register that developers can use to reset at any time during + their development cycle. + + The debug PCR does NOT need to be saved during TPM_SaveState. + + 8.7 PCR Attributes + + 1. The PCR attributes MUST be set during manufacturing. + + 2. For a specific PCR register, the PCR attributes MUST match the requirements of the TCG + platform specific specification that describes the platform. +*/ + +void TPM_PCRAttributes_Init(TPM_PCR_ATTRIBUTES *tpm_pcr_attributes) +{ + size_t i; + + printf(" TPM_PCRAttributes_Init:\n"); + for (i = 0 ; i < TPM_NUM_PCR ; i++) { +#if defined TPM_PCCLIENT /* These values are from the PC Client specification */ +#if TPM_NUM_PCR != 24 +#error "Number of PCRs must be 24 for PC Client" +#endif + if (i <=15) { + tpm_pcr_attributes[i].pcrReset = FALSE; /* 0-15 are not resettable */ + tpm_pcr_attributes[i].pcrResetLocal = 0; + tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_ALL; + } + else { + tpm_pcr_attributes[i].pcrReset = TRUE; + switch (i) { + case 16: + case 23: + tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_ALL; + tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_ALL; + break; + case 17: + case 18: + tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_FOUR; + tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_FOUR | TPM_LOC_THREE | TPM_LOC_TWO; + break; + case 19: + tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_FOUR; + tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_THREE | TPM_LOC_TWO; + break; + case 20: + tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_FOUR | TPM_LOC_TWO; + tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_THREE | TPM_LOC_TWO | TPM_LOC_ONE; + break; + case 21: + case 22: + tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_TWO; + tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_TWO; + break; + } + } + /* #elif Add other platform specific values here */ +#else /* This is the default case for the main specification */ + if (i != TPM_DEBUG_PCR) { + tpm_pcr_attributes[i].pcrReset = FALSE; + tpm_pcr_attributes[i].pcrResetLocal = 0; /* not relevant when pcrReset is FALSE */ + tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_ALL; + } + else { /* debug PCR */ + tpm_pcr_attributes[i].pcrReset = TRUE; + tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_ALL; + tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_ALL; + } +#endif + } + return; +} + +/* TPM_PCRInfo_Trace() traces some PCR Info components */ + +void TPM_PCRInfo_Trace(const char *message, + TPM_PCR_SELECTION pcrSelection, + TPM_COMPOSITE_HASH digestAtRelease) +{ + printf("%s\n", message); + printf("\tsizeOfSelect %hu\n", pcrSelection.sizeOfSelect); + printf("\tpcrSelect %02x %02x %02x\n", + pcrSelection.pcrSelect[0], + pcrSelection.pcrSelect[1], + pcrSelection.pcrSelect[2]); + TPM_PrintFour("\tdigestAtRelease", + digestAtRelease); + return; +} + +/* + PCRs - Functions that act on the entire set of PCRs +*/ + +/* TPM_PCRs_Init() initializes the entire PCR array. + + Typically called from TPM_Init. +*/ + +void TPM_PCRs_Init(TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ + const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes) +{ + size_t i; + + printf(" TPM_PCRs_Init:\n"); + for (i = 0 ; i < TPM_NUM_PCR ; i++) { + TPM_PCR_Init(tpm_pcrs, tpm_pcr_attributes, i); /* initialize a single PCR */ + } + return; +} + +TPM_RESULT TPM_PCRs_Load(TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ + const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_PCRs_Load:\n"); + for (i = 0 ; (rc == 0) && (i < TPM_NUM_PCR) ; i++) { + /* FALSE: Saved by TPM_SaveState + TRUE: MUST not be part of any state stored by TPM_SaveState */ + if (!(tpm_pcr_attributes[i].pcrReset)) { + rc = TPM_Digest_Load(tpm_pcrs[i], stream, stream_size); + } + } + return rc; +} + +TPM_RESULT TPM_PCRs_Store(TPM_STORE_BUFFER *sbuffer, + TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ + const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_PCRs_Store:\n"); + for (i = 0 ; (rc == 0) && (i < TPM_NUM_PCR) ; i++) { + /* FALSE: Saved by TPM_SaveState + TRUE: MUST not be part of any state stored by TPM_SaveState */ + if (!(tpm_pcr_attributes[i].pcrReset)) { + rc = TPM_Digest_Store(sbuffer, tpm_pcrs[i]); + } + } + return rc; +} + +/* + TPM_PCR_COMPOSITE +*/ + +/* TPM_PCRComposite_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_PCRComposite_Init(TPM_PCR_COMPOSITE *tpm_pcr_composite) +{ + TPM_PCRSelection_Init(&(tpm_pcr_composite->select)); + TPM_SizedBuffer_Init(&(tpm_pcr_composite->pcrValue)); + return; +} + +/* TPM_PCRComposite_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + After use, call TPM_PCRComposite_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRComposite_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_COMPOSITE *tpm_pcr_composite) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRComposite_Store:\n"); + + /* store TPM_PCR_SELECTION select */ + if (rc == 0) { + rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_composite->select)); + } + /* store pcrValue */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_pcr_composite->pcrValue)); + } + return rc; +} + +/* TPM_PCRComposite_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_PCRComposite_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_PCRComposite_Delete(TPM_PCR_COMPOSITE *tpm_pcr_composite) +{ + printf(" TPM_PCRComposite_Delete:\n"); + if (tpm_pcr_composite != NULL) { + TPM_PCRSelection_Delete(&(tpm_pcr_composite->select)); + TPM_SizedBuffer_Delete(&(tpm_pcr_composite->pcrValue)); + TPM_PCRComposite_Init(tpm_pcr_composite); + } + return; +} + +/* TPM_PCRComposite_Set() + + sets members to input parameter values + allocates memory as required to fill in pointers + returns 0 or error codes + + After use, call TPM_PCRComposite_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRComposite_Set(TPM_PCR_COMPOSITE *tpm_pcr_composite, + TPM_PCR_SELECTION *tpm_pcr_selection, /* input selection map */ + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ +{ + TPM_RESULT rc = 0; + size_t i; /* byte in map */ + size_t j; /* bit map in byte */ + size_t pcrs = 0; /* number of selected PCR's */ + TPM_PCRINDEX pcr_num; /* selected PCR being copied */ + size_t comp_num; /* index into composite */ + + printf(" TPM_PCRComposite_Set:\n"); + /* test sizeOfSelect value */ + if (rc == 0) { + rc = TPM_PCRSelection_CheckRange(tpm_pcr_selection); + } + /* construct the TPM_PCR_COMPOSITE structure */ + if (rc == 0) { + /* copy the TPM_PCR_SELECTION member */ + rc = TPM_PCRSelection_Copy(&(tpm_pcr_composite->select), tpm_pcr_selection); + } + /* iterate through all bytes in tpm_pcr_selection to count the number of selected PCR's */ + if (rc == 0) { + for (i = 0, pcrs = 0 ; i < tpm_pcr_selection->sizeOfSelect ; i++) { + /* iterate through all bits in each byte */ + for (j = 0x0001 ; j != (0x0001 << CHAR_BIT) ; j <<= 1) { + if (tpm_pcr_selection->pcrSelect[i] & j) { /* if the bit is set in the map */ + pcrs++; + } + } + } + } + /* allocate memory for the pcrValue member (a TPM_PCRVALUE for each selected PCR) */ + if ((rc == 0) && (pcrs > 0)) { + printf(" TPM_PCRComposite_Set: Digesting %lu pcrs\n", (unsigned long)pcrs); + rc = TPM_SizedBuffer_Allocate(&(tpm_pcr_composite->pcrValue), pcrs * sizeof(TPM_PCRVALUE)); + } + /* Next iterate through all bytes in tpm_pcr_selection and copy to TPM_PCR_COMPOSITE */ + if ((rc == 0) && (pcrs > 0)) { + for (i = 0, pcr_num = 0, comp_num = 0 ; i < tpm_pcr_selection->sizeOfSelect ; i++) { + /* iterate through all bits in each byte */ + for (j = 0x0001 ; j != (0x0001 << CHAR_BIT) ; j <<= 1, pcr_num++) { + if (tpm_pcr_selection->pcrSelect[i] & j) { /* if the bit is set in the map */ + printf(" TPM_PCRComposite_Set: Adding PCR %u\n", pcr_num); + /* append the the PCR value to TPM_PCR_COMPOSITE.pcrValue */ + /* NOTE: Ignore return code since range checked by + TPM_PCRSelection_CheckRange() */ + TPM_PCR_Load(&(tpm_pcr_composite->pcrValue.buffer[comp_num]), + tpm_pcrs, pcr_num); + comp_num += sizeof(TPM_PCRVALUE); + } + } + } + } + return rc; +} + +/* + TPM_PCR_INFO_SHORT +*/ + +void TPM_PCRInfoShort_Init(TPM_PCR_INFO_SHORT *tpm_pcr_info_short) +{ + TPM_PCRSelection_Init(&(tpm_pcr_info_short->pcrSelection)); + tpm_pcr_info_short->localityAtRelease = TPM_LOC_ALL; + TPM_Digest_Init(tpm_pcr_info_short->digestAtRelease); + return; +} + +/* TPM_PCRInfoShort_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + optimize invokes a special version used to an load TPM_NV_DATA_PUBLIC that may not include + digestAtRelease + + After use, call TPM_PCRInfoShort_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRInfoShort_Load(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + unsigned char **stream, + uint32_t *stream_size, + TPM_BOOL optimize) +{ + TPM_RESULT rc = 0; + TPM_BOOL pcrUsage = TRUE; + + printf(" TPM_PCRInfoShort_Load:\n"); + /* load pcrSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Load(&(tpm_pcr_info_short->pcrSelection), stream, stream_size); + } + /* load the localityAtRelease */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_pcr_info_short->localityAtRelease), stream, stream_size); + } + /* check locality value */ + if (rc == 0) { + rc = TPM_LocalitySelection_CheckLegal(tpm_pcr_info_short->localityAtRelease); + } + /* if the store was optimized, check whether the pcrSelection specifies PCRs */ + if ((rc == 0) && optimize) { + rc = TPM_PCRSelection_GetPCRUsage(&pcrUsage, + &(tpm_pcr_info_short->pcrSelection), + 0); /* start_index */ + } + /* load the digestAtRelease */ + if (rc == 0) { + if (pcrUsage) { + rc = TPM_Digest_Load(tpm_pcr_info_short->digestAtRelease, stream, stream_size); + } + /* A pcrSelect of 0 indicates that the digestAsRelease is not checked. In this case, the TPM is + not required to consume NVRAM space to store the digest, although it may do so. When + TPM_GetCapability (TPM_CAP_NV_INDEX) returns the structure, a TPM that does not store the + digest can return zero. A TPM that does store the digest may return either the digest or + zero. Software should not be written to depend on either implementation. + */ + else { + TPM_Digest_Init(tpm_pcr_info_short->digestAtRelease); + } + } + return rc; +} + +/* TPM_PCRInfoShort_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + optimize invokes a special version used to an store TPM_NV_DATA_PUBLIC that may not include + digestAtRelease + + After use, call TPM_Sbuffer_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRInfoShort_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + TPM_BOOL optimize) +{ + TPM_RESULT rc = 0; + TPM_BOOL pcrUsage = TRUE; + + printf(" TPM_PCRInfoShort_Store:\n"); + /* store pcrSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_info_short->pcrSelection)); + } + /* store the localityAtRelease */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_pcr_info_short->localityAtRelease), + sizeof(TPM_LOCALITY_SELECTION)); + } + /* check whether the pcrSelection specifies PCRs */ + if ((rc == 0) && optimize) { + rc = TPM_PCRSelection_GetPCRUsage(&pcrUsage, + &(tpm_pcr_info_short->pcrSelection), + 0); /* start_index */ + } + /* store the digestAtRelease */ + /* A pcrSelect of 0 indicates that the digestAsRelease is not checked. In this case, the TPM is + not required to consume NVRAM space to store the digest, although it may do so. When + TPM_GetCapability (TPM_CAP_NV_INDEX) returns the structure, a TPM that does not store the + digest can return zero. A TPM that does store the digest may return either the digest or + zero. Software should not be written to depend on either implementation. + */ if ((rc == 0) && pcrUsage) { + rc = TPM_Digest_Store(sbuffer, tpm_pcr_info_short->digestAtRelease); + } + return rc; +} + +/* TPM_PCRInfoShort_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the PCRInfoShort + sets pointers to NULL + calls TPM_PCRInfoShort_Init to set members back to default values + The PCRInfoShort itself is not freed + returns 0 or error codes +*/ + +void TPM_PCRInfoShort_Delete(TPM_PCR_INFO_SHORT *tpm_pcr_info_short) +{ + printf(" TPM_PCRInfoShort_Delete:\n"); + if (tpm_pcr_info_short != NULL) { + TPM_PCRSelection_Delete(&(tpm_pcr_info_short->pcrSelection)); + TPM_PCRInfoShort_Init(tpm_pcr_info_short); + } + return; +} + +/* TPM_PCRInfoShort_Create() allocates memory for a TPM_PCR_INFO_SHORT + +*/ + +TPM_RESULT TPM_PCRInfoShort_Create(TPM_PCR_INFO_SHORT **tpm_pcr_info_short) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoShort_Create:\n"); + /* This function should never be called when the TPM_PCR_INFO_SHORT structure has already been + loaded. This indicates an internal error. */ + if (rc == 0) { + if (*tpm_pcr_info_short != NULL) { + printf("TPM_PCRInfoShort_Create: Error (fatal), TPM_PCR_INFO_SHORT already loaded\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)tpm_pcr_info_short, sizeof(TPM_PCR_INFO_SHORT)); + } + return rc; +} + +/* TPM_PCRInfoShort_SetFromBuffer() sets a TPM_PCR_INFO_SHORT from a stream specified by a + TPM_SIZED_BUFFER. The TPM_SIZED_BUFFER is not modified. +*/ + +TPM_RESULT TPM_PCRInfoShort_LoadFromBuffer(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + const TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_PCRInfoShort_LoadFromBuffer:\n"); + if (rc == 0) { + TPM_PCRInfoShort_Init(tpm_pcr_info_short); + stream = tpm_sized_buffer->buffer; + stream_size = tpm_sized_buffer->size; + /* deserialize the TPM_SIZED_BUFFER into a TPM_PCR_INFO_SHORT structure */ + rc = TPM_PCRInfoShort_Load(tpm_pcr_info_short, &stream, &stream_size, FALSE); + } + return rc; +} + +/* TPM_PCRInfoShort_CreateFromBuffer() allocates the TPM_PCR_INFO_SHORT structure, typically a cache + within another structure. It then deserializes the TPM_SIZED_BUFFER into the structure. + + The TPM_SIZED_BUFFER is not modified. +*/ + +TPM_RESULT TPM_PCRInfoShort_CreateFromBuffer(TPM_PCR_INFO_SHORT **tpm_pcr_info_short, + const TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfoShort_CreateFromBuffer:\n"); + /* if there is no TPM_PCR_INFO_SHORT - done */ + if (rc == 0) { + if (tpm_sized_buffer->size == 0) { + done = TRUE; + } + } + if ((rc == 0) && !done) { + rc = TPM_PCRInfoShort_Create(tpm_pcr_info_short); + } + if ((rc == 0) && !done) { + rc = TPM_PCRInfoShort_LoadFromBuffer(*tpm_pcr_info_short, tpm_sized_buffer); + } + return rc; +} + +/* TPM_PCRInfoShort_Copy() copies the source pcrSelection, digestAtRelease, and digestAtCreation. + +*/ + +TPM_RESULT TPM_PCRInfoShort_Copy(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, + TPM_PCR_INFO_SHORT *src_tpm_pcr_info_short) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoShort_Copy:\n"); + /* copy TPM_PCR_SELECTION pcrSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_short->pcrSelection), + &(src_tpm_pcr_info_short->pcrSelection)); + } + if (rc == 0) { + /* copy TPM_LOCALITY_SELECTION localityAtRelease */ + dest_tpm_pcr_info_short->localityAtRelease = src_tpm_pcr_info_short->localityAtRelease; + /* copy TPM_COMPOSITE_HASH digestAtRelease */ + TPM_Digest_Copy(dest_tpm_pcr_info_short->digestAtRelease, + src_tpm_pcr_info_short->digestAtRelease); + } + return rc; +} + +/* TPM_PCRInfoShort_CopyInfo() copies the source TPM_PCR_INFO to the destination TPM_PCR_INFO_SHORT. + + It copies pcrSelection and digestAtRelease. + + It handles localityAtRelease as per the specification. +*/ + +TPM_RESULT TPM_PCRInfoShort_CopyInfo(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, + TPM_PCR_INFO *src_tpm_pcr_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoShort_CopyInfo:\n"); + /* 4. To set IS from IN */ + /* a. Set IS -> pcrSelection to IN -> pcrSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_short->pcrSelection), + &(src_tpm_pcr_info->pcrSelection)); + } + /* b. Set IS -> digestAtRelease to IN -> digestAtRelease */ + if (rc == 0) { + TPM_Digest_Copy(dest_tpm_pcr_info_short->digestAtRelease, + src_tpm_pcr_info->digestAtRelease); + /* c. Set IS -> localityAtRelease to 0x1F to indicate all localities are valid */ + dest_tpm_pcr_info_short->localityAtRelease = TPM_LOC_ALL; + /* d. Ignore IN -> digestAtCreation */ + } + return rc; +} + +/* TPM_PCRInfoShort_CopyInfoLong() copies the source TPM_PCR_INFO_LONG to the destination + TPM_PCR_INFO_SHORT. + + It copies creationPCRSelection, localityAtRelease, digestAtRelease. +*/ + +TPM_RESULT TPM_PCRInfoShort_CopyInfoLong(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoShort_CopyInfoLong:\n"); + /* 5. To set IS from IL */ + /* a. Set IS -> pcrSelection to IL -> releasePCRSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_short->pcrSelection), + &(src_tpm_pcr_info_long->releasePCRSelection)); + } + /* b. Set IS -> localityAtRelease to IL -> localityAtRelease */ + if (rc == 0) { + dest_tpm_pcr_info_short->localityAtRelease = src_tpm_pcr_info_long->localityAtRelease; + /* c. Set IS -> digestAtRelease to IL -> digestAtRelease */ + TPM_Digest_Copy(dest_tpm_pcr_info_short->digestAtRelease, + src_tpm_pcr_info_long->digestAtRelease); + /* d. Ignore all other IL values */ + } + return rc; +} + +/* TPM_PCRInfoShort_CreateFromInfo() allocates memory for the TPM_PCR_INFO_SHORT structure. It + copies the source to the destination. + + If the source is NULL, the destination is NULL. +*/ + +TPM_RESULT TPM_PCRInfoShort_CreateFromInfo(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, + TPM_PCR_INFO *src_tpm_pcr_info) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfoShort_CreateFromInfo:\n"); + if (rc == 0) { + /* if there is no source, leave the destination NULL */ + if (src_tpm_pcr_info == NULL) { + done = TRUE; + } + } + /* create the structure */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfoShort_Create(dest_tpm_pcr_info_short); + } + /* copy source to destination */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfoShort_CopyInfo(*dest_tpm_pcr_info_short, src_tpm_pcr_info); + } + return rc; +} + +/* TPM_PCRInfo_CreateFromInfoLong() allocates memory for the TPM_PCR_INFO structure. It copies the + source to the destination. + + If the source is NULL, the destination is NULL. +*/ + +TPM_RESULT TPM_PCRInfoShort_CreateFromInfoLong(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfoShort_CreateFromInfoLong:\n"); + /* if there is no source, leave the destination NULL */ + if (rc == 0) { + if (src_tpm_pcr_info_long == NULL) { + done = TRUE; + } + } + /* create the structure */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfoShort_Create(dest_tpm_pcr_info_short); + } + /* copy source to destination */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfoShort_CopyInfoLong(*dest_tpm_pcr_info_short, src_tpm_pcr_info_long); + } + return rc; +} + +/* TPM_PCRInfoShort_CreateFromKey() allocates memory for the TPM_PCR_INFO_SHORT structure. + + If the input is a TPM_KEY, it copies the TPM_PCR_INFO cache. + + If the input is a TPM_KEY12, it copies the TPM_PCR_INFO_LONG cache. + + If the source is NULL, the destination is NULL. +*/ + +TPM_RESULT TPM_PCRInfoShort_CreateFromKey(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoShort_CreateFromKey:\n"); + if (rc == 0) { + if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ + rc = TPM_PCRInfoShort_CreateFromInfo(dest_tpm_pcr_info_short, + tpm_key->tpm_pcr_info); + } + else { /* TPM_KEY12 */ + rc = TPM_PCRInfoShort_CreateFromInfoLong(dest_tpm_pcr_info_short, + tpm_key->tpm_pcr_info_long); + } + } + return rc; +} + +/* TPM_PCRInfoShort_GenerateDigest() generates a Part 2 5.3.1 PCR composite hash + +*/ + +TPM_RESULT TPM_PCRInfoShort_GenerateDigest(TPM_DIGEST tpm_digest, /* output digest */ + TPM_PCR_INFO_SHORT *tpm_pcr_info_short, /* input */ + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ +{ + TPM_RESULT rc = 0; + TPM_PCR_SELECTION *tpm_pcr_selection; + + printf(" TPM_PCRInfoShort_GenerateDigest:\n"); + if (rc == 0) { + if (tpm_pcr_info_short == NULL) { + printf("TPM_PCRInfoShort_GenerateDigest: Error (fatal), TPM_PCR_INFO_SHORT is NULL\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + tpm_pcr_selection = &(tpm_pcr_info_short->pcrSelection); /* get the TPM_PCR_SELECTION */ + rc = TPM_PCRSelection_GenerateDigest(tpm_digest, /* output digest */ + tpm_pcr_selection, /* input selection map */ + tpm_pcrs); /* points to the TPM PCR array */ + } + return rc; +} + +/* TPM_PCRInfoShort_CheckDigest() calculates a digestAtRelease based on the TPM_PCR_SELECTION and + compares it to digestAtRelease in the structure. +*/ + +TPM_RESULT TPM_PCRInfoShort_CheckDigest(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ + TPM_MODIFIER_INDICATOR localityModifier) +{ + TPM_RESULT rc = 0; + TPM_COMPOSITE_HASH tpm_composite_hash; + TPM_BOOL pcrUsage; /* TRUE if PCR's are specified */ + + printf(" TPM_PCRInfoShort_CheckDigest:\n"); + /* returns FALSE if tpm_pcr_info_short is NULL or selection bitmap is zero */ + if (rc == 0) { + rc = TPM_PCRInfoShort_GetPCRUsage(&pcrUsage, tpm_pcr_info_short); + } + /* Calculate a TPM_COMPOSITE_HASH of the PCR selected by tpm_pcr_info_short -> + pcrSelection */ + if ((rc == 0) && pcrUsage) { + rc = TPM_PCRSelection_GenerateDigest(tpm_composite_hash, + &(tpm_pcr_info_short->pcrSelection), + tpm_pcrs); /* array of PCR's */ + } + /* Compare to tpm_pcr_info_short -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ + if ((rc == 0) && pcrUsage) { + rc = TPM_Digest_Compare(tpm_composite_hash, + tpm_pcr_info_short->digestAtRelease); + if (rc != 0) { + printf("TPM_PCRInfoShort_CheckDigest: Error, wrong digestAtRelease value\n"); + rc = TPM_WRONGPCRVAL; + } + } + /* If localityAtRelease is NOT 0x1f */ + if ((rc == 0) && (tpm_pcr_info_short != NULL)) { + if (tpm_pcr_info_short->localityAtRelease != TPM_LOC_ALL) { + /* Validate that TPM_STANY_FLAGS -> localityModifier is matched by tpm_pcr_info_short -> + localityAtRelease on mismatch return TPM_BAD_LOCALITY */ + rc = TPM_Locality_Check(tpm_pcr_info_short->localityAtRelease, + localityModifier); + } + } + return rc; +} + +/* TPM_PCRInfoShort_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit + mask. Returns FALSE if the TPM_PCR_INFO_SHORT is NULL. +*/ + +TPM_RESULT TPM_PCRInfoShort_GetPCRUsage(TPM_BOOL *pcrUsage, + TPM_PCR_INFO_SHORT *tpm_pcr_info_short) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfoShort_GetPCRUsage\n"); + if (rc == 0) { + /* if a loaded key had no pcrInfoShort, the structure remains NULL */ + if (tpm_pcr_info_short == NULL) { + *pcrUsage = FALSE; + done = TRUE; + } + } + if ((rc == 0) && !done) { + rc = TPM_PCRSelection_GetPCRUsage(pcrUsage, &(tpm_pcr_info_short->pcrSelection), 0); + } + if (rc == 0) { + printf(" TPM_PCRInfoShort_GetPCRUsage: Result %d\n", *pcrUsage); + } + return rc; +} + +/* + TPM_PCR_INFO +*/ + +void TPM_PCRInfo_Init(TPM_PCR_INFO *tpm_pcr_info) +{ + TPM_PCRSelection_Init(&(tpm_pcr_info->pcrSelection)); + TPM_Digest_Init(tpm_pcr_info->digestAtRelease); + TPM_Digest_Init(tpm_pcr_info->digestAtCreation); + return; +} + +/* TPM_PCRInfo_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + After use, call TPM_PCRInfo_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRInfo_Load(TPM_PCR_INFO *tpm_pcr_info, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfo_Load:\n"); + /* load pcrSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Load(&(tpm_pcr_info->pcrSelection), stream, stream_size); + } + /* load the digestAtRelease */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_pcr_info->digestAtRelease, stream, stream_size); + } + /* load the digestAtCreation */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_pcr_info->digestAtCreation, stream, stream_size); + } + return rc; +} + +/* TPM_PCRInfo_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + After use, call TPM_Sbuffer_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_INFO *tpm_pcr_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfo_Store:\n"); + /* store pcrSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_info->pcrSelection)); + } + /* store digestAtRelease */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_pcr_info->digestAtRelease); + } + /* store digestAtCreation */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_pcr_info->digestAtCreation); + } + return rc; +} + +/* TPM_PCRInfo_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the PCRInfo + sets pointers to NULL2 + calls TPM_PCRInfo_Init to set members back to default values + The PCRInfo itself is not freed + returns 0 or error codes +*/ + +void TPM_PCRInfo_Delete(TPM_PCR_INFO *tpm_pcr_info) +{ + printf(" TPM_PCRInfo_Delete:\n"); + if (tpm_pcr_info != NULL) { + TPM_PCRSelection_Delete(&(tpm_pcr_info->pcrSelection)); + TPM_PCRInfo_Init(tpm_pcr_info); + } + return; +} + +/* TPM_PCRInfo_Create() allocates memory for a TPM_PCR_INFO + +*/ + +TPM_RESULT TPM_PCRInfo_Create(TPM_PCR_INFO **tpm_pcr_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfo_Create:\n"); + /* This function should never be called when the TPM_PCR_INFO structure has already been loaded. + This indicates an internal error. */ + if (rc == 0) { + if (*tpm_pcr_info != NULL) { + printf("TPM_PCRInfo_Create: Error (fatal), TPM_PCR_INFO already loaded\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)tpm_pcr_info, sizeof(TPM_PCR_INFO)); + } + return rc; +} + +/* TPM_PCRInfo_LoadFromBuffer() sets a TPM_PCR_INFO from a stream specified by a TPM_SIZED_BUFFER. + The TPM_SIZED_BUFFER is not modified. +*/ + +TPM_RESULT TPM_PCRInfo_LoadFromBuffer(TPM_PCR_INFO *tpm_pcr_info, + const TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_PCRInfo_LoadFromBuffer:\n"); + if (rc == 0) { + TPM_PCRInfo_Init(tpm_pcr_info); + stream = tpm_sized_buffer->buffer; + stream_size = tpm_sized_buffer->size; + /* deserialize the TPM_SIZED_BUFFER into a TPM_PCR_INFO structure */ + rc = TPM_PCRInfo_Load(tpm_pcr_info, &stream, &stream_size); + } + return rc; +} + +/* TPM_PCRInfo_CreateFromBuffer() allocates the TPM_PCR_INFO structure, typically a cache within + another structure. It then deserializes the TPM_SIZED_BUFFER into the structure. + + If the stream is empty, a NULL is returned. + + The TPM_SIZED_BUFFER is not modified. +*/ + +TPM_RESULT TPM_PCRInfo_CreateFromBuffer(TPM_PCR_INFO **tpm_pcr_info, + const TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfo_CreateFromBuffer:\n"); + /* if there is no TPM_PCR_INFO - done */ + if (rc == 0) { + if (tpm_sized_buffer->size == 0) { + done = TRUE; + } + } + if ((rc == 0) && !done) { + rc = TPM_PCRInfo_Create(tpm_pcr_info); + } + if ((rc == 0) && !done) { + rc = TPM_PCRInfo_LoadFromBuffer(*tpm_pcr_info, tpm_sized_buffer); + } + return rc; +} + +/* TPM_PCRInfo_Copy() copies the source to the destination. + + It copies pcrSelection, digestAtRelease, and digestAtCreation. +*/ + +TPM_RESULT TPM_PCRInfo_Copy(TPM_PCR_INFO *dest_tpm_pcr_info, + TPM_PCR_INFO *src_tpm_pcr_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfo_Copy:\n"); + /* copy TPM_PCR_SELECTION pcrSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info->pcrSelection), + &(src_tpm_pcr_info->pcrSelection)); + } + /* copy TPM_COMPOSITE_HASH's */ + if (rc == 0) { + TPM_Digest_Copy(dest_tpm_pcr_info->digestAtRelease, + src_tpm_pcr_info->digestAtRelease); + TPM_Digest_Copy(dest_tpm_pcr_info->digestAtCreation, + src_tpm_pcr_info->digestAtCreation); + } + return rc; +} + +/* TPM_PCRInfo_CopyInfoLong() copies the source TPM_PCR_INFO_LONG to the destination TPM_PCR_INFO. + + It copies pcrSelection and digestAtRelease. + + It handles digestAtCreation as per the specification. +*/ + +TPM_RESULT TPM_PCRInfo_CopyInfoLong(TPM_PCR_INFO *dest_tpm_pcr_info, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) +{ + TPM_RESULT rc = 0; + TPM_BOOL selectMatch; + TPM_BOOL localityMatch; + + printf(" TPM_PCRInfo_Copy:\n"); + /* 9. To set IN from IL */ + /* a. Set IN -> pcrSelection to IL -> releasePCRSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info->pcrSelection), + &(src_tpm_pcr_info_long->releasePCRSelection)); + } + /* copy TPM_COMPOSITE_HASH's */ + if (rc == 0) { + /* b. Set IN -> digestAtRelease to IL -> digestAtRelease */ + TPM_Digest_Copy(dest_tpm_pcr_info->digestAtRelease, + src_tpm_pcr_info_long->digestAtRelease); + TPM_PCRSelection_Compare(&selectMatch, + &(src_tpm_pcr_info_long->creationPCRSelection), + &(src_tpm_pcr_info_long->releasePCRSelection)); + TPM_PCRLocality_Compare(&localityMatch, + src_tpm_pcr_info_long->localityAtCreation, + src_tpm_pcr_info_long->localityAtRelease); + /* c. If IL -> creationPCRSelection and IL -> localityAtCreation both match IL -> + releasePCRSelection and IL -> localityAtRelease */ + if (selectMatch && localityMatch) { + /* i. Set IN -> digestAtCreation to IL -> digestAtCreation */ + TPM_Digest_Copy(dest_tpm_pcr_info->digestAtCreation, + src_tpm_pcr_info_long->digestAtCreation); + } + /* d. Else */ + else { + /* i. Set IN -> digestAtCreation to NULL */ + TPM_Digest_Init(dest_tpm_pcr_info->digestAtCreation); + } + } + return rc; +} + +/* TPM_PCRInfo_CreateFromInfo() allocates memory for the TPM_PCR_INFO structure. It copies the + source to the destination. + + If the source is NULL, the destination is NULL. +*/ + +TPM_RESULT TPM_PCRInfo_CreateFromInfo(TPM_PCR_INFO **dest_tpm_pcr_info, + TPM_PCR_INFO *src_tpm_pcr_info) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfo_CreateFromInfo:\n"); + /* if there is no source, leave the destination NULL */ + if (rc == 0) { + if (src_tpm_pcr_info == NULL) { + done = TRUE; + } + } + /* create the structure */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfo_Create(dest_tpm_pcr_info); + } + /* copy source to destination */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfo_Copy(*dest_tpm_pcr_info, src_tpm_pcr_info); + } + return rc; +} + +/* TPM_PCRInfo_CreateFromInfoLong() allocates memory for the TPM_PCR_INFO structure. It copies the + source to the destination. + + If the source is NULL, the destination is NULL. +*/ + +TPM_RESULT TPM_PCRInfo_CreateFromInfoLong(TPM_PCR_INFO **dest_tpm_pcr_info, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfo_CreateFromInfoLong:\n"); + /* if there is no source, leave the destination NULL */ + if (rc == 0) { + if (src_tpm_pcr_info_long == NULL) { + done = TRUE; + } + } + /* create the structure */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfo_Create(dest_tpm_pcr_info); + } + /* copy source to destination */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfo_CopyInfoLong(*dest_tpm_pcr_info, src_tpm_pcr_info_long); + } + return rc; +} + +/* TPM_PCRInfo_CreateFromKey() allocates memory for the TPM_PCR_INFO structure. + + If the input is a TPM_KEY, it copies the TPM_PCR_INFO cache. + + If the input is a TPM_KEY12, it copies the TPM_PCR_INFO_LONG cache. + + If the source is NULL, the destination is NULL. +*/ + + +TPM_RESULT TPM_PCRInfo_CreateFromKey(TPM_PCR_INFO **dest_tpm_pcr_info, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfo_CreateFromKey:\n"); + if (rc == 0) { + if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ + rc = TPM_PCRInfo_CreateFromInfo(dest_tpm_pcr_info, tpm_key->tpm_pcr_info); + } + else { /* TPM_KEY12 */ + rc = TPM_PCRInfo_CreateFromInfoLong(dest_tpm_pcr_info, tpm_key->tpm_pcr_info_long); + } + } + return rc; +} + +/* TPM_PCRInfo_GenerateDigest() generates a Part 2 5.3.1 PCR composite hash + +*/ + +TPM_RESULT TPM_PCRInfo_GenerateDigest(TPM_DIGEST tpm_digest, /* output digest */ + TPM_PCR_INFO *tpm_pcr_info, /* input */ + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ +{ + TPM_RESULT rc = 0; + TPM_PCR_SELECTION *tpm_pcr_selection; + + printf(" TPM_PCRInfo_GenerateDigest:\n"); + if (rc == 0) { + if (tpm_pcr_info == NULL) { + printf("TPM_PCRInfo_GenerateDigest: Error (fatal), TPM_PCR_INFO is NULL\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + tpm_pcr_selection = &(tpm_pcr_info->pcrSelection); /* get the TPM_PCR_SELECTION */ + rc = TPM_PCRSelection_GenerateDigest(tpm_digest, /* output digest */ + tpm_pcr_selection, /* input selection map */ + tpm_pcrs); /* points to the TPM PCR array */ + } + return rc; +} + +/* TPM_PCRInfo_CheckDigest() calculates a digestAtRelease based on the TPM_PCR_SELECTION + and compares it to digestAtRelease in the structure. +*/ + +TPM_RESULT TPM_PCRInfo_CheckDigest(TPM_PCR_INFO *tpm_pcr_info, + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR + array */ +{ + TPM_RESULT rc = 0; + TPM_COMPOSITE_HASH tpm_composite_hash; + TPM_BOOL pcrUsage; /* TRUE if PCR's are specified */ + + printf(" TPM_PCRInfo_CheckDigest:\n"); + /* Calculate a TPM_COMPOSITE_HASH of the PCR selected by tpm_pcr_info -> pcrSelection */ + if (rc == 0) { + rc = TPM_PCRInfo_GetPCRUsage(&pcrUsage, tpm_pcr_info, 0); + } + if ((rc == 0) && pcrUsage) { + rc = TPM_PCRSelection_GenerateDigest(tpm_composite_hash, + &(tpm_pcr_info->pcrSelection), + tpm_pcrs); /* array of PCR's */ + } + /* Compare to pcrInfo -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ + if ((rc == 0) && pcrUsage) { + rc = TPM_Digest_Compare(tpm_composite_hash, + tpm_pcr_info->digestAtRelease); + if (rc != 0) { + printf("TPM_PCRInfo_CheckDigest: Error, wrong digestAtRelease value\n"); + rc = TPM_WRONGPCRVAL; + } + } + return rc; +} + +/* TPM_PCRInfo_SetDigestAtCreation() calculates a digestAtCreation based on the TPM_PCR_SELECTION + already set in the TPM_PCR_INFO structure. +*/ + +TPM_RESULT TPM_PCRInfo_SetDigestAtCreation(TPM_PCR_INFO *tpm_pcr_info, + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR + array */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfo_SetDigestAtCreation:\n"); + if (rc == 0) { + rc = TPM_PCRInfo_GenerateDigest(tpm_pcr_info->digestAtCreation, tpm_pcr_info, tpm_pcrs); + } + return rc; +} + +/* TPM_PCRInfo_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit mask. + + 'start_pcr' indicates the starting byte index into pcrSelect[] +*/ + +TPM_RESULT TPM_PCRInfo_GetPCRUsage(TPM_BOOL *pcrUsage, + TPM_PCR_INFO *tpm_pcr_info, + size_t start_index) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfo_GetPCRUsage: Start %lu\n", (unsigned long)start_index); + if (rc == 0) { + /* if a loaded key had no pcrInfo, the structure remains NULL */ + if (tpm_pcr_info == NULL) { + *pcrUsage = FALSE; + done = TRUE; + } + } + if ((rc == 0) && !done) { + rc = TPM_PCRSelection_GetPCRUsage(pcrUsage, &(tpm_pcr_info->pcrSelection), start_index); + } + if (rc == 0) { + printf(" TPM_PCRInfo_GetPCRUsage: Result %d\n", *pcrUsage); + } + return rc; +} + +/* + TPM_PCR_INFO_LONG +*/ + +/* TPM_PCRInfoLong_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_PCRInfoLong_Init(TPM_PCR_INFO_LONG *tpm_pcr_info_long) +{ + printf(" TPM_PCRInfoLong_Init:\n"); +/* tpm_pcr_info_long->tag = TPM_TAG_PCR_INFO_LONG; */ + tpm_pcr_info_long->localityAtCreation = TPM_LOC_ZERO; + tpm_pcr_info_long->localityAtRelease = TPM_LOC_ALL; + TPM_PCRSelection_Init(&(tpm_pcr_info_long->creationPCRSelection)); + TPM_PCRSelection_Init(&(tpm_pcr_info_long->releasePCRSelection)); + TPM_Digest_Init(tpm_pcr_info_long->digestAtCreation); + TPM_Digest_Init(tpm_pcr_info_long->digestAtRelease); + return; +} + +/* TPM_PCRInfoLong_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_PCRInfoLong_Init() + After use, call TPM_PCRInfoLong_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRInfoLong_Load(TPM_PCR_INFO_LONG *tpm_pcr_info_long, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoLong_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_PCR_INFO_LONG, stream, stream_size); + } + /* load localityAtCreation */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_pcr_info_long->localityAtCreation), stream, stream_size); + } + /* check locality value. The TPM MAY treat a localityAtCreation value of 0 as an error. */ + if (rc == 0) { + rc = TPM_LocalitySelection_CheckLegal(tpm_pcr_info_long->localityAtCreation); + } + /* load localityAtRelease */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_pcr_info_long->localityAtRelease), stream, stream_size); + } + /* check locality value */ + if (rc == 0) { + rc = TPM_LocalitySelection_CheckLegal(tpm_pcr_info_long->localityAtRelease); + } + /* load creationPCRSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Load(&(tpm_pcr_info_long->creationPCRSelection), stream, stream_size); + } + /* load releasePCRSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Load(&(tpm_pcr_info_long->releasePCRSelection), stream, stream_size); + } + /* load digestAtCreation */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_pcr_info_long->digestAtCreation, stream, stream_size); + } + /* load digestAtRelease */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_pcr_info_long->digestAtRelease, stream, stream_size); + } + return rc; +} + +/* TPM_PCRInfoLong_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_PCRInfoLong_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_INFO_LONG *tpm_pcr_info_long) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoLong_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_PCR_INFO_LONG); + } + /* store localityAtCreation */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_pcr_info_long->localityAtCreation), + sizeof(TPM_LOCALITY_SELECTION)); + } + /* store localityAtRelease */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_pcr_info_long->localityAtRelease), + sizeof(TPM_LOCALITY_SELECTION)); + } + /* store creationPCRSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_info_long->creationPCRSelection)); + } + /* store releasePCRSelection */ + if (rc == 0) { + rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_info_long->releasePCRSelection)); + } + /* store digestAtCreation */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_pcr_info_long->digestAtCreation); + } + /* store digestAtRelease */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_pcr_info_long->digestAtRelease); + } + return rc; +} + +/* TPM_PCRInfoLong_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_PCRInfoLong_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_PCRInfoLong_Delete(TPM_PCR_INFO_LONG *tpm_pcr_info_long) +{ + printf(" TPM_PCRInfoLong_Delete:\n"); + if (tpm_pcr_info_long != NULL) { + TPM_PCRSelection_Delete(&(tpm_pcr_info_long->creationPCRSelection)); + TPM_PCRSelection_Delete(&(tpm_pcr_info_long->releasePCRSelection)); + TPM_PCRInfoLong_Init(tpm_pcr_info_long); + } + return; +} + +/* TPM_PCRInfoLong_Create() allocates memory for a TPM_PCR_INFO_LONG + +*/ + +TPM_RESULT TPM_PCRInfoLong_Create(TPM_PCR_INFO_LONG **tpm_pcr_info_long) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoLong_Create:\n"); + /* This function should never be called when the TPM_PCR_INFO_LONG structure has already been + loaded. This indicates an internal error. */ + if (rc == 0) { + if (*tpm_pcr_info_long != NULL) { + printf("TPM_PCRInfoLong_Create: Error (fatal), TPM_PCR_INFO_LONG already loaded\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + rc = TPM_Malloc((unsigned char **)tpm_pcr_info_long, sizeof(TPM_PCR_INFO_LONG)); + } + return rc; +} + +/* TPM_PCRInfoLong_LoadFromBuffer() sets a TPM_PCR_INFO_LONG from a stream specified by a + TPM_SIZED_BUFFER. The TPM_SIZED_BUFFER is not modified. +*/ + +TPM_RESULT TPM_PCRInfoLong_LoadFromBuffer(TPM_PCR_INFO_LONG *tpm_pcr_info_long, + const TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_PCRInfoLong_LoadFromBuffer:\n"); + if (rc == 0) { + TPM_PCRInfoLong_Init(tpm_pcr_info_long); + stream = tpm_sized_buffer->buffer; + stream_size = tpm_sized_buffer->size; + /* deserialize the TPM_SIZED_BUFFER into a TPM_PCR_INFO_LONG structure */ + rc = TPM_PCRInfoLong_Load(tpm_pcr_info_long, &stream, &stream_size); + } + return rc; +} + +/* TPM_PCRInfoLong_CreateFromBuffer() allocates the TPM_PCR_INFO_LONG structure, typically a cache + within another structure. It then deserializes the TPM_SIZED_BUFFER into the structure. + + If the stream is empty, a NULL is returned. + + The TPM_SIZED_BUFFER is not modified. +*/ + +TPM_RESULT TPM_PCRInfoLong_CreateFromBuffer(TPM_PCR_INFO_LONG **tpm_pcr_info_long, + const TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfoLong_CreateFromBuffer:\n"); + /* if there is no TPM_PCR_INFO_LONG - done */ + if (rc == 0) { + if (tpm_sized_buffer->size == 0) { + done = TRUE; + } + } + /* allocate memory for the buffer */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfoLong_Create(tpm_pcr_info_long); + } + /* deserialize the input stream */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfoLong_LoadFromBuffer(*tpm_pcr_info_long, tpm_sized_buffer); + } + return rc; +} + +/* TPM_PCRInfoLong_Copy() copies the source to the destination */ + +TPM_RESULT TPM_PCRInfoLong_Copy(TPM_PCR_INFO_LONG *dest_tpm_pcr_info_long, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoLong_Copy:\n"); + if (rc == 0) { + /* copy the localityAtCreation, localityAtRelease */ + dest_tpm_pcr_info_long->localityAtCreation = src_tpm_pcr_info_long->localityAtCreation; + dest_tpm_pcr_info_long->localityAtRelease = src_tpm_pcr_info_long->localityAtRelease; + /* copy TPM_PCR_SELECTION creationPCRSelection */ + rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_long->creationPCRSelection), + &(src_tpm_pcr_info_long->creationPCRSelection)); + } + if (rc == 0) { + /* copy TPM_PCR_SELECTION releasePCRSelection*/ + rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_long->releasePCRSelection), + &(src_tpm_pcr_info_long->releasePCRSelection)); + } + /* copy TPM_COMPOSITE_HASH's */ + if (rc == 0) { + TPM_Digest_Copy(dest_tpm_pcr_info_long->digestAtRelease, + src_tpm_pcr_info_long->digestAtRelease); + TPM_Digest_Copy(dest_tpm_pcr_info_long->digestAtCreation, + src_tpm_pcr_info_long->digestAtCreation); + } + return rc; +} + +/* TPM_PCRInfoLong_CreateFromInfoLong() allocates memory for the TPM_PCR_INFO_LONG structure. It + copies the source tag, localityAtCreation, localityAtRelease, creationPCRSelection, + releasePCRSelection digestAtCreation, and digestAtRelease. + + If the source is NULL, the destination is NULL. +*/ + +TPM_RESULT TPM_PCRInfoLong_CreateFromInfoLong(TPM_PCR_INFO_LONG **dest_tpm_pcr_info_long, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfoLong_CreateFromInfoLong:\n"); + if (rc == 0) { + /* if there is no source, leave the destination NULL */ + if (src_tpm_pcr_info_long == NULL) { + done = TRUE; + } + } + /* create the structure */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfoLong_Create(dest_tpm_pcr_info_long); + } + /* copy source to destination */ + if ((rc == 0) && !done) { + rc = TPM_PCRInfoLong_Copy(*dest_tpm_pcr_info_long, src_tpm_pcr_info_long); + } + return rc; +} + +/* TPM_PCRInfoLong_GenerateDigest() generates a Part 2 5.3.1 PCR composite hash + +*/ + +TPM_RESULT TPM_PCRInfoLong_GenerateDigest(TPM_DIGEST tpm_digest, /* output digest */ + TPM_PCR_INFO_LONG *tpm_pcr_info_long, /* input */ + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ +{ + TPM_RESULT rc = 0; + TPM_PCR_SELECTION *tpm_pcr_selection; + + printf(" TPM_PCRInfoLong_GenerateDigest:\n"); + if (rc == 0) { + if (tpm_pcr_info_long == NULL) { + printf("TPM_PCRInfoLong_GenerateDigest: Error (fatal), TPM_PCR_INFO_LONG is NULL\n"); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + tpm_pcr_selection = &(tpm_pcr_info_long->creationPCRSelection); /* get TPM_PCR_SELECTION */ + rc = TPM_PCRSelection_GenerateDigest(tpm_digest, /* output digest */ + tpm_pcr_selection, /* input selection map */ + tpm_pcrs); /* points to the TPM PCR array */ + } + return rc; +} + +/* TPM_PCRInfoLong_CheckDigest() calculates a digestAtRelease based on the TPM_PCR_SELECTION + and compares it to digestAtRelease in the structure. +*/ + +TPM_RESULT TPM_PCRInfoLong_CheckDigest(TPM_PCR_INFO_LONG *tpm_pcr_info_long, + TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ + TPM_MODIFIER_INDICATOR localityModifier) +{ + TPM_RESULT rc = 0; + TPM_COMPOSITE_HASH tpm_composite_hash; + TPM_BOOL pcrUsage; /* TRUE if PCR's are specified */ + + printf(" TPM_PCRInfoLong_CheckDigest:\n"); + /* returns FALSE if tpm_pcr_info_long is NULL or selection bitmap is zero */ + if (rc == 0) { + rc = TPM_PCRInfoLong_GetPCRUsage(&pcrUsage, tpm_pcr_info_long, 0); + } + /* Calculate a TPM_COMPOSITE_HASH of the PCR selected by tpm_pcr_info_long -> + releasePCRSelection */ + if ((rc == 0) && pcrUsage) { + rc = TPM_PCRSelection_GenerateDigest(tpm_composite_hash, + &(tpm_pcr_info_long->releasePCRSelection), + tpm_pcrs); /* array of PCR's */ + } + /* Compare to tpm_pcr_info_long -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ + if ((rc == 0) && pcrUsage) { + rc = TPM_Digest_Compare(tpm_composite_hash, + tpm_pcr_info_long->digestAtRelease); + if (rc != 0) { + printf("TPM_PCRInfoLong_CheckDigest: Error, wrong digestAtRelease value\n"); + rc = TPM_WRONGPCRVAL; + } + } + /* If localityAtRelease is NOT 0x1f */ + if ((rc == 0) && (tpm_pcr_info_long != NULL)) { + if (tpm_pcr_info_long->localityAtRelease != TPM_LOC_ALL) { + /* Validate that TPM_STANY_FLAGS -> localityModifier is matched by tpm_pcr_info_short -> + localityAtRelease on mismatch return TPM_BAD_LOCALITY */ + rc = TPM_Locality_Check(tpm_pcr_info_long->localityAtRelease, localityModifier); + } + } + return rc; +} + +/* TPM_PCRInfoLong_SetDigestAtCreation() calculates a digestAtCreation based on the + TPM_PCR_SELECTION creationPCRSelection already set in the TPM_PCR_INFO_LONG structure. +*/ + +TPM_RESULT TPM_PCRInfoLong_SetDigestAtCreation(TPM_PCR_INFO_LONG *tpm_pcr_info_long, + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR + array */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRInfoLong_SetDigestAtCreation:\n"); + if (rc == 0) { + rc = TPM_PCRInfoLong_GenerateDigest(tpm_pcr_info_long->digestAtCreation, + tpm_pcr_info_long, + tpm_pcrs); + } + return rc; +} + +/* TPM_PCRInfoLong_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit + mask. Returns FALSE if the TPM_PCR_INFO_LONG is NULL. + + 'start_pcr' indicates the starting byte index into pcrSelect[] +*/ + +TPM_RESULT TPM_PCRInfoLong_GetPCRUsage(TPM_BOOL *pcrUsage, + TPM_PCR_INFO_LONG *tpm_pcr_info_long, + size_t start_index) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + + printf(" TPM_PCRInfoLong_GetPCRUsage: Start %lu\n", (unsigned long)start_index);; + if (rc == 0) { + /* if a loaded key had no pcrInfo, the structure remains NULL */ + if (tpm_pcr_info_long == NULL) { + *pcrUsage = FALSE; + done = TRUE; + } + } + if ((rc == 0) && !done) { + rc = TPM_PCRSelection_GetPCRUsage(pcrUsage, + &(tpm_pcr_info_long->releasePCRSelection), start_index); + } + if (rc == 0) { + printf(" TPM_PCRInfoLong_GetPCRUsage: Result %d\n", *pcrUsage); + } + return rc; +} + + +/* + TPM_PCR_SELECTION +*/ + +void TPM_PCRSelection_Init(TPM_PCR_SELECTION *tpm_pcr_selection) +{ + size_t i; + + printf(" TPM_PCRSelection_Init:\n"); + tpm_pcr_selection->sizeOfSelect = TPM_NUM_PCR/CHAR_BIT; + for (i = 0 ; i < (TPM_NUM_PCR/CHAR_BIT) ; i++) { + tpm_pcr_selection->pcrSelect[i] = 0; + } + return; +} + +/* TPM_PCRSelection_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + After use, call TPM_PCRSelection_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRSelection_Load(TPM_PCR_SELECTION *tpm_pcr_selection, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_PCRSelection_Load:\n"); + /* load sizeOfSelect */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_pcr_selection->sizeOfSelect), stream, stream_size); + } + /* test sizeOfSelect value */ + if (rc == 0) { + rc = TPM_PCRSelection_CheckRange(tpm_pcr_selection); + } + /* load pcrSelect map */ + for (i = 0 ; (rc == 0) && (i < tpm_pcr_selection->sizeOfSelect) ; i++) { + rc = TPM_Load8(&(tpm_pcr_selection->pcrSelect[i]), stream, stream_size); + } + /* if there was insufficient input, zero the rest of the map */ + for ( ; (rc == 0) && (i < (TPM_NUM_PCR/CHAR_BIT)) ; i++) { + rc = tpm_pcr_selection->pcrSelect[i] = 0; + } + return rc; +} + +/* TPM_PCRSelection_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + After use, call TPM_Sbuffer_Delete() to free memory +*/ + +TPM_RESULT TPM_PCRSelection_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_SELECTION *tpm_pcr_selection) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PCRSelection_Store:\n"); + /* NOTE: Cannot use TPM_SizedBuffer_Store since the first parameter is a uint16_t */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_pcr_selection->sizeOfSelect); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + tpm_pcr_selection->pcrSelect, tpm_pcr_selection->sizeOfSelect); + } + return rc; +} + + +/* TPM_PCRSelection_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the PCRSelection + sets pointers to NULL + calls TPM_PCRSelection_Init to set members back to default values + The PCRSelection itself is not freed + returns 0 or error codes +*/ + +void TPM_PCRSelection_Delete(TPM_PCR_SELECTION *tpm_pcr_selection) +{ + printf(" TPM_PCRSelection_Delete:\n"); + if (tpm_pcr_selection != NULL) { + TPM_PCRSelection_Init(tpm_pcr_selection); + } + return; +} + +/* TPM_PCRSelection_Copy() copies the source to the destination + + It returns an error if the source -> sizeOfSelect is too large. If the source is smaller than + the internally defined, fixed size of the destination, the remainder of the destination is filled + with 0's. +*/ + +TPM_RESULT TPM_PCRSelection_Copy(TPM_PCR_SELECTION *destination, TPM_PCR_SELECTION *source) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_PCRSelection_Copy:\n"); + if (rc == 0) { + rc = TPM_PCRSelection_CheckRange(source); + } + if (rc == 0) { + /* copy sizeOfSelect member */ + destination->sizeOfSelect = source->sizeOfSelect; + /* copy pcrSelect map up to the size of the source */ + for (i = 0 ; i < source->sizeOfSelect ; i++) { + destination->pcrSelect[i] = source->pcrSelect[i]; + } + /* if the input wasn't sufficient, zero the rest of the map */ + for ( ; i < (TPM_NUM_PCR/CHAR_BIT) ; i++) { + destination->pcrSelect[i] = 0; + } + } + return rc; +} + +/* TPM_PCRSelection_GenerateDigest() generates a digest based on the TPM_PCR_SELECTION and the + current TPM PCR values. + + It internally generates a TPM_PCR_COMPOSITE according to Part 2 5.4.1. To return this structure + as well, use TPM_PCRSelection_GenerateDigest2(). +*/ + +TPM_RESULT TPM_PCRSelection_GenerateDigest(TPM_DIGEST tpm_digest, /* output digest */ + TPM_PCR_SELECTION *tpm_pcr_selection, /* input selection + map */ + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ +{ + TPM_RESULT rc = 0; + TPM_PCR_COMPOSITE tpm_pcr_composite; /* structure to be hashed */ + + printf(" TPM_PCRSelection_GenerateDigest:\n"); + TPM_PCRComposite_Init(&tpm_pcr_composite); /* freed @1 */ + rc = TPM_PCRSelection_GenerateDigest2(tpm_digest, + &tpm_pcr_composite, + tpm_pcr_selection, + tpm_pcrs); + TPM_PCRComposite_Delete(&tpm_pcr_composite); /* @1 */ + return rc; +} + +/* TPM_PCRSelection_GenerateDigest2() generates a digest based on the TPM_PCR_SELECTION and the + current TPM PCR values. + + It first generates a TPM_PCR_COMPOSITE according to Part 2 5.4.1. That structure is also + returned. + + TPM_PCR_COMPOSITE should be initialized and deleted by the caller. To generate and delete the + structure internally, use TPM_PCRSelection_GenerateDigest(). +*/ + +TPM_RESULT TPM_PCRSelection_GenerateDigest2(TPM_DIGEST tpm_digest, /* output digest */ + TPM_PCR_COMPOSITE *tpm_pcr_composite, /* output + structure + */ + TPM_PCR_SELECTION *tpm_pcr_selection, /* input selection + map */ + TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR + array */ +{ + TPM_RESULT rc = 0; + TPM_BOOL pcrUsage; + + printf(" TPM_PCRSelection_GenerateDigest2:\n"); + /* assemble the TPM_PCR_COMPOSITE structure */ + if (rc == 0) { + rc = TPM_PCRComposite_Set(tpm_pcr_composite, tpm_pcr_selection, tpm_pcrs); + } + if (rc == 0) { + rc = TPM_PCRSelection_GetPCRUsage(&pcrUsage, tpm_pcr_selection, 0); + } + if (rc == 0) { + printf(" TPM_PCRSelection_GenerateDigest2: pcrUsage %02x\n", pcrUsage); + if (pcrUsage) { + /* serialize and hash TPM_PCR_COMPOSITE */ + if (rc == 0) { + rc = TPM_SHA1_GenerateStructure(tpm_digest, tpm_pcr_composite, + (TPM_STORE_FUNCTION_T)TPM_PCRComposite_Store); + } + } + /* 4. If TPM_PCR_SELECTION.pcrSelect is all 0's */ + /* a. a.For digestAtCreation, the TPM MUST set TPM_COMPOSITE_HASH to be all 0's. */ + else { + TPM_Digest_Init(tpm_digest); + } + } + return rc; +} + +/* TPM_PCRSelection_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit + mask. + + 'start_pcr' indicates the starting byte index into pcrSelect[]. +*/ + +TPM_RESULT TPM_PCRSelection_GetPCRUsage(TPM_BOOL *pcrUsage, + const TPM_PCR_SELECTION *tpm_pcr_selection, + size_t start_index) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_PCRSelection_GetPCRUsage: Start %lu\n", (unsigned long)start_index); + if (rc == 0) { + rc = TPM_PCRSelection_CheckRange(tpm_pcr_selection); + } + if (rc == 0) { + *pcrUsage = FALSE; + /* If sizeOfSelect is 0 or start_index is past the end, this loop won't be entered and FALSE + will be returned */ + for (i = start_index ; i < tpm_pcr_selection->sizeOfSelect ; i++) { + if (tpm_pcr_selection->pcrSelect[i] != 0) { /* is any bit set in the mask */ + *pcrUsage = TRUE; + break; + } + } + } + return rc; +} + +/* TPM_PCRSelection_CheckRange() checks the sizeOfSelect index + +*/ + +TPM_RESULT TPM_PCRSelection_CheckRange(const TPM_PCR_SELECTION *tpm_pcr_selection) +{ + TPM_RESULT rc = 0; + + if (tpm_pcr_selection->sizeOfSelect > (TPM_NUM_PCR/CHAR_BIT)) { + printf("TPM_PCRSelection_CheckRange: Error, sizeOfSelect %u must be 0 - %u\n", + tpm_pcr_selection->sizeOfSelect, TPM_NUM_PCR/CHAR_BIT); + rc = TPM_INVALID_PCR_INFO; + } + return rc; +} + +/* TPM_PCRSelection_Compare() compares the TPM_PCR_SELECTION's for equality + +*/ + +void TPM_PCRSelection_Compare(TPM_BOOL *match, + TPM_PCR_SELECTION *tpm_pcr_selection1, + TPM_PCR_SELECTION *tpm_pcr_selection2) +{ + size_t i; + *match = TRUE; + + if (tpm_pcr_selection1->sizeOfSelect != tpm_pcr_selection2->sizeOfSelect) { + *match = FALSE; + } + for (i = 0 ; *match && (i < tpm_pcr_selection1->sizeOfSelect) ; i++) { + if (tpm_pcr_selection1->pcrSelect[i] != tpm_pcr_selection2->pcrSelect[i]) { + *match = FALSE; + } + } + return; +} + +#if 0 +/* TPM_PCRSelection_LessThan() compares the new selection to the old selection. It returns lessThan + TRUE is the new selection does not select a PCR that was selected by the old selection. +*/ + +void TPM_PCRSelection_LessThan(TPM_BOOL *lessThan, + TPM_PCR_SELECTION *tpm_pcr_selection_new, + TPM_PCR_SELECTION *tpm_pcr_selection_old) +{ + size_t i; + *lessThan = TRUE; + + if (tpm_pcr_selection_new->sizeOfSelect != tpm_pcr_selection_old->sizeOfSelect) { + *lessThan = FALSE; + } + for (i = 0 ; *lessThan && (i < tpm_pcr_selection_new->sizeOfSelect) ; i++) { + /* if there's a 0 in the new selection and a 1 on the old selection */ + if (~(tpm_pcr_selection_new->pcrSelect[i]) & tpm_pcr_selection_old->pcrSelect[i]) { + *lessThan = FALSE; + } + } + return; +} +#endif + + +/* + TPM_QUOTE_INFO +*/ + +/* TPM_QuoteInfo_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_QuoteInfo_Init(TPM_QUOTE_INFO *tpm_quote_info) +{ + printf(" TPM_QuoteInfo_Init:\n"); + TPM_StructVer_Init(&(tpm_quote_info->version)); + memcpy(&(tpm_quote_info->fixed), "QUOT", 4); + TPM_Digest_Init(tpm_quote_info->digestValue); + TPM_Nonce_Init(tpm_quote_info->externalData); + return; +} + +#if 0 +/* TPM_QuoteInfo_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_QuoteInfo_Init() + After use, call TPM_QuoteInfo_Delete() to free memory + + NOTE: Never called. +*/ + +TPM_RESULT TPM_QuoteInfo_Load(TPM_QUOTE_INFO *tpm_quote_info, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_QuoteInfo_Load:\n"); + /* load version */ + if (rc == 0) { + rc = TPM_StructVer_Load(&(tpm_quote_info->version), stream, stream_size); + } + /* check ver immediately to ease debugging */ + if (rc == 0) { + rc = TPM_StructVer_CheckVer(&(tpm_quote_info->version)); + } + /* load fixed */ + if (rc == 0) { + rc = TPM_Loadn(tpm_quote_info->fixed, 4, stream, stream_size); + } + /* load digestValue */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_quote_info->digestValue, stream, stream_size); + } + /* load externalData */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_quote_info->externalData, stream, stream_size); + } + return rc; +} +#endif + +/* TPM_QuoteInfo_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_QuoteInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_QUOTE_INFO *tpm_quote_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_QuoteInfo_Store:\n"); + /* store version */ + if (rc == 0) { + rc = TPM_StructVer_Store(sbuffer, &(tpm_quote_info->version)); + } + /* store fixed */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_quote_info->fixed, 4); + } + /* store digestValue */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_quote_info->digestValue); + } + /* store externalData */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_quote_info->externalData); + } + return rc; +} + +/* TPM_QuoteInfo_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_QuoteInfo_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_QuoteInfo_Delete(TPM_QUOTE_INFO *tpm_quote_info) +{ + printf(" TPM_QuoteInfo_Delete:\n"); + if (tpm_quote_info != NULL) { + TPM_QuoteInfo_Init(tpm_quote_info); + } + return; +} + +/* + TPM_QUOTE_INFO2 +*/ + +/* TPM_QuoteInfo2_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_QuoteInfo2_Init(TPM_QUOTE_INFO2 *tpm_quote_info2) +{ + printf(" TPM_QuoteInfo2_Init:\n"); + memcpy(tpm_quote_info2->fixed, "QUT2", 4); + TPM_Nonce_Init(tpm_quote_info2->externalData); + TPM_PCRInfoShort_Init(&(tpm_quote_info2->infoShort)); + return; +} + +#if 0 +/* TPM_QuoteInfo2_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_QuoteInfo2_Init() + After use, call TPM_QuoteInfo2_Delete() to free memory +*/ + +TPM_RESULT TPM_QuoteInfo2_Load(TPM_QUOTE_INFO2 *tpm_quote_info2, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_QuoteInfo2_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_QUOTE_INFO2, stream, stream_size); + } + /* load fixed */ + if (rc == 0) { + rc = TPM_Loadn(tpm_quote_info2->fixed, 4, stream, stream_size); + } + /* load externalData */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_quote_info2->externalData, stream, stream_size); + } + /* load infoShort */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Load(&(tpm_quote_info2->infoShort), stream, stream_size, FALSE); + } + return rc; +} +#endif + +/* TPM_QuoteInfo2_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_QuoteInfo2_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_QUOTE_INFO2 *tpm_quote_info2) +{ + TPM_RESULT rc = 0; + + printf(" TPM_QuoteInfo2_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_QUOTE_INFO2); + } + /* store fixed */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_quote_info2->fixed, 4); + } + /* store externalData */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_quote_info2->externalData); + } + /* store infoShort */ + if (rc == 0) { + rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_quote_info2->infoShort), FALSE); + } + return rc; +} + +/* TPM_QuoteInfo2_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_QuoteInfo2_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_QuoteInfo2_Delete(TPM_QUOTE_INFO2 *tpm_quote_info2) +{ + printf(" TPM_QuoteInfo2_Delete:\n"); + if (tpm_quote_info2 != NULL) { + TPM_PCRInfoShort_Delete(&(tpm_quote_info2->infoShort)); + TPM_QuoteInfo2_Init(tpm_quote_info2); + } + return; +} + +/* + Command Processing Functions +*/ + + +/* 16.2 TPM_PCRRead rev 109 + + The TPM_PCRRead operation provides non-cryptographic reporting of the contents of a named PCR. +*/ + +TPM_RESULT TPM_Process_PcrRead(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_PCRINDEX pcrIndex; /* Index of the PCR to be read */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_PCRVALUE outDigest; + + printf("TPM_Process_PcrRead: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get pcrIndex parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&pcrIndex, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_PcrRead: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1.Validate that pcrIndex represents a legal PCR number. On error, return TPM_BADINDEX. */ + /* 2. Set outDigest to TPM_STCLEAR_DATA -> PCR[pcrIndex] */ + /* NOTE Done by TPM_PCR_Load() */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_PcrRead: pcrIndex %u\n", pcrIndex); + returnCode = TPM_PCR_Load(outDigest, + tpm_state->tpm_stclear_data.PCRS, + pcrIndex); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_PcrRead: PCR value", outDigest); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_PcrRead: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append outDigest */ + returnCode = TPM_Digest_Store(response, outDigest); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 16.3 TPM_Quote rev 101 + + The TPM_Quote operation provides cryptographic reporting of PCR values. A loaded key is required + for operation. TPM_Quote uses a key to sign a statement that names the current value of a chosen + PCR and externally supplied data (which may be a nonce supplied by a Challenger). + + The term "ExternalData" is used because an important use of TPM_Quote is to provide a digital + signature on arbitrary data, where the signature includes the PCR values of the platform at time + of signing. Hence the "ExternalData" is not just for anti-replay purposes, although it is (of + course) used for that purpose in an integrity challenge. +*/ + +TPM_RESULT TPM_Process_Quote(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can sign + the PCR values. */ + TPM_NONCE externalData; /* 160 bits of externally supplied data (typically a nonce + provided by a server to prevent replay-attacks) */ + TPM_PCR_SELECTION targetPCR; /* The indices of the PCRs that are to be reported. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle + authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA privAuth; /* The authorization digest for inputs and keyHandle. HMAC + key: key -> usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ + TPM_SECRET *keyUsageAuth; + TPM_BOOL parentPCRStatus; + TPM_QUOTE_INFO q1QuoteInfo; + TPM_DIGEST q1_digest; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_PCR_COMPOSITE pcrData; /* A structure containing the same indices as + targetPCR, plus the corresponding current PCR + values. */ + TPM_SIZED_BUFFER sig; /* The signed data blob. */ + + printf("TPM_Process_Quote: Ordinal Entry\n"); + TPM_PCRSelection_Init(&targetPCR); /* freed @1 */ + TPM_PCRComposite_Init(&pcrData); /* freed @2 */ + TPM_QuoteInfo_Init(&q1QuoteInfo); /* freed @3 */ + TPM_SizedBuffer_Init(&sig); /* freed @4 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get externalData parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Quote: keyHandle %08x\n", keyHandle); + returnCode = TPM_Nonce_Load(externalData, &command, ¶mSize); + } + /* get targetPCR parameter */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_Quote: externalData", externalData); + returnCode = TPM_PCRSelection_Load(&targetPCR, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + printf("TPM_Process_Quote: authHandle %08x\n", authHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Quote: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not r/o, used to sign */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (sigKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_Quote: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + sigKey, + keyUsageAuth, /* OIAP */ + sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 1. The TPM MUST validate the authorization to use the key pointed to by keyHandle. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + /* 2. Validate that keyHandle -> sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1 or + TPM_SS_RSASSAPKCS1v15_INFO,, if not return TPM_INAPPROPRIATE_SIG. */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { + printf("TPM_Process_Quote: Error, invalid sigKey sigScheme %04hx\n", + sigKey->algorithmParms.sigScheme); + returnCode = TPM_INAPPROPRIATE_SIG; + } + } + /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or + TPM_KEY_LEGACY, if not return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->keyUsage != TPM_KEY_SIGNING) && + ((sigKey->keyUsage) != TPM_KEY_IDENTITY) && + ((sigKey->keyUsage) != TPM_KEY_LEGACY)) { + printf("TPM_Process_Quote: Error, keyUsage %04hx is invalid\n", sigKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. Validate targetPCR */ + /* a. targetPCR is a valid TPM_PCR_SELECTION structure */ + /* b. On errors return TPM_INVALID_PCR_INFO */ + /* NOTE: done during TPM_PCRSelection_Load() */ + /* 5. Create H1 a SHA-1 hash of a TPM_PCR_COMPOSITE using the PCRs indicated by targetPCR -> + pcrSelect */ + /* NOTE TPM_PCRSelection_GenerateDigest2() generates the TPM_PCR_COMPOSITE as well. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRSelection_GenerateDigest2(q1QuoteInfo.digestValue, + &pcrData, /* TPM_PCR_COMPOSITE */ + &targetPCR, + tpm_state->tpm_stclear_data.PCRS); + } + /* 6. Create Q1 a TPM_QUOTE_INFO structure */ + /* a. Set Q1 -> version to 1.1.0.0 */ + /* b. Set Q1 -> fixed to "QUOT" */ + /* NOTE: done at TPM_QuoteInfo_Init() */ + /* c. Set Q1 -> digestValue to H1 */ + /* NOTE: Generated directly in Q1 */ + /* d. Set Q1 -> externalData to externalData */ + if (returnCode == TPM_SUCCESS) { + TPM_Nonce_Copy(q1QuoteInfo.externalData, externalData); + } + /* 7. Sign SHA-1 hash of Q1 using keyHandle as the signature key */ + /* digest Q1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(q1_digest, &q1QuoteInfo, + (TPM_STORE_FUNCTION_T)TPM_QuoteInfo_Store); + } + /* sign the Q1 digest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ + q1_digest, /* message */ + TPM_DIGEST_SIZE, /* message size */ + sigKey); /* signing key and parameters */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_Quote: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the pcrData */ + returnCode = TPM_PCRComposite_Store(response, &pcrData); + } + /* 8. Return the signature in sig */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Store(response, &sig); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_PCRSelection_Delete(&targetPCR); /* @1 */ + TPM_PCRComposite_Delete(&pcrData); /* @2 */ + TPM_QuoteInfo_Delete(&q1QuoteInfo); /* @3 */ + TPM_SizedBuffer_Delete(&sig); /* @4 */ + return rcf; +} + + +/* 16.5 TPM_Quote2 rev 96 + + The TPM_Quote operation provides cryptographic reporting of PCR values. A loaded key is required + for operation. TPM_Quote uses a key to sign a statement that names the current value of a chosen + PCR and externally supplied data (which may be a nonce supplied by a Challenger). + + The term "ExternalData" is used because an important use of TPM_Quote is to provide a digital + signature on arbitrary data, where the signature includes the PCR values of the platform at time + of signing. Hence the "ExternalData" is not just for anti-replay purposes, although it is (of + course) used for that purpose in an integrity challenge. + + Quote2 differs from quote in that Quote2 uses TPM_PCR_INFO_SHORT to hold information relative to + the PCR registers. INFO_SHORT includes locality information to provide the requester a more + complete view of the current platform configuration. +*/ + +TPM_RESULT TPM_Process_Quote2(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can sign + the PCR values. */ + TPM_NONCE externalData; /* 160 bits of externally supplied data (typically a nonce + provided by a server to prevent replay-attacks) */ + TPM_PCR_SELECTION targetPCR; /* The indices of the PCRs that are to be reported. */ + TPM_BOOL addVersion; /* When TRUE add TPM_CAP_VERSION_INFO to the output */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle + authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA privAuth; /* The authorization session digest for inputs and + keyHandle. HMAC key: key -> usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ + TPM_SECRET *keyUsageAuth; + TPM_BOOL parentPCRStatus; + TPM_COMPOSITE_HASH h1CompositeHash; + TPM_QUOTE_INFO2 q1; + TPM_PCR_INFO_SHORT *s1 = NULL; + TPM_STORE_BUFFER q1_sbuffer; + TPM_STORE_BUFFER versionInfo_sbuffer; + const unsigned char *versionInfo_buffer; + TPM_DIGEST q1_digest; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + uint32_t versionInfoSize; /* Size of the version info */ + TPM_CAP_VERSION_INFO versionInfo; /* The version info */ + TPM_SIZED_BUFFER sig; /* The signed data blob. */ + + printf("TPM_Process_Quote2: Ordinal Entry\n"); + TPM_PCRSelection_Init(&targetPCR); /* freed @1 */ + TPM_CapVersionInfo_Set(&versionInfo, &(tpm_state->tpm_permanent_data)); /* freed @2 */ + TPM_SizedBuffer_Init(&sig); /* freed @3 */ + TPM_QuoteInfo2_Init(&q1); /* freed @4 */ + TPM_Sbuffer_Init(&q1_sbuffer); /* freed @5 */ + TPM_Sbuffer_Init(&versionInfo_sbuffer); /* freed @6 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get externalData */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Quote2: keyHandle %08x\n", keyHandle); + returnCode = TPM_Nonce_Load(externalData, &command, ¶mSize); + } + /* get targetPCR parameter */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_Quote2: externalData", externalData); + returnCode = TPM_PCRSelection_Load(&targetPCR, &command, ¶mSize); + } + /* get addVersion parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadBool(&addVersion, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Quote2: addVersion %02x\n", addVersion); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + printf("TPM_Process_Quote2: authHandle %08x\n", authHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Quote2: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not r/o, used to sign */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (sigKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_Quote2: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + sigKey, + keyUsageAuth, /* OIAP */ + sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 1. The TPM MUST validate the AuthData to use the key pointed to by keyHandle. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + /* 2. Validate that keyHandle -> sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1, if not return + TPM_INAPPROPRIATE_SIG. */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { + printf("TPM_Process_Quote2: Error, inappropriate signature scheme %04x\n", + sigKey->algorithmParms.sigScheme); + returnCode = TPM_INAPPROPRIATE_SIG; + } + } + /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or + TPM_KEY_LEGACY, if not return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->keyUsage != TPM_KEY_SIGNING) && + ((sigKey->keyUsage) != TPM_KEY_IDENTITY) && + ((sigKey->keyUsage) != TPM_KEY_LEGACY)) { + printf("TPM_Process_Quote2: Error, keyUsage %04hx is invalid\n", sigKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. Validate targetPCR is a valid TPM_PCR_SELECTION structure, on errors return + TPM_INVALID_PCR_INFO */ + /* NOTE: done during TPM_PCRSelection_Load() */ + /* 5. Create H1 a SHA-1 hash of a TPM_PCR_COMPOSITE using the PCRs indicated by targetPCR -> + pcrSelect */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRSelection_GenerateDigest(h1CompositeHash, + &targetPCR, + tpm_state->tpm_stclear_data.PCRS); + } + if (returnCode == TPM_SUCCESS) { + /* 6. Create S1 a TPM_PCR_INFO_SHORT */ + s1 = &(q1.infoShort); + /* a. Set S1->pcrSelection to pcrSelect */ + returnCode = TPM_PCRSelection_Copy(&(s1->pcrSelection), &targetPCR); + } + /* b. Set S1->localityAtRelease to TPM_STANY_DATA -> localityModifier */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Locality_Set(&(s1->localityAtRelease), + tpm_state->tpm_stany_flags.localityModifier); + } + /* c. Set S1->digestAtRelease to H1 */ + if (returnCode == TPM_SUCCESS) { + TPM_Digest_Copy(s1->digestAtRelease, h1CompositeHash); + /* 7. Create Q1 a TPM_QUOTE_INFO2 structure */ + /* a. Set Q1 -> fixed to "QUT2" */ + /* NOTE: done at TPM_QuoteInfo2_Init() */ + /* b. Set Q1 -> infoShort to S1 */ + /* NOTE: created S1 in place */ + /* c. Set Q1 -> externalData to externalData */ + TPM_Nonce_Copy(q1.externalData, externalData); + /* serialize q1 */ + returnCode = TPM_QuoteInfo2_Store(&q1_sbuffer, &q1); + } + if (returnCode == TPM_SUCCESS) { + /* 8. If addVersion is TRUE */ + if (addVersion) { + if (returnCode == TPM_SUCCESS) { + /* a. Concatenate to Q1 a TPM_CAP_VERSION_INFO structure */ + /* b. Set the output parameters for versionInfo */ + /* serialize versionInfo. The result cannot be added directly to q1_sbuffer because + it is needed as an outgoing parameter */ + /* NOTE: Created at TPM_CapVersionInfo_Set() */ + returnCode = TPM_CapVersionInfo_Store(&versionInfo_sbuffer, &versionInfo); + } + if (returnCode == TPM_SUCCESS) { + /* get the serialized results */ + TPM_Sbuffer_Get(&versionInfo_sbuffer, &versionInfo_buffer, &versionInfoSize); + /* concatenate TPM_CAP_VERSION_INFO versionInfo to TPM_QUOTE_INFO2 q1 buffer */ + returnCode = TPM_Sbuffer_Append(&q1_sbuffer, versionInfo_buffer, versionInfoSize); + } + } + /* 9. Else */ + else { + /* a. Set versionInfoSize to 0 */ + versionInfoSize = 0; + /* b. Return no bytes in versionInfo */ + /* NOTE Done at response, (&& addVersion) */ + } + } + /* 10. Sign a SHA-1 hash of Q1 using keyHandle as the signature key */ + /* hash q1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1Sbuffer(q1_digest, &q1_sbuffer); + } + /* sign the Q1 digest */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ + q1_digest, /* message */ + TPM_DIGEST_SIZE, /* message size */ + sigKey); /* signing key and parameters */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_Quote2: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the TPM_PCR_INFO_SHORT pcrData */ + returnCode = TPM_PCRInfoShort_Store(response, s1, FALSE); + } + /* An email clarification said that, if addVersion is FALSE, a versionInfoSize is 0 is + returned. This indicates the missing versionInfo. */ + /* return the versionInfoSize */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append32(response, versionInfoSize); + } + /* return the versionInfo */ + if ((returnCode == TPM_SUCCESS) && addVersion) { + returnCode = TPM_Sbuffer_Append(response, versionInfo_buffer, versionInfoSize); + } + /* 11. Return the signature in sig */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Store(response, &sig); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_PCRSelection_Delete(&targetPCR); /* @1 */ + TPM_CapVersionInfo_Delete(&versionInfo); /* @2 */ + TPM_SizedBuffer_Delete(&sig); /* @3 */ + TPM_QuoteInfo2_Delete(&q1); /* @4 */ + TPM_Sbuffer_Delete(&q1_sbuffer); /* @5 */ + TPM_Sbuffer_Delete(&versionInfo_sbuffer); /* @6 */ + return rcf; +} + +/* TPM_ExtendCommon() rev 109 + + Contains code common to TPM_Process_Extend() and TPM_Process_SHA1CompleteExtend(). + + Add a measurement value to a PCR +*/ + +TPM_RESULT TPM_ExtendCommon(TPM_PCRVALUE outDigest, /* The PCR value after execution of + the command */ + tpm_state_t *tpm_state, + TPM_COMMAND_CODE ordinal, /* command ordinal */ + TPM_PCRINDEX pcrNum, /* Index of the PCR to be modified */ + TPM_DIGEST inDigest) /* the event to be recorded */ +{ + TPM_RESULT rc = 0; + TPM_PCRVALUE currentPcrValue; + TPM_DIGEST h1; + + printf("TPM_ExtendCommon: pcrNum %u\n", pcrNum); + /* 1. Validate that pcrNum represents a legal PCR number. On error, return TPM_BADINDEX. */ + if (rc == 0) { + rc = TPM_PCR_CheckRange(pcrNum); + } + if (rc == 0) { + /* 2. Map V1 to TPM_STANY_FLAGS */ + /* 3. Map L1 to V1 -> localityModifier */ + /* 4. If the current locality, held in L1, is not selected in TPM_PERMANENT_DATA -> + pcrAttrib[PCRIndex].pcrExtendLocal, return TPM_BAD_LOCALITY */ + rc = TPM_Locality_Check(tpm_state->tpm_permanent_data.pcrAttrib[pcrNum].pcrExtendLocal, + tpm_state->tpm_stany_flags.localityModifier); + } + /* get the current PCR digest value */ + if (rc == 0) { + rc = TPM_PCR_Load(currentPcrValue, + tpm_state->tpm_stclear_data.PCRS, + pcrNum); + } +#if defined TPM_PCCLIENT + /* From the PC Client TIS spec + + 1. When the locality 4 PCR is at its reset value of 0, the entry for the locality 4 PCR in + section 7.2 SHALL be interpreted as if the column labeled pcrExtendLocal for locality + 4,3,2,1,0 contains the bit field definitions: 1,0,0,0,0. + + 2. Once the locality 4 PCR is no longer at its reset value of 0, table 4 in section 7.2 + applies as written. + */ + if (rc == 0) { + TPM_BOOL isZero; + if ((pcrNum == 17) && /* PCR 17 is the Locality 4 PCR */ + (tpm_state->tpm_stany_flags.localityModifier != 4)) { + /* if not locality 4, must not be at the reset value */ + TPM_Digest_IsZero(&isZero, currentPcrValue); + if (isZero) { + printf("TPM_ExtendCommon: Error, " + "pcrNum %u and locality %u and PCR at reset value\n", + pcrNum, tpm_state->tpm_stany_flags.localityModifier); + rc = TPM_BAD_LOCALITY; + } + } + } +#endif + /* 5. Create c1 by concatenating (PCRindex TPM_PCRVALUE || inDigest). This takes the current PCR + value and concatenates the inDigest parameter. */ + /* NOTE: Not required, SHA1 uses varargs */ + /* 6. Create h1 by performing a SHA-1 digest of c1. */ + if (rc == 0) { + TPM_PrintFour("TPM_ExtendCommon: Current PCR ", currentPcrValue); + /* TPM_PrintFour("TPM_ExtendCommon: Current PCR ", + tpm_state->tpm_stclear_data.PCR[pcrNum]); */ + TPM_PrintFour("TPM_ExtendCommon: Input Digest", inDigest); + rc = TPM_SHA1(h1, + TPM_DIGEST_SIZE, currentPcrValue, + TPM_DIGEST_SIZE, inDigest, + 0, NULL); + } + if (rc == 0) { + TPM_PrintFour("TPM_ExtendCommon: New PCR", h1); + /* 7. Store h1 as the new TPM_PCRVALUE of PCRindex */ + rc = TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, + pcrNum, + h1); + } + if (rc == 0) { + /* 8. If TPM_PERMANENT_FLAGS -> disable is TRUE or TPM_STCLEAR_FLAGS -> deactivated is + TRUE */ + if ((tpm_state->tpm_permanent_flags.disable) || + (tpm_state->tpm_stclear_flags.deactivated)) { + /* a. Set outDigest to 20 bytes of 0x00 */ + TPM_Digest_Init(outDigest); + } + /* 9. Else */ + else { + /* a. Set outDigest to h1 */ + TPM_Digest_Copy(outDigest, h1); + } + } + if (rc == 0) { + ordinal = ordinal; + } + return rc; +} + +/* 16.1 TPM_Extend rev 109 + + This adds a new measurement to a PCR. +*/ + +TPM_RESULT TPM_Process_Extend(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_PCRINDEX pcrNum; /* The PCR to be updated. */ + TPM_DIGEST inDigest; /* The 160 bit value representing the event to be + recorded. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_PCRVALUE outDigest; /* The PCR value after execution of the command. */ + + printf("TPM_Process_Extend: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get pcrNum parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&pcrNum, &command, ¶mSize); + } + /* get inDigest parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Digest_Load(inDigest, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Extend: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* extend the resultant digest into a PCR */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ExtendCommon(outDigest, tpm_state, ordinal, pcrNum, inDigest); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_Extend: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* append outDigest */ + returnCode = TPM_Digest_Store(response, outDigest); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 16.4 TPM_PCR_Reset rev 87 + + For PCR with the pcrReset attribute set to TRUE, this command resets the PCR back to the default + value, this mimics the actions of TPM_Init. The PCR may have restrictions as to which locality + can perform the reset operation. + + Sending a null pcrSelection results in an error is due to the requirement that the command + actually do something. If pcrSelection is null there are no PCR to reset and the command would + then do nothing. + + For PCR that are resettable, the presence of a Trusted Operating System (TOS) can change the + behavior of TPM_PCR_Reset. The following pseudo code shows how the behavior changes + + At TPM_Startup + If TPM_PCR_ATTRIBUTES->pcrReset is FALSE + Set PCR to 0x00...00 + Else + Set PCR to 0xFF...FF + + At TPM_PCR_Reset + If TPM_PCR_ATTRIBUTES->pcrReset is TRUE + If TOSPresent + Set PCR to 0x00...00 + Else + Set PCR to 0xFF...FF + Else + Return error + + The above pseudocode is for example only, for the details of a specific platform, the reader must + review the platform specific specification. The purpose of the above pseudocode is to show that + both pcrReset and the TOSPresent bit control the value in use to when the PCR resets. +*/ + +TPM_RESULT TPM_Process_PcrReset(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_PCR_SELECTION pcrSelection; /* The PCR's to reset*/ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL pcrUsage; /* TRUE if pcrSelection specifies one or more + PCR's */ + TPM_PERMANENT_DATA *tpm_permanent_data = NULL; + size_t i; /* PCR selection iterator */ + size_t j; /* PCR selection bit map in byte */ + TPM_PCRINDEX pcr_num; /* PCR iterator */ + TPM_MODIFIER_INDICATOR localityModifier = 0; + uint16_t sizeOfSelect = 0; /* from pcrSelection input parameter */ + + /* output parameters */ + uint16_t outParamStart; /* starting point of outParam's */ + uint16_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_PcrReset: Ordinal Entry\n"); + TPM_PCRSelection_Init(&pcrSelection); /* freed @1 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get pcrSelection */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRSelection_Load(&pcrSelection, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_PcrReset: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Validate that pcrSelection is valid */ + /* a. is a valid TPM_PCR_SELECTION structure */ + /* NOTE: Done during TPM_PCRSelection_Load() */ + /* b. pcrSelection -> pcrSelect is non-zero */ + /* NOTE: TPM_PCRSelection_GetPCRUsage() range checks pcrSelection */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_PcrReset: Getting input PCR usage\n"); + returnCode = TPM_PCRSelection_GetPCRUsage(&pcrUsage, &pcrSelection, 0); + } + /* c. On errors return TPM_INVALID_PCR_INFO */ + if (returnCode == TPM_SUCCESS) { + if (!pcrUsage) { + printf("TPM_Process_PcrReset: Error, pcrSelect is zero\n"); + returnCode = TPM_INVALID_PCR_INFO; + } + } + /* 2. Map L1 to TPM_STANY_FLAGS -> localityModifier (NOTE and other optimizations of the inner + loop) */ + if (returnCode == TPM_SUCCESS) { + localityModifier = tpm_state->tpm_stany_flags.localityModifier; + tpm_permanent_data = &(tpm_state->tpm_permanent_data); + sizeOfSelect = pcrSelection.sizeOfSelect; /* bytes of input PCR selection */ + } + /* 3. For each PCR selected perform the following */ + for (i = 0, pcr_num = 0 ; (returnCode == TPM_SUCCESS) && (i < sizeOfSelect) ; i++) { + /* iterate through all bits in each selection byte */ + for (j = 0x0001 ; + (returnCode == TPM_SUCCESS) && (j != (0x0001 << CHAR_BIT)) ; + j <<= 1, pcr_num++) { + + if (pcrSelection.pcrSelect[i] & j) { /* if the bit is set in the selection map */ + /* a. If pcrAttrib[pcrIndex].pcrReset is FALSE */ + if (!(tpm_permanent_data->pcrAttrib[pcr_num].pcrReset)) { + printf("TPM_Process_PcrReset: Error, PCR %u not resettable\n", pcr_num); + /* a. Return TPM_NOTRESETABLE */ + returnCode = TPM_NOTRESETABLE; + } + /* b. If, for the value L1, the corresponding bit is clear in the bit map + TPM_PERMANENT_DATA -> pcrAttrib[pcrIndex].pcrResetLocal, return + TPM_NOTLOCAL */ + else { + returnCode = + TPM_Locality_Check(tpm_permanent_data->pcrAttrib[pcr_num].pcrResetLocal, + localityModifier); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_PcrReset: Error, PCR %u bad pcrResetLocal %02x\n", + pcr_num, tpm_permanent_data->pcrAttrib[pcr_num].pcrResetLocal); + returnCode = TPM_NOTLOCAL; + } + } + /* NOTE: No 'else reset' here. The command MUST validate that all PCR registers + that are selected are available to be reset before resetting any PCR. */ + } + } + } + /* 3. For each PCR selected perform the following */ + if (returnCode == TPM_SUCCESS) { + for (i = 0, pcr_num = 0 ; i < sizeOfSelect ; i++) { + /* iterate through all bits in each selection byte */ + for (j = 0x0001 ; j != (0x0001 << CHAR_BIT) ; j <<= 1, pcr_num++) { + if (pcrSelection.pcrSelect[i] & j) { /* if the bit is set in the selection map */ + printf("TPM_Process_PcrReset: Resetting PCR %u\n", pcr_num); + /* a. The PCR MAY only reset to 0x00...00 or 0xFF...FF */ + /* b. The logic to determine which value to use MUST be described by a platform + specific specification + */ + /* Ignore errors here since PCR selection has already been validated. pcr_num + is guaranteed to be in range from from 'for' iterator, and pcrReset is + guaranteed to be TRUE from the previous loop. */ + TPM_PCR_Reset(tpm_state->tpm_stclear_data.PCRS, + tpm_state->tpm_stany_flags.TOSPresent, + pcr_num); + } + } + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_PcrReset: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_PCRSelection_Delete(&pcrSelection); /* @1 */ + return rcf; +} + diff --git a/src/tpm12/tpm_pcr.h b/src/tpm12/tpm_pcr.h new file mode 100644 index 0000000..6036c9d --- /dev/null +++ b/src/tpm12/tpm_pcr.h @@ -0,0 +1,367 @@ +/********************************************************************************/ +/* */ +/* PCR Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_pcr.h 4620 2011-09-07 21:43:19Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_PCR_H +#define TPM_PCR_H + +#include "tpm_global.h" +#include "tpm_sizedbuffer.h" +#include "tpm_store.h" + +/* + Locality Utilities +*/ + +TPM_RESULT TPM_Locality_Set(TPM_LOCALITY_SELECTION *tpm_locality_selection, + TPM_MODIFIER_INDICATOR tpm_modifier_indicator); +TPM_RESULT TPM_Locality_Check(TPM_LOCALITY_SELECTION tpm_locality_selection, + TPM_MODIFIER_INDICATOR localityModifier); + +TPM_RESULT TPM_LocalitySelection_CheckLegal(TPM_LOCALITY_SELECTION tpm_locality_selection); +TPM_RESULT TPM_LocalityModifier_CheckLegal(TPM_MODIFIER_INDICATOR localityModifier); + +void TPM_PCRLocality_Compare(TPM_BOOL *match, + TPM_LOCALITY_SELECTION tpm_locality_selection1, + TPM_LOCALITY_SELECTION tpm_locality_selection2); + +/* + state PCR's +*/ + +TPM_RESULT TPM_PCR_CheckRange(TPM_PCRINDEX index); +void TPM_PCR_Init(TPM_PCRVALUE *tpm_pcrs, + const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes, + size_t pcrIndex); +void TPM_PCR_Reset(TPM_PCRVALUE *tpm_pcrs, + TPM_BOOL TOSPresent, + TPM_PCRINDEX pcrIndex); +TPM_RESULT TPM_PCR_Load(TPM_PCRVALUE dest_pcr, + TPM_PCRVALUE *tpm_pcrs, + TPM_PCRINDEX index); +TPM_RESULT TPM_PCR_Store(TPM_PCRVALUE *tpm_pcrs, + TPM_PCRINDEX index, + TPM_PCRVALUE src_pcr); + +/* + TPM_SELECT_SIZE +*/ + +void TPM_SelectSize_Init(TPM_SELECT_SIZE *tpm_select_size); +TPM_RESULT TPM_SelectSize_Load(TPM_SELECT_SIZE *tpm_select_size, + unsigned char **stream, + uint32_t *stream_size); + + +/* + TPM_PCR_SELECTION +*/ + +void TPM_PCRSelection_Init(TPM_PCR_SELECTION *tpm_pcr_selection); +TPM_RESULT TPM_PCRSelection_Load(TPM_PCR_SELECTION *tpm_pcr_selection, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_PCRSelection_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_SELECTION *tpm_pcr_selection); +void TPM_PCRSelection_Delete(TPM_PCR_SELECTION *tpm_pcr_selection); +/* copy */ +TPM_RESULT TPM_PCRSelection_Copy(TPM_PCR_SELECTION *destination, + TPM_PCR_SELECTION *source); +/* setters */ +TPM_RESULT TPM_PCRSelection_GenerateDigest(TPM_DIGEST tpm_digest, + TPM_PCR_SELECTION *tpm_pcr_selection, + TPM_PCRVALUE *tpm_pcrs); +TPM_RESULT TPM_PCRSelection_GenerateDigest2(TPM_DIGEST tpm_digest, + TPM_PCR_COMPOSITE *tpm_pcr_composite, + TPM_PCR_SELECTION *tpm_pcr_selection, + TPM_PCRVALUE *tpm_pcrs); +/* getters */ +TPM_RESULT TPM_PCRSelection_GetPCRUsage(TPM_BOOL *pcrUsage, + const TPM_PCR_SELECTION *tpm_pcr_selection, + size_t start_index); +/* checkers */ +TPM_RESULT TPM_PCRSelection_CheckRange(const TPM_PCR_SELECTION *tpm_pcr_selection); +void TPM_PCRSelection_Compare(TPM_BOOL *match, + TPM_PCR_SELECTION *tpm_pcr_selection1, + TPM_PCR_SELECTION *tpm_pcr_selection2); +#if 0 +void TPM_PCRSelection_LessThan(TPM_BOOL *lessThan, + TPM_PCR_SELECTION *tpm_pcr_selection_new, + TPM_PCR_SELECTION *tpm_pcr_selection_old); +#endif + +/* TPM_PCR_ATTRIBUTES */ + +void TPM_PCRAttributes_Init(TPM_PCR_ATTRIBUTES *tpm_pcr_attributes); + +void TPM_PCRInfo_Trace(const char *message, + TPM_PCR_SELECTION pcrSelection, + TPM_COMPOSITE_HASH digestAtRelease); +/* + PCRs - Functions that act on the entire set of PCRs +*/ + +void TPM_PCRs_Init(TPM_PCRVALUE *tpm_pcrs, + const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes); +TPM_RESULT TPM_PCRs_Load(TPM_PCRVALUE *tpm_pcrs, + const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_PCRs_Store(TPM_STORE_BUFFER *sbuffer, + TPM_PCRVALUE *tpm_pcrs, + const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes); + +/* + TPM_PCR_INFO +*/ + +void TPM_PCRInfo_Init(TPM_PCR_INFO *tpm_pcr_info); +TPM_RESULT TPM_PCRInfo_Load(TPM_PCR_INFO *tpm_pcr_info, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_PCRInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_INFO *tpm_pcr_info); +void TPM_PCRInfo_Delete(TPM_PCR_INFO *tpm_pcr_info); +/* create */ +TPM_RESULT TPM_PCRInfo_Create(TPM_PCR_INFO **tpm_pcr_info); +/* load */ +TPM_RESULT TPM_PCRInfo_LoadFromBuffer(TPM_PCR_INFO *tpm_pcr_info, + const TPM_SIZED_BUFFER *tpm_sized_buffer); +TPM_RESULT TPM_PCRInfo_CreateFromBuffer(TPM_PCR_INFO **tpm_pcr_info, + const TPM_SIZED_BUFFER *tpm_sized_buffer); +/* copy */ +TPM_RESULT TPM_PCRInfo_Copy(TPM_PCR_INFO *dest_tpm_pcr_info, + TPM_PCR_INFO *src_tpm_pcr_info); +TPM_RESULT TPM_PCRInfo_CopyInfoLong(TPM_PCR_INFO *dest_tpm_pcr_info, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); +TPM_RESULT TPM_PCRInfo_CreateFromInfo(TPM_PCR_INFO **dest_tpm_pcr_info, + TPM_PCR_INFO *src_tpm_pcr_info); +TPM_RESULT TPM_PCRInfo_CreateFromInfoLong(TPM_PCR_INFO **dest_tpm_pcr_info, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); +TPM_RESULT TPM_PCRInfo_CreateFromKey(TPM_PCR_INFO **dest_tpm_pcr_info, + TPM_KEY *tpm_key); + +/* setters */ +TPM_RESULT TPM_PCRInfo_GenerateDigest(TPM_DIGEST tpm_digest, + TPM_PCR_INFO *tpm_pcr_info, + TPM_PCRVALUE *tpm_pcrs); +TPM_RESULT TPM_PCRInfo_CheckDigest(TPM_PCR_INFO *tpm_pcr_info, + TPM_PCRVALUE *tpm_pcrs); +TPM_RESULT TPM_PCRInfo_SetDigestAtCreation(TPM_PCR_INFO *tpm_pcr_info, + TPM_PCRVALUE *tpm_pcrs); +/* getters */ +TPM_RESULT TPM_PCRInfo_GetPCRUsage(TPM_BOOL *pcrUsage, + TPM_PCR_INFO *tpm_pcr_info, + size_t start_index); + +/* + TPM_PCR_INFO_LONG +*/ + +void TPM_PCRInfoLong_Init(TPM_PCR_INFO_LONG *tpm_pcr_info_long); +TPM_RESULT TPM_PCRInfoLong_Load(TPM_PCR_INFO_LONG *tpm_pcr_info_long, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_PCRInfoLong_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_INFO_LONG *tpm_pcr_info_long); +void TPM_PCRInfoLong_Delete(TPM_PCR_INFO_LONG *tpm_pcr_info_long); +/* create */ +TPM_RESULT TPM_PCRInfoLong_Create(TPM_PCR_INFO_LONG **tpm_pcr_info_long); +/* load */ +TPM_RESULT TPM_PCRInfoLong_LoadFromBuffer(TPM_PCR_INFO_LONG *tpm_pcr_info_long, + const TPM_SIZED_BUFFER *tpm_sized_buffer); +TPM_RESULT TPM_PCRInfoLong_CreateFromBuffer(TPM_PCR_INFO_LONG **tpm_pcr_info_long, + const TPM_SIZED_BUFFER *tpm_sized_buffer); +/* copy */ +TPM_RESULT TPM_PCRInfoLong_Copy(TPM_PCR_INFO_LONG *dest_tpm_pcr_info_long, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); +TPM_RESULT TPM_PCRInfoLong_CreateFromInfoLong(TPM_PCR_INFO_LONG **dest_tpm_pcr_info_long, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); +/* setters */ +TPM_RESULT TPM_PCRInfoLong_GenerateDigest(TPM_DIGEST tpm_digest, + TPM_PCR_INFO_LONG *tpm_pcr_info_long, + TPM_PCRVALUE *tpm_pcrs); +TPM_RESULT TPM_PCRInfoLong_CheckDigest(TPM_PCR_INFO_LONG *tpm_pcr_info_long, + TPM_PCRVALUE *tpm_pcrs, + TPM_MODIFIER_INDICATOR localityModifier); +TPM_RESULT TPM_PCRInfoLong_SetDigestAtCreation(TPM_PCR_INFO_LONG *tpm_pcr_info_long, + TPM_PCRVALUE *tpm_pcrs); +/* getters */ +TPM_RESULT TPM_PCRInfoLong_GetPCRUsage(TPM_BOOL *pcrUsage, + TPM_PCR_INFO_LONG *tpm_pcr_info_long, + size_t start_index); + +/* + TPM_PCR_INFO_SHORT +*/ + +void TPM_PCRInfoShort_Init(TPM_PCR_INFO_SHORT *tpm_pcr_info_short); +TPM_RESULT TPM_PCRInfoShort_Load(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + unsigned char **stream, + uint32_t *stream_size, + TPM_BOOL optimize); +TPM_RESULT TPM_PCRInfoShort_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + TPM_BOOL optimize); +void TPM_PCRInfoShort_Delete(TPM_PCR_INFO_SHORT *tpm_pcr_info_short); +/* create */ +TPM_RESULT TPM_PCRInfoShort_Create(TPM_PCR_INFO_SHORT **tpm_pcr_info_short); +/* load */ +TPM_RESULT TPM_PCRInfoShort_LoadFromBuffer(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + const TPM_SIZED_BUFFER *tpm_sized_buffer); +TPM_RESULT TPM_PCRInfoShort_CreateFromBuffer(TPM_PCR_INFO_SHORT **tpm_pcr_info_short, + const TPM_SIZED_BUFFER *tpm_sized_buffer); +/* copy */ +TPM_RESULT TPM_PCRInfoShort_Copy(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, + TPM_PCR_INFO_SHORT *src_tpm_pcr_info_short); +TPM_RESULT TPM_PCRInfoShort_CopyInfo(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, + TPM_PCR_INFO *src_tpm_pcr_info); +TPM_RESULT TPM_PCRInfoShort_CopyInfoLong(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); +TPM_RESULT TPM_PCRInfoShort_CreateFromInfo(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, + TPM_PCR_INFO *src_tpm_pcr_info); +TPM_RESULT TPM_PCRInfoShort_CreateFromInfoLong(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, + TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); +TPM_RESULT TPM_PCRInfoShort_CreateFromKey(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, + TPM_KEY *tpm_key); + +/* setters */ +TPM_RESULT TPM_PCRInfoShort_GenerateDigest(TPM_DIGEST tpm_digest, + TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + TPM_PCRVALUE *tpm_pcrs); +TPM_RESULT TPM_PCRInfoShort_CheckDigest(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, + TPM_PCRVALUE *tpm_pcrs, + TPM_MODIFIER_INDICATOR localityModifier); + +/* getters */ +TPM_RESULT TPM_PCRInfoShort_GetPCRUsage(TPM_BOOL *pcrUsage, + TPM_PCR_INFO_SHORT *tpm_pcr_info_short); + +/* + TPM_PCR_COMPOSITE +*/ + +void TPM_PCRComposite_Init(TPM_PCR_COMPOSITE *tpm_pcr_composite); +TPM_RESULT TPM_PCRComposite_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PCR_COMPOSITE *tpm_pcr_composite); +void TPM_PCRComposite_Delete(TPM_PCR_COMPOSITE *tpm_pcr_composite); + +TPM_RESULT TPM_PCRComposite_Set(TPM_PCR_COMPOSITE *tpm_pcr_composite, + TPM_PCR_SELECTION *tpm_pcr_selection, + TPM_PCRVALUE *tpm_pcrs); + +/* + TPM_QUOTE_INFO +*/ + +void TPM_QuoteInfo_Init(TPM_QUOTE_INFO *tpm_quote_info); +#if 0 +TPM_RESULT TPM_QuoteInfo_Load(TPM_QUOTE_INFO *tpm_quote_info, + unsigned char **stream, + uint32_t *stream_size); +#endif +TPM_RESULT TPM_QuoteInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_QUOTE_INFO *tpm_quote_info); +void TPM_QuoteInfo_Delete(TPM_QUOTE_INFO *tpm_quote_info); + +/* + TPM_QUOTE_INFO2 +*/ + +void TPM_QuoteInfo2_Init(TPM_QUOTE_INFO2 *tpm_quote_info2); +#if 0 +TPM_RESULT TPM_QuoteInfo2_Load(TPM_QUOTE_INFO2 *tpm_quote_info2, + unsigned char **stream, + uint32_t *stream_size); +#endif +TPM_RESULT TPM_QuoteInfo2_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_QUOTE_INFO2 *tpm_quote_info2); +void TPM_QuoteInfo2_Delete(TPM_QUOTE_INFO2 *tpm_quote_info2); + + +/* + Common command processing +*/ + +TPM_RESULT TPM_ExtendCommon(TPM_PCRVALUE outDigest, + tpm_state_t *tpm_state, + TPM_COMMAND_CODE ordinal, + TPM_PCRINDEX pcrNum, + TPM_DIGEST inDigest); +/* + Command Processing +*/ + +TPM_RESULT TPM_Process_PcrRead(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_Quote(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_Quote2(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_Extend(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_PcrReset(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +#endif diff --git a/src/tpm12/tpm_permanent.c b/src/tpm12/tpm_permanent.c new file mode 100644 index 0000000..b9a6209 --- /dev/null +++ b/src/tpm12/tpm_permanent.c @@ -0,0 +1,1333 @@ +/********************************************************************************/ +/* */ +/* Permanent Flag and Data Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_permanent.c 4623 2011-09-28 15:15:09Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_audit.h" +#include "tpm_counter.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_delegate.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_global.h" +#include "tpm_key.h" +#include "tpm_nonce.h" +#include "tpm_nvfile.h" +#include "tpm_nvfilename.h" +#include "tpm_nvram.h" +#include "tpm_pcr.h" +#include "tpm_secret.h" +#include "tpm_storage.h" +#include "tpm_structures.h" +#include "tpm_types.h" +#include "tpm_svnrevision.h" + + +#include "tpm_permanent.h" + +/* + TPM_PERMANENT_FLAGS +*/ + +void TPM_PermanentFlags_Init(TPM_PERMANENT_FLAGS *tpm_permanent_flags) +{ + printf(" TPM_PermanentFlags_Init:\n"); +#ifndef TPM_ENABLE_ACTIVATE + tpm_permanent_flags->disable = TRUE; +#else /* for servers, not TCG standard */ + tpm_permanent_flags->disable = FALSE; +#endif + tpm_permanent_flags->ownership = TRUE; +#ifndef TPM_ENABLE_ACTIVATE + tpm_permanent_flags->deactivated = TRUE; +#else /* for servers, not TCG standard */ + tpm_permanent_flags->deactivated = FALSE; +#endif + tpm_permanent_flags->readPubek = TRUE; + tpm_permanent_flags->disableOwnerClear = FALSE; + tpm_permanent_flags->allowMaintenance = TRUE; + tpm_permanent_flags->physicalPresenceLifetimeLock = FALSE; + tpm_permanent_flags->physicalPresenceHWEnable = FALSE; +#ifndef TPM_PP_CMD_ENABLE /* TCG standard */ + tpm_permanent_flags->physicalPresenceCMDEnable = FALSE; +#else /* 'ship' TRUE */ + tpm_permanent_flags->physicalPresenceCMDEnable = TRUE; +#endif + /* tpm_permanent_flags->CEKPUsed = ; This flag has no default value */ + tpm_permanent_flags->TPMpost = FALSE; + tpm_permanent_flags->TPMpostLock = FALSE; + tpm_permanent_flags->FIPS = FALSE; /* if TRUE, could not test no-auth commands */ + tpm_permanent_flags->tpmOperator = FALSE; + tpm_permanent_flags->enableRevokeEK = TRUE; + tpm_permanent_flags->nvLocked = FALSE; + tpm_permanent_flags->readSRKPub = FALSE; + tpm_permanent_flags->tpmEstablished = FALSE; + tpm_permanent_flags->maintenanceDone = FALSE; +#if (TPM_REVISION >= 103) /* added for rev 103 */ + tpm_permanent_flags->disableFullDALogicInfo = FALSE; +#endif +} + +/* TPM_PermanentFlags_Load() + + deserializes the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + It is used when deserializing the structure from storage in NVRAM. +*/ + +TPM_RESULT TPM_PermanentFlags_Load(TPM_PERMANENT_FLAGS *tpm_permanent_flags, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t tpm_bitmap; + TPM_TAG permanentFlagsVersion; + + printf(" TPM_PermanentFlags_Load:\n"); + /* load the TPM_PERMANENT_FLAGS version tag from the stream */ + if (rc == 0) { + rc = TPM_Load16(&permanentFlagsVersion, stream, stream_size); + } + /* load the TPM_PERMANENT_FLAGS from the stream */ + if (rc == 0) { + rc = TPM_Load32(&tpm_bitmap, stream, stream_size); + } + /* load the TPM_PERMANENT_FLAGS from the bitmap */ + if (rc == 0) { + rc = TPM_PermanentFlags_LoadBitmap(tpm_permanent_flags, permanentFlagsVersion, tpm_bitmap); + } + return rc; +} + +/* TPM_PermanentFlags_Store() serializes the TPM_PERMANENT_FLAGS structure as a bitmap. + + It is used when serializing the structure for storage in NVRAM. +*/ + +TPM_RESULT TPM_PermanentFlags_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PERMANENT_FLAGS *tpm_permanent_flags) + +{ + TPM_RESULT rc = 0; + uint32_t tpm_bitmap; + + printf(" TPM_PermanentFlags_Store:\n"); + /* store the TPM_PERMANENT_FLAGS structure in a bit map */ + if (rc == 0) { + rc = TPM_PermanentFlags_StoreBitmap(&tpm_bitmap, tpm_permanent_flags); + } + /* append a TPM_PERMANENT_FLAGS version tag */ +#if (TPM_REVISION >= 103) + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_PF103); + } +#else + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_PF94); + } +#endif + /* append the bitmap to the stream */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_bitmap); + } + return rc; +} + +/* TPM_PermanentFlags_StoreBytes() serializes the TPM_PERMANENT_FLAGS structure as bytes + + */ + +TPM_RESULT TPM_PermanentFlags_StoreBytes(TPM_STORE_BUFFER *sbuffer, + const TPM_PERMANENT_FLAGS *tpm_permanent_flags) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PermanentFlags_StoreBytes:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_PERMANENT_FLAGS); + } + /* store disable */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->disable), sizeof(BYTE)); + } + /* store ownership */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->ownership), sizeof(BYTE)); + } + /* store deactivated */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->deactivated), sizeof(BYTE)); + } + /* store readPubek */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->readPubek), sizeof(BYTE)); + } + /* store disableOwnerClear */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->disableOwnerClear), sizeof(BYTE)); + } + /* store allowMaintenance */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->allowMaintenance), sizeof(BYTE)); + } + /* store physicalPresenceLifetimeLock */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceLifetimeLock), + sizeof(BYTE)); + } + /* store physicalPresenceHWEnable */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceHWEnable), + sizeof(BYTE)); + } + /* store physicalPresenceCMDEnable */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceCMDEnable), + sizeof(BYTE)); + } + /* store CEKPUsed */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->CEKPUsed), sizeof(BYTE)); + } + /* store TPMpost */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->TPMpost), sizeof(BYTE)); + } + /* store TPMpostLock */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->TPMpostLock), sizeof(BYTE)); + } + /* store FIPS */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->FIPS), sizeof(BYTE)); + } + /* store operator */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->tpmOperator), sizeof(BYTE)); + } + /* store enableRevokeEK */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->enableRevokeEK), sizeof(BYTE)); + } + /* store nvLocked */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->nvLocked), sizeof(BYTE)); + } + /* store readSRKPub */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->readSRKPub), sizeof(BYTE)); + } + /* store tpmEstablished */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->tpmEstablished), sizeof(BYTE)); + } + /* store maintenanceDone */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->maintenanceDone), sizeof(BYTE)); + } +#if (TPM_REVISION >= 103) /* added for rev 103 */ + /* store disableFullDALogicInfo */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + &(tpm_permanent_flags->disableFullDALogicInfo), sizeof(BYTE)); + } +#endif + return rc; +} + +/* TPM_PermanentFlags_LoadBitmap() loads the TPM_PERMANENT_FLAGS structure from the bit map + + permanentFlagsVersion indicates the version being loaded from NVRAM +*/ + +TPM_RESULT TPM_PermanentFlags_LoadBitmap(TPM_PERMANENT_FLAGS *tpm_permanent_flags, + TPM_TAG permanentFlagsVersion, + uint32_t tpm_bitmap) +{ + TPM_RESULT rc = 0; + uint32_t pos = 0; /* position in bitmap */ + + if (rc == 0) { + switch (permanentFlagsVersion) { + case TPM_TAG_NVSTATE_PF94: + break; + case TPM_TAG_NVSTATE_PF103: + /* if the TPM_REVISION supports the permanentFlagsVersion, break with no error. If it + doesn't, omit the break and fall through to the unsupported case. */ +#if (TPM_REVISION >= 103) + break; +#endif + default: + /* no forward compatibility */ + printf("TPM_PermanentFlags_LoadBitmap: Error (fatal) unsupported version tag %04x\n", + permanentFlagsVersion); + rc = TPM_FAIL; + break; + } + } + printf(" TPM_PermanentFlags_LoadBitmap:\n"); + /* load disable */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disable), tpm_bitmap, &pos); + } + /* load ownership */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->ownership), tpm_bitmap, &pos); + } + /* load deactivated */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->deactivated), tpm_bitmap, &pos); + } + /* load readPubek */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->readPubek), tpm_bitmap, &pos); + } + /* load disableOwnerClear */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disableOwnerClear), tpm_bitmap, &pos); + } + /* load allowMaintenance */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->allowMaintenance), tpm_bitmap, &pos); + } + /* load physicalPresenceLifetimeLock */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceLifetimeLock), + tpm_bitmap, &pos); + } + /* load physicalPresenceHWEnable */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceHWEnable), tpm_bitmap, &pos); + } + /* load physicalPresenceCMDEnable */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceCMDEnable), tpm_bitmap, &pos); + } + /* load CEKPUsed */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->CEKPUsed), tpm_bitmap, &pos); + } + /* load TPMpost */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->TPMpost), tpm_bitmap, &pos); + } + /* load TPMpostLock */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->TPMpostLock), tpm_bitmap, &pos); + } + /* load FIPS */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->FIPS), tpm_bitmap, &pos); + } + /* load operator */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->tpmOperator), tpm_bitmap, &pos); + } + /* load enableRevokeEK */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->enableRevokeEK), tpm_bitmap, &pos); + } + /* load nvLocked */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->nvLocked), tpm_bitmap, &pos); + } + /* load readSRKPub */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->readSRKPub), tpm_bitmap, &pos); + } + /* load tpmEstablished */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->tpmEstablished), tpm_bitmap, &pos); + } + /* load maintenanceDone */ + if (rc == 0) { + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->maintenanceDone), tpm_bitmap, &pos); + } +#if (TPM_REVISION >= 103) /* added for rev 103 */ + if (rc == 0) { + switch (permanentFlagsVersion) { + case TPM_TAG_NVSTATE_PF94: + /* 94 to 103, set extra flags to default value */ + tpm_permanent_flags->disableFullDALogicInfo = FALSE; + break; + case TPM_TAG_NVSTATE_PF103: + /* 103 to 103, process normally */ + /* load disableFullDALogicInfo */ + rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disableFullDALogicInfo), tpm_bitmap, &pos); + break; + } + } +#endif + return rc; +} + +/* TPM_PermanentFlags_StoreBitmap() stores the TPM_PERMANENT_FLAGS structure in a bit map + + It is used when serializing the structure for storage in NVRAM and as the return to + TPM_GetCapability. +*/ + +TPM_RESULT TPM_PermanentFlags_StoreBitmap(uint32_t *tpm_bitmap, + const TPM_PERMANENT_FLAGS *tpm_permanent_flags) +{ + TPM_RESULT rc = 0; + uint32_t pos = 0; /* position in bitmap */ + + printf(" TPM_PermanentFlags_StoreBitmap:\n"); + *tpm_bitmap = 0; /* set unused bits to 0 */ + /* store disable */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disable, &pos); + } + /* store ownership */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->ownership, &pos); + } + /* store deactivated */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->deactivated, &pos); + } + /* store readPubek */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->readPubek, &pos); + } + /* store disableOwnerClear */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disableOwnerClear, &pos); + } + /* store allowMaintenance */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->allowMaintenance, &pos); + } + /* store physicalPresenceLifetimeLock */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceLifetimeLock, &pos); + } + /* store physicalPresenceHWEnable */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceHWEnable, &pos); + } + /* store physicalPresenceCMDEnable */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceCMDEnable, &pos); + } + /* store CEKPUsed */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->CEKPUsed, &pos); + } + /* store TPMpost */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->TPMpost, &pos); + } + /* store TPMpostLock */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->TPMpostLock, &pos); + } + /* store FIPS */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->FIPS, &pos); + } + /* store operator */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->tpmOperator, &pos); + } + /* store enableRevokeEK */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->enableRevokeEK, &pos); + } + /* store nvLocked */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->nvLocked, &pos); + } + /* store readSRKPub */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->readSRKPub, &pos); + } + /* store tpmEstablished */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->tpmEstablished, &pos); + } + /* store maintenanceDone */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->maintenanceDone, &pos); + } +#if (TPM_REVISION >= 103) /* added for rev 103 */ + /* store disableFullDALogicInfo */ + if (rc == 0) { + rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disableFullDALogicInfo, &pos); + } +#endif + return rc; +} + +/* + TPM_PERMANENT_DATA +*/ + +/* TPM_PermanentData_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + + This function generates a new contextKey, delegateKey, daaBlobKey. +*/ + + +TPM_RESULT TPM_PermanentData_Init(TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL instanceData) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PermanentData_Init:\n"); + if (rc == 0) { + tpm_permanent_data->revMajor = ((tpm_svn_revision >> 8) & 0xff); + tpm_permanent_data->revMinor = ((tpm_svn_revision ) & 0xff); + printf(" TPM_PermanentData_Init: revMajor %02x revMinor %02x\n", + tpm_permanent_data->revMajor, tpm_permanent_data->revMinor); + /* zero all secrets */ + TPM_PermanentData_Zero(tpm_permanent_data, instanceData); + +#ifndef TPM_NOMAINTENANCE + TPM_Pubkey_Init(&(tpm_permanent_data->manuMaintPub)); +#endif + TPM_Key_Init(&(tpm_permanent_data->endorsementKey)); + TPM_Key_Init(&(tpm_permanent_data->srk)); + tpm_permanent_data->contextKey = NULL; + rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->contextKey)); + } + if (rc == 0) { + tpm_permanent_data->delegateKey = NULL; + rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->delegateKey)); + } + if (rc == 0) { + TPM_CounterValue_Init(&(tpm_permanent_data->auditMonotonicCounter)); + TPM_Counters_Init(tpm_permanent_data->monotonicCounter); + TPM_PCRAttributes_Init(tpm_permanent_data->pcrAttrib); + rc = TPM_OrdinalAuditStatus_Init(tpm_permanent_data); + } + if (rc == 0) { + TPM_FamilyTable_Init(&(tpm_permanent_data->familyTable)); + TPM_DelegateTable_Init(&(tpm_permanent_data->delegateTable)); + tpm_permanent_data->lastFamilyID = 0; + tpm_permanent_data->noOwnerNVWrite = 0; + tpm_permanent_data->restrictDelegate = 0; + /* tpmDAASeed done by TPM_PermanentData_Zero() */ + /* daaProof done by TPM_PermanentData_Zero() */ + rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->daaBlobKey)); + } + if (rc == 0) { + tpm_permanent_data->ownerInstalled = FALSE; + /* tscOrdinalAuditStatus initialized by TPM_OrdinalAuditStatus_Init() */ + /* instanceOrdinalAuditStatus initialized by TPM_OrdinalAuditStatus_Init() */ + tpm_permanent_data->allowLoadMaintPub = TRUE; + if (instanceData) { + } + } + return rc; +} + +/* TPM_PermanentData_Load() + + deserializes the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes +*/ + +TPM_RESULT TPM_PermanentData_Load(TPM_PERMANENT_DATA *tpm_permanent_data, + unsigned char **stream, + uint32_t *stream_size, + TPM_BOOL instanceData) +{ + TPM_RESULT rc = 0; + size_t i; + TPM_BOOL tpm_bool; + + + printf(" TPM_PermanentData_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_PERMANENT_DATA, stream, stream_size); + } + /* load revMajor */ + /* load revMinor */ + /* not stored, loaded from hard coded value */ + if (rc == 0) { + tpm_permanent_data->revMajor = (tpm_svn_revision >> 8) & 0xff; + tpm_permanent_data->revMinor = tpm_svn_revision & 0xff; + } + /* load tpmProof */ + if (rc == 0) { + printf(" TPM_PermanentData_Load: Loading tpmProof\n"); + rc = TPM_Secret_Load(tpm_permanent_data->tpmProof, stream, stream_size); + } + /* load EKReset */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_permanent_data->EKReset, stream, stream_size); + } + /* load ownerAuth */ + if (rc == 0) { + printf(" TPM_PermanentData_Load: Loading ownerAuth \n"); + rc = TPM_Secret_Load(tpm_permanent_data->ownerAuth, stream, stream_size); + } + /* load operatorAuth */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_permanent_data->operatorAuth, stream, stream_size); + } + /* load authDIR */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_permanent_data->authDIR, stream, stream_size); + } + /* load manuMaintPub present marker */ + if (rc == 0) { + rc = TPM_Load8(&tpm_bool, stream, stream_size); + } +#ifndef TPM_NOMAINTENANCE + /* check that manuMaintPub is present */ + if (rc == 0) { + if (!tpm_bool) { + printf(" TPM_PermanentData_Load: Error (fatal) missing manuMaintPub\n"); + rc = TPM_FAIL; + } + } + /* load manuMaintPub */ + if (rc == 0) { + printf(" TPM_PermanentData_Load: Load manuMaintPub\n"); + rc = TPM_Pubkey_Load(&(tpm_permanent_data->manuMaintPub), stream, stream_size); + } +#else + /* check that manuMaintPub is absent */ + if (tpm_bool) { + printf(" TPM_PermanentData_Load: Error (fatal) contains manuMaintPub\n"); + rc = TPM_FAIL; + } +#endif + /* load endorsementKey */ + if (rc == 0) { + printf(" TPM_PermanentData_Load: Load endorsement key\n"); + rc = TPM_Key_LoadClear(&(tpm_permanent_data->endorsementKey), TRUE, stream, stream_size); + } + /* load srk */ + if (rc == 0) { + printf(" TPM_PermanentData_Load: Load SRK\n"); + rc = TPM_Key_LoadClear(&(tpm_permanent_data->srk), FALSE, stream, stream_size); + } + /* load contextKey */ + if (rc == 0) { + printf(" TPM_PermanentData_Load: Load contextKey\n"); + rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->contextKey, stream, stream_size); + } + /* load delegateKey */ + if (rc == 0) { + printf(" TPM_PermanentData_Load: Load delegateKey\n"); + rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->delegateKey, stream, stream_size); + } + /* load auditMonotonicCounter */ + if (rc == 0) { + rc = TPM_CounterValue_Load(&(tpm_permanent_data->auditMonotonicCounter), + stream, stream_size); + } + /* load monotonicCounter's */ + if (rc == 0) { + rc = TPM_Counters_Load(tpm_permanent_data->monotonicCounter, stream, stream_size); + } + /* load pcrAttrib's, since they are constants, no need to load from NV space */ + if (rc == 0) { + TPM_PCRAttributes_Init(tpm_permanent_data->pcrAttrib); + } + if (rc == 0) { + printf(" TPM_PermanentData_Load: Load ordinalAuditStatus\n"); + } + /* load ordinalAuditStatus's */ + for (i = 0 ; (rc == 0) && (i < (TPM_ORDINALS_MAX/CHAR_BIT)) ; i++) { + rc = TPM_Load8(&(tpm_permanent_data->ordinalAuditStatus[i]), stream, stream_size); + } + /* load familyTable */ + if (rc == 0) { + rc = TPM_FamilyTable_Load(&(tpm_permanent_data->familyTable), stream, stream_size); + } + /* load delegateTable */ + if (rc == 0) { + rc = TPM_DelegateTable_Load(&(tpm_permanent_data->delegateTable), stream, stream_size); + } + /* load lastFamilyID */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_permanent_data->lastFamilyID), stream, stream_size); + } + /* load noOwnerNVWrite */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_permanent_data->noOwnerNVWrite), stream, stream_size); + } + /* load restrictDelegate */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_permanent_data->restrictDelegate), stream, stream_size); + } + /* load tpmDAASeed */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_permanent_data->tpmDAASeed, stream, stream_size); + } + /* load ownerInstalled */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_permanent_data->ownerInstalled), stream, stream_size); + } + /* load tscOrdinalAuditStatus */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_permanent_data->tscOrdinalAuditStatus), stream, stream_size); + } + /* load allowLoadMaintPub */ + if (rc == 0) { + rc = TPM_LoadBool(&(tpm_permanent_data->allowLoadMaintPub), stream, stream_size); + } + /* load daaProof */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_permanent_data->daaProof, stream, stream_size); + } + /* load daaBlobKey */ + if (rc == 0) { + printf(" TPM_PermanentData_Load: Loading DAA Blob key\n"); + rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->daaBlobKey, stream, stream_size); + } + instanceData = instanceData; /* to quiet the compiler */ + return rc; +} + +/* TPM_PermanentData_Store() serializes the TPM_PERMANENT_DATA structure + + */ + +TPM_RESULT TPM_PermanentData_Store(TPM_STORE_BUFFER *sbuffer, + TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL instanceData) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_PermanentData_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_PERMANENT_DATA); + } + /* store revMajor */ + /* store revMinor */ + /* not stored, loaded from hard coded value */ + /* store tpmProof */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->tpmProof); + } + /* store EKReset */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->EKReset); + } + /* store ownerAuth */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->ownerAuth); + } + /* store operatorAuth */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->operatorAuth); + } + /* store authDIR */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_permanent_data->authDIR); + } +#ifndef TPM_NOMAINTENANCE + /* mark that manuMaintPub is present */ + if (rc == 0) { + rc = TPM_Sbuffer_Append8(sbuffer, TRUE); + } + /* store manuMaintPub */ + if (rc == 0) { + rc = TPM_Pubkey_Store(sbuffer, &(tpm_permanent_data->manuMaintPub)); + } +#else + /* mark that manuMaintPub is absent */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, FALSE); + } +#endif + /* store endorsementKey */ + if (rc == 0) { + rc = TPM_Key_StoreClear(sbuffer, TRUE, &(tpm_permanent_data->endorsementKey)); + } + /* store srk */ + if (rc == 0) { + rc = TPM_Key_StoreClear(sbuffer, FALSE, &(tpm_permanent_data->srk)); + } + /* store contextKey */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->contextKey); + } + /* store delegateKey */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->delegateKey); + } + /* store auditMonotonicCounter */ + if (rc == 0) { + rc = TPM_CounterValue_Store(sbuffer, &(tpm_permanent_data->auditMonotonicCounter)); + } + /* store monotonicCounter */ + if (rc == 0) { + rc = TPM_Counters_Store(sbuffer, tpm_permanent_data->monotonicCounter); + } + /* store pcrAttrib, since they are constants, no need to store to NV space */ + /* store ordinalAuditStatus */ + for (i = 0 ; (rc == 0) && (i < (TPM_ORDINALS_MAX/CHAR_BIT)) ; i++) { + rc = TPM_Sbuffer_Append(sbuffer, + &(tpm_permanent_data->ordinalAuditStatus[i]), sizeof(BYTE)); + } + /* store familyTable */ + if (rc == 0) { + rc = TPM_FamilyTable_Store(sbuffer, + &(tpm_permanent_data->familyTable), + FALSE); /* don't store the tag, to save NV space */ + } + /* store delegateTable */ + if (rc == 0) { + rc = TPM_DelegateTable_Store(sbuffer, &(tpm_permanent_data->delegateTable)); + } + /* store lastFamilyID */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->lastFamilyID); + } + /* store noOwnerNVWrite */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->noOwnerNVWrite); + } + /* store restrictDelegate */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->restrictDelegate); + } + /* store tpmDAASeed */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->tpmDAASeed); + } + /* store ownerInstalled */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->ownerInstalled), sizeof(BYTE)); + } + /* store tscOrdinalAuditStatus */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->tscOrdinalAuditStatus), + sizeof(BYTE)); + } + /* store allowLoadMaintPub */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->allowLoadMaintPub), sizeof(BYTE)); + } + /* store daaProof */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->daaProof); + } + /* store daaBlobKey */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->daaBlobKey); + } + instanceData = instanceData; /* to quiet the compiler */ + return rc; +} + +/* TPM_PermanentData_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_PermanentData_Zero to zero secrets that are not Delete'd + The object itself is not freed +*/ + +void TPM_PermanentData_Delete(TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL instanceData) +{ + printf(" TPM_PermanentData_Delete:\n"); + if (tpm_permanent_data != NULL) { +#ifndef TPM_NOMAINTENANCE + TPM_Pubkey_Delete(&(tpm_permanent_data->manuMaintPub)); +#endif + TPM_Key_Delete(&(tpm_permanent_data->endorsementKey)); + TPM_Key_Delete(&(tpm_permanent_data->srk)); + TPM_SymmetricKeyData_Free(&(tpm_permanent_data->contextKey)); + TPM_SymmetricKeyData_Free(&(tpm_permanent_data->delegateKey)); + TPM_FamilyTable_Delete(&(tpm_permanent_data->familyTable)); + TPM_DelegateTable_Delete(&(tpm_permanent_data->delegateTable)); + TPM_SymmetricKeyData_Free(&(tpm_permanent_data->daaBlobKey)); + /* zero all secrets */ + TPM_PermanentData_Zero(tpm_permanent_data, instanceData); + } + return; +} + +/* TPM_PermanentData_Zero() zeros all secrets not already zeroed and freed by + TPM_PermanentData_Delete() + + It is called by TPM_PermanentData_Delete() and TPM_PermanentData_Init(). It does a subset of + TPM_PermanentData_Init() that will never fail. +*/ + +void TPM_PermanentData_Zero(TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL instanceData) +{ + printf(" TPM_PermanentData_Zero:\n"); + instanceData = instanceData; + if (tpm_permanent_data != NULL) { + TPM_Secret_Init(tpm_permanent_data->tpmProof); + TPM_Nonce_Init(tpm_permanent_data->EKReset); + TPM_Secret_Init(tpm_permanent_data->ownerAuth); + TPM_Secret_Init(tpm_permanent_data->operatorAuth); + TPM_Digest_Init(tpm_permanent_data->authDIR); + /* endorsementKey handled by TPM_Key_Delete() */ + /* srk handled by TPM_Key_Delete() */ + /* contextKey handled by TPM_SymmetricKeyData_Free() */ + /* delegateKey handled by TPM_SymmetricKeyData_Free() */ + TPM_Nonce_Init(tpm_permanent_data->tpmDAASeed); + TPM_Nonce_Init(tpm_permanent_data->daaProof); + /* daaBlobKey handled by TPM_SymmetricKeyData_Free() */ + } + return; +} + +/* TPM_PermanentData_InitDaa() generates new values for the 3 DAA elements: tpmDAASeed, daaProof, + and daaBlobKey. + + This is common code, use when creating the EK, revoke trust, and the set capability + used by the owner to invalidate DAA blobs. +*/ + +TPM_RESULT TPM_PermanentData_InitDaa(TPM_PERMANENT_DATA *tpm_permanent_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PermanentData_InitDaa:\n"); + /* generate tpmDAASeed */ + if (rc == 0) { + rc = TPM_Nonce_Generate(tpm_permanent_data->tpmDAASeed); + } + /* generate daaProof*/ + if (rc == 0) { + rc = TPM_Nonce_Generate(tpm_permanent_data->daaProof); + } + /* generate daaBlobKey */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_GenerateKey(tpm_permanent_data->daaBlobKey); + } + return rc; +} + +/* + PermanentAll is TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys, and NV defined space. +*/ + +/* TPM_PermanentAll_Load() deserializes all TPM NV data from a stream created by + TPM_PermanentAll_Store(). + + The two functions must be kept in sync. + + Data includes TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, Owner Evict keys, and NV defined space. +*/ + +TPM_RESULT TPM_PermanentAll_Load(tpm_state_t *tpm_state, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + unsigned char *stream_start = *stream; /* copy for integrity check */ + uint32_t stream_size_start = *stream_size; + + printf(" TPM_PermanentAll_Load:\n"); + /* check format tag */ + /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' + on the tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_NVSTATE_V1, stream, stream_size); + } + /* TPM_PERMANENT_DATA deserialize from stream */ + if (rc == 0) { + rc = TPM_PermanentData_Load(&(tpm_state->tpm_permanent_data), + stream, stream_size, TRUE); + } + /* TPM_PERMANENT_FLAGS deserialize from stream */ + if (rc == 0) { + rc = TPM_PermanentFlags_Load(&(tpm_state->tpm_permanent_flags), + stream, stream_size); + } + /* owner evict keys deserialize from stream */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_OwnerEvictLoad(tpm_state->tpm_key_handle_entries, + stream, stream_size); + } + /* NV defined space deserialize from stream */ + if (rc == 0) { + rc = TPM_NVIndexEntries_Load(&(tpm_state->tpm_nv_index_entries), + stream, stream_size); + } + /* sanity check the stream size */ + if (rc == 0) { + if (*stream_size != TPM_DIGEST_SIZE) { + printf("TPM_PermanentAll_Load: Error (fatal) stream size %u not %u\n", + *stream_size, TPM_DIGEST_SIZE); + rc = TPM_FAIL; + } + } + /* check the integrity digest */ + if (rc == 0) { + printf(" TPM_PermanentAll_Load: Checking integrity digest\n"); + rc = TPM_SHA1_Check(*stream, /* currently points to integrity digest */ + stream_size_start - TPM_DIGEST_SIZE, stream_start, + 0, NULL); + } + /* remove the integrity digest from the stream */ + if (rc == 0) { + *stream_size -= TPM_DIGEST_SIZE; + } + return rc; +} + +/* TPM_PermanentAll_Store() serializes all TPM NV data into a stream that can be restored through + TPM_PermanentAll_Load(). + + The two functions must be kept in sync. + + Data includes TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, Owner Evict keys, and NV defined space. + + The TPM_STORE_BUFFER, buffer and length are returned for convenience. + + This has two uses: + + - It is called before the actual NV store to serialize the data + - It is called by TPM_NV_DefineSpace to determine if there is enough NV space for the new index +*/ + +TPM_RESULT TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer, /* freed by caller */ + const unsigned char **buffer, + uint32_t *length, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_DIGEST tpm_digest; + + printf(" TPM_PermanentAll_Store:\n"); + /* overall format tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_V1); + } + /* serialize TPM_PERMANENT_DATA */ + if (rc == 0) { + rc = TPM_PermanentData_Store(sbuffer, + &(tpm_state->tpm_permanent_data), TRUE); + } + /* serialize TPM_PERMANENT_FLAGS */ + if (rc == 0) { + rc = TPM_PermanentFlags_Store(sbuffer, + &(tpm_state->tpm_permanent_flags)); + } + /* serialize owner evict keys */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_OwnerEvictStore(sbuffer, + tpm_state->tpm_key_handle_entries); + } + /* serialize NV defined space */ + if (rc == 0) { + rc = TPM_NVIndexEntries_Store(sbuffer, + &(tpm_state->tpm_nv_index_entries)); + } + if (rc == 0) { + /* get the current serialized buffer and its length */ + TPM_Sbuffer_Get(sbuffer, buffer, length); + /* generate the integrity digest */ + rc = TPM_SHA1(tpm_digest, + *length, *buffer, + 0, NULL); + } + /* append the integrity digest to the stream */ + if (rc == 0) { + printf(" TPM_PermanentAll_Store: Appending integrity digest\n"); + rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE); + } + /* get the final serialized buffer and its length */ + if (rc == 0) { + TPM_Sbuffer_Get(sbuffer, buffer, length); + } + return rc; +} + +/* TPM_PermanentAll_NVLoad() + + Deserialize the TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys, and NV defined + space from a stream read from the NV file TPM_PERMANENT_ALL_NAME. + + Returns: + + 0 success + TPM_RETRY if file does not exist (first time) + TPM_FAIL on failure to load (fatal), since they should never occur +*/ + +TPM_RESULT TPM_PermanentAll_NVLoad(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + unsigned char *stream = NULL; + unsigned char *stream_start = NULL; + uint32_t stream_size; + + printf(" TPM_PermanentAll_NVLoad:\n"); + if (rc == 0) { + /* try loading from NVRAM */ + /* Returns TPM_RETRY on non-existent file */ + rc = TPM_NVRAM_LoadData(&stream, /* freed @1 */ + &stream_size, + tpm_state->tpm_number, + TPM_PERMANENT_ALL_NAME); + } + /* deserialize from stream */ + if (rc == 0) { + stream_start = stream; /* save starting point for free() */ + rc = TPM_PermanentAll_Load(tpm_state, &stream, &stream_size); + if (rc != 0) { + printf("TPM_PermanentAll_NVLoad: Error (fatal) loading deserializing NV state\n"); + rc = TPM_FAIL; + } + } + free(stream_start); /* @1 */ + return rc; +} + +/* TPM_PermanentAll_NVStore() serializes all NV data and stores it in the NV file + TPM_PERMANENT_ALL_NAME + + If the writeAllNV flag is FALSE, the function is a no-op, and returns the input 'rcIn'. + + If writeAllNV is TRUE and rcIn is not TPM_SUCCESS, this indicates that the ordinal + modified the in-memory TPM_PERMANENT_DATA and/or TPM_PERMANENT_FLAGS structures (perhaps only + partially) and then detected an error. Since the command is failing, roll back the structure by + reading the NV file. If the read then fails, this is a fatal error. + + Similarly, if writeAllNV is TRUE and the actual NV write fails, this is a fatal error. +*/ + +TPM_RESULT TPM_PermanentAll_NVStore(tpm_state_t *tpm_state, + TPM_BOOL writeAllNV, + TPM_RESULT rcIn) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ + const unsigned char *buffer; + uint32_t length; + TPM_NV_DATA_ST *tpm_nv_data_st = NULL; /* array of saved NV index volatile flags */ + + printf(" TPM_PermanentAll_NVStore: write flag %u\n", writeAllNV); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + if (writeAllNV) { + if (rcIn == TPM_SUCCESS) { + /* serialize state to be written to NV */ + if (rc == 0) { + rc = TPM_PermanentAll_Store(&sbuffer, + &buffer, &length, + tpm_state); + } + /* validate the length of the stream against the maximum provided NV space */ + if (rc == 0) { + printf(" TPM_PermanentAll_NVStore: Require %u bytes\n", length); + if (length > TPM_MAX_NV_SPACE) { + printf("TPM_PermanentAll_NVStore: Error, No space, need %u max %u\n", + length, TPM_MAX_NV_SPACE); + rc = TPM_NOSPACE; + } + } + /* store the buffer in NVRAM */ + if (rc == 0) { + rc = TPM_NVRAM_StoreData(buffer, + length, + tpm_state->tpm_number, + TPM_PERMANENT_ALL_NAME); + } + if (rc != 0) { + printf("TPM_PermanentAll_NVStore: Error (fatal), " + "NV structure in-memory caches are in invalid state\n"); + rc = TPM_FAIL; + } + } + else { + /* An in-memory structure was altered, but the ordinal had a subsequent error. Since + the structure is in an invalid state, roll back to the previous value by reading the + NV file. */ + printf(" TPM_PermanentAll_NVStore: Ordinal error, " + "rolling back NV structure cache\n"); + /* Save a copy of the NV defined space volatile state. It is not stored in NV, so it + will be destroyed during the rollback. */ + /* get a copy of the NV volatile flags, to be used during a rollback */ + if (rc == 0) { + rc = TPM_NVIndexEntries_GetVolatile(&tpm_nv_data_st, /* freed @2 */ + &(tpm_state->tpm_nv_index_entries)); + } + /* Returns TPM_RETRY on non-existent file */ + if (rc == 0) { + printf(" TPM_PermanentAllNVStore: Deleting TPM_PERMANENT_DATA structure\n"); + TPM_PermanentData_Delete(&(tpm_state->tpm_permanent_data), TRUE); + printf(" TPM_PermanentAllNVStore: Deleting owner evict keys\n"); + TPM_KeyHandleEntries_OwnerEvictDelete(tpm_state->tpm_key_handle_entries); + printf(" TPM_PermanentAllNVStore: Deleting NV defined space \n"); + TPM_NVIndexEntries_Delete(&(tpm_state->tpm_nv_index_entries)); + printf(" TPM_PermanentAllNVStore: " + "Rereading TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys\n"); + /* re-allocate TPM_PERMANENT_DATA data structures */ + rc = TPM_PermanentData_Init(&(tpm_state->tpm_permanent_data), TRUE); + } + if (rc == 0) { + rc = TPM_PermanentAll_NVLoad(tpm_state); + } + if (rc == 0) { + rc = TPM_NVIndexEntries_SetVolatile(tpm_nv_data_st, + &(tpm_state->tpm_nv_index_entries)); + } + /* after a successful rollback, return the ordinal's original error code */ + if (rc == 0) { + rc = rcIn; + } + /* a failure during rollback is fatal */ + else { + printf("TPM_PermanentAll_NVStore: Error (fatal), " + "Permanent Data, Flags, or owner evict keys structure is invalid\n"); + rc = TPM_FAIL; + } + + } + } + /* no write required, no-op */ + else { + rc = rcIn; + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + free(tpm_nv_data_st); /* @2 */ + return rc; +} + +/* TPM_PermanentAll_NVDelete() deletes ann NV data in the NV file TPM_PERMANENT_ALL_NAME. + + If mustExist is TRUE, returns an error if the file does not exist. + + It does not delete the in-memory copy. +*/ + +TPM_RESULT TPM_PermanentAll_NVDelete(uint32_t tpm_number, + TPM_BOOL mustExist) +{ + TPM_RESULT rc = 0; + + printf(" TPM_PermanentAll_NVDelete:\n"); + /* remove the NVRAM file */ + if (rc == 0) { + rc = TPM_NVRAM_DeleteName(tpm_number, + TPM_PERMANENT_ALL_NAME, + mustExist); + } + return rc; +} + +/* TPM_PermanentAll_IsSpace() determines if there is enough NV space for the serialized NV state. + + It does this by serializing the entire state and comparing the length to the configured maximum. +*/ + +TPM_RESULT TPM_PermanentAll_IsSpace(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ + const unsigned char *buffer; + uint32_t length; + + printf("TPM_PermanentAll_IsSpace :\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + if (rc == 0) { + rc = TPM_PermanentAll_Store(&sbuffer, + &buffer, &length, + tpm_state); + } + if (rc == 0) { + printf(" TPM_PermanentAll_IsSpace: Require %u bytes\n", length); + if (length > TPM_MAX_NV_SPACE) { + printf("TPM_PermanentAll_IsSpace: No space, need %u max %u\n", + length, TPM_MAX_NV_SPACE); + rc = TPM_NOSPACE; + } + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_PermanentAll_GetSpace() returns the NV free space. + + It does this by serializing the entire state and comparing the length to the configured maximum. +*/ + +TPM_RESULT TPM_PermanentAll_GetSpace(uint32_t *bytes_free, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ + const unsigned char *buffer; + uint32_t length; + + printf(" TPM_NVRAM_IsSpace:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + if (rc == 0) { + rc = TPM_PermanentAll_Store(&sbuffer, + &buffer, &length, + tpm_state); + } + if (rc == 0) { + printf(" TPM_PermanentAll_GetSpace: Used %u max %u bytes\n", length, TPM_MAX_NV_SPACE); + if (length > TPM_MAX_NV_SPACE) { + /* This should never occur */ + printf("TPM_PermanentAll_GetSpace: Error (fatal) Used more than maximum\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + *bytes_free = TPM_MAX_NV_SPACE - length; + printf(" TPM_PermanentAll_GetSpace: Free space %u\n", *bytes_free); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + diff --git a/src/tpm12/tpm_permanent.h b/src/tpm12/tpm_permanent.h new file mode 100644 index 0000000..2d95acb --- /dev/null +++ b/src/tpm12/tpm_permanent.h @@ -0,0 +1,108 @@ +/********************************************************************************/ +/* */ +/* Permanent Flag and Data Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_permanent.h 4623 2011-09-28 15:15:09Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_PERMANENT_H +#define TPM_PERMANENT_H + +#include "tpm_global.h" +#include "tpm_structures.h" + + +/* + TPM_PERMANENT_FLAGS +*/ + +void TPM_PermanentFlags_Init(TPM_PERMANENT_FLAGS *tpm_permanent_flags); +TPM_RESULT TPM_PermanentFlags_Load(TPM_PERMANENT_FLAGS *tpm_permanent_flags, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_PermanentFlags_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_PERMANENT_FLAGS *tpm_permanent_flags); +TPM_RESULT TPM_PermanentFlags_LoadBitmap(TPM_PERMANENT_FLAGS *tpm_permanent_flags, + TPM_TAG permanentFlagsVersion, + uint32_t tpm_bitmap); +TPM_RESULT TPM_PermanentFlags_StoreBitmap(uint32_t *tpm_bitmap, + const TPM_PERMANENT_FLAGS *tpm_permanent_flags); +TPM_RESULT TPM_PermanentFlags_StoreBytes(TPM_STORE_BUFFER *sbuffer, + const TPM_PERMANENT_FLAGS *tpm_permanent_flags); + +/* + TPM_PERMANENT_DATA +*/ + +TPM_RESULT TPM_PermanentData_Init(TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL instanceData); +TPM_RESULT TPM_PermanentData_Load(TPM_PERMANENT_DATA *tpm_permanent_data, + unsigned char **stream, + uint32_t *stream_size, + TPM_BOOL instanceData); +TPM_RESULT TPM_PermanentData_Store(TPM_STORE_BUFFER *sbuffer, + TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL instanceData); +void TPM_PermanentData_Delete(TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL instanceData); +void TPM_PermanentData_Zero(TPM_PERMANENT_DATA *tpm_permanent_data, + TPM_BOOL instanceData); + +TPM_RESULT TPM_PermanentData_InitDaa(TPM_PERMANENT_DATA *tpm_permanent_data); + +/* + PermanentAll is TPM_PERMANENT_DATA plus TPM_PERMANENT_FLAGS +*/ + +TPM_RESULT TPM_PermanentAll_Load(tpm_state_t *tpm_state, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer, + const unsigned char **buffer, + uint32_t *length, + tpm_state_t *tpm_state); + +TPM_RESULT TPM_PermanentAll_NVLoad(tpm_state_t *tpm_state); +TPM_RESULT TPM_PermanentAll_NVStore(tpm_state_t *tpm_state, + TPM_BOOL writeAllNV, + TPM_RESULT rcIn); +TPM_RESULT TPM_PermanentAll_NVDelete(uint32_t tpm_number, + TPM_BOOL mustExist); + +TPM_RESULT TPM_PermanentAll_IsSpace(tpm_state_t *tpm_state); +TPM_RESULT TPM_PermanentAll_GetSpace(uint32_t *bytes_free, + tpm_state_t *tpm_state); + +#endif diff --git a/src/tpm12/tpm_platform.c b/src/tpm12/tpm_platform.c new file mode 100644 index 0000000..16da5db --- /dev/null +++ b/src/tpm12/tpm_platform.c @@ -0,0 +1,175 @@ +/********************************************************************************/ +/* */ +/* TPM Platform I/O */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_platform.c 4621 2011-09-09 20:19:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_debug.h" +#include "tpm_pcr.h" +#include "tpm_platform.h" + +#ifdef TPM_LIBTPMS_CALLBACKS +#include "tpm_library_intern.h" +#endif + +#ifndef TPM_IO_LOCALITY + +/* TPM_IO_GetLocality() is platform specific code to set the localityModifier before an ordinal is + processed. + + Place holder, to be modified for the platform. +*/ + +TPM_RESULT TPM_IO_GetLocality(TPM_MODIFIER_INDICATOR *localityModifier, + uint32_t tpm_number) +{ + TPM_RESULT rc = 0; + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + /* call user-provided function if available, otherwise execute + default behavior */ + if (cbs->tpm_io_getlocality) { + rc = cbs->tpm_io_getlocality(localityModifier, tpm_number); + return rc; + } +#else + tpm_number = tpm_number; /* to silence the compiler */ +#endif + + if (rc == 0) { + *localityModifier = 0; + printf(" TPM_IO_GetLocality: localityModifier %u\n", *localityModifier); + rc = TPM_LocalityModifier_CheckLegal(*localityModifier); + } + return rc; +} + +#endif /* TPM_IO_LOCALITY */ + +#ifndef TPM_IO_PHYSICAL_PRESENCE + +/* TPM_IO_GetPhysicalPresence() is platform specific code to get the hardware physicalPresence + state. + + Place holder, to be modified for the platform. +*/ + +TPM_RESULT TPM_IO_GetPhysicalPresence(TPM_BOOL *physicalPresence, + uint32_t tpm_number) +{ + TPM_RESULT rc = 0; + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + /* call user-provided function if available, otherwise execute + default behavior */ + if (cbs->tpm_io_getphysicalpresence) { + rc = cbs->tpm_io_getphysicalpresence(physicalPresence, tpm_number); + return rc; + } +#else + tpm_number = tpm_number; /* to silence the compiler */ +#endif + *physicalPresence = FALSE; + return rc; +} + +#endif /* TPM_IO_PHYSICAL_PRESENCE */ + +#ifndef TPM_IO_GPIO + +/* TPM_IO_GPIO_Write() should write 'dataSize' bytes of 'data' to 'nvIndex' at the GPIO port. + + Place holder, to be modified for the platform. +*/ + +TPM_RESULT TPM_IO_GPIO_Write(TPM_NV_INDEX nvIndex, + uint32_t dataSize, + BYTE *data, + uint32_t tpm_number) +{ + TPM_RESULT rc = 0; + tpm_number = tpm_number; /* to silence the compiler */ + +#if defined TPM_PCCLIENT /* These values are from the PC Client specification */ + printf(" TPM_IO_GPIO_Write: nvIndex %08x\n", nvIndex); + TPM_PrintAll(" TPM_IO_GPIO_Write: Stub", data, dataSize); + /* #elif Add other platform specific values here */ +#else /* This is the default case for the main specification */ + nvIndex = nvIndex; /* unused parameter, to quiet the compiler */ + dataSize = dataSize; + data = data; + printf("TPM_IO_GPIO_Write: Error (fatal), platform does not support GPIO\n"); + rc = TPM_FAIL; /* Should never get here. The invalid address be detected earlier */ +#endif + return rc; +} + +/* TPM_IO_GPIO_Read() + + Place holder, to be modified for the platform. +*/ + +TPM_RESULT TPM_IO_GPIO_Read(TPM_NV_INDEX nvIndex, + uint32_t dataSize, + BYTE *data, + uint32_t tpm_number) +{ + TPM_RESULT rc = 0; + tpm_number = tpm_number; /* to silence the compiler */ + +#if defined TPM_PCCLIENT /* These values are from the PC Client specification */ + printf(" TPM_IO_GPIO_Read: nvIndex %08x\n", nvIndex); + memset(data, 0, dataSize); + /* #elif Add other platform specific values here */ +#else /* This is the default case for the main specification */ + nvIndex = nvIndex;; /* unused parameter, to quiet the compiler */ + dataSize = dataSize;; + data = data; + printf("TPM_IO_GPIO_Read: Error (fatal), platform does not support GPIO\n"); + rc = TPM_FAIL; /* Should never get here. The invalid address be detected earlier */ +#endif + return rc; +} + +#endif /* TPM_IO_GPIO */ + diff --git a/src/tpm12/tpm_platform.h b/src/tpm12/tpm_platform.h new file mode 100644 index 0000000..94036e0 --- /dev/null +++ b/src/tpm12/tpm_platform.h @@ -0,0 +1,64 @@ +/********************************************************************************/ +/* */ +/* TPM Platform I/O */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_platform.h 4621 2011-09-09 20:19:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* Interface independent platform I/O Functions */ + +#ifndef TPM_PLATFORM_H +#define TPM_PLATFORM_H + +#include "tpm_types.h" + +/* Every platform will need this function, as TPM_MainInit() calls it. */ + +TPM_RESULT TPM_IO_Init(void); + +TPM_RESULT TPM_IO_GetLocality(TPM_MODIFIER_INDICATOR *localityModifier, + uint32_t tpm_number); +TPM_RESULT TPM_IO_GetPhysicalPresence(TPM_BOOL *physicalPresence, + uint32_t tpm_number); +TPM_RESULT TPM_IO_GPIO_Write(TPM_NV_INDEX nvIndex, + uint32_t dataSize, + BYTE *data, + uint32_t tpm_number); +TPM_RESULT TPM_IO_GPIO_Read(TPM_NV_INDEX nvIndex, + uint32_t dataSize, + BYTE *data, + uint32_t tpm_number); + +#endif diff --git a/src/tpm12/tpm_process.c b/src/tpm12/tpm_process.c new file mode 100644 index 0000000..02c2f49 --- /dev/null +++ b/src/tpm12/tpm_process.c @@ -0,0 +1,6051 @@ +/********************************************************************************/ +/* */ +/* TPM Command Processor */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_process.c 4621 2011-09-09 20:19:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#ifdef TPM_POSIX +#include +#include +#endif + +#include "tpm_admin.h" +#include "tpm_audit.h" +#include "tpm_auth.h" +#include "tpm_constants.h" +#include "tpm_commands.h" +#include "tpm_counter.h" +#include "tpm_cryptoh.h" +#include "tpm_crypto.h" +#include "tpm_daa.h" +#include "tpm_debug.h" +#include "tpm_delegate.h" +#include "tpm_error.h" +#include "tpm_identity.h" +#include "tpm_init.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_maint.h" +#include "tpm_memory.h" +#include "tpm_migration.h" +#include "tpm_nonce.h" +#include "tpm_nvram.h" +#include "tpm_owner.h" +#include "tpm_pcr.h" +#include "tpm_permanent.h" +#include "tpm_platform.h" +#include "tpm_session.h" +#include "tpm_sizedbuffer.h" +#include "tpm_startup.h" +#include "tpm_storage.h" +#include "tpm_ticks.h" +#include "tpm_transport.h" +#include "tpm_ver.h" + +#include "tpm_process.h" + +/* local prototypes */ + +/* get capabilities */ + +static TPM_RESULT TPM_GetCapability_CapOrd(TPM_STORE_BUFFER *capabilityResponse, + uint32_t ordinal); +static TPM_RESULT TPM_GetCapability_CapAlg(TPM_STORE_BUFFER *capabilityResponse, + uint32_t algorithmID); +static TPM_RESULT TPM_GetCapability_CapPid(TPM_STORE_BUFFER *capabilityResponse, + uint16_t protocolID); +static TPM_RESULT TPM_GetCapability_CapFlag(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + uint32_t capFlag); +static TPM_RESULT TPM_GetCapability_CapProperty(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + uint32_t capProperty); +static TPM_RESULT TPM_GetCapability_CapVersion(TPM_STORE_BUFFER *capabilityResponse); +static TPM_RESULT TPM_GetCapability_CapCheckLoaded(TPM_STORE_BUFFER *capabilityResponse, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry, + TPM_SIZED_BUFFER *subCap); +static TPM_RESULT TPM_GetCapability_CapSymMode(TPM_STORE_BUFFER *capabilityResponse, + TPM_SYM_MODE symMode); +static TPM_RESULT TPM_GetCapability_CapKeyStatus(TPM_STORE_BUFFER *capabilityResponse, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + uint32_t tpm_key_handle); +static TPM_RESULT TPM_GetCapability_CapMfr(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + TPM_SIZED_BUFFER *subCap); +static TPM_RESULT TPM_GetCapability_CapNVIndex(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + uint32_t nvIndex); +static TPM_RESULT TPM_GetCapability_CapTransAlg(TPM_STORE_BUFFER *capabilityResponse, + TPM_ALGORITHM_ID algorithmID); +static TPM_RESULT TPM_GetCapability_CapHandle(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + TPM_RESOURCE_TYPE resourceType); +static TPM_RESULT TPM_GetCapability_CapTransEs(TPM_STORE_BUFFER *capabilityResponse, + TPM_ENC_SCHEME encScheme); +static TPM_RESULT TPM_GetCapability_CapAuthEncrypt(TPM_STORE_BUFFER *capabilityResponse, + uint32_t algorithmID); +static TPM_RESULT TPM_GetCapability_CapSelectSize(TPM_STORE_BUFFER *capabilityResponse, + TPM_SIZED_BUFFER *subCap); +#if (TPM_REVISION >= 103) /* added for rev 103 */ +static TPM_RESULT TPM_GetCapability_CapDaLogic(TPM_STORE_BUFFER *capabilityResponse, + TPM_SIZED_BUFFER *subCap, + tpm_state_t *tpm_state); +#endif +static TPM_RESULT TPM_GetCapability_CapVersionVal(TPM_STORE_BUFFER *capabilityResponse, + TPM_PERMANENT_DATA *tpm_permanent_data); + +static TPM_RESULT TPM_GetCapability_CapPropTisTimeout(TPM_STORE_BUFFER *capabilityResponse); +static TPM_RESULT TPM_GetCapability_CapPropDuration(TPM_STORE_BUFFER *capabilityResponse); + +/* set capabilities */ + +static TPM_RESULT TPM_SetCapability_CapPermFlags(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_BOOL valueBool); +static TPM_RESULT TPM_SetCapability_CapPermData(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + uint32_t valueUint32); +static TPM_RESULT TPM_SetCapability_CapStclearFlags(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_BOOL valueBool); +static TPM_RESULT TPM_SetCapability_CapStclearData(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + uint32_t valueUint32); +static TPM_RESULT TPM_SetCapability_CapStanyFlags(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_BOOL valueBool); +static TPM_RESULT TPM_SetCapability_CapStanyData(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_SIZED_BUFFER *setValue); +static TPM_RESULT TPM_SetCapability_CapVendor(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_SIZED_BUFFER *setValue); + +/* + TPM_CAP_VERSION_INFO +*/ + +/* TPM_CapVersionInfo_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_CapVersionInfo_Init(TPM_CAP_VERSION_INFO *tpm_cap_version_info) +{ + printf(" TPM_CapVersionInfo_Init:\n"); + TPM_Version_Init(&(tpm_cap_version_info->version)); + tpm_cap_version_info->specLevel = TPM_SPEC_LEVEL; + tpm_cap_version_info->errataRev = TPM_ERRATA_REV; + memcpy(&(tpm_cap_version_info->tpmVendorID), TPM_VENDOR_ID, + sizeof(tpm_cap_version_info->tpmVendorID)); + tpm_cap_version_info->vendorSpecificSize = 0; + tpm_cap_version_info->vendorSpecific = NULL; + return; +} + +/* TPM_CapVersionInfo_Set() sets members to software specific data */ + +void TPM_CapVersionInfo_Set(TPM_CAP_VERSION_INFO *tpm_cap_version_info, + TPM_PERMANENT_DATA *tpm_permanent_data) +{ + printf(" TPM_CapVersionInfo_Set:\n"); + TPM_Version_Set(&(tpm_cap_version_info->version), tpm_permanent_data); + tpm_cap_version_info->specLevel = TPM_SPEC_LEVEL; + tpm_cap_version_info->errataRev = TPM_ERRATA_REV; + memcpy(&(tpm_cap_version_info->tpmVendorID), TPM_VENDOR_ID, + sizeof(tpm_cap_version_info->tpmVendorID)); + tpm_cap_version_info->vendorSpecificSize = 0; + tpm_cap_version_info->vendorSpecific = NULL; + return; +} + +#if 0 /* not required */ +/* TPM_CapVersionInfo_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_CapVersionInfo_Init() or TPM_CapVersionInfo_Set() + After use, call TPM_CapVersionInfo_Delete() to free memory +*/ + +TPM_RESULT TPM_CapVersionInfo_Load(TPM_CAP_VERSION_INFO *tpm_cap_version_info, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CapVersionInfo_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_CAP_VERSION_INFO, stream, stream_size); + } + /* load version */ + if (rc == 0) { + rc = TPM_Version_Load(&(tpm_cap_version_info->version), stream, stream_size); + } + /* load specLevel */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_cap_version_info->specLevel), stream, stream_size); + } + /* load errataRev */ + if (rc == 0) { + rc = TPM_Loadn(&(tpm_cap_version_info->errataRev), sizeof(tpm_cap_version_info->errataRev), + stream, stream_size); + } + /* load tpmVendorID */ + if (rc == 0) { + rc = TPM_Loadn(tpm_cap_version_info->tpmVendorID, sizeof(tpm_cap_version_info->tpmVendorID), + stream, stream_size); + } + /* load vendorSpecificSize */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_cap_version_info->vendorSpecificSize), stream, stream_size); + } + /* allocate memory for vendorSpecific */ + if ((rc == 0) && (tpm_cap_version_info->vendorSpecificSize > 0)) { + rc = TPM_Malloc(&(tpm_cap_version_info->vendorSpecific), + tpm_cap_version_info->vendorSpecificSize); + } + /* load vendorSpecific */ + if ((rc == 0) && (tpm_cap_version_info->vendorSpecificSize > 0)) { + rc = TPM_Loadn(tpm_cap_version_info->vendorSpecific, + tpm_cap_version_info->vendorSpecificSize, + stream, stream_size); + } + return rc; +} +#endif + +/* TPM_CapVersionInfo_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CapVersionInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CAP_VERSION_INFO *tpm_cap_version_info) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CapVersionInfo_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CAP_VERSION_INFO); + } + /* store version */ + if (rc == 0) { + rc = TPM_Version_Store(sbuffer, &(tpm_cap_version_info->version)); + } + /* store specLevel */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_cap_version_info->specLevel); + } + /* store errataRev */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_cap_version_info->errataRev), + sizeof(tpm_cap_version_info->errataRev)); + } + /* store tpmVendorID */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_cap_version_info->tpmVendorID, + sizeof(tpm_cap_version_info->tpmVendorID)); + } + /* store vendorSpecificSize */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_cap_version_info->vendorSpecificSize); + } + /* store vendorSpecific */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, + tpm_cap_version_info->vendorSpecific, + tpm_cap_version_info->vendorSpecificSize); + } + return rc; +} + +/* TPM_CapVersionInfo_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_CapVersionInfo_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_CapVersionInfo_Delete(TPM_CAP_VERSION_INFO *tpm_cap_version_info) +{ + printf(" TPM_CapVersionInfo_Delete:\n"); + if (tpm_cap_version_info != NULL) { + free(tpm_cap_version_info->vendorSpecific); + TPM_CapVersionInfo_Init(tpm_cap_version_info); + } + return; +} + +/* + Processing Commands +*/ + + +/* 17. Ordinals rev 107 + + This structure maps the specification Ordinals table to software functions and parameters. + + It provides direct mapping that easier to understand and maintain than scattering and hard coding + these values. + + The functions currently supported are: + + - processing jump table for 1.1 and 1.2 (implied get capability - ordinals supported) + - allow audit + - audit default value + - owner delegation permissions + - key delegation permissions + - wrappable + + Future possibilities include: + + - no owner, disabled, deactivated + - 0,1,2 auth + + typedef struct tdTPM_ORDINAL_TABLE { + + TPM_COMMAND_CODE ordinal; + tpm_process_function_t process_function_v11; + tpm_process_function_t process_function_v12; + TPM_BOOL auditable; + TPM_BOOL auditDefault; + uint16_t ownerPermissionBlock; + uint32_t ownerPermissionPosition; + uint16_t keyPermissionBlock; + uint32_t keyPermissionPosition; + uint32_t inputHandleSize; + uint32_t keyHandles; + uint32_t outputHandleSize; + TPM_BOOL transportWrappable; + TPM_BOOL instanceWrappable; + TPM_BOOL hardwareWrappable; + } TPM_ORDINAL_TABLE; +*/ + +static TPM_ORDINAL_TABLE tpm_ordinal_table[] = +{ + {TPM_ORD_ActivateIdentity, + TPM_Process_ActivateIdentity, TPM_Process_ActivateIdentity, + TRUE, + TRUE, + 1, TPM_DELEGATE_ActivateIdentity, + 1, TPM_KEY_DELEGATE_ActivateIdentity, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_AuthorizeMigrationKey, + TPM_Process_AuthorizeMigrationKey, TPM_Process_AuthorizeMigrationKey, + TRUE, + TRUE, + 1, TPM_DELEGATE_AuthorizeMigrationKey, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CertifyKey, + TPM_Process_CertifyKey, TPM_Process_CertifyKey, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_CertifyKey, + sizeof(TPM_KEY_HANDLE) + sizeof(TPM_KEY_HANDLE), + 2, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CertifyKey2, + TPM_Process_Unused, TPM_Process_CertifyKey2, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_CertifyKey2, + sizeof(TPM_KEY_HANDLE) + sizeof(TPM_KEY_HANDLE), + 2, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CertifySelfTest, + TPM_Process_CertifySelfTest, TPM_Process_Unused, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ChangeAuth, + TPM_Process_ChangeAuth, TPM_Process_ChangeAuth, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_ChangeAuth, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ChangeAuthAsymFinish, + TPM_Process_ChangeAuthAsymFinish, TPM_Process_ChangeAuthAsymFinish, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_ChangeAuthAsymFinish, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ChangeAuthAsymStart, + TPM_Process_ChangeAuthAsymStart, TPM_Process_ChangeAuthAsymStart, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_ChangeAuthAsymStart, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ChangeAuthOwner, + TPM_Process_ChangeAuthOwner, TPM_Process_ChangeAuthOwner, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CMK_ApproveMA, + TPM_Process_Unused, TPM_Process_CMK_ApproveMA, + TRUE, + FALSE, + 1, TPM_DELEGATE_CMK_ApproveMA, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CMK_ConvertMigration, + TPM_Process_Unused, TPM_Process_CMK_ConvertMigration, + TRUE, + FALSE, + 1, TPM_KEY_DELEGATE_CMK_ConvertMigration, + 0, 0, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CMK_CreateBlob, + TPM_Process_Unused, TPM_Process_CMK_CreateBlob, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_CMK_CreateBlob, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CMK_CreateKey, + TPM_Process_Unused, TPM_Process_CMK_CreateKey, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_CMK_CreateKey, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CMK_CreateTicket, + TPM_Process_Unused, TPM_Process_CMK_CreateTicket, + TRUE, + FALSE, + 1, TPM_DELEGATE_CMK_CreateTicket, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CMK_SetRestrictions, + TPM_Process_Unused, TPM_Process_CMK_SetRestrictions, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ContinueSelfTest, + TPM_Process_ContinueSelfTest, TPM_Process_ContinueSelfTest, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ConvertMigrationBlob, + TPM_Process_ConvertMigrationBlob, TPM_Process_ConvertMigrationBlob, + TRUE, + TRUE, + 0, 0, + 1, TPM_KEY_DELEGATE_ConvertMigrationBlob, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CreateCounter, + TPM_Process_Unused, TPM_Process_CreateCounter, + TRUE, + FALSE, + 1, TPM_DELEGATE_CreateCounter, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CreateEndorsementKeyPair, + TPM_Process_CreateEndorsementKeyPair, TPM_Process_CreateEndorsementKeyPair, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_CreateMaintenanceArchive, +#if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) + TPM_Process_Unused, TPM_Process_Unused, + FALSE, + FALSE, +#else + TPM_Process_CreateMaintenanceArchive, TPM_Process_CreateMaintenanceArchive, + TRUE, + TRUE, +#endif + 1, TPM_DELEGATE_CreateMaintenanceArchive, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CreateMigrationBlob, + TPM_Process_CreateMigrationBlob, TPM_Process_CreateMigrationBlob, + TRUE, + TRUE, + 0, 0, + 1, TPM_KEY_DELEGATE_CreateMigrationBlob, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CreateRevocableEK, + TPM_Process_Unused, TPM_Process_CreateRevocableEK, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_CreateWrapKey, + TPM_Process_CreateWrapKey, TPM_Process_CreateWrapKey, + TRUE, + TRUE, + 0, 0, + 1, TPM_KEY_DELEGATE_CreateWrapKey, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_DAA_Join, + TPM_Process_Unused, TPM_Process_DAAJoin, + TRUE, + FALSE, + 1, TPM_DELEGATE_DAA_Join, + 0, 0, + sizeof(TPM_HANDLE), + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_DAA_Sign, + TPM_Process_Unused, TPM_Process_DAASign, + TRUE, + FALSE, + 1, TPM_DELEGATE_DAA_Sign, + 0, 0, + sizeof(TPM_HANDLE), + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Delegate_CreateKeyDelegation, + TPM_Process_Unused, TPM_Process_DelegateCreateKeyDelegation, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_Delegate_CreateKeyDelegation, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Delegate_CreateOwnerDelegation, + TPM_Process_Unused, TPM_Process_DelegateCreateOwnerDelegation, + TRUE, + FALSE, + 1, TPM_DELEGATE_Delegate_CreateOwnerDelegation, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Delegate_LoadOwnerDelegation, + TPM_Process_Unused, TPM_Process_DelegateLoadOwnerDelegation, + TRUE, + FALSE, + 1, TPM_DELEGATE_Delegate_LoadOwnerDelegation, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Delegate_Manage, + TPM_Process_Unused, TPM_Process_DelegateManage, + TRUE, + FALSE, + 1, TPM_DELEGATE_Delegate_Manage, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Delegate_ReadTable, + TPM_Process_Unused, TPM_Process_DelegateReadTable, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Delegate_UpdateVerification, + TPM_Process_Unused, TPM_Process_DelegateUpdateVerification, + TRUE, + FALSE, + 1, TPM_DELEGATE_Delegate_UpdateVerification, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Delegate_VerifyDelegation, + TPM_Process_Unused, TPM_Process_DelegateVerifyDelegation, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_DirRead, + TPM_Process_DirRead, TPM_Process_DirRead, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_DirWriteAuth, + TPM_Process_DirWriteAuth, TPM_Process_DirWriteAuth, + TRUE, + FALSE, + 1, TPM_DELEGATE_DirWriteAuth, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_DisableForceClear, + TPM_Process_DisableForceClear, TPM_Process_DisableForceClear, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_DisableOwnerClear, + TPM_Process_DisableOwnerClear, TPM_Process_DisableOwnerClear, + TRUE, + TRUE, + 1, TPM_DELEGATE_DisableOwnerClear, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_DisablePubekRead, + TPM_Process_DisablePubekRead, TPM_Process_DisablePubekRead, + TRUE, + TRUE, + 1, TPM_DELEGATE_DisablePubekRead, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_DSAP, + TPM_Process_Unused, TPM_Process_DSAP, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_ENTITY_TYPE) + sizeof(TPM_KEY_HANDLE) + TPM_NONCE_SIZE + sizeof(uint32_t), + 0xffffffff, + sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE + TPM_NONCE_SIZE, + TRUE, + TRUE, + TRUE}, + + {TPM_ORD_EstablishTransport, + TPM_Process_Unused, TPM_Process_EstablishTransport, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_EstablishTransport, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + FALSE, + FALSE, + FALSE}, + + {TPM_ORD_EvictKey, + TPM_Process_EvictKey, TPM_Process_EvictKey, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ExecuteTransport, + TPM_Process_Unused, TPM_Process_ExecuteTransport, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + FALSE, + FALSE, + FALSE}, + + {TPM_ORD_Extend, + TPM_Process_Extend, TPM_Process_Extend, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_FieldUpgrade, + TPM_Process_Unused, TPM_Process_Unused, + TRUE, + FALSE, + 1, TPM_DELEGATE_FieldUpgrade, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_FlushSpecific, + TPM_Process_Unused, TPM_Process_FlushSpecific, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_HANDLE), + 0xffffffff, + 0, + TRUE, + TRUE, + TRUE}, + + {TPM_ORD_ForceClear, + TPM_Process_ForceClear, TPM_Process_ForceClear, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetAuditDigest, + TPM_Process_Unused, TPM_Process_GetAuditDigest, + FALSE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetAuditDigestSigned, + TPM_Process_Unused, TPM_Process_GetAuditDigestSigned, + FALSE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_GetAuditDigestSigned, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetAuditEvent, + TPM_Process_Unused, TPM_Process_Unused, + FALSE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetAuditEventSigned, + TPM_Process_Unused, TPM_Process_Unused, + FALSE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetCapability, + TPM_Process_GetCapability, TPM_Process_GetCapability, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_GetCapabilityOwner, + TPM_Process_GetCapabilityOwner, TPM_Process_GetCapabilityOwner, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetCapabilitySigned, + TPM_Process_GetCapabilitySigned, TPM_Process_Unused, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetOrdinalAuditStatus, + TPM_Process_Unused, TPM_Process_Unused, + FALSE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetPubKey, + TPM_Process_GetPubKey, TPM_Process_GetPubKey, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_GetPubKey, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetRandom, + TPM_Process_GetRandom, TPM_Process_GetRandom, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetTestResult, + TPM_Process_GetTestResult, TPM_Process_GetTestResult, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_GetTicks, + TPM_Process_Unused, TPM_Process_GetTicks, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_IncrementCounter, + TPM_Process_Unused, TPM_Process_IncrementCounter, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Init, + TPM_Process_Init, TPM_Process_Init, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_KeyControlOwner, + TPM_Process_Unused, TPM_Process_KeyControlOwner, + TRUE, + FALSE, + 1, TPM_DELEGATE_KeyControlOwner, + 0, 0, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_KillMaintenanceFeature, +#if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) + TPM_Process_Unused, TPM_Process_Unused, + FALSE, + FALSE, +#else + TPM_Process_KillMaintenanceFeature, TPM_Process_KillMaintenanceFeature, + TRUE, + TRUE, +#endif + 1, TPM_DELEGATE_KillMaintenanceFeature, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_LoadAuthContext, + TPM_Process_LoadAuthContext, TPM_Process_LoadAuthContext, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + sizeof(TPM_HANDLE), + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_LoadContext, + TPM_Process_Unused, TPM_Process_LoadContext, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_HANDLE), + 0, + sizeof(TPM_HANDLE), + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_LoadKey, + TPM_Process_LoadKey, TPM_Process_LoadKey, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_LoadKey, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_LoadKey2, + TPM_Process_Unused, TPM_Process_LoadKey2, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_LoadKey2, + sizeof(TPM_KEY_HANDLE), + 1, + sizeof(TPM_KEY_HANDLE), + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_LoadKeyContext, + TPM_Process_LoadKeyContext, TPM_Process_LoadKeyContext, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + sizeof(TPM_KEY_HANDLE), + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_LoadMaintenanceArchive, +#if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) + TPM_Process_Unused, TPM_Process_Unused, + FALSE, + FALSE, +#else + TPM_Process_LoadMaintenanceArchive, TPM_Process_LoadMaintenanceArchive, + TRUE, + TRUE, +#endif + 1, TPM_DELEGATE_LoadMaintenanceArchive, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_LoadManuMaintPub, +#if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) + TPM_Process_Unused, TPM_Process_Unused, + FALSE, + FALSE, +#else + TPM_Process_LoadManuMaintPub, TPM_Process_LoadManuMaintPub, + TRUE, + TRUE, +#endif + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_MakeIdentity, + TPM_Process_MakeIdentity, TPM_Process_MakeIdentity, + TRUE, + TRUE, + 1, TPM_DELEGATE_MakeIdentity, + 1, TPM_KEY_DELEGATE_MakeIdentity, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_MigrateKey, + TPM_Process_Unused, TPM_Process_MigrateKey, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_MigrateKey, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_NV_DefineSpace, + TPM_Process_Unused, TPM_Process_NVDefineSpace, + TRUE, + FALSE, + 1, TPM_DELEGATE_NV_DefineSpace, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_NV_ReadValue, + TPM_Process_Unused, TPM_Process_NVReadValue, + TRUE, + FALSE, + 1, TPM_DELEGATE_NV_ReadValue, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_NV_ReadValueAuth, + TPM_Process_Unused, TPM_Process_NVReadValueAuth, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_NV_WriteValue, + TPM_Process_Unused, TPM_Process_NVWriteValue, + TRUE, + FALSE, + 1, TPM_DELEGATE_NV_WriteValue, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_NV_WriteValueAuth, + TPM_Process_Unused, TPM_Process_NVWriteValueAuth, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_OIAP, + TPM_Process_OIAP, TPM_Process_OIAP, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE, + TRUE, + TRUE, + TRUE}, + + {TPM_ORD_OSAP, + TPM_Process_OSAP, TPM_Process_OSAP, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_ENTITY_TYPE) + sizeof(uint32_t) + TPM_NONCE_SIZE, + 0, /* TPM_OSAP: no input or output parameters are encrypted or logged */ + sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE + TPM_NONCE_SIZE, + TRUE, + TRUE, + TRUE}, + + {TPM_ORD_OwnerClear, + TPM_Process_OwnerClear, TPM_Process_OwnerClear, + TRUE, + TRUE, + 1, TPM_DELEGATE_OwnerClear, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_OwnerReadInternalPub, + TPM_Process_Unused, TPM_Process_OwnerReadInternalPub, + TRUE, + FALSE, + 1, TPM_DELEGATE_OwnerReadInternalPub, + 0, 0, + 0, + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_OwnerReadPubek, + TPM_Process_OwnerReadPubek, TPM_Process_OwnerReadPubek, + TRUE, + TRUE, + 1, TPM_DELEGATE_OwnerReadPubek, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_OwnerSetDisable, + TPM_Process_OwnerSetDisable, TPM_Process_OwnerSetDisable, + TRUE, + TRUE, + 1, TPM_DELEGATE_OwnerSetDisable, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_PCR_Reset, + TPM_Process_Unused, TPM_Process_PcrReset, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_PcrRead, + TPM_Process_PcrRead, TPM_Process_PcrRead, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_PhysicalDisable, + TPM_Process_PhysicalDisable, TPM_Process_PhysicalDisable, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_PhysicalEnable, + TPM_Process_PhysicalEnable, TPM_Process_PhysicalEnable, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_PhysicalSetDeactivated, + TPM_Process_PhysicalSetDeactivated, TPM_Process_PhysicalSetDeactivated, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_Quote, + TPM_Process_Quote, TPM_Process_Quote, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_Quote, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + TRUE}, + + {TPM_ORD_Quote2, + TPM_Process_Unused, TPM_Process_Quote2, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_Quote2, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + TRUE}, + + {TPM_ORD_ReadCounter, + TPM_Process_Unused, TPM_Process_ReadCounter, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ReadManuMaintPub, +#if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) + TPM_Process_Unused, TPM_Process_Unused, + FALSE, + FALSE, +#else + TPM_Process_ReadManuMaintPub, TPM_Process_ReadManuMaintPub, + TRUE, + TRUE, +#endif + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ReadPubek, + TPM_Process_ReadPubek, TPM_Process_ReadPubek, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ReleaseCounter, + TPM_Process_Unused, TPM_Process_ReleaseCounter, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ReleaseCounterOwner, + TPM_Process_Unused, TPM_Process_ReleaseCounterOwner, + TRUE, + FALSE, + 1, TPM_DELEGATE_ReleaseCounterOwner, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ReleaseTransportSigned, + TPM_Process_Unused, TPM_Process_ReleaseTransportSigned, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_ReleaseTransportSigned, + 0, + 0, + 0, + FALSE, + FALSE, + FALSE}, + + {TPM_ORD_Reset, + TPM_Process_Reset, TPM_Process_Reset, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_ResetLockValue, + TPM_Process_Unused, TPM_Process_ResetLockValue, + TRUE, + FALSE, + 1, TPM_DELEGATE_ResetLockValue, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_RevokeTrust, + TPM_Process_Unused, TPM_Process_RevokeTrust, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SaveAuthContext, + TPM_Process_SaveAuthContext, TPM_Process_SaveAuthContext, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_AUTHHANDLE), + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SaveContext, + TPM_Process_Unused, TPM_Process_SaveContext, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_HANDLE), + 0xffffffff, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_SaveKeyContext, + TPM_Process_SaveKeyContext, TPM_Process_SaveKeyContext, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SaveState, + TPM_Process_SaveState, TPM_Process_SaveState, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_Seal, + TPM_Process_Seal, TPM_Process_Seal, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_Seal, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Sealx, + TPM_Process_Unused, TPM_Process_Sealx, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_Sealx, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SelfTestFull, + TPM_Process_SelfTestFull, TPM_Process_SelfTestFull, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SetCapability, + TPM_Process_Unused, TPM_Process_SetCapability, + TRUE, + FALSE, + 1, TPM_DELEGATE_SetCapability, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_SetOperatorAuth, + TPM_Process_Unused, TPM_Process_SetOperatorAuth, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SetOrdinalAuditStatus, + TPM_Process_SetOrdinalAuditStatus, TPM_Process_SetOrdinalAuditStatus, + TRUE, + TRUE, + 1, TPM_DELEGATE_SetOrdinalAuditStatus, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SetOwnerInstall, + TPM_Process_SetOwnerInstall, TPM_Process_SetOwnerInstall, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SetOwnerPointer, + TPM_Process_Unused, TPM_Process_SetOwnerPointer, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SetRedirection, + TPM_Process_Unused, TPM_Process_Unused, + TRUE, + FALSE, + 1, TPM_DELEGATE_SetRedirection, + 0, 0, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SetTempDeactivated, + TPM_Process_SetTempDeactivated, TPM_Process_SetTempDeactivated, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SHA1Complete, + TPM_Process_SHA1Complete, TPM_Process_SHA1Complete, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SHA1CompleteExtend, + TPM_Process_SHA1CompleteExtend, TPM_Process_SHA1CompleteExtend, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SHA1Start, + TPM_Process_SHA1Start, TPM_Process_SHA1Start, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_SHA1Update, + TPM_Process_SHA1Update, TPM_Process_SHA1Update, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Sign, + TPM_Process_Sign, TPM_Process_Sign, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_Sign, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Startup, + TPM_Process_Startup, TPM_Process_Startup, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TPM_ORD_StirRandom, + TPM_Process_StirRandom, TPM_Process_StirRandom, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_TakeOwnership, + TPM_Process_TakeOwnership, TPM_Process_TakeOwnership, + TRUE, + TRUE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Terminate_Handle, + TPM_Process_TerminateHandle, TPM_Process_TerminateHandle, + TRUE, + FALSE, + 0, 0, + 0, 0, + sizeof(TPM_AUTHHANDLE), + 0, + 0, + TRUE, + TRUE, + TRUE}, + + {TPM_ORD_TickStampBlob, + TPM_Process_Unused, TPM_Process_TickStampBlob, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_TickStampBlob, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_UnBind, + TPM_Process_UnBind, TPM_Process_UnBind, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_UnBind, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TPM_ORD_Unseal, + TPM_Process_Unseal, TPM_Process_Unseal, + TRUE, + FALSE, + 0, 0, + 1, TPM_KEY_DELEGATE_Unseal, + sizeof(TPM_KEY_HANDLE), + 1, + 0, + TRUE, + FALSE, + FALSE}, + + {TSC_ORD_PhysicalPresence, + TPM_Process_PhysicalPresence, TPM_Process_PhysicalPresence, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + TRUE, + FALSE}, + + {TSC_ORD_ResetEstablishmentBit, + TPM_Process_Unused, TPM_Process_ResetEstablishmentBit, + TRUE, + FALSE, + 0, 0, + 0, 0, + 0, + 0, + 0, + TRUE, + FALSE, + FALSE} + + + +}; + +/* + Ordinal Table Utilities +*/ + +/* TPM_OrdinalTable_GetEntry() gets the table entry for the ordinal. + + If the ordinal is not in the table, TPM_BAD_ORDINAL is returned +*/ + +TPM_RESULT TPM_OrdinalTable_GetEntry(TPM_ORDINAL_TABLE **entry, + TPM_ORDINAL_TABLE *ordinalTable, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = TPM_BAD_ORDINAL; + size_t i; + + /* printf(" TPM_OrdinalTable_GetEntry: Ordinal %08x\n", ordinal); */ + *entry = NULL; + for (i = 0 ; i < (sizeof(tpm_ordinal_table)/sizeof(TPM_ORDINAL_TABLE)) ; i++) { + if (ordinalTable[i].ordinal == ordinal) { /* if found */ + *entry = &(ordinalTable[i]); /* return the entry */ + rc = 0; /* return found */ + break; + } + } + return rc; +} + +/* TPM_OrdinalTable_GetProcessFunction() returns the processing function for the ordinal. + + If the ordinal is not in the table, the function TPM_Process_Unused() is returned. +*/ + +void TPM_OrdinalTable_GetProcessFunction(tpm_process_function_t *tpm_process_function, + TPM_ORDINAL_TABLE *ordinalTable, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + TPM_ORDINAL_TABLE *entry; + + printf(" TPM_OrdinalTable_GetProcessFunction: Ordinal %08x\n", ordinal); + + if (rc == 0) { + rc = TPM_OrdinalTable_GetEntry(&entry, ordinalTable, ordinal); + } + if (rc == 0) { /* if found */ +#ifdef TPM_V12 + *tpm_process_function = entry->process_function_v12; +#else + *tpm_process_function = entry->process_function_v11; +#endif + } + else { /* if not found, default processing function */ + *tpm_process_function = TPM_Process_Unused; + } + return; +} + +/* TPM_OrdinalTable_GetAuditable() determines whether the ordinal can ever be audited. + + Used by TPM_Process_SetOrdinalAuditStatus() +*/ + +void TPM_OrdinalTable_GetAuditable(TPM_BOOL *auditable, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + TPM_ORDINAL_TABLE *entry; + + printf(" TPM_OrdinalTable_GetAuditable: Ordinal %08x\n", ordinal); + if (rc == 0) { + rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); + } + /* if not found, unimplemented, not auditable */ + if (rc != 0) { + *auditable = FALSE; + } + /* if unimplemented, not auditable */ +#ifdef TPM_V12 + else if (entry->process_function_v12 == TPM_Process_Unused) { + *auditable = FALSE; + } +#else + else if (entry->process_function_v11 == TPM_Process_Unused) { + *auditable = FALSE; + } +#endif + /* if found an entry, use it */ + else { + *auditable = entry->auditable; + } + return; +} + +/* TPM_OrdinalTable_GetAuditDefault() determines whether the ordinal is audited by default. + + Used to initialize TPM_PERMANENT_DATA -> ordinalAuditStatus + + Returns FALSE if the ordinal is not in the ordinals table. +*/ + +void TPM_OrdinalTable_GetAuditDefault(TPM_BOOL *auditDefault, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + TPM_ORDINAL_TABLE *entry; + + if (rc == 0) { + rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); + } + /* if not found, unimplemented, not auditable */ + if (rc != 0) { + *auditDefault = FALSE; + } + /* found an entry, return it */ + else { + *auditDefault = entry->auditDefault; + } + return; +} + + +/* TPM_OrdinalTable_GetOwnerPermission() gets the owner permission block and the position within the + block for a permission bit based on the ordinal +*/ + +TPM_RESULT TPM_OrdinalTable_GetOwnerPermission(uint16_t *ownerPermissionBlock, + uint32_t *ownerPermissionPosition, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + TPM_ORDINAL_TABLE *entry; + + if (rc == 0) { + rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); + } + if (rc == 0) { + *ownerPermissionBlock = entry->ownerPermissionBlock; + *ownerPermissionPosition = entry->ownerPermissionPosition; + /* sanity check ordinal table entry value */ + if (*ownerPermissionPosition >= (sizeof(uint32_t) * CHAR_BIT)) { + printf("TPM_OrdinalTable_GetOwnerPermission: Error (fatal): " + "ownerPermissionPosition out of range %u\n", *ownerPermissionPosition); + rc = TPM_FAIL; /* should never occur */ + } + } + return rc; +} + +/* TPM_OrdinalTable_GetKeyPermission() gets the key permission block and the position within the + block for a permission bit based on the ordinal +*/ + +TPM_RESULT TPM_OrdinalTable_GetKeyPermission(uint16_t *keyPermissionBlock, + uint32_t *keyPermissionPosition, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; + TPM_ORDINAL_TABLE *entry; + + if (rc == 0) { + rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); + } + if (rc == 0) { + *keyPermissionBlock = entry->keyPermissionBlock; + *keyPermissionPosition = entry->keyPermissionPosition; + if (*keyPermissionPosition >= (sizeof(uint32_t) * CHAR_BIT)) { + printf("TPM_OrdinalTable_GetKeyPermission: Error (fatal): " + "keyPermissionPosition out of range %u\n", *keyPermissionPosition); + rc = TPM_FAIL; /* should never occur */ + } + } + return rc; +} + +/* TPM_OrdinalTable_ParseWrappedCmd() parses a transport wrapped command, extracting + + - index into DATAw + - length of DATAw + - number of key handles and their indexes + - ordinal + - transportWrappable FALSE if the command cannot be wrapped in a transport session + + FIXME if audit has to occur before command parsing, this command becomes more generally useful, + and might do the auditing and return the inParamDigest as well. + + This function cannot get the actual key handle(s) because the value may be encrypted, and the + decryption has not occurred yet. +*/ + +TPM_RESULT TPM_OrdinalTable_ParseWrappedCmd(uint32_t *datawStart, + uint32_t *datawLen, + uint32_t *keyHandles, + uint32_t *keyHandle1Index, + uint32_t *keyHandle2Index, + TPM_COMMAND_CODE *ordinal, + TPM_BOOL *transportWrappable, + TPM_SIZED_BUFFER *wrappedCmd) +{ + TPM_RESULT rc = 0; + uint32_t stream_size; + unsigned char *stream; + TPM_TAG tag = 0; + uint32_t paramSize = 0; + TPM_ORDINAL_TABLE *entry; /* table entry for the ordinal */ + uint32_t authLen; /* length of below the line parameters */ + + printf(" TPM_OrdinalTable_ParseWrappedCmd:\n"); + /* Extract the standard command parameters from the command stream. This also validates + paramSize against wrappedCmdSize */ + if (rc == 0) { + /* make temporary copies so the wrappedCmd is not touched */ + /* FIXME might want to return paramSize and tag and move the wrappedCmd pointers */ + stream = wrappedCmd->buffer; + stream_size = wrappedCmd->size; + /* parse the three standard input parameters, check paramSize against wrappedCmd->size */ + rc = TPM_Process_GetCommandParams(&tag, ¶mSize, ordinal, + &stream, &stream_size); + } + /* get the entry from the ordinal table */ + if (rc == 0) { + printf(" TPM_OrdinalTable_ParseWrappedCmd: ordinal %08x\n", *ordinal); + rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, *ordinal); + } + if (rc == 0) { + /* datawStart indexes into the dataW area, skip the standard 3 inputs and the handles */ + *datawStart = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE) + + entry->inputHandleSize; + /* authLen is the length of the below-the-line auth parameters that are excluded from the + dataW area */ + switch (tag) { + case TPM_TAG_RQU_AUTH1_COMMAND: + authLen = sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE + + sizeof(TPM_BOOL) + TPM_AUTHDATA_SIZE; + break; + case TPM_TAG_RQU_AUTH2_COMMAND: + authLen = 2 * + (sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE + + sizeof(TPM_BOOL) + TPM_AUTHDATA_SIZE); + break; + case TPM_TAG_RQU_COMMAND: + /* if the tag is illegal, assume the dataW area goes to the end of the command */ + default: + authLen = 0; + break; + } + if (paramSize < *datawStart + authLen) { + printf("TPM_OrdinalTable_ParseWrappedCmd: Error, " + "paramSize %u less than datawStart %u + authLen %u\n", + paramSize, *datawStart, authLen); + rc = TPM_BAD_PARAM_SIZE; + } + } + if (rc == 0) { + /* subtract safe, cannot be negative after above check */ + *datawLen = paramSize - *datawStart - authLen; + printf(" TPM_OrdinalTable_ParseWrappedCmd: datawStart %u datawLen %u\n", + *datawStart, *datawLen); + /* determine whether the command can be wrapped in a transport session */ + *transportWrappable = entry->transportWrappable; + /* return the number of key handles */ + *keyHandles = entry->keyHandles; + } + if (rc == 0) { + printf(" TPM_OrdinalTable_ParseWrappedCmd: key handles %u\n", *keyHandles); + switch (*keyHandles) { + case 0: + /* no key handles */ + break; + case 1: + /* one key handle */ + *keyHandle1Index = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE); + break; + case 2: + /* first key handle */ + *keyHandle1Index = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE); + /* second key handle */ + *keyHandle2Index = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE) + + sizeof(TPM_KEY_HANDLE); + break; + case 0xffffffff: + printf(" TPM_OrdinalTable_ParseWrappedCmd: key handles special case\n"); + /* potential key handle */ + *keyHandle1Index = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE); + /* can't determine handle type here since resourceType is encrypted */ + break; + default: + /* sanity check ordinal table */ + printf("TPM_OrdinalTable_ParseWrappedCmd: Error (fatal), " + "invalid key handles for %08x for ordinal %08x\n", *keyHandles, *ordinal); + rc = TPM_FAIL; /* should never occur */ + break; + } + } + return rc; +} + +/* TPM_OrdinalTable_ParseWrappedRsp() parses a transport wrapped response, extracting + + - index into DATAw + - length of DATAw + - return code RCw + + FIXME this command might do the auditing and return the outParamDigest as well. +*/ + +TPM_RESULT TPM_OrdinalTable_ParseWrappedRsp(uint32_t *datawStart, + uint32_t *datawLen, + TPM_RESULT *rcw, + TPM_COMMAND_CODE ordinal, + const unsigned char *wrappedRspStream, + uint32_t wrappedRspStreamSize) +{ + TPM_RESULT rc = 0; + TPM_TAG tag = 0; + uint32_t paramSize = 0; + TPM_ORDINAL_TABLE *entry; /* table entry for the ordinal */ + uint32_t authLen; /* length of below the line parameters */ + + printf(" TPM_OrdinalTable_ParseWrappedRsp: ordinal %08x\n", ordinal); + /* Extract the standard response parameters from the response stream. This also validates + paramSize against wrappedRspSize */ + if (rc == 0) { + rc = TPM_Process_GetResponseParams(&tag, ¶mSize, rcw, + (unsigned char **)&wrappedRspStream, + &wrappedRspStreamSize); + } + /* get the entry from the ordinal table */ + if (rc == 0) { + printf(" TPM_OrdinalTable_ParseWrappedRsp: returnCode %08x\n", *rcw); + rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); + } + /* parse the success return code case */ + if ((rc == 0) && (*rcw == TPM_SUCCESS)) { + if (rc == 0) { + /* datawStart indexes into the dataW area, skip the standard 3 inputs and the handles */ + *datawStart = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT) + + entry->outputHandleSize; + /* authLen is the length of the below-the-line auth parameters that are excluded from + the dataW area */ + switch (tag) { + case TPM_TAG_RSP_AUTH1_COMMAND: + authLen = TPM_NONCE_SIZE + sizeof(TPM_BOOL) + TPM_AUTHDATA_SIZE; + break; + case TPM_TAG_RSP_AUTH2_COMMAND: + authLen = 2 * (TPM_NONCE_SIZE + sizeof(TPM_BOOL) + TPM_AUTHDATA_SIZE); + break; + case TPM_TAG_RSP_COMMAND: + /* if the tag is illegal, assume the dataW area goes to the end of the response */ + default: + authLen = 0; + break; + } + if (paramSize < *datawStart + authLen) { + printf("TPM_OrdinalTable_ParseWrappedRsp: Error, " + "paramSize %u less than datawStart %u + authLen %u\n", + paramSize, *datawStart, authLen); + rc = TPM_BAD_PARAM_SIZE; /* FIXME not clear what to do here */ + } + } + if (rc == 0) { + /* subtract safe, cannot be negative after about check */ + *datawLen = paramSize - *datawStart - authLen; + printf(" TPM_OrdinalTable_ParseWrappedRsp: datawStart %u datawLen %u\n", + *datawStart, *datawLen); + } + } + /* if the wrapped command failed, datawStart is not used, and datawLen is 0 */ + else if ((rc == 0) && (*rcw != TPM_SUCCESS)) { + *datawStart = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT); + *datawLen = 0; + printf(" TPM_OrdinalTable_ParseWrappedRsp: datawLen %u\n", *datawLen); + } + return rc; +} + +void TPM_KeyHandleEntries_Trace(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); + +void TPM_KeyHandleEntries_Trace(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) +{ + size_t i; + for (i = 0 ; (i < 4) && (i < TPM_KEY_HANDLES) ; i++) { + printf("TPM_KeyHandleEntries_Trace: %lu handle %08x tpm_key %p\n", + (unsigned long)i, tpm_key_handle_entries[i].handle, tpm_key_handle_entries[i].key); + } + return; +} + +void TPM_State_Trace(tpm_state_t *tpm_state); + +void TPM_State_Trace(tpm_state_t *tpm_state) +{ + printf("TPM_State_Trace: disable %u p_deactive %u v_deactive %u owned %u state %u\n", + tpm_state->tpm_permanent_flags.disable, + tpm_state->tpm_permanent_flags.deactivated, + tpm_state->tpm_stclear_flags.deactivated, + tpm_state->tpm_permanent_data.ownerInstalled, + tpm_state->testState); + return; +} + +/* TPM_ProcessA() is an alternate to TPM_Process() that uses standard C types. It provides an entry + point to the TPM without requiring the TPM_STORE_BUFFER class. + + The design pattern for the response is: + + - set '*response' to NULL at the first call + + - on subsequent calls, pass 'response' and 'response_total' back in. Set 'response_size' back + to 0. + + On input: + + '*response' - pointer to a buffer that was allocated (can be NULL) + + 'response_size' - the number of valid bytes in buffer (ignored if buffer is NULL, can be 0, + cannot be greater than total. Set to zero, unless one wants the TPM_Process() function to append + a response to some existing data. + + '*response_total' - the total number of allocated bytes (ignored if buffer is NULL) + + On output: + + '*response' - pointer to a buffer that was allocated or reallocated + + 'response_size' - the number of valid bytes in buffer + + '*response_total' - the total number of allocated or reallocated bytes +*/ + +TPM_RESULT TPM_ProcessA(unsigned char **response, + uint32_t *response_size, + uint32_t *response_total, + unsigned char *command, /* complete command array */ + uint32_t command_size) /* actual bytes in command */ + +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER responseSbuffer; + + /* set the sbuffer from the response parameters */ + if (rc == 0) { + rc = TPM_Sbuffer_Set(&responseSbuffer, + *response, + *response_size, + *response_total); + } + if (rc == 0) { + rc = TPM_Process(&responseSbuffer, + command, /* complete command array */ + command_size); /* actual bytes in command */ + + } + /* get the response parameters from the sbuffer */ + if (rc == 0) { + TPM_Sbuffer_GetAll(&responseSbuffer, + response, + response_size, + response_total); + } + return rc; +} + +/* Process the command from the host to the TPM. + + 'command_size' is the actual size of the command stream. + + Returns: + 0 on success + + non-zero on a fatal error preventing the command from being processed. The response is + invalid in this case. +*/ + +TPM_RESULT TPM_Process(TPM_STORE_BUFFER *response, + unsigned char *command, /* complete command array */ + uint32_t command_size) /* actual bytes in command */ +{ + TPM_RESULT rc = 0; /* fatal error, no response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* fatal error in ordinal processing, + can be returned */ + TPM_TAG tag = 0; + uint32_t paramSize = 0; + TPM_COMMAND_CODE ordinal = 0; + tpm_process_function_t tpm_process_function = NULL; /* based on ordinal */ + tpm_state_t *targetInstance = NULL; /* TPM global state */ + TPM_STORE_BUFFER localBuffer; /* for response if instance was not found */ + TPM_STORE_BUFFER *sbuffer; /* either localBuffer or the instance response + buffer */ + + TPM_Sbuffer_Init(&localBuffer); /* freed @1 */ + /* get the global TPM state */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + targetInstance = tpm_instances[0]; + } + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + /* clear the response form the previous ordinal, the response buffer is reused */ + TPM_Sbuffer_Clear(&(targetInstance->tpm_stclear_data.ordinalResponse)); + /* extract the standard command parameters from the command stream */ + returnCode = TPM_Process_GetCommandParams(&tag, ¶mSize, &ordinal, + &command, &command_size); + } + /* preprocessing common to all ordinals */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + returnCode = TPM_Process_Preprocess(targetInstance, ordinal, NULL); + } + /* NOTE Only for debugging */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + TPM_KeyHandleEntries_Trace(targetInstance->tpm_key_handle_entries); + } + /* process the ordinal */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + /* get the processing function from the ordinal table */ + TPM_OrdinalTable_GetProcessFunction(&tpm_process_function, tpm_ordinal_table, ordinal); + /* call the processing function to execute the command */ + returnCode = tpm_process_function(targetInstance, + &(targetInstance->tpm_stclear_data.ordinalResponse), + tag, command_size, ordinal, command, + NULL); /* not from encrypted transport */ + } + /* NOTE Only for debugging */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + TPM_KeyHandleEntries_Trace(targetInstance->tpm_key_handle_entries); + } + /* NOTE Only for debugging */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + TPM_State_Trace(targetInstance); + } +#ifdef TPM_VOLATILE_STORE + /* save the volatile state after each command to handle fail-over restart */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + returnCode = TPM_VolatileAll_NVStore(targetInstance); + } +#endif /* TPM_VOLATILE_STORE */ + /* If the ordinal processing function returned without a fatal error, append its ordinalResponse + to the output response buffer */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + returnCode = TPM_Sbuffer_AppendSBuffer(response, + &(targetInstance->tpm_stclear_data.ordinalResponse)); + } + if ((rc == 0) && (returnCode != TPM_SUCCESS)) { + /* gets here if: + + - there was an error before the ordinal was processed + - the ordinal returned a fatal error + - an error occurred appending the ordinal response + + returnCode should be the response + errors here are fatal, can't create an error response + */ + /* if it failed after the target instance was found, use the instance's response buffer */ + if (targetInstance != NULL) { + sbuffer = &(targetInstance->tpm_stclear_data.ordinalResponse); + } + /* if it failed before even the target instance was found, use a local buffer */ + else { + sbuffer = &localBuffer; + } + if (rc == 0) { + /* it's not even known whether the initial response was stored, so just start + over */ + TPM_Sbuffer_Clear(sbuffer); + /* store the tag, paramSize, and returnCode */ + printf("TPM_Process: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rc = TPM_Sbuffer_StoreInitialResponse(sbuffer, TPM_TAG_RQU_COMMAND, returnCode); + } + /* call this to handle the TPM_FAIL causing the TPM going into failure mode */ + if (rc == 0) { + rc = TPM_Sbuffer_StoreFinalResponse(sbuffer, returnCode, targetInstance); + } + if (rc == 0) { + rc = TPM_Sbuffer_AppendSBuffer(response, sbuffer); + } + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&localBuffer); /* @1 */ + return rc; +} + +/* TPM_Process_Wrapped() is called recursively to process a wrapped command. + + 'command_size' is the actual size of the command stream. + + 'targetInstance' is an input indicating the TPM instance being called. + + 'transportInternal' not NULL indicates that this function was called recursively from + TPM_ExecuteTransport + + For wrapped commands, this function cannot trust that command_size and the incoming paramSize in + the command stream are consistent. Therefore, this function checks for consistency. + + The processor ensures that the response bytes are set according to the outgoing paramSize on + return. + + Returns: + 0 on success + + non-zero on a fatal error preventing the command from being processed. The response is + invalid in this case. +*/ + +TPM_RESULT TPM_Process_Wrapped(TPM_STORE_BUFFER *response, + unsigned char *command, /* complete command array */ + uint32_t command_size, /* actual bytes in command */ + tpm_state_t *targetInstance, /* global TPM state */ + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rc = 0; /* fatal error, no response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* non-fatal error, returned in response */ + TPM_TAG tag = 0; + uint32_t paramSize = 0; + TPM_COMMAND_CODE ordinal = 0; + tpm_process_function_t tpm_process_function = NULL; /* based on ordinal */ + TPM_STORE_BUFFER ordinalResponse; /* response for this ordinal */ + + printf("TPM_Process_Wrapped:\n"); + TPM_Sbuffer_Init(&ordinalResponse); /* freed @1 */ + /* Set the tag, paramSize, and ordinal from the wrapped command stream */ + /* If paramSize does not equal the command stream size, return TPM_BAD_PARAM_SIZE */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + returnCode = TPM_Process_GetCommandParams(&tag, ¶mSize, &ordinal, + &command, &command_size); + } + /* preprocessing common to all ordinals */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + returnCode = TPM_Process_Preprocess(targetInstance, ordinal, transportInternal); + } + /* process the ordinal */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + /* get the processing function from the ordinal table */ + TPM_OrdinalTable_GetProcessFunction(&tpm_process_function, tpm_ordinal_table, ordinal); + /* call the processing function to execute the command */ + returnCode = tpm_process_function(targetInstance, &ordinalResponse, + tag, command_size, ordinal, command, + transportInternal); + } + /* If the ordinal processing function returned without a fatal error, append its ordinalResponse + to the output response buffer */ + if ((rc == 0) && (returnCode == TPM_SUCCESS)) { + returnCode = TPM_Sbuffer_AppendSBuffer(response, &ordinalResponse); + } + /* If: + + - an error in this function occurred before the ordinal was processed + - the ordinal processing function returned a fatal error + - an error occurred appending the ordinal response + + then use the return code of that failure as the final response. Failure here is fatal, since + no error code can be returned. + */ + if ((rc == 0) && (returnCode != TPM_SUCCESS)) { + rc = TPM_Sbuffer_StoreFinalResponse(response, returnCode, targetInstance); + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&ordinalResponse); /* @1 */ + return rc; +} + +/* TPM_Process_GetCommandParams() gets the standard 3 parameters from the command input stream + + The stream is adjusted to point past the parameters. + + The resulting paramSize is checked against the stream size for consistency. paramSize is + returned for reference, but command_size reflects the remaining bytes in the stream. +*/ + +TPM_RESULT TPM_Process_GetCommandParams(TPM_TAG *tag, + uint32_t *paramSize , + TPM_COMMAND_CODE *ordinal, + unsigned char **command, + uint32_t *command_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Process_GetCommandParams:\n"); + /* get tag */ + if (rc == 0) { + rc = TPM_Load16(tag, command, command_size); + } + /* get paramSize */ + if (rc == 0) { + rc = TPM_Load32(paramSize, command, command_size); + } + /* get ordinal */ + if (rc == 0) { + rc = TPM_Load32(ordinal, command, command_size); + } + /* check the paramSize against the command_size */ + if (rc == 0) { + if (*paramSize != + *command_size + sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE)) { + + printf("TPM_Process_GetCommandParams: Error, " + "command size %lu not equal to paramSize %u\n", + (unsigned long) + (*command_size + sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE)), + *paramSize); + rc = TPM_BAD_PARAM_SIZE; + } + else { + printf(" TPM_Process_GetCommandParams: tag %04x paramSize %u ordinal %08x\n", + *tag, *paramSize, *ordinal); + } + } + return rc; +} + +/* TPM_Process_GetResponseParams() gets the standard 3 parameters from the response output stream + + The stream is adjusted to point past the parameters. + + The resulting paramSize is checked against the stream size for consistency. paramSize is + returned for reference, but response_size reflects the remaining bytes in the stream. +*/ + +TPM_RESULT TPM_Process_GetResponseParams(TPM_TAG *tag, + uint32_t *paramSize , + TPM_RESULT *returnCode, + unsigned char **response, + uint32_t *response_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Process_GetResponseParams:\n"); + /* get tag */ + if (rc == 0) { + rc = TPM_Load16(tag, response, response_size); + } + /* get paramSize */ + if (rc == 0) { + rc = TPM_Load32(paramSize, response, response_size); + } + /* get returnCode */ + if (rc == 0) { + rc = TPM_Load32(returnCode, response, response_size); + } + /* check the paramSize against the response_size */ + if (rc == 0) { + if (*paramSize != (*response_size + sizeof(TPM_TAG) + + sizeof(uint32_t) + sizeof(TPM_RESULT))) { + + printf("TPM_Process_GetResponseParams: Error, " + "response size %lu not equal to paramSize %u\n", + (unsigned long) + (*response_size + sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT)), + *paramSize); + rc = TPM_BAD_PARAM_SIZE; + } + else { + printf(" TPM_Process_GetResponseParams: tag %04x paramSize %u ordinal %08x\n", + *tag, *paramSize, *returnCode); + } + } + return rc; +} + +/* TPM_CheckRequestTagnnn() is common code to verify the command tag */ + +TPM_RESULT TPM_CheckRequestTag210(TPM_TAG tpm_tag) +{ + TPM_RESULT rc = 0; + + if ((tpm_tag != TPM_TAG_RQU_AUTH2_COMMAND) && + (tpm_tag != TPM_TAG_RQU_AUTH1_COMMAND) && + (tpm_tag != TPM_TAG_RQU_COMMAND)) { + printf("TPM_CheckRequestTag210: Error, tag %04hx\n", tpm_tag); + rc = TPM_BADTAG; + } + return rc; +} + +TPM_RESULT TPM_CheckRequestTag21(TPM_TAG tpm_tag) +{ + TPM_RESULT rc = 0; + + if ((tpm_tag != TPM_TAG_RQU_AUTH2_COMMAND) && + (tpm_tag != TPM_TAG_RQU_AUTH1_COMMAND)) { + printf("TPM_CheckRequestTag21: Error, tag %04hx\n", tpm_tag); + rc = TPM_BADTAG; + } + return rc; +} + +TPM_RESULT TPM_CheckRequestTag2(TPM_TAG tpm_tag) +{ + TPM_RESULT rc = 0; + + if (tpm_tag != TPM_TAG_RQU_AUTH2_COMMAND) { + printf("TPM_CheckRequestTag2: Error, tag %04hx\n", tpm_tag); + rc = TPM_BADTAG; + } + return rc; +} + +TPM_RESULT TPM_CheckRequestTag10(TPM_TAG tpm_tag) +{ + TPM_RESULT rc = 0; + + if ((tpm_tag != TPM_TAG_RQU_AUTH1_COMMAND) && + (tpm_tag != TPM_TAG_RQU_COMMAND)) { + printf("TPM_CheckRequestTag10: Error, tag %04hx\n", tpm_tag); + rc = TPM_BADTAG; + } + return rc; +} + +TPM_RESULT TPM_CheckRequestTag1(TPM_TAG tpm_tag) +{ + TPM_RESULT rc = 0; + + if (tpm_tag != TPM_TAG_RQU_AUTH1_COMMAND) { + printf("TPM_CheckRequestTag1: Error, tag %04hx\n", tpm_tag); + rc = TPM_BADTAG; + } + return rc; +} + +TPM_RESULT TPM_CheckRequestTag0(TPM_TAG tpm_tag) +{ + TPM_RESULT rc = 0; + + if (tpm_tag != TPM_TAG_RQU_COMMAND) { + printf("TPM_CheckRequestTag0: Error, tag %04hx\n", tpm_tag); + rc = TPM_BADTAG; + } + return rc; +} + +TPM_RESULT TPM_Process_Unused(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; + + printf("TPM_Process_Unused:\n"); + tpm_state = tpm_state; /* not used */ + paramSize = paramSize; /* not used */ + ordinal = ordinal; /* not used */ + command = command; /* not used */ + transportInternal = transportInternal; /* not used */ + printf("TPM_Process_Unused: Ordinal returnCode %08x %u\n", + TPM_BAD_ORDINAL, TPM_BAD_ORDINAL); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, TPM_BAD_ORDINAL); + return rcf; +} + +/* TPM_CheckState() should be called by all commands. It checks a set of flags specified by + tpm_check_map to determine whether the command can execute in that state. + + Returns: 0 if the command can execute + non-zero error code that should be returned as a response +*/ + +TPM_RESULT TPM_CheckState(tpm_state_t *tpm_state, + TPM_TAG tag, + uint32_t tpm_check_map) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CheckState: Check map %08x\n", tpm_check_map); + /* check the dictionary attack lockout, only for authorized commands */ + if (rc == 0) { + if ((tpm_check_map & TPM_CHECK_NO_LOCKOUT) && (tag != TPM_TAG_RQU_COMMAND)) { + rc = TPM_Authdata_CheckState(tpm_state); + } + } + /* TPM_GetTestResult. This command can assist the TPM manufacturer in determining the cause of + the self-test failure. iii. All other operations will return the error code + TPM_FAILEDSELFTEST. */ + if (rc == 0) { + if (tpm_check_map & TPM_CHECK_NOT_SHUTDOWN) { + if (tpm_state->testState == TPM_TEST_STATE_FAILURE) { + printf("TPM_CheckState: Error, shutdown is TRUE\n"); + rc = TPM_FAILEDSELFTEST; + } + } + } + /* TPM_Startup SHALL execute as normal, and is the only function that does not call + TPM_CheckState(). All other commands SHALL return TPM_INVALID_POSTINIT */ + if (rc == 0) { + if (tpm_state->tpm_stany_flags.postInitialise) { + printf("TPM_CheckState: Error, postInitialise is TRUE\n"); + rc = TPM_INVALID_POSTINIT; + } + } + /* + For checking disabled and deactivated, the check is NOT done if it's one of the special NV + commands (indicated by TPM_CHECK_NV_NOAUTH) and nvLocked is FALSE, indicating that the NV + store does not require authorization + */ + /* For commands available only when enabled. */ + if (rc == 0) { + if ((tpm_check_map & TPM_CHECK_ENABLED) && + !((tpm_check_map & TPM_CHECK_NV_NOAUTH) && !tpm_state->tpm_permanent_flags.nvLocked)) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_CheckState: Error, disable is TRUE\n"); + rc = TPM_DISABLED; + } + } + } + /* For commands only available when activated. */ + if (rc == 0) { + if ((tpm_check_map & TPM_CHECK_ACTIVATED) && + !((tpm_check_map & TPM_CHECK_NV_NOAUTH) && !tpm_state->tpm_permanent_flags.nvLocked)) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_CheckState: Error, deactivated is TRUE\n"); + rc = TPM_DEACTIVATED; + } + } + } + /* For commands available only after an owner is installed. see Ordinals chart */ + if (rc == 0) { + if (tpm_check_map & TPM_CHECK_OWNER) { + if (!tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_CheckState: Error, ownerInstalled is FALSE\n"); + rc = TPM_NOSRK; + } + } + } + return rc; +} + +/* TPM_Process_Preprocess() handles check functions common to all ordinals + + 'transportPublic' not NULL indicates that this function was called recursively from + TPM_ExecuteTransport +*/ + +TPM_RESULT TPM_Process_Preprocess(tpm_state_t *tpm_state, + TPM_COMMAND_CODE ordinal, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rc = 0; /* fatal error, no response */ + + printf(" TPM_Process_Preprocess: Ordinal %08x\n", ordinal); + /* Preprocess to check if command can be run in limited operation mode */ + if (rc == 0) { + if (tpm_state->testState == TPM_TEST_STATE_LIMITED) { + /* 1. At startup, a TPM MUST self-test all internal functions that are necessary to do + TPM_SHA1Start, TPM_SHA1Update, TPM_SHA1Complete, TPM_SHA1CompleteExtend, TPM_Extend, + TPM_Startup, TPM_ContinueSelfTest, a subset of TPM_GetCapability, and + TPM_GetTestResult.. + */ + if (!((ordinal == TPM_ORD_Startup) || + (ordinal == TPM_ORD_SHA1Start) || + (ordinal == TPM_ORD_SHA1Update) || + (ordinal == TPM_ORD_SHA1Complete) || + (ordinal == TPM_ORD_SHA1CompleteExtend) || + (ordinal == TPM_ORD_Extend) || + (ordinal == TPM_ORD_Startup) || + (ordinal == TPM_ORD_ContinueSelfTest) || + /* a subset of TPM_GetCapability does not require self-test. The ordinal itself + decides whether to run TPM_ContinueSelfTest() */ + (ordinal == TPM_ORD_GetCapability) || + /* 3. The TPM MAY allow TPM_SelfTestFull to be used before completion of the + actions of TPM_ContinueSelfTest. */ + (ordinal == TPM_ORD_SelfTestFull) || + (ordinal == TPM_ORD_GetTestResult) || + /* 2. The TSC_PhysicalPresence and TSC_ResetEstablishmentBit commands do not + operate on shielded-locations and have no requirement to be self-tested before + any use. TPM's SHOULD test these functions before operation. */ + (ordinal == TSC_ORD_PhysicalPresence) || + (ordinal == TSC_ORD_ResetEstablishmentBit) + )) { + /* One of the optional actions. */ + /* rc = TPM_NEEDS_SELFTEST; */ + /* Alternatively, could run the actions of continue self-test */ + rc = TPM_ContinueSelfTestCmd(tpm_state); + } + } + } + /* special pre-processing for SHA1 context */ + if (rc == 0) { + rc = TPM_Check_SHA1Context(tpm_state, ordinal, transportInternal); + } + /* Special pre-processing to invalidate the saved state if it exists. Omit this processing for + TPM_Startup, since that function might restore the state first */ + if (rc == 0) { + if (tpm_state->tpm_stany_flags.stateSaved && + !((ordinal == TPM_ORD_Startup) || + (ordinal == TPM_ORD_Init))) { + /* For any other ordinal, invalidate the saved state if it exists. */ + rc = TPM_SaveState_NVDelete(tpm_state, TRUE); + } + } + /* When an exclusive session is running, execution of any command other then + TPM_ExecuteTransport or TPM_ReleaseTransportSigned targeting the exclusive session causes the + abnormal invalidation of the exclusive transport session. */ + if ((rc == 0) && (transportInternal == NULL)) { /* do test only for the outer ordinal */ + if ((tpm_state->tpm_stany_flags.transportExclusive != 0) && /* active exclusive */ + /* These two ordinals terminate the exclusive transport session if the transport handle + is not the specified handle. So the check is deferred until the command is parsed + for the transport handle. */ + !((ordinal == TPM_ORD_ExecuteTransport) || + (ordinal == TPM_ORD_ReleaseTransportSigned))) { + rc = TPM_TransportSessions_TerminateHandle + (tpm_state->tpm_stclear_data.transSessions, + tpm_state->tpm_stany_flags.transportExclusive, + &(tpm_state->tpm_stany_flags.transportExclusive)); + } + } + /* call platform specific code to set the localityModifier */ + if ((rc == 0) && (transportInternal == NULL)) { /* do only for the outer ordinal */ + rc = TPM_IO_GetLocality(&(tpm_state->tpm_stany_flags.localityModifier), + tpm_state->tpm_number); + } + return rc; +} + + +/* TPM_Check_SHA1Context() checks the current SHA1 context + + The TPM may not allow any other types of processing during the execution of a SHA-1 + session. There is only one SHA-1 session active on a TPM. After the execution of SHA1Start, and + prior to SHA1End, the receipt of any command other than SHA1Update will cause the invalidation of + the SHA-1 session. + + 2. After receipt of TPM_SHA1Start, and prior to the receipt of TPM_SHA1Complete or + TPM_SHA1CompleteExtend, receipt of any command other than TPM_SHA1Update invalidates the SHA-1 + session. + + a. If the command received is TPM_ExecuteTransport, the SHA-1 session invalidation is based on + the wrapped command, not the TPM_ExecuteTransport ordinal. + + b. A SHA-1 thread (start, update, complete) MUST take place either completely outside a transport + session or completely within a single transport session. +*/ + +TPM_RESULT TPM_Check_SHA1Context(tpm_state_t *tpm_state, + TPM_COMMAND_CODE ordinal, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rc = 0; + + if ((tpm_state->sha1_context != NULL) && /* if there was a SHA-1 context set up */ + (ordinal != TPM_ORD_ExecuteTransport)) /* depends on the wrapped command */ + { + /* the non-SHA1 ordinals invalidate the SHA-1 session */ + if ( + ((ordinal != TPM_ORD_SHA1Update) && + (ordinal != TPM_ORD_SHA1Complete) && + (ordinal != TPM_ORD_SHA1CompleteExtend)) || + + /* invalidate if the SHA1 ordinal is within a transport session and the session was not + set up within the same transport session. */ + ((transportInternal != NULL) && + (tpm_state->transportHandle != transportInternal->transHandle)) || + + /* invalidate if the SHA1 ordinal is not within a transport session and the session was + set up with a transport session */ + ((transportInternal == NULL) && + (tpm_state->transportHandle != 0)) + + ) { + + printf("TPM_Check_SHA1Context: Invalidating SHA1 context\n"); + TPM_SHA1Delete(&(tpm_state->sha1_context)); + } + } + return rc; +} + +/* TPM_GetInParamDigest() does common processing of input parameters. + + Common processing includes: + + - determining if the ordinal is being run within an encrypted transport session, since the + inParamDigest does not have to be calculated for audit in that case. + + - retrieving the audit status. It is determinant of whether the input parameter digest should be + calculated. + + - calculating the input parameter digest for HMAC authorization and/or auditing + + This function is called before authorization for several reasons. + + 1 - It makes ordinal processing code more uniform, since authorization sometimes occurs far into + the actions. + + 2 - It is a minor optimization, since the resulting inParamDigest can be used twice in an auth-2 + command, as well as extending the audit digest. +*/ + +TPM_RESULT TPM_GetInParamDigest(TPM_DIGEST inParamDigest, /* output */ + TPM_BOOL *auditStatus, /* output */ + TPM_BOOL *transportEncrypt, /* output */ + tpm_state_t *tpm_state, + TPM_TAG tag, + TPM_COMMAND_CODE ordinal, + unsigned char *inParamStart, + unsigned char *inParamEnd, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rc = 0; /* this function return code */ + TPM_COMMAND_CODE nOrdinal; /* ordinal in network byte order */ + + printf(" TPM_GetInParamDigest:\n"); + if (rc == 0) { + /* TRUE if called from encrypted transport session. This is currently only needed when + auditing, but it's safer to always initialize it */ + *transportEncrypt = + (transportInternal != NULL) && + (transportInternal->transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT); + printf(" TPM_GetInParamDigest: transportEncrypt %02x\n", *transportEncrypt); + /* Determine if the ordinal should be audited. */ + rc = TPM_OrdinalAuditStatus_GetAuditStatus(auditStatus, + ordinal, + &(tpm_state->tpm_permanent_data)); + } + /* If inParamDigest is needed for: + + 1 - for auditing (auditStatus == TRUE) and not called from an encrypted transport. Different + parameters are audited if the ordinal is called through an encrypted transport session. + + 2 - for authorization (tag != auth-0) + */ + if (rc == 0) { + if ((*auditStatus && !(*transportEncrypt)) || /* digest for auditing */ + (tag != TPM_TAG_RQU_COMMAND)) { /* digest for authorization */ + + /* convert ordinal to network byte order */ + nOrdinal = htonl(ordinal); + + /* a. Create inParamDigest - digest of inputs above the double line. NOTE: If there + are no inputs other than the ordinal, inParamEnd - inParamStart will be 0, + terminating the SHA1 vararg hash. It is important that the termination condition + be the length and not the NULL pointer. */ + rc = TPM_SHA1(inParamDigest, + sizeof(TPM_COMMAND_CODE), &nOrdinal, /* 1S */ + inParamEnd - inParamStart, inParamStart, /* 2S - ... */ + 0, NULL); + if (rc == 0) { + TPM_PrintFour(" TPM_GetInParamDigest: inParamDigest", inParamDigest); + } + } + } + return rc; +} + +/* TPM_GetOutParamDigest() does common processing of output parameters. + + It calculates the output parameter digest for HMAC generation and/or auditing if required. +*/ + +TPM_RESULT TPM_GetOutParamDigest(TPM_DIGEST outParamDigest, /* output */ + TPM_BOOL auditStatus, /* input audit status */ + TPM_BOOL transportEncrypt, /* wrapped in encrypt transport */ + TPM_TAG tag, + TPM_RESULT returnCode, + TPM_COMMAND_CODE ordinal, /* command ordinal (hbo) */ + unsigned char *outParamStart, /* starting point of param's */ + uint32_t outParamLength) /* length of param's */ +{ + TPM_RESULT rc = 0; + TPM_RESULT nreturnCode; /* returnCode in nbo */ + TPM_COMMAND_CODE nOrdinal; /* ordinal in network byte order */ + + printf(" TPM_GetOutParamDigest:\n"); + if (rc == 0) { + if ((auditStatus && !transportEncrypt) || (tag != TPM_TAG_RQU_COMMAND)) { + nreturnCode = htonl(returnCode); + nOrdinal = htonl(ordinal); + /* a. Create outParamDigest - digest of outputs above the double line. NOTE: If there + are no outputs other than the returnCode and ordinal, outParamLength + will be 0, terminating the SHA1 vararg hash. It is important that the termination + condition be the length and not the NULL pointer. */ + rc = TPM_SHA1(outParamDigest, + sizeof(TPM_RESULT), &nreturnCode, /* 1S */ + sizeof(TPM_COMMAND_CODE), &nOrdinal, /* 2S */ + outParamLength, outParamStart, /* 3S - ...*/ + 0, NULL); + if (rc == 0) { + TPM_PrintFour(" TPM_GetOutParamDigest: outParamDigest", outParamDigest); + } + } + } + return rc; +} + +/* TPM_ProcessAudit() rev 109 + + This function is called when command auditing is required. + + This function must be called after the output authorization, since it requires the (almost) final + return code. +*/ + +TPM_RESULT TPM_ProcessAudit(tpm_state_t *tpm_state, + TPM_BOOL transportEncrypt, /* wrapped in encrypt transport */ + TPM_DIGEST inParamDigest, + TPM_DIGEST outParamDigest, + TPM_COMMAND_CODE ordinal) +{ + TPM_RESULT rc = 0; /* audit return code */ + TPM_BOOL isZero; + TPM_RESULT nreturnCode; /* returnCode in nbo */ + TPM_COMMAND_CODE nOrdinal; /* ordinal in network byte order */ + TPM_DIGEST transportDigest; /* special case digest in encrypted transport */ + + printf(" TPM_ProcessAudit:\n"); + + /* The TPM will execute the ordinal and perform auditing in the following manner: */ + /* 1. Execute command */ + /* a. Execution implies the performance of the listed actions for the ordinal. */ + /* 2. If the command will return TPM_SUCCESS */ + /* a. If TPM_STANY_DATA -> auditDigest is all zeros */ + if (rc == 0) { + TPM_Digest_IsZero(&isZero, tpm_state->tpm_stclear_data.auditDigest); + if (isZero) { + /* i. Increment TPM_PERMANENT_DATA -> auditMonotonicCounter by 1 */ + tpm_state->tpm_permanent_data.auditMonotonicCounter.counter++; + printf(" TPM_ProcessAudit: Incrementing auditMonotonicCounter to %u\n", + tpm_state->tpm_permanent_data.auditMonotonicCounter.counter); + rc = TPM_PermanentAll_NVStore(tpm_state, + TRUE, /* write NV */ + 0); /* no roll back */ + } + } + /* b. Create A1 a TPM_AUDIT_EVENT_IN structure */ + /* i. Set A1 -> inputParms to the digest of the input parameters from the command */ + /* (1) Digest value according to the HMAC digest rules of the "above the line" parameters + (i.e. the first HMAC digest calculation). */ + /* ii. Set A1 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */ + /* c. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A1) */ + if (rc == 0) { + /* normal case, audit uses inParamDigest */ + if (!transportEncrypt) { + rc = TPM_AuditDigest_ExtendIn(tpm_state, inParamDigest); + } + /* 1. When the wrapped command requires auditing and the transport session specifies + encryption, the TPM MUST perform the audit. However, when computing the audit digest: + */ + else { + /* a. For input, only the ordinal is audited. */ + if (rc == 0) { + nOrdinal = htonl(ordinal); + rc = TPM_SHA1(transportDigest, + sizeof(TPM_COMMAND_CODE), &nOrdinal, + 0, NULL); + } + if (rc == 0) { + rc = TPM_AuditDigest_ExtendIn(tpm_state, transportDigest); + } + } + } + /* d. Create A2 a TPM_AUDIT_EVENT_OUT structure */ + /* i. Set A2 -> outputParms to the digest of the output parameters from the command */ + /* (1). Digest value according to the HMAC digest rules of the "above the line" parameters + (i.e. the first HMAC digest calculation). */ + /* ii. Set A2 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */ + /* e. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A2) */ + + /* Audit Generation Corner cases 3.a. TPM_SaveState: Only the input parameters are audited, and + the audit occurs before the state is saved. If an error occurs while or after the state is + saved, the audit still occurs. + */ + if ((rc == 0) && (ordinal != TPM_ORD_SaveState)) { + /* normal case, audit uses outParamDigest */ + if (!transportEncrypt) { + rc = TPM_AuditDigest_ExtendOut(tpm_state, outParamDigest); + } + /* 1. When the wrapped command requires auditing and the transport session specifies + encryption, the TPM MUST perform the audit. However, when computing the audit digest: + */ + else { + /* b. For output, only the ordinal and return code are audited. */ + if (rc == 0) { + nreturnCode = htonl(TPM_SUCCESS); /* only called when TPM_SUCCESS */ + nOrdinal = htonl(ordinal); + rc = TPM_SHA1(transportDigest, + sizeof(TPM_RESULT), &nreturnCode, + sizeof(TPM_COMMAND_CODE), &nOrdinal, + 0, NULL); + } + if (rc == 0) { + rc = TPM_AuditDigest_ExtendOut(tpm_state, transportDigest); + } + } + } + /* 1. When, in performing the audit process, the TPM has an internal failure (unable to write, + SHA-1 failure etc.) the TPM MUST set the internal TPM state such that the TPM returns the + TPM_FAILEDSELFTEST error on subsequent attempts to execute a command. */ + /* 2. The return code for the command uses the following rules */ + /* a. Command result success, audit success -> return TPM_SUCCESS */ + /* b. Command result failure, no audit -> return command result failure */ + /* c. Command result success, audit failure -> return TPM_AUDITFAIL_SUCCESSFUL */ + /* 3. If the TPM is permanently nonrecoverable after an audit failure, then the TPM MUST always + return TPM_FAILEDSELFTEST for every command other than TPM_GetTestResult. This state must + persist regardless of power cycling, the execution of TPM_Init or any other actions. */ + if (rc != 0) { + rc = TPM_AUDITFAIL_SUCCESSFUL; + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + return rc; +} + +/* + Processing Functions +*/ + +/* 7.1 TPM_GetCapability rev 99 + + This command returns current information regarding the TPM. + + The limitation on what can be returned in failure mode restricts the information a manufacturer + may return when capArea indicates TPM_CAP_MFR. +*/ + +TPM_RESULT TPM_Process_GetCapability(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_TAG returnCode = 0; /* command return code */ + + /* input parameters */ + TPM_CAPABILITY_AREA capArea; /* Partition of capabilities to be interrogated */ + TPM_SIZED_BUFFER subCap; /* Further definition of information */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE;/* wrapped in encrypted transport session */ + uint16_t subCap16 = 0; /* the subCap as a uint16_t */ + uint32_t subCap32 = 0; /* the subCap as a uint32_t */ + TPM_STORE_BUFFER capabilityResponse; /* response */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_GetCapability: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&subCap); /* freed @1 */ + TPM_Sbuffer_Init(&capabilityResponse); /* freed @2 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get capArea parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&capArea, &command, ¶mSize); + } + /* get subCap parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetCapability: capArea %08x\n", capArea); + returnCode = TPM_SizedBuffer_Load(&subCap, &command, ¶mSize); + } + /* subCap is often a uint16_t or uint32_t, create them now */ + if (returnCode == TPM_SUCCESS) { + TPM_GetSubCapInt(&subCap16, &subCap32, &subCap); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + /* The shutdown test is delayed until after the subcap is calculated */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_NO_LOCKOUT); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetCapability: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + check state + */ + /* 1. The TPM validates the capArea and subCap indicators. If the information is available, the + TPM creates the response field and fills in the actual information. */ + /* 2. The structure document contains the list of caparea and subCap values */ + if (returnCode == TPM_SUCCESS) { + /* 3. If the TPM is in failure mode or limited operation mode, the TPM MUST return */ + if ((tpm_state->testState == TPM_TEST_STATE_FAILURE) || + (tpm_state->testState == TPM_TEST_STATE_LIMITED)) { + /* a. TPM_CAP_VERSION */ + /* b. TPM_CAP_VERSION_VAL */ + /* c. TPM_CAP_MFR */ + /* d. TPM_CAP_PROPERTY -> TPM_CAP_PROP_MANUFACTURER */ + /* e. TPM_CAP_PROPERTY -> TPM_CAP_PROP_DURATION */ + /* f. TPM_CAP_PROPERTY -> TPM_CAP_PROP_TIS_TIMEOUT */ + /* g. The TPM MAY return any other capability. */ + if ( + !(capArea == TPM_CAP_VERSION) && + !(capArea == TPM_CAP_VERSION_VAL) && + !(capArea == TPM_CAP_MFR) && + !((capArea == TPM_CAP_PROPERTY) && (subCap32 == TPM_CAP_PROP_MANUFACTURER)) && + !((capArea == TPM_CAP_PROPERTY) && (subCap32 == TPM_CAP_PROP_DURATION)) && + !((capArea == TPM_CAP_PROPERTY) && (subCap32 == TPM_CAP_PROP_TIS_TIMEOUT)) + ) { + if (tpm_state->testState == TPM_TEST_STATE_FAILURE) { + printf("TPM_Process_GetCapability: Error, shutdown capArea %08x subCap %08x\n", + capArea, subCap32); + returnCode = TPM_FAILEDSELFTEST; + } + else { + printf("TPM_Process_GetCapability: Limited operation, run self-test\n"); + returnCode = TPM_ContinueSelfTestCmd(tpm_state); + } + } + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetCapability: capArea %08x subCap32 subCap16 %08x %04x\n", + capArea, subCap32, subCap16); + returnCode = TPM_GetCapabilityCommon(&capabilityResponse, tpm_state, + capArea, subCap16, subCap32, &subCap); + } + /* + response + */ + if (rcf == 0) { + printf("TPM_Process_GetCapability: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* store the capabilityResponse */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &capabilityResponse); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&subCap); /* @1 */ + TPM_Sbuffer_Delete(&capabilityResponse); /* @2 */ + return rcf; +} + +/* TPM_GetSubCapInt() converts from a TPM_SIZED_BUFFER to either a uint16_t or uint32_t as + applicable + + No return code is needed. If the size it not applicable, a 0 value is returned, which is + (fortunately) always illegal for subCap integral values. +*/ + +void TPM_GetSubCapInt(uint16_t *subCap16, + uint32_t *subCap32, + TPM_SIZED_BUFFER *subCap) +{ + *subCap16 = 0; /* default, means was not a uint16_t */ + *subCap32 = 0; /* default, means was not a uint32_t */ + if (subCap->size == sizeof(uint32_t)) { + *subCap32 = htonl(*(uint32_t *)subCap->buffer); + printf(" TPM_GetSubCapInt: subCap %08x\n", *subCap32); + } + else if (subCap->size == sizeof(uint16_t)) { + *subCap16 = htons(*(uint16_t *)subCap->buffer); + printf(" TPM_GetSubCapInt: subCap %04x\n", *subCap16); + } +} + + +/* TPM_GetCapabilityCommon() is common code for getting a capability. + + It loads the result to 'capabilityResponse' + + A previously called TPM_GetSubCapInt() converts the subCap buffer into a subCap16 if the size is + 2 or subCap32 if the size is 4. If the values are used, this function checks the size to ensure + that the incoming subCap parameter was correct for the capArea. +*/ + +TPM_RESULT TPM_GetCapabilityCommon(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + TPM_CAPABILITY_AREA capArea, + uint16_t subCap16, + uint32_t subCap32, + TPM_SIZED_BUFFER *subCap) + +{ + TPM_RESULT rc = 0; + + printf(" TPM_GetCapabilityCommon: capArea %08x\n", capArea); + switch (capArea) { + case TPM_CAP_ORD: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapOrd(capabilityResponse, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_ALG: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapAlg(capabilityResponse, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_PID: + if (subCap->size == sizeof(uint16_t)) { + rc = TPM_GetCapability_CapPid(capabilityResponse, subCap16); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_FLAG: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapFlag(capabilityResponse, tpm_state, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_PROPERTY: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapProperty(capabilityResponse, tpm_state, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_VERSION: + rc = TPM_GetCapability_CapVersion(capabilityResponse); + break; + case TPM_CAP_KEY_HANDLE: + /* This is command is available for backwards compatibility. It is the same as + TPM_CAP_HANDLE with a resource type of keys. */ + rc = TPM_KeyHandleEntries_StoreHandles(capabilityResponse, + tpm_state->tpm_key_handle_entries); + break; + case TPM_CAP_CHECK_LOADED: + rc = TPM_GetCapability_CapCheckLoaded(capabilityResponse, + tpm_state->tpm_key_handle_entries, + subCap); + break; + case TPM_CAP_SYM_MODE: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapSymMode(capabilityResponse, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_KEY_STATUS: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapKeyStatus(capabilityResponse, + tpm_state->tpm_key_handle_entries, + subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_NV_LIST: + rc = TPM_NVIndexEntries_GetNVList(capabilityResponse, &(tpm_state->tpm_nv_index_entries)); + break; + case TPM_CAP_MFR: + rc = TPM_GetCapability_CapMfr(capabilityResponse, tpm_state, subCap); + break; + case TPM_CAP_NV_INDEX: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapNVIndex(capabilityResponse, tpm_state, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_TRANS_ALG: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapTransAlg(capabilityResponse, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_HANDLE: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapHandle(capabilityResponse, tpm_state, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_TRANS_ES: + if (subCap->size == sizeof(uint16_t)) { + rc = TPM_GetCapability_CapTransEs(capabilityResponse, subCap16); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_AUTH_ENCRYPT: + if (subCap->size == sizeof(uint32_t)) { + rc = TPM_GetCapability_CapAuthEncrypt(capabilityResponse, subCap32); + } + else { + printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; + case TPM_CAP_SELECT_SIZE: + rc = TPM_GetCapability_CapSelectSize(capabilityResponse, subCap); + break; +#if (TPM_REVISION >= 103) /* added for rev 103 */ + case TPM_CAP_DA_LOGIC: + rc = TPM_GetCapability_CapDaLogic(capabilityResponse, subCap, tpm_state); + break; +#endif + case TPM_CAP_VERSION_VAL: + rc = TPM_GetCapability_CapVersionVal(capabilityResponse, + &(tpm_state->tpm_permanent_data)); + break; + default: + printf("TPM_GetCapabilityCommon: Error, unsupported capArea %08x", capArea); + rc = TPM_BAD_MODE; + break; + } + return rc; +} + +/* Boolean value. + + TRUE indicates that the TPM supports the ordinal. + + FALSE indicates that the TPM does not support the ordinal. +*/ + +static TPM_RESULT TPM_GetCapability_CapOrd(TPM_STORE_BUFFER *capabilityResponse, + uint32_t ordinal) +{ + TPM_RESULT rc = 0; + tpm_process_function_t tpm_process_function; + TPM_BOOL supported; + + TPM_OrdinalTable_GetProcessFunction(&tpm_process_function, tpm_ordinal_table, ordinal); + /* determine of the ordinal is supported */ + if (tpm_process_function != TPM_Process_Unused) { + supported = TRUE; + } + /* if the processing function is 'Unused', it's not supported */ + else { + supported = FALSE; + } + printf(" TPM_GetCapability_CapOrd: Ordinal %08x, result %02x\n", + ordinal, supported); + rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); + return rc; +} + +/* algorithmID is TPM_ALG_XX: A value from TPM_ALGORITHM_ID + + Boolean value. TRUE means that the TPM supports the asymmetric algorithm for TPM_Sign, TPM_Seal, + TPM_UnSeal and TPM_UnBind and related commands. FALSE indicates that the asymmetric algorithm is + not supported for these types of commands. The TPM MAY return TRUE or FALSE for other than + asymmetric algorithms that it supports. Unassigned and unsupported algorithm IDs return FALSE. +*/ + +static TPM_RESULT TPM_GetCapability_CapAlg(TPM_STORE_BUFFER *capabilityResponse, + uint32_t algorithmID) +{ + TPM_RESULT rc = 0; + TPM_BOOL supported; + + printf(" TPM_GetCapability_CapAlg: algorithmID %08x\n", algorithmID); + if (algorithmID == TPM_ALG_RSA) { + supported = TRUE; + } + else { + supported = FALSE; + } + printf(" TPM_GetCapability_CapAlg: Result %08x\n", supported); + rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); + return rc; +} + +/* Boolean value. + + TRUE indicates that the TPM supports the protocol, + + FALSE indicates that the TPM does not support the protocol. +*/ + +static TPM_RESULT TPM_GetCapability_CapPid(TPM_STORE_BUFFER *capabilityResponse, + uint16_t protocolID) +{ + TPM_RESULT rc = 0; + TPM_BOOL supported; + + printf(" TPM_GetCapability_CapPid: protocolID %04hx\n", protocolID); + switch (protocolID) { + /* supported protocols */ + case TPM_PID_OIAP: + case TPM_PID_OSAP: + case TPM_PID_ADIP: + case TPM_PID_ADCP: + case TPM_PID_DSAP: + case TPM_PID_TRANSPORT: + case TPM_PID_OWNER: + supported = TRUE; + break; + /* unsupported protocols */ + default: + supported = FALSE; + break; + } + printf(" TPM_GetCapability_CapPid: Result %08x\n", supported); + rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); + return rc; +} + +/* + Either of the next two subcaps + + TPM_CAP_FLAG_PERMANENT Return the TPM_PERMANENT_FLAGS structure + + TPM_CAP_FLAG_VOLATILE Return the TPM_STCLEAR_FLAGS structure +*/ + +static TPM_RESULT TPM_GetCapability_CapFlag(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + uint32_t capFlag) +{ + TPM_RESULT rc = 0; + + printf(" TPM_GetCapability_CapFlag: capFlag %08x\n", capFlag); + switch (capFlag) { + case TPM_CAP_FLAG_PERMANENT: + printf(" TPM_GetCapability_CapFlag: TPM_CAP_FLAG_PERMANENT\n");; + rc = TPM_PermanentFlags_StoreBytes(capabilityResponse, &(tpm_state->tpm_permanent_flags)); + break; + case TPM_CAP_FLAG_VOLATILE: + printf(" TPM_GetCapability_CapFlag: TPM_CAP_FLAG_VOLATILE\n"); + rc = TPM_StclearFlags_Store(capabilityResponse, &(tpm_state->tpm_stclear_flags)); + break; + default: + printf("TPM_GetCapability_CapFlag: Error, illegal capFlag %08x\n", capFlag); + rc = TPM_BAD_MODE; + break; + } + return rc; +} + +/* TPM_GetCapability_CapProperty() handles Subcap values for CAP_PROPERTY rev 100 + */ + +static TPM_RESULT TPM_GetCapability_CapProperty(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + uint32_t capProperty) +{ + TPM_RESULT rc = 0; + uint32_t uint32; + uint32_t uint32a; + uint32_t dummy; /* to hold unused response parameter */ + + printf(" TPM_GetCapability_CapProperty: capProperty %08x\n", capProperty); + switch (capProperty) { + case TPM_CAP_PROP_PCR: /* Returns the number of PCR registers supported by the TPM */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_PCR %u\n", TPM_NUM_PCR); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_NUM_PCR); + break; + case TPM_CAP_PROP_DIR: /* Returns the number of DIR registers under control of the TPM + owner supported by the TPM. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DIR %u\n", TPM_AUTHDIR_SIZE); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_AUTHDIR_SIZE); + break; + case TPM_CAP_PROP_MANUFACTURER: /* Returns the Identifier of the TPM manufacturer. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MANUFACTURER %.4s\n", + TPM_MANUFACTURER); + rc = TPM_Sbuffer_Append(capabilityResponse, (const unsigned char *)TPM_MANUFACTURER, 4); + break; + case TPM_CAP_PROP_KEYS: /* Returns the number of 2048-bit RSA keys that can be loaded. This + MAY vary with time and circumstances. */ + TPM_KeyHandleEntries_GetSpace(&uint32, tpm_state->tpm_key_handle_entries); + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_KEYS %u\n", uint32); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); + break; + case TPM_CAP_PROP_MIN_COUNTER: /* uint32_t. The minimum amount of time in 10ths of a second + that must pass between invocations of incrementing the + monotonic counter. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MIN_COUNTER\n"); + rc = TPM_Sbuffer_Append32(capabilityResponse, 0); + break; + case TPM_CAP_PROP_AUTHSESS: /* The number of available authorization sessions. This MAY + vary with time and circumstances. */ + TPM_AuthSessions_GetSpace(&uint32, tpm_state->tpm_stclear_data.authSessions); + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_AUTHSESS space %u\n", uint32); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); + break; + case TPM_CAP_PROP_TRANSESS: /* The number of available transport sessions. This MAY vary + with time and circumstances. */ + TPM_TransportSessions_GetSpace(&uint32, tpm_state->tpm_stclear_data.transSessions); + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_TRANSESS space %u\n", uint32); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); + break; + case TPM_CAP_PROP_COUNTERS: /* The number of available monotonic counters. This MAY vary + with time and circumstances. */ + TPM_Counters_GetSpace(&uint32, tpm_state->tpm_permanent_data.monotonicCounter); + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_COUNTERS %u\n", uint32); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); + break; + case TPM_CAP_PROP_MAX_AUTHSESS: /* The maximum number of loaded authorization sessions the + TPM supports. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_AUTHSESS %u\n", + TPM_MIN_AUTH_SESSIONS); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_AUTH_SESSIONS); + break; + case TPM_CAP_PROP_MAX_TRANSESS: /* The maximum number of loaded transport sessions the TPM + supports. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_TRANSESS %u\n", + TPM_MIN_TRANS_SESSIONS); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_TRANS_SESSIONS); + break; + case TPM_CAP_PROP_MAX_COUNTERS: /* The maximum number of monotonic counters under control of + TPM_CreateCounter */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_COUNTERS %u\n", + TPM_MIN_COUNTERS); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_COUNTERS); + break; + case TPM_CAP_PROP_MAX_KEYS: /* The maximum number of 2048 RSA keys that the TPM can + support. The number does not include the EK or SRK. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_KEYS %u\n", TPM_KEY_HANDLES); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_KEY_HANDLES); + break; + case TPM_CAP_PROP_OWNER: /* A value of TRUE indicates that the TPM has successfully installed + an owner. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_OWNER %02x\n", + tpm_state->tpm_permanent_data.ownerInstalled); + rc = TPM_Sbuffer_Append(capabilityResponse, + &(tpm_state->tpm_permanent_data.ownerInstalled), sizeof(TPM_BOOL)); + break; + case TPM_CAP_PROP_CONTEXT: /* The number of available saved session slots. This MAY + vary with time and circumstances. */ + TPM_ContextList_GetSpace(&uint32, &dummy, tpm_state->tpm_stclear_data.contextList); + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_CONTEXT %u\n", uint32); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); + break; + case TPM_CAP_PROP_MAX_CONTEXT: /* The maximum number of saved session slots. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_CONTEXT %u\n", + TPM_MIN_SESSION_LIST); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_SESSION_LIST); + break; + case TPM_CAP_PROP_FAMILYROWS: /* The number of rows in the family table */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_FAMILYROWS %u\n", + TPM_NUM_FAMILY_TABLE_ENTRY_MIN); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_NUM_FAMILY_TABLE_ENTRY_MIN); + break; + case TPM_CAP_PROP_TIS_TIMEOUT: + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_TIS_TIMEOUT\n"); + rc = TPM_GetCapability_CapPropTisTimeout(capabilityResponse); + break; + case TPM_CAP_PROP_STARTUP_EFFECT: /* The TPM_STARTUP_EFFECTS structure */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_STARTUP_EFFECT %08x\n", + TPM_STARTUP_EFFECTS_VALUE); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_STARTUP_EFFECTS_VALUE); + break; + case TPM_CAP_PROP_DELEGATE_ROW: /* The size of the delegate table in rows. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DELEGATE_ENTRIES %u\n", + TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); + break; + case TPM_CAP_PROP_MAX_DAASESS: /* The maximum number of loaded DAA sessions (join or sign) + that the TPM supports */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DAA_MAX\n"); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_DAA_SESSIONS); + break; + case TPM_CAP_PROP_DAASESS: /* The number of available DAA sessions. This may vary with + time and circumstances */ + TPM_DaaSessions_GetSpace(&uint32, tpm_state->tpm_stclear_data.daaSessions); + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_SESSION_DAA space %u\n", uint32); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); + break; + case TPM_CAP_PROP_CONTEXT_DIST: /* The maximum distance between context count values. This + MUST be at least 2^16-1. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_CONTEXT_DIST\n"); + rc = TPM_Sbuffer_Append32(capabilityResponse, 0xffffffff); + break; + case TPM_CAP_PROP_DAA_INTERRUPT: /* BOOL. A value of TRUE indicates that the TPM will accept + ANY command while executing a DAA Join or Sign. + + A value of FALSE indicates that the TPM will invalidate + the DAA Join or Sign upon the receipt of any command + other than the next join/sign in the session or a + TPM_SaveContext */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DAA_INTERRUPT\n"); + rc = TPM_Sbuffer_Append8(capabilityResponse, TRUE); + break; + case TPM_CAP_PROP_SESSIONS: /* UNIT32. The number of available authorization and transport + sessions from the pool. This may vary with time and + circumstances. */ + TPM_AuthSessions_GetSpace(&uint32, tpm_state->tpm_stclear_data.authSessions); + TPM_TransportSessions_GetSpace(&uint32a, tpm_state->tpm_stclear_data.transSessions); + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_SESSIONS %u + %u\n", uint32, uint32a); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32 + uint32a); + break; + case TPM_CAP_PROP_MAX_SESSIONS: /* uint32_t. The maximum number of sessions the + TPM supports. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_SESSIONS\n"); + rc = TPM_Sbuffer_Append32(capabilityResponse, + TPM_MIN_AUTH_SESSIONS + TPM_MIN_TRANS_SESSIONS); + break; + case TPM_CAP_PROP_CMK_RESTRICTION: /* uint32_t TPM_Permanent_Data -> restrictDelegate */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_CMK_RESTRICTION %08x\n", + tpm_state->tpm_permanent_data.restrictDelegate); + rc = TPM_Sbuffer_Append32(capabilityResponse, + tpm_state->tpm_permanent_data.restrictDelegate); + break; + case TPM_CAP_PROP_DURATION: + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DURATION\n"); + rc = TPM_GetCapability_CapPropDuration(capabilityResponse); + break; + case TPM_CAP_PROP_ACTIVE_COUNTER: /* TPM_COUNT_ID. The id of the current counter. 0xff..ff if + no counter is active */ + TPM_Counters_GetActiveCounter(&uint32, tpm_state->tpm_stclear_data.countID); + /* The illegal value after releasing an active counter must be mapped back to the null + value */ + if (uint32 == TPM_COUNT_ID_ILLEGAL) { + uint32 = TPM_COUNT_ID_NULL; + } + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_ACTIVE_COUNTER %u\n", uint32); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); + break; + case TPM_CAP_PROP_MAX_NV_AVAILABLE: /* uint32_t. Deprecated. The maximum number of NV space + that can be allocated, MAY vary with time and + circumstances. This capability was not implemented + consistently, and is replaced by + TPM_NV_INDEX_TRIAL. */ + rc = TPM_NVIndexEntries_GetFreeSpace(&uint32, &(tpm_state->tpm_nv_index_entries)); + if (rc == 0) { + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_NV_AVAILABLE %u\n", uint32); + rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); + } + /* There should always be free space >= 0. If the call fails here, there is an internal + error. */ + else { + printf(" TPM_GetCapability_CapProperty: Error (fatal) " + "in TPM_CAP_PROP_MAX_NV_AVAILABLE\n"); + rc = TPM_FAIL; + } + break; + case TPM_CAP_PROP_INPUT_BUFFER: /* uint32_t. The size of the TPM input and output buffers in + bytes. */ + printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_INPUT_BUFFER %u\n", + TPM_BUFFER_MAX); + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_BUFFER_MAX); + break; + default: + printf("TPM_GetCapability_CapProperty: Error, illegal capProperty %08x\n", capProperty); + rc = TPM_BAD_MODE; + break; + } + return rc; +} + +/* TPM_VERSION structure. The Major and Minor must indicate 1.1. + + The manufacturer information MUST indicate the firmware version of the TPM. + + Any software using this structure MUST be aware that when included in a structure the value MUST + be 1.1.0.0, when reported by this command the manufacturer information MAY include firmware + versions. The use of this value is deprecated, new software SHOULD use TPM_CAP_VERSION_VAL to + obtain version information regarding the TPM. + + Return 0.0 for revision for 1.1 backward compatibility, since TPM_PERMANENT_DATA now holds the + new type TPM_VERSION_BYTE. +*/ + +static TPM_RESULT TPM_GetCapability_CapVersion(TPM_STORE_BUFFER *capabilityResponse) +{ + TPM_RESULT rc = 0; + TPM_STRUCT_VER tpm_struct_ver; + + TPM_StructVer_Init(&tpm_struct_ver); + printf(" TPM_GetCapability_CapVersion: %u.%u.%u.%u\n", + tpm_struct_ver.major, tpm_struct_ver.minor, + tpm_struct_ver.revMajor, tpm_struct_ver.revMinor); + rc = TPM_StructVer_Store(capabilityResponse, &tpm_struct_ver); + return rc; +} + +/* A Boolean value. + + TRUE indicates that the TPM has enough memory available to load a key of the type specified by + ALGORITHM. + + FALSE indicates that the TPM does not have enough memory. +*/ + +static TPM_RESULT TPM_GetCapability_CapCheckLoaded(TPM_STORE_BUFFER *capabilityResponse, + const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry, + TPM_SIZED_BUFFER *subCap) +{ + TPM_RESULT rc = 0; + uint32_t stream_size; + unsigned char *stream; + TPM_KEY_PARMS keyParms; + TPM_BOOL isSpace; + uint32_t index; + + TPM_KeyParms_Init(&keyParms); /* freed @1 */ + if (rc == 0) { + /* make temporary copies so the subCap is not touched */ + stream = subCap->buffer; + stream_size = subCap->size; + rc = TPM_KeyParms_Load(&keyParms, &stream, &stream_size); + } + if (rc == 0) { + if (keyParms.algorithmID == TPM_ALG_RSA) { + TPM_KeyHandleEntries_IsSpace(&isSpace, &index, tpm_key_handle_entry); + } + else { + printf(" TPM_GetCapability_CapCheckLoaded: algorithmID %08x is not TPM_ALG_RSA %08x\n", + keyParms.algorithmID, TPM_ALG_RSA); + isSpace = FALSE; + } + } + if (rc == 0) { + printf(" TPM_GetCapability_CapCheckLoaded: Return %02x\n", isSpace); + rc = TPM_Sbuffer_Append(capabilityResponse, &isSpace, sizeof(TPM_BOOL)); + } + TPM_KeyParms_Delete(&keyParms); /* @1 */ + return rc; +} + +/* (Deprecated) This indicates the mode of a symmetric encryption. Mode is Electronic CookBook (ECB) + or some other such mechanism. +*/ + +static TPM_RESULT TPM_GetCapability_CapSymMode(TPM_STORE_BUFFER *capabilityResponse, + TPM_SYM_MODE symMode) +{ + TPM_RESULT rc = 0; + + symMode = symMode; /* not currently used */ + printf(" TPM_GetCapability_CapSymMode: Return %02x\n", FALSE); + rc = TPM_Sbuffer_Append8(capabilityResponse, FALSE); + return rc; +} + +/* Boolean value of ownerEvict. The handle MUST point to a valid key handle. + */ + +static TPM_RESULT TPM_GetCapability_CapKeyStatus(TPM_STORE_BUFFER *capabilityResponse, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, + uint32_t tpm_key_handle) +{ + TPM_RESULT rc = 0; + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* corresponding to handle */ + TPM_BOOL ownerEvict; + + printf(" TPM_GetCapability_CapKeyStatus: key handle %08x\n", tpm_key_handle); + /* map from the handle to the TPM_KEY structure */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_key_handle_entries, + tpm_key_handle); + if (rc != 0) { + printf("TPM_GetCapability_CapKeyStatus: Error, key handle %08x not found\n", + tpm_key_handle); + } + } + /* test the ownerEvict bit */ + if (rc == 0) { + ownerEvict = (tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) ? + TRUE : FALSE;; + printf(" TPM_GetCapability_CapKeyStatus: return %02x\n", ownerEvict); + rc = TPM_Sbuffer_Append(capabilityResponse, &ownerEvict, sizeof(TPM_BOOL)); + } + return rc; +} + +/* Manufacturer specific. The manufacturer may provide any additional information regarding the TPM + and the TPM state but MUST not expose any sensitive information. +*/ + +static TPM_RESULT TPM_GetCapability_CapMfr(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + TPM_SIZED_BUFFER *subCap) +{ + TPM_RESULT rc = 0; + uint32_t subCap32; + + /* all of the subCaps are at least a uint32_t. Some have more data */ + if (rc == 0) { + if (subCap->size >= sizeof(uint32_t)) { + subCap32 = htonl(*(uint32_t *)subCap->buffer); + printf(" TPM_GetCapability_CapMfr: subCap %08x\n", subCap32); + } + else { + printf("TPM_GetCapability_CapMfr: Error, subCap size %u < %lu\n", + subCap->size, (unsigned long)sizeof(uint32_t)); + rc = TPM_BAD_MODE; + } + } + /* switch on the subCap and append the get capability response to the capabilityResponse + buffer */ + if (rc == 0) { + switch(subCap32) { +#ifdef TPM_POSIX + case TPM_CAP_PROCESS_ID: + if (subCap->size == sizeof(uint32_t)) { + pid_t pid = getpid(); + printf(" TPM_GetCapability_CapMfr: TPM_CAP_PROCESS_ID %u\n", (uint32_t)pid); + rc = TPM_Sbuffer_Append32(capabilityResponse, (uint32_t)pid); + } + else { + printf("TPM_GetCapability_CapMfr: Error, Bad subCap size %u\n", subCap->size); + rc = TPM_BAD_MODE; + } + break; +#endif + default: + capabilityResponse = capabilityResponse; /* not used */ + tpm_state = tpm_state; /* not used */ + printf("TPM_GetCapability_CapMfr: Error, unsupported subCap %08x\n", subCap32); + rc = TPM_BAD_MODE; + break; + } + } + return rc; +} + +/* Returns a TPM_NV_DATA_PUBLIC structure that indicates the values for the TPM_NV_INDEX +*/ + +static TPM_RESULT TPM_GetCapability_CapNVIndex(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + uint32_t nvIndex) +{ + TPM_RESULT rc = 0; + TPM_NV_DATA_PUBLIC *tpm_nv_data_public; + + printf(" TPM_GetCapability_CapNVIndex: nvIndex %08x\n", nvIndex); + /* map from the nvIndex to the TPM_NV_DATA_PUBLIC structure */ + if (rc == 0) { + rc = TPM_NVIndexEntries_GetDataPublic(&tpm_nv_data_public, + &(tpm_state->tpm_nv_index_entries), + nvIndex); + } + /* serialize the structure */ + if (rc == 0) { + rc = TPM_NVDataPublic_Store(capabilityResponse, tpm_nv_data_public, + FALSE); /* do not optimize digestAtRelease */ + } + return rc; +} + +/* Returns a Boolean value. + + TRUE means that the TPM supports the algorithm for TPM_EstablishTransport, TPM_ExecuteTransport + and TPM_ReleaseTransportSigned. + + FALSE indicates that for these three commands the algorithm is not supported." +*/ + +static TPM_RESULT TPM_GetCapability_CapTransAlg(TPM_STORE_BUFFER *capabilityResponse, + TPM_ALGORITHM_ID algorithmID) +{ + TPM_RESULT rc = 0; + TPM_BOOL supported; + + printf(" TPM_GetCapability_CapTransAlg: algorithmID %08x\n", algorithmID); + TPM_TransportPublic_CheckAlgId(&supported, algorithmID); + printf(" TPM_GetCapability_CapTransAlg: Result %08x\n", supported); + rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); + return rc; +} + +/* Returns a TPM_KEY_HANDLE_LIST structure that enumerates all handles currently loaded in the TPM + for the given resource type. + + TPM_KEY_HANDLE_LIST is the number of handles followed by a list of the handles. + + When describing keys the handle list only contains the number of handles that an external manager + can operate with and does not include the EK or SRK. + + Legal resources are TPM_RT_KEY, TPM_RT_AUTH, TPM_RT_TRANS, TPM_RT_COUNTER + + TPM_RT_CONTEXT is valid and returns not a list of handles but a list of the context count values. +*/ + +static TPM_RESULT TPM_GetCapability_CapHandle(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + TPM_RESOURCE_TYPE resourceType) +{ + TPM_RESULT rc = 0; + + printf(" TPM_GetCapability_CapHandle: resourceType %08x\n", resourceType); + switch (resourceType) { + case TPM_RT_KEY: + printf(" TPM_GetCapability_CapHandle: TPM_RT_KEY\n"); + rc = TPM_KeyHandleEntries_StoreHandles(capabilityResponse, + tpm_state->tpm_key_handle_entries); + break; + case TPM_RT_AUTH: + printf(" TPM_GetCapability_CapHandle: TPM_RT_AUTH\n"); + rc = TPM_AuthSessions_StoreHandles(capabilityResponse, + tpm_state->tpm_stclear_data.authSessions); + break; + case TPM_RT_TRANS: + printf(" TPM_GetCapability_CapHandle: TPM_RT_TRANS\n"); + rc = TPM_TransportSessions_StoreHandles(capabilityResponse, + tpm_state->tpm_stclear_data.transSessions); + break; + case TPM_RT_CONTEXT: + printf(" TPM_GetCapability_CapHandle: TPM_RT_CONTEXT\n"); + rc = TPM_ContextList_StoreHandles(capabilityResponse, + tpm_state->tpm_stclear_data.contextList); + break; + case TPM_RT_COUNTER: + printf(" TPM_GetCapability_CapHandle: TPM_RT_COUNTER\n"); + rc = TPM_Counters_StoreHandles(capabilityResponse, + tpm_state->tpm_permanent_data.monotonicCounter); + break; + case TPM_RT_DAA_TPM: + printf(" TPM_GetCapability_CapHandle: TPM_RT_DAA_TPM\n"); + rc = TPM_DaaSessions_StoreHandles(capabilityResponse, + tpm_state->tpm_stclear_data.daaSessions); + break; + default: + printf("TPM_GetCapability_CapHandle: Error, illegal resource type %08x\n", + resourceType); + rc = TPM_BAD_PARAMETER; + } + return rc; +} + +/* Returns Boolean value. + + TRUE means the TPM supports the encryption scheme in a transport session. +*/ + +static TPM_RESULT TPM_GetCapability_CapTransEs(TPM_STORE_BUFFER *capabilityResponse, + TPM_ENC_SCHEME encScheme) +{ + TPM_RESULT rc = 0; + TPM_BOOL supported; + + printf(" TPM_GetCapability_CapTransEs: encScheme %04hx\n", encScheme); + switch (encScheme) { + /* supported protocols */ + case TPM_ES_SYM_CTR: + case TPM_ES_SYM_OFB: + supported = TRUE; + break; + /* unsupported protocols */ + case TPM_ES_RSAESPKCSv15: + case TPM_ES_RSAESOAEP_SHA1_MGF1: + default: + supported = FALSE; + break; + } + printf(" TPM_GetCapability_CapTransEs: Result %08x\n", supported); + rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); + return rc; +} + +/* Boolean value. + + TRUE indicates that the TPM supports the encryption algorithm in OSAP encryption of AuthData + values +*/ + +static TPM_RESULT TPM_GetCapability_CapAuthEncrypt(TPM_STORE_BUFFER *capabilityResponse, + TPM_ALGORITHM_ID algorithmID) +{ + TPM_RESULT rc = 0; + TPM_BOOL supported; + + printf(" TPM_GetCapability_CapAuthEncrypt: algorithmID %08x\n", algorithmID); + switch (algorithmID) { + case TPM_ALG_XOR: + case TPM_ALG_AES128: + /* supported protocols */ + supported = TRUE; + break; + case TPM_ALG_RSA: + case TPM_ALG_SHA: + case TPM_ALG_HMAC: + case TPM_ALG_MGF1: + case TPM_ALG_AES192: + case TPM_ALG_AES256: + default: + /* unsupported protocols */ + supported = FALSE; + break; + } + printf(" TPM_GetCapability_CapAuthEncrypt: Result %08x\n", supported); + rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); + return rc; +} + +/* Boolean value. + + TRUE indicates that the TPM supports the size for the given version. + + For instance a request could ask for version 1.1 size 2 and the TPM would indicate TRUE. For 1.1 + size 3 the TPM would indicate FALSE. For 1.2 size 3 the TPM would indicate TRUE. +*/ + +static TPM_RESULT TPM_GetCapability_CapSelectSize(TPM_STORE_BUFFER *capabilityResponse, + TPM_SIZED_BUFFER *subCap) +{ + TPM_RESULT rc = 0; + TPM_SELECT_SIZE tpm_select_size; + unsigned char *stream; + uint32_t stream_size; + TPM_BOOL supported; + + printf(" TPM_GetCapability_CapSelectSize:\n"); + TPM_SelectSize_Init(&tpm_select_size); /* no free required */ + /* deserialize the subCap to the structure */ + if (rc == 0) { + stream = subCap->buffer; + stream_size = subCap->size; + rc = TPM_SelectSize_Load(&tpm_select_size, &stream , &stream_size); + } + if (rc == 0) { + /* The TPM MUST return an error if sizeOfSelect is 0 */ + printf(" TPM_GetCapability_CapSelectSize: subCap reqSize %u\n", + tpm_select_size.reqSize); + if ((tpm_select_size.reqSize > (TPM_NUM_PCR/CHAR_BIT)) || + (tpm_select_size.reqSize == 0)) { + supported = FALSE; + } + else { + supported = TRUE; + } + } + if (rc == 0) { + printf(" TPM_GetCapability_CapSelectSize: Result %08x\n", supported); + rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); + } + return rc; +} + +#if (TPM_REVISION >= 103) /* added for rev 103 */ +/* TPM_GetCapability_CapDaLogic() rev 100 + + A TPM_DA_INFO or TPM_DA_INFO_LIMITED structure that returns data according to the selected entity + type (e.g., TPM_ET_KEYHANDLE, TPM_ET_OWNER, TPM_ET_SRK, TPM_ET_COUNTER, TPM_ET_OPERATOR, + etc.). If the implemented dictionary attack logic does not support different secret types, the + entity type can be ignored. +*/ + +static TPM_RESULT TPM_GetCapability_CapDaLogic(TPM_STORE_BUFFER *capabilityResponse, + TPM_SIZED_BUFFER *subCap, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_DA_INFO_LIMITED tpm_da_info_limited; + TPM_DA_INFO tpm_da_info; + + printf(" TPM_GetCapability_CapDaLogic:\n"); + TPM_DaInfoLimited_Init(&tpm_da_info_limited); /* freed @1 */ + TPM_DaInfo_Init(&tpm_da_info); /* freed @2 */ + subCap = subCap; /* dictionary attack mitigation not per entity type in this + implementation. */ + /* if disableFullDALogicInfo is TRUE, the full dictionary attack TPM_GetCapability info is + deactivated. The returned structure is TPM_DA_INFO_LIMITED. */ + if (tpm_state->tpm_permanent_flags.disableFullDALogicInfo) { + TPM_DaInfoLimited_Set(&tpm_da_info_limited, tpm_state); + rc = TPM_DaInfoLimited_Store(capabilityResponse, &tpm_da_info_limited); + + } + /* if disableFullDALogicInfo is FALSE, the full dictionary attack TPM_GetCapability + info is activated. The returned structure is + TPM_DA_INFO. */ + else { + TPM_DaInfo_Set(&tpm_da_info, tpm_state); + rc = TPM_DaInfo_Store(capabilityResponse, &tpm_da_info); + } + TPM_DaInfoLimited_Delete(&tpm_da_info_limited); /* @1 */ + TPM_DaInfo_Delete(&tpm_da_info); /* @2 */ + return rc; +} +#endif + +/* Returns TPM_CAP_VERSION_INFO structure. + + The TPM fills in the structure and returns the information indicating what the TPM currently + supports. +*/ + +static TPM_RESULT TPM_GetCapability_CapVersionVal(TPM_STORE_BUFFER *capabilityResponse, + TPM_PERMANENT_DATA *tpm_permanent_data) +{ + TPM_RESULT rc = 0; + TPM_CAP_VERSION_INFO tpm_cap_version_info; + + printf(" TPM_GetCapability_CapVersionVal:\n"); + TPM_CapVersionInfo_Set(&tpm_cap_version_info, tpm_permanent_data); /* freed @1 */ + printf(" TPM_GetCapability_CapVersionVal: specLevel %04hx\n", tpm_cap_version_info.specLevel); + printf(" TPM_GetCapability_CapVersionVal: errataRev %02x\n", tpm_cap_version_info.errataRev); + printf(" TPM_GetCapability_CapVersionVal: revMajor %02x revMinor %02x\n", + tpm_cap_version_info.version.revMajor, tpm_cap_version_info.version.revMinor); + printf(" TPM_GetCapability_CapVersionVal: tpmVendorID %02x %02x %02x %02x\n", + tpm_cap_version_info.tpmVendorID[0], + tpm_cap_version_info.tpmVendorID[1], + tpm_cap_version_info.tpmVendorID[2], + tpm_cap_version_info.tpmVendorID[3]); + rc = TPM_CapVersionInfo_Store(capabilityResponse, &tpm_cap_version_info); + TPM_CapVersionInfo_Delete(&tpm_cap_version_info); /* @1 */ + return rc; +} + +/* Returns a 4 element array of uint32_t values each denoting the timeout value in microseconds for + the following in this order: + + TIMEOUT_A, TIMEOUT_B, TIMEOUT_C, TIMEOUT_D + + Where these timeouts are to be used is determined by the platform specific TPM Interface + Specification. +*/ + +static TPM_RESULT TPM_GetCapability_CapPropTisTimeout(TPM_STORE_BUFFER *capabilityResponse) +{ + TPM_RESULT rc = 0; + + printf(" TPM_GetCapability_CapPropTisTimeout:\n"); + if (rc == 0) { + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_TIMEOUT_A); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_TIMEOUT_B); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_TIMEOUT_C); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_TIMEOUT_D); + } + return rc; +} + +/* Returns a 3 element array of uint32_t values each denoting the duration value in microseconds of + the duration of the three classes of commands: Small, Medium and Long in the following in this + order: + + SMALL_DURATION, MEDIUM_DURATION, LONG_DURATION +*/ + +static TPM_RESULT TPM_GetCapability_CapPropDuration(TPM_STORE_BUFFER *capabilityResponse) +{ + TPM_RESULT rc = 0; + + printf(" TPM_GetCapability_CapPropDuration:\n"); + if (rc == 0) { + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_SMALL_DURATION); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MEDIUM_DURATION); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_LONG_DURATION); + } + return rc; +} + +/* 7.3 TPM_GetCapabilityOwner rev 98 + + TPM_GetCapabilityOwner enables the TPM Owner to retrieve all the non-volatile flags and the + volatile flags in a single operation. This command is deprecated, mandatory. + + The flags summarize many operational aspects of the TPM. The information represented by some + flags is private to the TPM Owner. So, for simplicity, proof of ownership of the TPM must be + presented to retrieve the set of flags. When necessary, the flags that are not private to the + Owner can be deduced by Users via other (more specific) means. + + The normal TPM authentication mechanisms are sufficient to prove the integrity of the + response. No additional integrity check is required. + + For 31>=N>=0 + + 1. Bit-N of the TPM_PERMANENT_FLAGS structure is the Nth bit after the opening bracket in the + definition of TPM_PERMANENT_FLAGS in the version of the specification indicated by the parameter + "version". The bit immediately after the opening bracket is the 0th bit. + + 2. Bit-N of the TPM_STCLEAR_FLAGS structure is the Nth bit after the opening bracket in the + definition of TPM_STCLEAR_FLAGS in the version of the specification indicated by the parameter + "version". The bit immediately after the opening bracket is the 0th bit. + + 3. Bit-N of non_volatile_flags corresponds to the Nth bit in TPM_PERMANENT_FLAGS, and the lsb of + non_volatile_flags corresponds to bit0 of TPM_PERMANENT_FLAGS + + 4. Bit-N of volatile_flags corresponds to the Nth bit in TPM_STCLEAR_FLAGS, and the lsb of + volatile_flags corresponds to bit0 of TPM_STCLEAR_FLAGS +*/ + +TPM_RESULT TPM_Process_GetCapabilityOwner(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for Owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session */ + TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner + authentication. HMAC key: ownerAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_VERSION version; /* A properly filled out version structure. */ + uint32_t non_volatile_flags; /* The current state of the non-volatile flags. */ + uint32_t volatile_flags; /* The current state of the volatile flags. */ + + printf("TPM_Process_GetCapabilityOwner: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetCapabilityOwner: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. The TPM validates that the TPM Owner authorizes the command. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. The TPM creates the parameter non_volatile_flags by setting each bit to the same state as + the corresponding bit in TPM_PERMANENT_FLAGS. Bits in non_volatile_flags for which there is + no corresponding bit in TPM_PERMANENT_FLAGS are set to zero. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PermanentFlags_StoreBitmap(&non_volatile_flags, + &(tpm_state->tpm_permanent_flags)); + } + /* 3. The TPM creates the parameter volatile_flags by setting each bit to the same state as the + corresponding bit in TPM_STCLEAR_FLAGS. Bits in volatile_flags for which there is no + corresponding bit in TPM_STCLEAR_FLAGS are set to zero. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_StclearFlags_StoreBitmap(&volatile_flags, + &(tpm_state->tpm_stclear_flags)); + } + /* 4. The TPM generates the parameter "version". */ + if (returnCode == TPM_SUCCESS) { + TPM_Version_Set(&version, &(tpm_state->tpm_permanent_data)); + } + /* 5. The TPM returns non_volatile_flags, volatile_flags and version to the caller. */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_GetCapabilityOwner: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the version */ + returnCode = TPM_Version_Store(response, &version); + } + /* return the non_volatile_flags */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append32(response, non_volatile_flags); + } + /* return the volatile_flags */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append32(response, volatile_flags); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + return rcf; +} + +/* 29.1 TPM_GetCapabilitySigned rev 94 + + TPM_GetCapabilitySigned is almost the same as TPM_GetCapability. The differences are that the + input includes a challenge (a nonce) and the response includes a digital signature to vouch for + the source of the answer. + + If a caller itself requires proof, it is sufficient to use any signing key for which only the TPM + and the caller have AuthData. + + If a caller requires proof for a third party, the signing key must be one whose signature is + trusted by the third party. A TPM-identity key may be suitable. +*/ + +TPM_RESULT TPM_Process_GetCapabilitySigned(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The handle of a loaded key that can perform digital + signatures. */ + TPM_NONCE antiReplay; /* Nonce provided to allow caller to defend against replay + of messages */ + TPM_CAPABILITY_AREA capArea = 0; /* Partition of capabilities to be interrogated */ + TPM_SIZED_BUFFER subCap; /* Further definition of information */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle + authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the use + of keyHandle. HMAC key: key.usageAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE;/* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ + TPM_SECRET *keyUsageAuth; + TPM_BOOL parentPCRStatus; + uint16_t subCap16; /* the subCap as a uint16_t */ + uint32_t subCap32; /* the subCap as a uint32_t */ + TPM_STORE_BUFFER r1Response; /* capability response */ + const unsigned char *r1_buffer; /* r1 serialization */ + uint32_t r1_length; + TPM_DIGEST s1; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_VERSION version; /* A properly filled out version structure. */ + TPM_SIZED_BUFFER resp; /* The capability response */ + TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ + + printf("TPM_Process_GetCapabilitySigned: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&subCap); /* freed @1 */ + TPM_SizedBuffer_Init(&resp); /* freed @2 */ + TPM_SizedBuffer_Init(&sig); /* freed @3 */ + TPM_Sbuffer_Init(&r1Response); /* freed @4 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetCapabilitySigned: keyHandle %08x\n", keyHandle); + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* get capArea parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&capArea, &command, ¶mSize); + } + /* get get subCap parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&subCap, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetCapabilitySigned: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not r/o, used to sign */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* 1. The TPM validates the authority to use keyHandle */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (sigKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_GetCapabilitySigned: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + sigKey, + keyUsageAuth, /* OIAP */ + sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 1. The TPM MUST validate the authorization to use the key pointed to by keyHandle. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + + + /* subCap is often a uint16_t or uint32_t, create them now */ + if (returnCode == TPM_SUCCESS) { + TPM_GetSubCapInt(&subCap16, &subCap32, &subCap); + } + /* 2. The TPM calls TPM_GetCapability passing the capArea and subCap fields and saving the resp + field as R1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetCapabilityCommon(&r1Response, tpm_state, + capArea, subCap16, subCap32, &subCap); + } + if (returnCode == TPM_SUCCESS) { + /* get the capability r1 serialization */ + TPM_Sbuffer_Get(&r1Response, &r1_buffer, &r1_length); + printf("TPM_Process_GetCapabilitySigned: resp length %08x\n", r1_length); + TPM_PrintFour("TPM_Process_GetCapabilitySigned: Hashing resp", r1_buffer); + TPM_PrintFour("TPM_Process_GetCapabilitySigned: antiReplay", antiReplay); + /* 3. The TPM creates S1 by taking a SHA1 hash of the concatenation (r1 || antiReplay). */ + returnCode = TPM_SHA1(s1, + r1_length, r1_buffer, + TPM_NONCE_SIZE, antiReplay, + 0, NULL); + } + /* 4. The TPM validates the authority to use keyHandle */ + /* The key in keyHandle MUST have a KEYUSAGE value of type TPM_KEY_SIGNING or TPM_KEY_LEGACY or + TPM_KEY_IDENTITY. */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->keyUsage != TPM_KEY_SIGNING) && + ((sigKey->keyUsage) != TPM_KEY_IDENTITY) && + ((sigKey->keyUsage) != TPM_KEY_LEGACY)) { + printf("TPM_Process_GetCapabilitySigned: Error, keyUsage %04hx is invalid\n", + sigKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 5. The TPM creates a digital signature of S1 using the key in keyHandle and returns the + result in sig. */ + if (returnCode == TPM_SUCCESS) { + if (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { + printf("TPM_Process_GetCapabilitySigned: Error, inappropriate signature scheme %04x\n", + sigKey->algorithmParms.sigScheme); + returnCode = TPM_INAPPROPRIATE_SIG; + } + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_GetCapabilitySigned: Signing s1", s1); + returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ + s1, /* message */ + TPM_DIGEST_SIZE, /* message size */ + sigKey); /* signing key and parameters */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_GetCapabilitySigned: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the version */ + TPM_Version_Set(&version, &(tpm_state->tpm_permanent_data)); + returnCode = TPM_Version_Store(response, &version); + } + /* return the capability response size */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append32(response, r1_length); + } + /* return the capability response */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append(response, r1_buffer, r1_length); + } + /* return the signature */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Store(response, &sig); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&subCap); /* @1 */ + TPM_SizedBuffer_Delete(&resp); /* @2 */ + TPM_SizedBuffer_Delete(&sig); /* @3 */ + TPM_Sbuffer_Delete(&r1Response); /* @4 */ + return rcf; +} + +/* 7.2 TPM_SetCapability rev 96 + + This command sets values in the TPM +*/ + +TPM_RESULT TPM_Process_SetCapability(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_TAG returnCode = 0; /* command return code */ + + /* input parameters */ + TPM_CAPABILITY_AREA capArea; /* Partition of capabilities to be set */ + TPM_SIZED_BUFFER subCap; /* Further definition of information */ + TPM_SIZED_BUFFER setValue; /* The value to set */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the + authorization session handle */ + TPM_AUTHDATA ownerAuth; /* Authorization. HMAC key: owner.usageAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE;/* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ + TPM_SECRET *hmacKey; + uint16_t subCap16; /* the subCap as a uint16_t */ + uint32_t subCap32; /* the subCap as a uint32_t */ + TPM_BOOL ownerAuthorized = FALSE; /* TRUE if owner authorization validated */ + TPM_BOOL presenceAuthorized = FALSE; /* TRUE if physicalPresence validated */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SetCapability: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&subCap); /* freed @1 */ + TPM_SizedBuffer_Init(&setValue); /* freed @2 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get capArea parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&capArea, &command, ¶mSize); + } + /* get subCap parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SetCapability: capArea %08x \n", capArea); + returnCode = TPM_SizedBuffer_Load(&subCap, &command, ¶mSize); + } + /* get setValue parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&setValue , &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + ownerAuthorized = TRUE; + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SetCapability: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. If tag = TPM_TAG_RQU_AUTH1_COMMAND, validate the command and parameters using ownerAuth, + return TPM_AUTHFAIL on error */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&presenceAuthorized, tpm_state); + } + /* 2. The TPM validates the capArea and subCap indicators, including the ability to set value + based on any set restrictions */ + /* 3. If the capArea and subCap indicators conform with one of the entries in the structure + TPM_CAPABILITY_AREA (Values for TPM_SetCapability) */ + /* a. The TPM sets the relevant flag/data to the value of setValue parameter. */ + /* 4. Else */ + /* a. Return the error code TPM_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + /* subCap is often a uint16_t or uint32_t, create them now */ + TPM_GetSubCapInt(&subCap16, &subCap32, &subCap); + returnCode = TPM_SetCapabilityCommon(tpm_state, ownerAuthorized, presenceAuthorized, + capArea, subCap16, subCap32, &subCap, + &setValue); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SetCapability: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, terminate the session. */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&subCap); /* @1 */ + TPM_SizedBuffer_Delete(&setValue); /* @2 */ + return rcf; +} + +/* TPM_SetCapabilityCommon() is common code for setting a capability from setValue + + NOTE: This function assumes that the caller has validated either owner authorization or physical + presence! +*/ + +TPM_RESULT TPM_SetCapabilityCommon(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + TPM_CAPABILITY_AREA capArea, + uint16_t subCap16, + uint32_t subCap32, + TPM_SIZED_BUFFER *subCap, + TPM_SIZED_BUFFER *setValue) +{ + TPM_RESULT rc = 0; + TPM_BOOL valueBool; + uint32_t valueUint32 = 0; /* start with illegal value */ + + printf(" TPM_SetCapabilityCommon:\n"); + subCap16 = subCap16; /* not used */ + subCap = subCap; /* not used */ + if (rc == 0) { + if ((capArea == TPM_SET_PERM_FLAGS) || + (capArea == TPM_SET_STCLEAR_FLAGS) || + (capArea == TPM_SET_STANY_FLAGS)) { + rc = TPM_SizedBuffer_GetBool(&valueBool, setValue); + } + else if (((capArea == TPM_SET_PERM_DATA) && (subCap32 != TPM_PD_DAAPROOF)) || + (capArea == TPM_SET_STCLEAR_DATA)) { /* deferredPhysicalPresence */ + rc = TPM_SizedBuffer_GetUint32(&valueUint32, setValue); + } + } + if (rc == 0) { + switch (capArea) { + case TPM_SET_PERM_FLAGS: + rc = TPM_SetCapability_CapPermFlags(tpm_state, ownerAuthorized, presenceAuthorized, + subCap32, valueBool); + break; + case TPM_SET_PERM_DATA: + rc = TPM_SetCapability_CapPermData(tpm_state, ownerAuthorized, presenceAuthorized, + subCap32, valueUint32); + break; + case TPM_SET_STCLEAR_FLAGS: + rc = TPM_SetCapability_CapStclearFlags(tpm_state, ownerAuthorized, presenceAuthorized, + subCap32, valueBool); + break; + case TPM_SET_STCLEAR_DATA: + rc = TPM_SetCapability_CapStclearData(tpm_state, ownerAuthorized, presenceAuthorized, + subCap32, valueUint32); + break; + case TPM_SET_STANY_FLAGS: + rc = TPM_SetCapability_CapStanyFlags(tpm_state, ownerAuthorized, presenceAuthorized, + subCap32, valueBool); + break; + case TPM_SET_STANY_DATA: + rc = TPM_SetCapability_CapStanyData(tpm_state, ownerAuthorized, presenceAuthorized, + subCap32, setValue); + break; + case TPM_SET_VENDOR: + rc = TPM_SetCapability_CapVendor(tpm_state, ownerAuthorized, presenceAuthorized, + subCap32, setValue); + break; + default: + printf("TPM_SetCapabilityCommon: Error, unsupported capArea %08x", capArea); + rc = TPM_BAD_MODE; + break; + } + } + return rc; +} + +/* TPM_SetCapability_Flag() tests if the values are not already equal. If they are not, 'flag' is + set to 'value' and 'altered' is set TRUE. Otherwise 'altered' is returned unchanged. + + The 'altered' flag is used by the caller to determine if an NVRAM write is required. +*/ + +void TPM_SetCapability_Flag(TPM_BOOL *altered, + TPM_BOOL *flag, + TPM_BOOL value) +{ + /* If the values are not already equal. Can't use != since there are many values for TRUE. */ + if ((value && !*flag) || + (!value && *flag)) { + *altered = TRUE; + *flag = value; + } + return; +} + +/* TPM_SetCapability_CapPermFlags() rev 100 + + Sets TPM_PERMANENT_FLAGS values +*/ + +static TPM_RESULT TPM_SetCapability_CapPermFlags(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_BOOL valueBool) +{ + TPM_RESULT rc = 0; + TPM_BOOL altered = FALSE; /* TRUE if the structure has been changed */ + + printf(" TPM_SetCapability_CapPermFlags: valueBool %02x\n", valueBool); + if (rc == 0) { + switch (subCap32) { + case TPM_PF_DISABLE: + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_DISABLE\n"); + /* Owner authorization or physical presence + TPM_OwnerSetDisable + TPM_PhysicalEnable + TPM_PhysicalDisable + */ + if (rc == 0) { + if (!ownerAuthorized && !presenceAuthorized) { + printf("TPM_SetCapability_CapPermFlags: Error, no authorization\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.disable), + valueBool); + } + break; + case TPM_PF_OWNERSHIP: + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_OWNERSHIP\n"); + /* No authorization. No ownerInstalled. Physical presence asserted + Not available when TPM deactivated or disabled + TPM_SetOwnerInstall + */ + if (rc == 0) { + if (tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_SetCapability_CapPermFlags: Error, owner installed\n"); + rc = TPM_OWNER_SET; + } + } + if (rc == 0) { + if (!presenceAuthorized) { + printf("TPM_SetCapability_CapPermFlags: Error, no physicalPresence\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_SetCapability_CapPermFlags: Error, deactivated\n"); + rc = TPM_DEACTIVATED; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.ownership), + valueBool); + } + break; + case TPM_PF_DEACTIVATED: + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_DEACTIVATED\n"); + /* No authorization, physical presence assertion + Not available when TPM disabled + TPM_PhysicalSetDeactivated + */ + if (rc == 0) { + if (!presenceAuthorized) { + printf("TPM_SetCapability_CapPermFlags: Error, no physicalPresence\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.deactivated), + valueBool); + } + break; + case TPM_PF_READPUBEK: + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_READPUBEK\n"); + /* Owner authorization + Not available when TPM deactivated or disabled + */ + if (rc == 0) { + if (!ownerAuthorized) { + printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_SetCapability_CapPermFlags: Error, deactivated\n"); + rc = TPM_DEACTIVATED; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.readPubek), + valueBool); + } + if (rc == 0) { + printf(" TPM_SetCapability_CapPermFlags : readPubek %02x\n", + tpm_state->tpm_permanent_flags.readPubek); + } + break; + case TPM_PF_DISABLEOWNERCLEAR: + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_DISABLEOWNERCLEAR\n"); + /* Owner authorization. Can only set to TRUE, FALSE invalid value. + After being set only ForceClear resets back to FALSE. + Not available when TPM deactivated or disabled + TPM_DisableOwnerClear */ + if (rc == 0) { + if (!ownerAuthorized) { + printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + if (!valueBool) { + printf("TPM_SetCapability_CapPermFlags: Error, cannot set FALSE\n"); + rc = TPM_BAD_PARAMETER; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_SetCapability_CapPermFlags: Error, deactivated\n"); + rc = TPM_DEACTIVATED; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.disableOwnerClear), + valueBool); + } + break; + case TPM_PF_ALLOWMAINTENANCE: + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_ALLOWMAINTENANCE\n"); + /* Owner authorization. Can only set to FALSE, TRUE invalid value. + After being set only changing TPM owner resets back to TRUE + Not available when TPM deactivated or disabled + TPM_KillMaintenanceFeature + */ + if (rc == 0) { + if (!ownerAuthorized) { + printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + if (valueBool) { + printf("TPM_SetCapability_CapPermFlags: Error, cannot set TRUE\n"); + rc = TPM_BAD_PARAMETER; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_SetCapability_CapPermFlags: Error, deactivated\n"); + rc = TPM_DEACTIVATED; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.allowMaintenance), + valueBool); + } + break; + case TPM_PF_READSRKPUB: + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_READSRKPUB\n"); + /* Owner Authorization + Not available when TPM deactivated or disabled + TPM_SetCapability + */ + if (rc == 0) { + if (!ownerAuthorized) { + printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapPermFlags: Error, disable is TRUE\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_SetCapability_CapPermFlags: Error, deactivated is TRUE\n"); + rc = TPM_DEACTIVATED; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.readSRKPub), + valueBool); + } + break; + case TPM_PF_TPMESTABLISHED: + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_TPMESTABLISHED\n"); + /* Locality 3 or locality 4 + Can only set to FALSE + TPM_ResetEstablishmentBit + */ + if (rc == 0) { + rc = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, /* BYTE bitmap */ + tpm_state->tpm_stany_flags.localityModifier); + } + if (rc == 0) { + if (valueBool) { + printf("TPM_SetCapability_CapPermFlags: Error, can only set to FALSE\n"); + rc = TPM_BAD_PARAMETER; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.tpmEstablished), + valueBool); + } + break; +#if (TPM_REVISION >= 103) /* added for rev 103 */ + case TPM_PF_DISABLEFULLDALOGICINFO: + /* Owner Authorization + TPM_SetCapability + */ + printf(" TPM_SetCapability_CapPermFlags: TPM_PF_DISABLEFULLDALOGICINFO\n"); + if (rc == 0) { + if (!ownerAuthorized) { + printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.disableFullDALogicInfo), + valueBool); + } + break; +#endif + case TPM_PF_PHYSICALPRESENCELIFETIMELOCK: + case TPM_PF_PHYSICALPRESENCEHWENABLE: + case TPM_PF_PHYSICALPRESENCECMDENABLE: + case TPM_PF_CEKPUSED: + case TPM_PF_TPMPOST: + case TPM_PF_TPMPOSTLOCK: + case TPM_PF_FIPS: + case TPM_PF_OPERATOR: + case TPM_PF_ENABLEREVOKEEK: + case TPM_PF_NV_LOCKED: + case TPM_PF_MAINTENANCEDONE: + default: + printf("TPM_SetCapability_CapPermFlags: Error, bad subCap32 %u\n", + subCap32); + rc = TPM_BAD_PARAMETER; + } + } + rc = TPM_PermanentAll_NVStore(tpm_state, + altered, + rc); + return rc; +} + +/* TPM_SetCapability_CapPermData() rev 105 + + Sets TPM_PERMANENT_DATA values +*/ + +static TPM_RESULT TPM_SetCapability_CapPermData(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + uint32_t valueUint32) +{ + TPM_RESULT rc = 0; + TPM_BOOL writeAllNV = FALSE; /* TRUE if the structure has been changed */ + + printf(" TPM_SetCapability_CapPermData:\n"); + presenceAuthorized = presenceAuthorized; /* not used */ + if (rc == 0) { + switch (subCap32) { + case TPM_PD_RESTRICTDELEGATE: + printf(" TPM_SetCapability_CapPermData: TPM_PD_RESTRICTDELEGATE\n"); + /* Owner authorization. Not available when TPM deactivated or disabled */ + /* TPM_CMK_SetRestrictions */ + if (rc == 0) { + if (!ownerAuthorized) { + printf("TPM_SetCapability_CapPermData: Error, not owner authorized\n"); + rc = TPM_AUTHFAIL; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapPermData: Error, disabled\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_SetCapability_CapPermData: Error, deactivated\n"); + rc = TPM_DEACTIVATED; + } + } + if (rc == 0) { + if (tpm_state->tpm_permanent_data.restrictDelegate != valueUint32) { + tpm_state->tpm_permanent_data.restrictDelegate = valueUint32; + writeAllNV = TRUE; + } + } + break; + case TPM_PD_DAAPROOF: + /* TPM_PD_DAAPROOF This capability has no value. When specified by TPM_SetCapability, a + new daaProof, tpmDAASeed, and daaBlobKey are generated. */ + rc = TPM_PermanentData_InitDaa(&(tpm_state->tpm_permanent_data)); + writeAllNV = TRUE; + break; + case TPM_PD_REVMAJOR: + case TPM_PD_REVMINOR: + case TPM_PD_TPMPROOF: + case TPM_PD_OWNERAUTH: + case TPM_PD_OPERATORAUTH: + case TPM_PD_MANUMAINTPUB: + case TPM_PD_ENDORSEMENTKEY: + case TPM_PD_SRK: + case TPM_PD_DELEGATEKEY: + case TPM_PD_CONTEXTKEY: + case TPM_PD_AUDITMONOTONICCOUNTER: + case TPM_PD_MONOTONICCOUNTER: + case TPM_PD_PCRATTRIB: + case TPM_PD_ORDINALAUDITSTATUS: + case TPM_PD_AUTHDIR: + case TPM_PD_RNGSTATE: + case TPM_PD_FAMILYTABLE: + case TPM_DELEGATETABLE: + case TPM_PD_EKRESET: + case TPM_PD_LASTFAMILYID: + case TPM_PD_NOOWNERNVWRITE: + case TPM_PD_TPMDAASEED: + default: + printf("TPM_SetCapability_CapPermData: Error, bad subCap32 %u\n", + subCap32); + rc = TPM_BAD_PARAMETER; + } + } + rc = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + rc); + return rc; +} + +/* TPM_SetCapability_CapStclearFlags() rev 85 + + Sets TPM_STCLEAR_FLAGS values +*/ + +static TPM_RESULT TPM_SetCapability_CapStclearFlags(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_BOOL valueBool) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SetCapability_CapStclearFlags: valueBool %02x\n", valueBool); + ownerAuthorized = ownerAuthorized; /* not used */ + presenceAuthorized = presenceAuthorized; /* not used */ + if (rc == 0) { + switch (subCap32) { + case TPM_SF_DISABLEFORCECLEAR: + printf(" TPM_SetCapability_CapStclearFlags: TPM_SF_DISABLEFORCECLEAR\n"); + /* Not available when TPM deactivated or disabled */ + /* TPM_DisableForceClear */ + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapStclearFlags: Error, disabled\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_SetCapability_CapStclearFlags: Error, deactivated\n"); + rc = TPM_DEACTIVATED; + } + } + /* Can only set to TRUE */ + if (rc == 0) { + if (!valueBool) { + printf("TPM_SetCapability_CapStclearFlags: Error, cannot set FALSE\n"); + rc = TPM_BAD_PARAMETER; + } + } + if (rc == 0) { + tpm_state->tpm_stclear_flags.disableForceClear = TRUE; + } + break; + case TPM_SF_DEACTIVATED: + case TPM_SF_PHYSICALPRESENCE: + case TPM_SF_PHYSICALPRESENCELOCK: + case TPM_SF_BGLOBALLOCK: + default: + printf("TPM_SetCapability_CapStclearFlags: Error, bad subCap32 %u\n", + subCap32); + rc = TPM_BAD_PARAMETER; + } + } + return rc; +} + +/* TPM_SetCapability_CapStclearData() rev 100 + + Sets TPM_STCLEAR_DATA values +*/ + +static TPM_RESULT TPM_SetCapability_CapStclearData(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + uint32_t valueUint32) +{ + TPM_RESULT rc = 0; +#if (TPM_REVISION < 103) /* added for rev 103 */ + tpm_state = tpm_state; /* to quiet the compiler */ + presenceAuthorized = presenceAuthorized; + valueUint32 = valueUint32; +#endif + + printf(" TPM_SetCapability_CapStclearData:\n"); + ownerAuthorized = ownerAuthorized; /* not used */ + if (rc == 0) { + switch (subCap32) { +#if (TPM_REVISION >= 103) /* added for rev 103 */ + case TPM_SD_DEFERREDPHYSICALPRESENCE: + printf(" TPM_SetCapability_CapStclearData: TPM_SD_DEFERREDPHYSICALPRESENCE\n"); + /* Can only set to TRUE if PhysicalPresence is asserted. Can set to FALSE at any + time. */ + /* 1. If physical presence is not asserted */ + /* a. If TPM_SetCapability -> setValue has a bit set that is not already set in + TPM_STCLEAR_DATA -> deferredPhysicalPresence, return TPM_BAD_PRESENCE. */ + if (rc == 0) { + if (!presenceAuthorized) { + if (~(tpm_state->tpm_stclear_data.deferredPhysicalPresence) & valueUint32) { + printf("TPM_SetCapability_CapStclearData: " + "Error, no physicalPresence and deferredPhysicalPresence %08x\n", + tpm_state->tpm_stclear_data.deferredPhysicalPresence); + rc = TPM_BAD_PRESENCE; + } + } + } + /* 2.Set TPM_STCLEAR_DATA -> deferredPhysicalPresence to TPM_SetCapability -> setValue. + */ + if (rc == 0) { + printf(" TPM_SetCapability_CapStclearData: deferredPhysicalPresence now %08x\n", + valueUint32); + tpm_state->tpm_stclear_data.deferredPhysicalPresence = valueUint32; + } + break; +#endif + case TPM_SD_CONTEXTNONCEKEY: + case TPM_SD_COUNTID: + case TPM_SD_OWNERREFERENCE: + case TPM_SD_DISABLERESETLOCK: + case TPM_SD_PCR: + default: + printf("TPM_SetCapability_CapStclearData: Error, bad subCap32 %u\n", + subCap32); + rc = TPM_BAD_PARAMETER; + } + } + return rc; +} + +/* TPM_SetCapability_CapStanyFlags() rev 85 + + Sets TPM_STANY_FLAGS values +*/ + +static TPM_RESULT TPM_SetCapability_CapStanyFlags(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_BOOL valueBool) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SetCapability_CapStanyFlags:\n"); + ownerAuthorized = ownerAuthorized; /* not used */ + presenceAuthorized = presenceAuthorized; /* not used */ + if (rc == 0) { + switch (subCap32) { + case TPM_AF_TOSPRESENT: + printf(" TPM_SetCapability_CapStanyFlags: TPM_AF_TOSPRESENT\n"); + /* locality 3 or 4 */ + /* Not available when TPM deactivated or disabled */ + if (rc == 0) { + rc = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, + tpm_state->tpm_stany_flags.localityModifier); + } + if (rc == 0) { + if (tpm_state->tpm_permanent_flags.disable) { + printf("TPM_SetCapability_CapStanyFlags: Error, disabled\n"); + rc = TPM_DISABLED; + } + } + if (rc == 0) { + if (tpm_state->tpm_stclear_flags.deactivated) { + printf("TPM_SetCapability_CapStanyFlags: Error, deactivated\n"); + rc = TPM_DEACTIVATED; + } + } + /* can only be set to FALSE */ + if (rc == 0) { + if (valueBool) { + printf("TPM_SetCapability_CapStanyFlags: Error, cannot set TRUE\n"); + rc = TPM_BAD_PARAMETER; + } + } + if (rc == 0) { + tpm_state->tpm_stany_flags.TOSPresent = FALSE; + } + break; + case TPM_AF_POSTINITIALISE: + case TPM_AF_LOCALITYMODIFIER: + case TPM_AF_TRANSPORTEXCLUSIVE: + default: + printf("TPM_SetCapability_CapStanyFlags: Error, bad subCap32 %u\n", + subCap32); + rc = TPM_BAD_PARAMETER; + } + } + return rc; +} + +/* TPM_SetCapability_CapStanyData() rev 85 + + Sets TPM_STANY_DATA values +*/ + +static TPM_RESULT TPM_SetCapability_CapStanyData(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_SIZED_BUFFER *setValue) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SetCapability_CapStanyData:\n"); + tpm_state = tpm_state; /* not used */ + ownerAuthorized = ownerAuthorized; /* not used */ + presenceAuthorized = presenceAuthorized; /* not used */ + setValue = setValue; /* not used */ + if (rc == 0) { + switch (subCap32) { + case TPM_AD_CONTEXTNONCESESSION: + case TPM_AD_AUDITDIGEST: + case TPM_AD_CURRENTTICKS: + case TPM_AD_CONTEXTCOUNT: + case TPM_AD_CONTEXTLIST: + case TPM_AD_SESSIONS: + default: + printf("TPM_SetCapability_CapStanyData: Error, bad subCap32 %u\n", + subCap32); + rc = TPM_BAD_PARAMETER; + } + } + return rc; +} + +/* These are subCaps to TPM_SetCapability -> TPM_SET_VENDOR capArea, the vendor specific area. +*/ + +static TPM_RESULT TPM_SetCapability_CapVendor(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + uint32_t subCap32, + TPM_SIZED_BUFFER *setValue) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SetCapability_CapVendor:\n"); + ownerAuthorized = ownerAuthorized; /* not used */ + presenceAuthorized = presenceAuthorized; /* not used */ + setValue = setValue; + /* make temporary copies so the setValue is not touched */ + if (rc == 0) { + switch(subCap32) { + default: + printf("TPM_SetCapability_CapVendor: Error, unsupported subCap %08x\n", subCap32); + tpm_state = tpm_state; /* not used */ + rc = TPM_BAD_PARAMETER; + break; + + } + } + return rc; +} diff --git a/src/tpm12/tpm_process.h b/src/tpm12/tpm_process.h new file mode 100644 index 0000000..dfe7b3c --- /dev/null +++ b/src/tpm12/tpm_process.h @@ -0,0 +1,298 @@ +/********************************************************************************/ +/* */ +/* TPM Command Processor */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_process.h 4120 2010-10-26 22:00:40Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_PROCESS_H +#define TPM_PROCESS_H + +#include + +/* Commented out. This is not a standard header. If needed for a particular platform, replace but + also add comments and ifdef. */ +/* #include */ + +#include "tpm_global.h" +#include "tpm_store.h" + +/* + TPM_CAP_VERSION_INFO +*/ + +void TPM_CapVersionInfo_Init(TPM_CAP_VERSION_INFO *tpm_cap_version_info); +TPM_RESULT TPM_CapVersionInfo_Load(TPM_CAP_VERSION_INFO *tpm_cap_version_info, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_CapVersionInfo_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CAP_VERSION_INFO *tpm_cap_version_info); +void TPM_CapVersionInfo_Delete(TPM_CAP_VERSION_INFO *tpm_cap_version_info); +void TPM_CapVersionInfo_Set(TPM_CAP_VERSION_INFO *tpm_cap_version_info, + TPM_PERMANENT_DATA *tpm_permanent_data); + +/* + Capability Common Code +*/ + +void TPM_SetCapability_Flag(TPM_BOOL *altered, + TPM_BOOL *flag, + TPM_BOOL value); +void TPM_GetSubCapInt(uint16_t *subCap16, + uint32_t *subCap32, + TPM_SIZED_BUFFER *subCap); + +TPM_RESULT TPM_GetCapabilityCommon(TPM_STORE_BUFFER *capabilityResponse, + tpm_state_t *tpm_state, + TPM_CAPABILITY_AREA capArea, + uint16_t subCap16, + uint32_t subCap32, + TPM_SIZED_BUFFER *subCap); +TPM_RESULT TPM_SetCapabilityCommon(tpm_state_t *tpm_state, + TPM_BOOL ownerAuthorized, + TPM_BOOL presenceAuthorized, + TPM_CAPABILITY_AREA capArea, + uint16_t subCap16, + uint32_t subCap32, + TPM_SIZED_BUFFER *subCap, + TPM_SIZED_BUFFER *setValue); + +/* + Processing Functions +*/ + +TPM_RESULT TPM_ProcessA(unsigned char **response, + uint32_t *response_size, + uint32_t *response_total, + unsigned char *command, + uint32_t command_size); +TPM_RESULT TPM_Process(TPM_STORE_BUFFER *response, + unsigned char *command, + uint32_t command_size); +TPM_RESULT TPM_Process_Wrapped(TPM_STORE_BUFFER *response, + unsigned char *command, + uint32_t command_size, + tpm_state_t *targetInstance, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_GetCommandParams(TPM_TAG *tag, + uint32_t *paramSize , + TPM_COMMAND_CODE *ordinal, + unsigned char **command, + uint32_t *command_size); +TPM_RESULT TPM_Process_GetResponseParams(TPM_TAG *tag, + uint32_t *paramSize , + TPM_RESULT *returnCode, + unsigned char **response, + uint32_t *response_size); + +TPM_RESULT TPM_Process_Unused(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_GetCapability(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_GetCapabilityOwner(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_GetCapabilitySigned(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_SetCapability(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +/* + Processing Utilities +*/ + +/* tag checking */ + +TPM_RESULT TPM_CheckRequestTag210(TPM_TAG tpm_tag); +TPM_RESULT TPM_CheckRequestTag21 (TPM_TAG tpm_tag); +TPM_RESULT TPM_CheckRequestTag2 (TPM_TAG tpm_tag); +TPM_RESULT TPM_CheckRequestTag10 (TPM_TAG tpm_tag); +TPM_RESULT TPM_CheckRequestTag1 (TPM_TAG tpm_tag); +TPM_RESULT TPM_CheckRequestTag0 (TPM_TAG tpm_tag); + +/* TPM state checking */ + +TPM_RESULT TPM_CheckState(tpm_state_t *tpm_state, + TPM_TAG tag, + uint32_t tpm_check_map); +TPM_RESULT TPM_Process_Preprocess(tpm_state_t *tpm_state, + TPM_COMMAND_CODE ordinal, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Check_SHA1Context(tpm_state_t *tpm_state, + TPM_COMMAND_CODE ordinal, + TPM_TRANSPORT_INTERNAL *transportInternal); + +/* ordinal processing */ + +/* Prototype for all ordinal processing functions + + tpm_state: the entire TPM instance non-volatile and volatile state + response: the buffer to hold the ordinal response + tag: the command tag + paramSize: bytes left after the tag, paramSize, and ordinal + ordinal: the ordinal being called (could be hard coded, but eliminates cut/paste errors) + command: the remainder of the command packet + transportInternal: if not NULL, indicates that this function was called recursively from + TPM_ExecuteTransport +*/ + +typedef TPM_RESULT (*tpm_process_function_t)(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +typedef struct tdTPM_ORDINAL_TABLE { + TPM_COMMAND_CODE ordinal; + tpm_process_function_t process_function_v11; /* processing function for TPM 1.1 */ + tpm_process_function_t process_function_v12; /* processing function for TPM 1.2 */ + TPM_BOOL auditable; /* FALSE for functions never audited */ + TPM_BOOL auditDefault; /* TRUE if auditing is enabled by default */ + uint16_t ownerPermissionBlock; /* 0:unused, 1:per1 2:per2 */ + uint32_t ownerPermissionPosition; /* owner permission bit position */ + uint16_t keyPermissionBlock; /* 0:unused, 1:per1 2:per2 */ + uint32_t keyPermissionPosition; /* key permission bit position */ + uint32_t inputHandleSize; /* bytes of input handles (or other bytes + not to be encrypted or transport + audited) */ + uint32_t keyHandles; /* number of input key handles */ + uint32_t outputHandleSize; /* bytes of output handles (or other bytes + not to be encrypted or transport + audited */ + TPM_BOOL transportWrappable; /* can be wrapped in transport session */ + TPM_BOOL instanceWrappable; /* ordinal can be wrapped and called by + a parent instance */ + TPM_BOOL hardwareWrappable; /* ordinal can be wrapped and call the + hardware TPM instance */ +} TPM_ORDINAL_TABLE; + +TPM_RESULT TPM_OrdinalTable_GetEntry(TPM_ORDINAL_TABLE **entry, + TPM_ORDINAL_TABLE *ordinalTable, + TPM_COMMAND_CODE ordinal); +void TPM_OrdinalTable_GetProcessFunction(tpm_process_function_t *tpm_process_function, + TPM_ORDINAL_TABLE *ordinalTable, + TPM_COMMAND_CODE ordinal); +void TPM_OrdinalTable_GetAuditable(TPM_BOOL *auditable, + TPM_COMMAND_CODE ordinal); +void TPM_OrdinalTable_GetAuditDefault(TPM_BOOL *auditDefault, + TPM_COMMAND_CODE ordinal); +TPM_RESULT TPM_OrdinalTable_GetOwnerPermission(uint16_t *ownerPermissionBlock, + uint32_t *ownerPermissionPosition, + TPM_COMMAND_CODE ordinal); +TPM_RESULT TPM_OrdinalTable_GetKeyPermission(uint16_t *keyPermissionBlock, + uint32_t *keyPermissionPosition, + TPM_COMMAND_CODE ordinal); +TPM_RESULT TPM_OrdinalTable_ParseWrappedCmd(uint32_t *datawStart, + uint32_t *datawLen, + uint32_t *keyHandles, + uint32_t *keyHandle1Index, + uint32_t *keyHandle2Index, + TPM_COMMAND_CODE *ordinal, + TPM_BOOL *transportWrappable, + TPM_SIZED_BUFFER *wrappedCmd); +TPM_RESULT TPM_OrdinalTable_ParseWrappedRsp(uint32_t *datawStart, + uint32_t *datawLen, + TPM_RESULT *rcw, + TPM_COMMAND_CODE ordinal, + const unsigned char *wrappedRspStream, + uint32_t wrappedRspStreamSize); + + +TPM_RESULT TPM_GetInParamDigest(TPM_DIGEST inParamDigest, + TPM_BOOL *auditStatus, + TPM_BOOL *transportEncrypt, + tpm_state_t *tpm_state, + TPM_TAG tag, + TPM_COMMAND_CODE ordinal, + unsigned char *inParamStart, + unsigned char *inParamEnd, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_GetOutParamDigest(TPM_DIGEST outParamDigest, + TPM_BOOL auditStatus, + TPM_BOOL transportEncrypt, + TPM_TAG tag, + TPM_RESULT returnCode, + TPM_COMMAND_CODE ordinal, + unsigned char *outParamStart, + uint32_t outParamLength); +TPM_RESULT TPM_ProcessAudit(tpm_state_t *tpm_state, + TPM_BOOL transportEncrypt, + TPM_DIGEST inParamDigest, + TPM_DIGEST outParamDigest, + TPM_COMMAND_CODE ordinal); + +/* + defines for TPM_CheckState check map +*/ + +#define TPM_CHECK_NOT_SHUTDOWN 0x00000001 +#define TPM_CHECK_ENABLED 0x00000004 +#define TPM_CHECK_ACTIVATED 0x00000008 +#define TPM_CHECK_OWNER 0x00000010 +#define TPM_CHECK_NO_LOCKOUT 0x00000020 +#define TPM_CHECK_NV_NOAUTH 0x00000040 + +/* default conditions to check */ +#define TPM_CHECK_ALL 0x0000003f /* all state */ +#define TPM_CHECK_ALLOW_NO_OWNER 0x0000002f /* all state but owner installed */ + +#endif diff --git a/src/tpm12/tpm_secret.c b/src/tpm12/tpm_secret.c new file mode 100644 index 0000000..8dedf14 --- /dev/null +++ b/src/tpm12/tpm_secret.c @@ -0,0 +1,166 @@ +/********************************************************************************/ +/* */ +/* Secret Data Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_secret.c 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_crypto.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_store.h" + +#include "tpm_secret.h" + +void TPM_Secret_Init(TPM_SECRET tpm_secret) +{ + printf(" TPM_Secret_Init:\n"); + memset(tpm_secret, 0, TPM_SECRET_SIZE); + return; +} + +/* TPM_Secret_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + After use, call TPM_Secret_Delete() to free memory +*/ + +TPM_RESULT TPM_Secret_Load(TPM_SECRET tpm_secret, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Secret_Load:\n"); + rc = TPM_Loadn(tpm_secret, TPM_SECRET_SIZE, stream, stream_size); + return rc; +} + +/* TPM_Secret_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + After use, call TPM_Sbuffer_Delete() to free memory +*/ + +TPM_RESULT TPM_Secret_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SECRET tpm_secret) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Secret_Store:\n"); + rc = TPM_Sbuffer_Append(sbuffer, tpm_secret, TPM_SECRET_SIZE); + return rc; +} + +/* TPM_Secret_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the secret + sets pointers to NULL + calls TPM_Secret_Init to set members back to default values + The secret itself is not freed + returns 0 or error codes +*/ + +void TPM_Secret_Delete(TPM_SECRET tpm_secret) +{ + printf(" TPM_Secret_Delete:\n"); + if (tpm_secret != NULL) { + TPM_Secret_Init(tpm_secret); + } + return; +} + +/* TPM_Secret_Copy() copies the source to the destination + */ + +void TPM_Secret_Copy(TPM_SECRET destination, const TPM_SECRET source) +{ + printf(" TPM_Secret_Copy:\n"); + memcpy(destination, source, TPM_SECRET_SIZE); + return; +} + +/* TPM_Secret_Compare() compares the source to the destination. + + Returns TPM_AUTHFAIL if the nonces are not equal +*/ + +TPM_RESULT TPM_Secret_Compare(TPM_SECRET expect, const TPM_SECRET actual) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Secret_Compare:\n"); + rc = memcmp(expect, actual, TPM_SECRET_SIZE); + if (rc != 0) { + printf("TPM_Secret_Compare: Error comparing secret\n"); + rc = TPM_AUTHFAIL; + } + return rc; +} + +/* TPM_Secret_Generate() generates a new TPM_SECRET from the random number generator + */ + +TPM_RESULT TPM_Secret_Generate(TPM_SECRET tpm_secret) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Secret_Generate:\n"); + rc = TPM_Random(tpm_secret, TPM_SECRET_SIZE); + return rc; +} + +/* TPM_Secret_XOR() XOR's the source and the destination, and returns the result on output. + */ + +void TPM_Secret_XOR(TPM_SECRET output, TPM_SECRET input1, TPM_SECRET input2) +{ + size_t i; + + printf(" TPM_Secret_XOR:\n"); + for (i = 0 ; i < TPM_SECRET_SIZE ; i++) { + output[i] = input1[i] ^ input2[i]; + } + return; +} diff --git a/src/tpm12/tpm_secret.h b/src/tpm12/tpm_secret.h new file mode 100644 index 0000000..5621b2e --- /dev/null +++ b/src/tpm12/tpm_secret.h @@ -0,0 +1,62 @@ +/********************************************************************************/ +/* */ +/* Secret Data Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_secret.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_SECRET_H +#define TPM_SECRET_H + +#include "tpm_store.h" +#include "tpm_structures.h" +#include "tpm_types.h" + +void TPM_Secret_Init(TPM_SECRET tpm_secret); +TPM_RESULT TPM_Secret_Load(TPM_SECRET tpm_secret, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Secret_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SECRET tpm_secret); +void TPM_Secret_Delete(TPM_SECRET tpm_secret); + + +void TPM_Secret_Copy(TPM_SECRET destination, const TPM_SECRET source); +TPM_RESULT TPM_Secret_Compare(TPM_SECRET expect, const TPM_SECRET actual); +TPM_RESULT TPM_Secret_Generate(TPM_SECRET tpm_secret); +void TPM_Secret_XOR(TPM_SECRET output, TPM_SECRET input1, TPM_SECRET input2); + + +#endif diff --git a/src/tpm12/tpm_session.c b/src/tpm12/tpm_session.c new file mode 100644 index 0000000..da6cbe6 --- /dev/null +++ b/src/tpm12/tpm_session.c @@ -0,0 +1,5540 @@ +/********************************************************************************/ +/* */ +/* Session Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_session.c 4584 2011-06-22 15:49:41Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_auth.h" +#include "tpm_counter.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_daa.h" +#include "tpm_debug.h" +#include "tpm_delegate.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_init.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_nonce.h" +#include "tpm_nvram.h" +#include "tpm_pcr.h" +#include "tpm_process.h" +#include "tpm_permanent.h" +#include "tpm_secret.h" +#include "tpm_transport.h" +#include "tpm_types.h" + +#include "tpm_session.h" + +/* local function prototypes */ + +static TPM_RESULT TPM_OSAPDelegate(TPM_DIGEST **entityDigest, + TPM_SECRET **authData, + TPM_AUTH_SESSION_DATA *authSession, + tpm_state_t *tpm_state, + uint32_t delegateRowIndex); + +static TPM_RESULT TPM_LoadContext_CheckKeyLoaded(tpm_state_t *tpm_state, + TPM_HANDLE entityHandle, + TPM_DIGEST entityDigest); +static TPM_RESULT TPM_LoadContext_CheckKeyLoadedByDigest(tpm_state_t *tpm_state, + TPM_DIGEST entityDigest); +static TPM_RESULT TPM_LoadContext_CheckOwnerLoaded(tpm_state_t *tpm_state, + TPM_DIGEST entityDigest); +static TPM_RESULT TPM_LoadContext_CheckSrkLoaded(tpm_state_t *tpm_state, + TPM_DIGEST entityDigest); +static TPM_RESULT TPM_LoadContext_CheckCounterLoaded(tpm_state_t *tpm_state, + TPM_HANDLE entityHandle, + TPM_DIGEST entityDigest); +static TPM_RESULT TPM_LoadContext_CheckNvLoaded(tpm_state_t *tpm_state, + TPM_HANDLE entityHandle, + TPM_DIGEST entityDigest); + +/* + TPM_AUTH_SESSION_DATA (one element of the array) +*/ + +/* TPM_AuthSessionData_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_AuthSessionData_Init(TPM_AUTH_SESSION_DATA *tpm_auth_session_data) +{ + printf(" TPM_AuthSessionData_Init:\n"); + tpm_auth_session_data->handle = 0; + tpm_auth_session_data->protocolID = 0; + tpm_auth_session_data->entityTypeByte = 0; + tpm_auth_session_data->adipEncScheme = 0; + TPM_Nonce_Init(tpm_auth_session_data->nonceEven); + TPM_Secret_Init(tpm_auth_session_data->sharedSecret); + TPM_Digest_Init(tpm_auth_session_data->entityDigest); + TPM_DelegatePublic_Init(&(tpm_auth_session_data->pub)); + tpm_auth_session_data->valid = FALSE; + return; +} + +/* TPM_AuthSessionData_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_AuthSessionData_Init() + After use, call TPM_AuthSessionData_Delete() to free memory +*/ + +TPM_RESULT TPM_AuthSessionData_Load(TPM_AUTH_SESSION_DATA *tpm_auth_session_data, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_AuthSessionData_Load:\n"); + /* load handle */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_auth_session_data->handle), stream, stream_size); + } + /* load protocolID */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_auth_session_data->protocolID), stream, stream_size); + } + /* load entityTypeByte */ + if (rc == 0) { + rc = TPM_Loadn(&(tpm_auth_session_data->entityTypeByte), sizeof(BYTE), stream, stream_size); + } + /* load adipEncScheme */ + if (rc == 0) { + rc = TPM_Loadn(&(tpm_auth_session_data->adipEncScheme), sizeof(BYTE), stream, stream_size); + } + /* load nonceEven */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_auth_session_data->nonceEven, stream, stream_size); + } + /* load sharedSecret */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_auth_session_data->sharedSecret, stream, stream_size); + } + /* load entityDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_auth_session_data->entityDigest, stream, stream_size); + } + /* load pub */ + if (rc == 0) { + rc = TPM_DelegatePublic_Load(&(tpm_auth_session_data->pub), stream, stream_size); + } + /* set valid */ + if (rc == 0) { + tpm_auth_session_data->valid = TRUE; + } + return rc; +} + +/* TPM_AuthSessionData_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_AuthSessionData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_AUTH_SESSION_DATA *tpm_auth_session_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_AuthSessionData_Store:\n"); + /* store handle */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_auth_session_data->handle); + } + /* store protocolID */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_auth_session_data->protocolID); + } + /* store entityTypeByte */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_auth_session_data->entityTypeByte), sizeof(BYTE)); + } + /* store adipEncScheme */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_auth_session_data->adipEncScheme), sizeof(BYTE)); + } + /* store nonceEven */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_auth_session_data->nonceEven); + } + /* store sharedSecret */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_auth_session_data->sharedSecret); + } + /* store entityDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_auth_session_data->entityDigest); + } + /* store pub */ + if (rc == 0) { + rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_auth_session_data->pub)); + } + return rc; +} + +/* TPM_AuthSessionData_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_AuthSessionData_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_AuthSessionData_Delete(TPM_AUTH_SESSION_DATA *tpm_auth_session_data) +{ + printf(" TPM_AuthSessionData_Delete:\n"); + if (tpm_auth_session_data != NULL) { + TPM_DelegatePublic_Delete(&(tpm_auth_session_data->pub)); + TPM_AuthSessionData_Init(tpm_auth_session_data); + } + return; +} + +/* TPM_AuthSessionData_Copy() copies the source to the destination. The source handle is ignored, + since it might already be used. +*/ + +void TPM_AuthSessionData_Copy(TPM_AUTH_SESSION_DATA *dest_auth_session_data, + TPM_HANDLE tpm_handle, + TPM_AUTH_SESSION_DATA *src_auth_session_data) +{ + dest_auth_session_data->handle = tpm_handle; + dest_auth_session_data->protocolID = src_auth_session_data->protocolID; + dest_auth_session_data->entityTypeByte = src_auth_session_data->entityTypeByte; + dest_auth_session_data-> adipEncScheme = src_auth_session_data->adipEncScheme; + TPM_Nonce_Copy(dest_auth_session_data->nonceEven, src_auth_session_data->nonceEven); + TPM_Secret_Copy(dest_auth_session_data->sharedSecret, src_auth_session_data->sharedSecret); + TPM_Digest_Copy(dest_auth_session_data->entityDigest, src_auth_session_data->entityDigest); + TPM_DelegatePublic_Copy(&(dest_auth_session_data->pub), &(src_auth_session_data->pub)); + dest_auth_session_data->valid= src_auth_session_data->valid; +} + +/* TPM_AuthSessionData_GetDelegatePublic() */ + +TPM_RESULT TPM_AuthSessionData_GetDelegatePublic(TPM_DELEGATE_PUBLIC **delegatePublic, + TPM_AUTH_SESSION_DATA *auth_session_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_AuthSessionData_GetDelegatePublic:\n"); + if (rc == 0) { + *delegatePublic = &(auth_session_data->pub); + } + return rc; +} + +/* TPM_AuthSessionData_CheckEncScheme() checks that the encryption scheme specified by + TPM_ENTITY_TYPE is supported by the TPM (by TPM_AuthSessionData_Decrypt) +*/ + +TPM_RESULT TPM_AuthSessionData_CheckEncScheme(TPM_ADIP_ENC_SCHEME adipEncScheme, + TPM_BOOL FIPS) +{ + TPM_RESULT rc = 0; + + printf(" TPM_AuthSessionData_CheckEncScheme: adipEncScheme %02x\n", adipEncScheme); + switch (adipEncScheme) { + case TPM_ET_XOR: + /* i.If TPM_PERMANENT_FLAGS -> FIPS is TRUE */ + /* (1) All encrypted authorizations MUST use a symmetric key encryption scheme. */ + if (FIPS) { + rc = TPM_INAPPROPRIATE_ENC; + } + break; + case TPM_ET_AES128_CTR: + break; + default: + printf("TPM_AuthSessionData_CheckEncScheme: Error, unsupported adipEncScheme\n"); + rc = TPM_INAPPROPRIATE_ENC; + break; + } + return rc; +} + +/* TPM_AuthSessionData_Decrypt() decrypts the encAuth secret using the algorithm indicated in the + OSAP or DSAP session + + If 'odd' is FALSE, one decrypt of encAuthEven to a1Even. + If 'odd' is TRUE, a second decrypt of encAuthOdd to a1Odd is also performed. +*/ + +TPM_RESULT TPM_AuthSessionData_Decrypt(TPM_DIGEST a1Even, + TPM_DIGEST a1Odd, + TPM_ENCAUTH encAuthEven, + TPM_AUTH_SESSION_DATA *tpm_auth_session_data, + TPM_NONCE nonceOdd, + TPM_ENCAUTH encAuthOdd, + TPM_BOOL odd) +{ + TPM_RESULT rc = 0; + TPM_DIGEST x1Even; + TPM_DIGEST x2Odd; + + printf(" TPM_AuthSessionData_Decrypt:\n"); + /* sanity check - the session must be OSAP or DSAP */ + if (rc == 0) { + if ((tpm_auth_session_data->protocolID != TPM_PID_OSAP) && + (tpm_auth_session_data->protocolID != TPM_PID_DSAP)) { + printf("TPM_AuthSessionData_Decrypt: Error, protocolID should be OSAP, is %04hx\n", + tpm_auth_session_data->protocolID); + rc = TPM_BAD_MODE; + } + } + if (rc == 0) { + /* algorithm indicated in the OSAP session */ + switch(tpm_auth_session_data->adipEncScheme) { + case TPM_ET_XOR: + /* 4. If the entity type indicates XOR encryption for the AuthData secret */ + /* a.Create X1 the SHA-1 of the concatenation of (authHandle -> sharedSecret || + authLastNonceEven). */ + if (rc == 0) { + rc = TPM_SHA1(x1Even, + TPM_SECRET_SIZE, tpm_auth_session_data->sharedSecret, + TPM_NONCE_SIZE, tpm_auth_session_data->nonceEven, + 0, NULL); + } + /* b. Create the decrypted AuthData the XOR of X1 and the encrypted AuthData. */ + if (rc == 0) { + TPM_Digest_XOR(a1Even, encAuthEven, x1Even); + } + /* c. If the command ordinal contains a second AuthData2 secret + (e.g. TPM_CreateWrapKey) */ + /* i. Create X2 the SHA-1 of the concatenation of (authHandle -> sharedSecret || + nonceOdd). */ + if ((rc == 0) && (odd)) { + rc = TPM_SHA1(x2Odd, + TPM_SECRET_SIZE, tpm_auth_session_data->sharedSecret, + TPM_NONCE_SIZE, nonceOdd, + 0, NULL); + } + /* ii. Create the decrypted AuthData2 the XOR of X2 and the encrypted AuthData2. */ + if ((rc == 0) && (odd)) { + TPM_Digest_XOR(a1Odd, encAuthOdd, x2Odd); + } + break; +#ifdef TPM_AES /* if AES is supported */ + case TPM_ET_AES128_CTR: + /* 5. If the entity type indicates symmetric key encryption */ + /* a. The key for the encryption algorithm is the first bytes of the OSAP shared + secret. */ + /* i. E.g., For AES128, the key is the first 16 bytes of the OSAP shared secret. */ + /* ii. There is no support for AES keys greater than 128 bits. */ + /* b. If the entity type indicates CTR mode */ + /* i. The initial counter value for AuthData is the first bytes of authLastNonceEven. */ + /* (1) E.g., For AES128, the initial counter value is the first 16 bytes of + authLastNonceEven. */ + /* b. Create the decrypted AuthData from the encrypted AuthData. */ + if (rc == 0) { + rc = TPM_SymmetricKeyData_CtrCrypt(a1Even, /* output data */ + encAuthEven, /* input data */ + TPM_AUTHDATA_SIZE, /* data size */ + tpm_auth_session_data->sharedSecret, /* key */ + TPM_SECRET_SIZE, + tpm_auth_session_data->nonceEven, /* CTR */ + TPM_NONCE_SIZE); + } + /* ii. If the command ordinal contains a second AuthData2 secret + (e.g. TPM_CreateWrapKey) */ + /* (1) The initial counter value for AuthData2 is the first bytes of + nonceOdd. */ + /* ii. Create the decrypted AuthData2 from the the encrypted AuthData2. */ + if ((rc == 0) && (odd)) { + rc = TPM_SymmetricKeyData_CtrCrypt(a1Odd, /* output data */ + encAuthOdd, /* input data */ + TPM_AUTHDATA_SIZE, /* data size */ + tpm_auth_session_data->sharedSecret, /* key */ + TPM_SECRET_SIZE, + nonceOdd, /* CTR */ + TPM_NONCE_SIZE); + } + /* iii. Additional counter values as required are generated by incrementing the + entire counter value as a big endian number. */ + break; +#endif /* TPM_AES */ + default: + printf("TPM_AuthSessionData_Decrypt: Error, entityType %02x not supported\n", + tpm_auth_session_data->adipEncScheme); + rc = TPM_INAPPROPRIATE_ENC; + break; + } + } + return rc; +} + +/* + TPM_AUTH_SESSION_DATA (the entire array) +*/ + +void TPM_AuthSessions_Init(TPM_AUTH_SESSION_DATA *authSessions) +{ + size_t i; + + printf(" TPM_AuthSessions_Init:\n"); + for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { + TPM_AuthSessionData_Init(&(authSessions[i])); + } + return; +} + +/* TPM_AuthSessions_Load() reads a count of the number of stored sessions and then loads those + sessions. + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_AuthSessions_Init() +*/ + +TPM_RESULT TPM_AuthSessions_Load(TPM_AUTH_SESSION_DATA *authSessions, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + uint32_t activeCount; + + printf(" TPM_AuthSessions_Load:\n"); + /* load active count */ + if (rc == 0) { + rc = TPM_Load32(&activeCount, stream, stream_size); + } + /* load authorization sessions */ + if (rc == 0) { + if (activeCount > TPM_MIN_AUTH_SESSIONS) { + printf("TPM_AuthSessions_Load: Error (fatal) %u sessions, %u slots\n", + activeCount, TPM_MIN_AUTH_SESSIONS); + rc = TPM_FAIL; + } + } + if (rc == 0) { + printf(" TPM_AuthSessions_Load: Loading %u sessions\n", activeCount); + } + for (i = 0 ; (rc == 0) && (i < activeCount) ; i++) { + rc = TPM_AuthSessionData_Load(&(authSessions[i]), stream, stream_size); + } + return rc; +} + +/* TPM_AuthSessions_Store() stores a count of the active sessions, followed by the sessions. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_AuthSessions_Store(TPM_STORE_BUFFER *sbuffer, + TPM_AUTH_SESSION_DATA *authSessions) +{ + TPM_RESULT rc = 0; + size_t i; + uint32_t space; /* free authorization session slots */ + uint32_t activeCount; /* used authorization session slots */ + + /* store active count */ + if (rc == 0) { + TPM_AuthSessions_GetSpace(&space, authSessions); + activeCount = TPM_MIN_AUTH_SESSIONS - space; + printf(" TPM_AuthSessions_Store: Storing %u sessions\n", activeCount); + rc = TPM_Sbuffer_Append32(sbuffer, activeCount); + } + /* store auth sessions */ + for (i = 0 ; (rc == 0) && (i < TPM_MIN_AUTH_SESSIONS) ; i++) { + if ((authSessions[i]).valid) { /* if the session is active */ + printf(" TPM_AuthSessions_Store: Storing %08x\n", authSessions[i].handle); + rc = TPM_AuthSessionData_Store(sbuffer, &(authSessions[i])); + } + } + return rc; +} + +/* TPM_AuthSessions_Delete() terminates all sessions + +*/ + +void TPM_AuthSessions_Delete(TPM_AUTH_SESSION_DATA *authSessions) +{ + size_t i; + + printf(" TPM_AuthSessions_Delete:\n"); + for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { + TPM_AuthSessionData_Delete(&(authSessions[i])); + } + return; +} + +/* TPM_AuthSessions_IsSpace() returns 'isSpace' TRUE if an entry is available, FALSE if not. + + If TRUE, 'index' holds the first free position. +*/ + +void TPM_AuthSessions_IsSpace(TPM_BOOL *isSpace, + uint32_t *index, + TPM_AUTH_SESSION_DATA *authSessions) +{ + printf(" TPM_AuthSessions_IsSpace:\n"); + for (*index = 0, *isSpace = FALSE ; *index < TPM_MIN_AUTH_SESSIONS ; (*index)++) { + if (!((authSessions[*index]).valid)) { + printf(" TPM_AuthSessions_IsSpace: Found space at %u\n", *index); + *isSpace = TRUE; + break; + } + } + return; +} + +void TPM_AuthSessions_Trace(TPM_AUTH_SESSION_DATA *authSessions) +{ + size_t i; + for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { + if ((authSessions[i]).valid) { + printf(" TPM_AuthSessions_Trace: %lu handle %08x\n", + (unsigned long)i, authSessions[i].handle); + } + } + return; +} + +/* TPM_AuthSessions_GetSpace() returns the number of unused authHandle's. + +*/ + +void TPM_AuthSessions_GetSpace(uint32_t *space, + TPM_AUTH_SESSION_DATA *authSessions) +{ + uint32_t i; + + printf(" TPM_AuthSessions_GetSpace:\n"); + for (*space = 0 , i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { + if (!((authSessions[i]).valid)) { + (*space)++; + } + } + return; +} + +/* TPM_AuthSessions_StoreHandles() stores + + - the number of loaded sessions + - a list of session handles +*/ + +TPM_RESULT TPM_AuthSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, + TPM_AUTH_SESSION_DATA *authSessions) +{ + TPM_RESULT rc = 0; + uint16_t i; + uint32_t space; + + printf(" TPM_AuthSessions_StoreHandles:\n"); + /* get the number of loaded handles */ + if (rc == 0) { + TPM_AuthSessions_GetSpace(&space, authSessions); + /* store loaded handle count. Cast safe because of TPM_MIN_AUTH_SESSIONS value */ + rc = TPM_Sbuffer_Append16(sbuffer, (uint16_t)(TPM_MIN_AUTH_SESSIONS - space)); + } + for (i = 0 ; (rc == 0) && (i < TPM_MIN_AUTH_SESSIONS) ; i++) { + if ((authSessions[i]).valid) { /* if the index is loaded */ + rc = TPM_Sbuffer_Append32(sbuffer, (authSessions[i]).handle); /* store it */ + } + } + return rc; +} + +/* TPM_AuthSessions_GetNewHandle() checks for space in the authorization sessions table. + + If there is space, it returns a TPM_AUTH_SESSION_DATA entry in 'tpm_auth_session_data' and its + handle in 'authHandle'. The entry is marked 'valid'. + + If *authHandle non-zero, the suggested value is tried first. + + Returns TPM_RESOURCES if there is no space in the sessions table. +*/ + +TPM_RESULT TPM_AuthSessions_GetNewHandle(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, + TPM_AUTHHANDLE *authHandle, + TPM_AUTH_SESSION_DATA *authSessions) +{ + TPM_RESULT rc = 0; + uint32_t index; + TPM_BOOL isSpace; + + printf(" TPM_AuthSessions_GetNewHandle:\n"); + /* is there an empty entry, get the location index */ + if (rc == 0) { + TPM_AuthSessions_IsSpace(&isSpace, &index, authSessions); + if (!isSpace) { + printf("TPM_AuthSessions_GetNewHandle: Error, no space in authSessions table\n"); + TPM_AuthSessions_Trace(authSessions); + rc = TPM_RESOURCES; + } + } + if (rc == 0) { + rc = TPM_Handle_GenerateHandle(authHandle, /* I/O */ + authSessions, /* handle array */ + FALSE, /* keepHandle */ + FALSE, /* isKeyHandle */ + (TPM_GETENTRY_FUNCTION_T)TPM_AuthSessions_GetEntry); + } + if (rc == 0) { + printf(" TPM_AuthSessions_GetNewHandle: Assigned handle %08x\n", *authHandle); + *tpm_auth_session_data = &(authSessions[index]); + /* assign the handle */ + (*tpm_auth_session_data)->handle = *authHandle; + (*tpm_auth_session_data)->valid = TRUE; + } + return rc; +} + +/* TPM_AuthSessions_GetEntry() searches all entries for the entry matching the handle, and + returns the TPM_AUTH_SESSION_DATA entry associated with the handle. + + Returns + 0 for success + TPM_INVALID_AUTHHANDLE if the handle is not found +*/ + +TPM_RESULT TPM_AuthSessions_GetEntry(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, /* session for + authHandle */ + TPM_AUTH_SESSION_DATA *authSessions, /* points to first session + */ + TPM_AUTHHANDLE authHandle) /* input */ +{ + TPM_RESULT rc = 0; + size_t i; + TPM_BOOL found; + + printf(" TPM_AuthSessions_GetEntry: authHandle %08x\n", authHandle); + for (i = 0, found = FALSE ; (i < TPM_MIN_AUTH_SESSIONS) && !found ; i++) { + if ((authSessions[i].valid) && + (authSessions[i].handle == authHandle)) { /* found */ + found = TRUE; + *tpm_auth_session_data = &(authSessions[i]); + } + } + if (!found) { + printf(" TPM_AuthSessions_GetEntry: session handle %08x not found\n", + authHandle); + rc = TPM_INVALID_AUTHHANDLE; + } + return rc; +} + +/* TPM_AuthSessions_AddEntry() adds an TPM_AUTH_SESSION_DATA object to the list. + + If *tpm_handle == 0, a value is assigned. If *tpm_handle != 0, that value is used if it it not + currently in use. + + The handle is returned in tpm_handle. +*/ + +TPM_RESULT TPM_AuthSessions_AddEntry(TPM_HANDLE *tpm_handle, /* i/o */ + TPM_BOOL keepHandle, /* input */ + TPM_AUTH_SESSION_DATA *authSessions, /* input */ + TPM_AUTH_SESSION_DATA *tpm_auth_session_data) /* input */ +{ + TPM_RESULT rc = 0; + uint32_t index; + TPM_BOOL isSpace; + + printf(" TPM_AuthSessions_AddEntry: handle %08x, keepHandle %u\n", + *tpm_handle, keepHandle); + /* check for valid TPM_AUTH_SESSION_DATA */ + if (rc == 0) { + if (tpm_auth_session_data == NULL) { /* NOTE: should never occur */ + printf("TPM_AuthSessions_AddEntry: Error (fatal), NULL TPM_AUTH_SESSION_DATA\n"); + rc = TPM_FAIL; + } + } + /* is there an empty entry, get the location index */ + if (rc == 0) { + TPM_AuthSessions_IsSpace(&isSpace, &index, authSessions); + if (!isSpace) { + printf("TPM_AuthSessions_AddEntry: Error, session entries full\n"); + TPM_AuthSessions_Trace(authSessions); + rc = TPM_RESOURCES; + } + } + if (rc == 0) { + rc = TPM_Handle_GenerateHandle(tpm_handle, /* I/O */ + authSessions, /* handle array */ + keepHandle, /* keepHandle */ + FALSE, /* isKeyHandle */ + (TPM_GETENTRY_FUNCTION_T)TPM_AuthSessions_GetEntry); + } + if (rc == 0) { + TPM_AuthSessionData_Copy(&(authSessions[index]), *tpm_handle, tpm_auth_session_data); + authSessions[index].valid = TRUE; + printf(" TPM_AuthSessions_AddEntry: Index %u handle %08x\n", + index, authSessions[index].handle); + } + return rc; +} + +/* TPM_AuthSessions_GetData() checks that authHandle indexes a valid TPM_AUTH_SESSION_DATA object. + If so, a pointer to the object is returned in tpm_auth_session_data. + + If required protocolID is either TPM_PID_OIAP or TPM_PID_OSAP, the object is checked for that + type. TPM_PID_OSAP will accept DSAP as well. If it is TPM_PID_NONE, either is accepted. Any + other value is unsupported. + + If the session protocolID is OIAP, the input entityAuth is echoed back as the HMAC key. + entityDigest is ignored and may be NULL. + + If the session protocolID is OSAP or DSAP, the function must check that the entity used to set up + the session is the same as the entity specified in the processing command. It does that by + comparing the entityDigest to that saved during setup of the OSAP session. The shared secret is + returned as the HMAC key. entityAuth is ignored and may be NULL. + + If the session protocolID is DSAP, the TPM_DELEGATE_PUBLIC saved during the TPM_DSAP session + setup is checked for permission and PCR's. The entityType (TPM_ET_KEYHANDLE or TPM_ET_OWNER) is + checked against the TPM_DELEGATE_PUBLIC -> TPM_DELEGATIONS delegateType. Then the bit map is + fetched from the ordinals table and verified against the per1 or per 2 values. The pcrInfo is + checked against the current PCR values. + + The saved entityDigest depends upon the entity type: + + TPM_ET_KEYHANDLE: pubDataDigest + TPM_ET_OWNER: ownerAuth + TPM_ET_SRK: TPM_KEY -> key_digest + TPM_ET_COUNTER: TPM_COUNTER_VALUE -> digest + TPM_ET_NV: TPM_NV_DATA_SENSITIVE -> digest +*/ + +TPM_RESULT TPM_AuthSessions_GetData(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, /* session for + authHandle */ + TPM_SECRET **hmacKey, /* output */ + tpm_state_t *tpm_state, /* input */ + TPM_AUTHHANDLE authHandle, /* input */ + TPM_PROTOCOL_ID protocolID, /* input: required protocol */ + TPM_ENT_TYPE entityType, /* input: entity type */ + TPM_COMMAND_CODE ordinal, /* input: for delegation */ + TPM_KEY *tpmKey, /* input, for delegate restrictions */ + TPM_SECRET *entityAuth, /* input OIAP hmac key */ + TPM_DIGEST entityDigest) /* input OSAP session setup auth */ +{ + TPM_RESULT rc = 0; + TPM_DELEGATE_TABLE_ROW *delegateTableRow; + + printf(" TPM_AuthSessions_GetData: authHandle %08x\n", authHandle); + if (rc == 0) { + rc = TPM_AuthSessions_GetEntry(tpm_auth_session_data, + tpm_state->tpm_stclear_data.authSessions, + authHandle); + if (rc != 0) { + printf("TPM_AuthSessions_GetData: Error, authHandle %08x not found\n", authHandle); + } + } + /* If a specific protocol is required, check that the handle points to the correct session type + */ + if (rc == 0) { + switch (protocolID) { /* what protocol is required */ + case TPM_PID_NONE: /* accept any protocol */ + break; + case TPM_PID_OIAP: + if ((*tpm_auth_session_data)->protocolID != TPM_PID_OIAP) { + printf("TPM_AuthSessions_GetData: Error, " + "session protocolID should be OIAP, is %04hx\n", + (*tpm_auth_session_data)->protocolID); + rc = TPM_BAD_MODE; + } + break; + case TPM_PID_OSAP: + /* Any ordinal requiring OSAP should also accept DSAP */ + if (((*tpm_auth_session_data)->protocolID != TPM_PID_OSAP) && + ((*tpm_auth_session_data)->protocolID != TPM_PID_DSAP)) { + printf("TPM_AuthSessions_GetData: Error, " + "session protocolID should be OSAP or DSAP, is %04hx\n", + (*tpm_auth_session_data)->protocolID); + rc = TPM_BAD_MODE; + } + break; + default: /* should not occur */ + printf("TPM_AuthSessions_GetData: Error, required protocolID %04hx unsupported\n", + protocolID); + rc = TPM_BAD_MODE; + break; + } + } + /* if the entity is owner auth, verify that an owner is installed */ + if (rc == 0) { + if (entityType == TPM_ET_OWNER) { + if (!tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_AuthSessions_GetData: Error, no owner installed\n"); + rc = TPM_AUTHFAIL; + } + } + } + /* session protocol specific processing */ + if (rc == 0) { + switch ((*tpm_auth_session_data)->protocolID) { + case TPM_PID_OIAP: + /* a. If the command using the OIAP session requires owner authorization */ + /* i. If TPM_STCLEAR_DATA -> ownerReference is TPM_KH_OWNER, the secret AuthData is + TPM_PERMANENT_DATA -> ownerAuth */ + /* ii. If TPM_STCLEAR_DATA -> ownerReference is pointing to a delegate row */ + if ((entityType == TPM_ET_OWNER) && + (tpm_state->tpm_stclear_data.ownerReference != TPM_KH_OWNER)) { + printf(" TPM_AuthSessions_GetData: Delegating to row %u\n", + tpm_state->tpm_stclear_data.ownerReference); + /* (1) Set R1 a row index to TPM_STCLEAR_DATA -> ownerReference */ + /* (2) Set D1 a TPM_DELEGATE_TABLE_ROW to TPM_PERMANENT_DATA -> delegateTable -> + delRow[R1] */ + if (rc == 0) { + rc = TPM_DelegateTable_GetValidRow + (&delegateTableRow, + &(tpm_state->tpm_permanent_data.delegateTable), + tpm_state->tpm_stclear_data.ownerReference); + } + /* (4) Validate the TPM_DELEGATE_PUBLIC D1 -> pub based on the command ordinal */ + /* (a) Validate D1 -> pub -> permissions based on the command ordinal */ + /* (b) Validate D1 -> pub -> pcrInfo based on the PCR values */ + if (rc == 0) { + rc = TPM_Delegations_CheckPermission(tpm_state, + &(delegateTableRow->pub), + entityType, + ordinal); + } + /* (3) Set the secret AuthData to D1 -> authValue */ + if (rc == 0) { + *hmacKey = &(delegateTableRow->authValue); + } + } + /* not owner or owner but not delegated */ + else { + /* the hmac key is the input authorization secret */ + *hmacKey = entityAuth; + } + break; + case TPM_PID_OSAP: + case TPM_PID_DSAP: /* the first part of DSAP is the same as OSAP */ + /* ensure that the OSAP shared secret is that derived from the entity using OSAP */ + if (rc == 0) { + rc = TPM_Digest_Compare(entityDigest, (*tpm_auth_session_data)->entityDigest); + } + /* extra processing for DSAP sessions */ + if ((*tpm_auth_session_data)->protocolID == TPM_PID_DSAP) { + /* check that delegation is allowed for the ordinal */ + if (rc == 0) { + rc = TPM_Delegations_CheckPermission(tpm_state, + &((*tpm_auth_session_data)->pub), + entityType, /* required for ordinal */ + ordinal); + } + /* check restrictions on delegation of a certified migration key */ + if ((rc == 0) && (entityType == TPM_ET_KEYHANDLE)) { + rc = TPM_Key_CheckRestrictDelegate + (tpmKey, + tpm_state->tpm_permanent_data.restrictDelegate); + } + } + /* the HMAC key is the shared secret calculated during OSAP setup */ + if (rc == 0) { + *hmacKey = &((*tpm_auth_session_data)->sharedSecret); + } + break; + default: /* should not occur */ + printf("TPM_AuthSessions_GetData: session protocolID %04hx unsupported\n", + (*tpm_auth_session_data)->protocolID); + rc = TPM_AUTHFAIL; + break; + } + } + return rc; +} + +/* TPM_AuthSessions_TerminateHandle() terminates the session associated with 'authHandle'. + +*/ + +TPM_RESULT TPM_AuthSessions_TerminateHandle(TPM_AUTH_SESSION_DATA *authSessions, + TPM_AUTHHANDLE authHandle) +{ + TPM_RESULT rc = 0; + TPM_AUTH_SESSION_DATA *tpm_auth_session_data; + + printf(" TPM_AuthSessions_TerminateHandle: Handle %08x\n", authHandle); + /* get the TPM_AUTH_SESSION_DATA associated with the TPM_AUTHHANDLE */ + if (rc == 0) { + rc = TPM_AuthSessions_GetEntry(&tpm_auth_session_data, authSessions, authHandle); + } + /* invalidate the valid handle */ + if (rc == 0) { + TPM_AuthSessionData_Delete(tpm_auth_session_data); + } + return rc; +} + +/* TPM_AuthSessions_TerminateEntity() terminates all OSAP and DSAP sessions connected to the + entityType. + + If the session associated with authHandle is terminated, continueAuthSession is set to FALSE for + the ordinal response. + + If the entityDigest is NULL, all sessions are terminated. If entityDigest is not NULL, only + those with a matching entityDigest are terminated. + */ + +void TPM_AuthSessions_TerminateEntity(TPM_BOOL *continueAuthSession, + TPM_AUTHHANDLE authHandle, + TPM_AUTH_SESSION_DATA *authSessions, + TPM_ENT_TYPE entityType, + TPM_DIGEST *entityDigest) +{ + uint32_t i; + TPM_BOOL terminate; + TPM_RESULT match; + + printf(" TPM_AuthSessions_TerminateEntity: entityType %04x\n", entityType); + for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { + terminate = FALSE; + if ((authSessions[i].valid) && /* if the entry is valid */ + ((authSessions[i].protocolID == TPM_PID_OSAP) || /* if it's OSAP or DSAP */ + (authSessions[i].protocolID == TPM_PID_DSAP)) && + (authSessions[i].entityTypeByte == entityType)) { /* connected to entity type */ + /* if entityDigest is NULL, terminate all matching entityType */ + if (entityDigest == NULL) { + terminate = TRUE; + } + /* if entityDigest is not NULL, terminate only those matching entityDigest */ + else { + match = TPM_Digest_Compare(*entityDigest, authSessions[i].entityDigest); + if (match == 0) { + terminate = TRUE; + } + } + } + if (terminate) { + printf(" TPM_AuthSessions_TerminateEntity: Terminating handle %08x\n", + authSessions[i].handle); + /* if terminating the ordinal's session */ + if (authSessions[i].handle == authHandle) { + *continueAuthSession = FALSE; /* for the ordinal response */ + } + TPM_AuthSessionData_Delete(&authSessions[i]); + } + } + return; +} + +/* TPM_AuthSessions_TerminatexSAP terminates all OSAP and DSAP sessions + + If the session associated with authHandle is terminated, continueAuthSession is set to FALSE for + the ordinal response. + + It is safe to call this function during ordinal processing provided a copy of the shared secret + is first saved for the response HMAC calculation. + + The evenNonce is newly created for the response. The oddNonce and continueAuthSession are + command inputs, not part of the session data structure. +*/ + +void TPM_AuthSessions_TerminatexSAP(TPM_BOOL *continueAuthSession, + TPM_AUTHHANDLE authHandle, + TPM_AUTH_SESSION_DATA *authSessions) +{ + uint32_t i; + + printf(" TPM_AuthSessions_TerminatexSAP:\n"); + for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { + if ((authSessions[i].protocolID == TPM_PID_OSAP) || + (authSessions[i]. protocolID == TPM_PID_DSAP)) { + /* if terminating the ordinal's session */ + if (authSessions[i].handle == authHandle) { + *continueAuthSession = FALSE; /* for the ordinal response */ + } + printf(" TPM_AuthSessions_TerminatexSAP: Terminating handle %08x\n", + authSessions[i].handle); + TPM_AuthSessionData_Delete(&authSessions[i]); + } + } + return; +} + +/* + Context List + + Methods to manipulate the TPM_STANY_DATA->contextList[TPM_MAX_SESSION_LIST] array +*/ + +/* TPM_ContextList_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_ContextList_Init(uint32_t *contextList) +{ + size_t i; + + printf(" TPM_ContextList_Init:\n"); + for (i = 0 ; i < TPM_MIN_SESSION_LIST ; i++) { + contextList[i] = 0; + } + return; +} + +/* TPM_ContextList_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_ContextList_Init() +*/ + +TPM_RESULT TPM_ContextList_Load(uint32_t *contextList, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_ContextList_Load:\n"); + for (i = 0 ; (rc == 0) && (i < TPM_MIN_SESSION_LIST) ; i++) { + rc = TPM_Load32(&(contextList[i]), stream, stream_size); + } + return rc; +} + +/* TPM_ContextList_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_ContextList_Store(TPM_STORE_BUFFER *sbuffer, + const uint32_t *contextList) +{ + TPM_RESULT rc = 0; + size_t i; + + printf(" TPM_ContextList_Store: Storing %u contexts\n", TPM_MIN_SESSION_LIST); + for (i = 0 ; (rc == 0) && (i < TPM_MIN_SESSION_LIST) ; i++) { + rc = TPM_Sbuffer_Append32(sbuffer, contextList[i]); + } + return rc; +} + +/* TPM_ContextList_GetSpace() returns 'space', the number of unused context list entries. + + If 'space' is non-zero, 'entry' points to the first unused index. +*/ + +void TPM_ContextList_GetSpace(uint32_t *space, + uint32_t *entry, + const uint32_t *contextList) +{ + uint32_t i; + + printf(" TPM_ContextList_GetSpace:\n"); + for (*space = 0 , i = 0 ; i < TPM_MIN_SESSION_LIST ; i++) { + if (contextList[i] == 0) { /* zero values are free space */ + if (*space == 0) { + *entry = i; /* point to the first non-zero entry */ + } + (*space)++; + } + } + return; +} + +/* TPM_ContextList_GetEntry() gets the entry index corresponding to the value + +*/ + +TPM_RESULT TPM_ContextList_GetEntry(uint32_t *entry, + const uint32_t *contextList, + uint32_t value) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ContextList_GetEntry:\n"); + if (rc == 0) { + if (value == 0) { + printf("TPM_ContextList_GetEntry: Error, value %d never found\n", value); + rc = TPM_BADCONTEXT; + } + } + if (rc == 0) { + for (*entry = 0 ; *entry < TPM_MIN_SESSION_LIST ; (*entry)++) { + if (contextList[*entry] == value) { + break; + } + } + if (*entry == TPM_MIN_SESSION_LIST) { + printf("TPM_ContextList_GetEntry: Error, value %d not found\n", value); + rc = TPM_BADCONTEXT; + } + } + return rc; +} + +/* TPM_ContextList_StoreHandles() stores + + - the number of loaded context entries + - a list of context handles +*/ + +TPM_RESULT TPM_ContextList_StoreHandles(TPM_STORE_BUFFER *sbuffer, + const uint32_t *contextList) +{ + TPM_RESULT rc = 0; + uint16_t i; + uint16_t loaded; + + printf(" TPM_ContextList_StoreHandles:\n"); + if (rc == 0) { + loaded = 0; + /* count the number of loaded handles */ + for (i = 0 ; i < TPM_MIN_SESSION_LIST ; i++) { + if (contextList[i] != 0) { + loaded++; + } + } + /* store 'loaded' handle count */ + rc = TPM_Sbuffer_Append16(sbuffer, loaded); + } + for (i = 0 ; (rc == 0) && (i < TPM_MIN_SESSION_LIST ) ; i++) { + if (contextList[i] != 0) { /* if the index is loaded */ + rc = TPM_Sbuffer_Append32(sbuffer, contextList[i]); /* store it */ + } + } + return rc; +} + +/* + TPM_CONTEXT_BLOB +*/ + +/* TPM_ContextBlob_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_ContextBlob_Init(TPM_CONTEXT_BLOB *tpm_context_blob) +{ + printf(" TPM_ContextBlob_Init:\n"); + tpm_context_blob->resourceType = 0; + tpm_context_blob->handle = 0; + memset(tpm_context_blob->label, 0, TPM_CONTEXT_LABEL_SIZE); + tpm_context_blob->contextCount = 0; + TPM_Digest_Init(tpm_context_blob->integrityDigest); + TPM_SizedBuffer_Init(&(tpm_context_blob->additionalData)); + TPM_SizedBuffer_Init(&(tpm_context_blob->sensitiveData)); + return; +} + +/* TPM_ContextBlob_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_ContextBlob_Init() + After use, call TPM_ContextBlob_Delete() to free memory +*/ + +TPM_RESULT TPM_ContextBlob_Load(TPM_CONTEXT_BLOB *tpm_context_blob, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ContextBlob_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_CONTEXTBLOB, stream, stream_size); + } + /* load resourceType */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_context_blob->resourceType), stream, stream_size); + } + /* load handle */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_context_blob->handle), stream, stream_size); + } + /* load label */ + if (rc == 0) { + rc = TPM_Loadn(tpm_context_blob->label, TPM_CONTEXT_LABEL_SIZE, stream, stream_size); + } + /* load contextCount */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_context_blob->contextCount), stream, stream_size); + } + /* load integrityDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_context_blob->integrityDigest, stream, stream_size); + } + /* load additionalData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_context_blob->additionalData), stream, stream_size); + } + /* load sensitiveData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_context_blob->sensitiveData), stream, stream_size); + } + return rc; +} + +/* TPM_ContextBlob_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_ContextBlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CONTEXT_BLOB *tpm_context_blob) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ContextBlob_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CONTEXTBLOB); + } + /* store resourceType */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_context_blob->resourceType); + } + /* store handle */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_context_blob->handle); + } + /* store label */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_context_blob->label, TPM_CONTEXT_LABEL_SIZE); + } + /* store contextCount */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_context_blob->contextCount); + } + /* store integrityDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_context_blob->integrityDigest); + } + /* store additionalData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_context_blob->additionalData)); + } + /* store sensitiveData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_context_blob->sensitiveData)); + } + return rc; +} + +/* TPM_ContextBlob_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_ContextBlob_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_ContextBlob_Delete(TPM_CONTEXT_BLOB *tpm_context_blob) +{ + printf(" TPM_ContextBlob_Delete:\n"); + if (tpm_context_blob != NULL) { + TPM_SizedBuffer_Delete(&(tpm_context_blob->additionalData)); + TPM_SizedBuffer_Delete(&(tpm_context_blob->sensitiveData)); + TPM_ContextBlob_Init(tpm_context_blob); + } + return; +} + +/* + TPM_CONTEXT_SENSITIVE +*/ + +/* TPM_ContextSensitive_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_ContextSensitive_Init(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive) +{ + printf(" TPM_ContextSensitive_Init:\n"); + TPM_Nonce_Init(tpm_context_sensitive->contextNonce); + TPM_SizedBuffer_Init(&(tpm_context_sensitive->internalData)); + return; +} + +/* TPM_ContextSensitive_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_ContextSensitive_Init() + After use, call TPM_ContextSensitive_Delete() to free memory +*/ + +TPM_RESULT TPM_ContextSensitive_Load(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ContextSensitive_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_CONTEXT_SENSITIVE, stream, stream_size); + } + /* load contextNonce */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_context_sensitive->contextNonce, stream, stream_size); + } + /* load internalData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_context_sensitive->internalData), stream, stream_size); + } + return rc; +} + +/* TPM_ContextSensitive_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_ContextSensitive_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CONTEXT_SENSITIVE *tpm_context_sensitive) +{ + TPM_RESULT rc = 0; + + printf(" TPM_ContextSensitive_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CONTEXT_SENSITIVE); + } + /* store contextNonce */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_context_sensitive->contextNonce); + } + /* store internalData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_context_sensitive->internalData)); + } + return rc; +} + +/* TPM_ContextSensitive_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_ContextSensitive_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_ContextSensitive_Delete(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive) +{ + printf(" TPM_ContextSensitive_Delete:\n"); + if (tpm_context_sensitive != NULL) { + TPM_SizedBuffer_Delete(&(tpm_context_sensitive->internalData)); + TPM_ContextSensitive_Init(tpm_context_sensitive); + } + return; +} + +/* + Processing Functions +*/ + + +/* 18.1 TPM_OIAP rev 87 + +*/ + +TPM_RESULT TPM_Process_OIAP(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_AUTH_SESSION_DATA *authSession; /* the empty structure to be filled */ + TPM_BOOL got_handle = FALSE; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_AUTHHANDLE authHandle = 0; /* 0, no suggested value */ + + printf("TPM_Process_OIAP: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_OIAP: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM_OIAP command allows the creation of an authorization session handle and the + tracking of the handle by the TPM. The TPM generates the handle and nonce. */ + /* 2. The TPM has an internal limit as to the number of handles that may be open at one time, so + the request for a new handle may fail if there is insufficient space available. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetNewHandle(&authSession, + &authHandle, + tpm_state->tpm_stclear_data.authSessions); + } + /* 3. Internally the TPM will do the following: */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OIAP: Using authHandle %08x\n", authHandle); + got_handle = TRUE; + /* a. TPM allocates space to save handle, protocol identification, both nonces and any other + information the TPM needs to manage the session. */ + authSession->protocolID = TPM_PID_OIAP; + /* b. TPM generates authHandle and nonceEven, returns these to caller */ + returnCode = TPM_Nonce_Generate(authSession->nonceEven); + } + /* 4. On each subsequent use of the OIAP session the TPM MUST generate a new nonceEven value. */ + /* 5. When TPM_OIAP is wrapped in an encrypted transport session no input or output + parameters encrypted */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_OIAP: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + /* append authHandle */ + returnCode = TPM_Sbuffer_Append32(response, authHandle); + } + /* append nonceEven */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Store(response, authSession->nonceEven); + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if the handle is not being returned, it should be terminated */ + if (((returnCode != 0) || (rcf != 0)) && got_handle) { + TPM_AuthSessionData_Delete(authSession); + } + return rcf; +} + +/* 18.2 TPM_OSAP rev 98 + + The TPM_OSAP command creates the authorization handle, the shared secret and generates nonceEven + and nonceEvenOSAP. + + 1 The TPM_OSAP command allows the creation of an authorization handle and the tracking of the + handle by the TPM. The TPM generates the handle, nonceEven and nonceEvenOSAP. + + 2. The TPM has an internal limit on the number of handles that may be open at one time, so the + request for a new handle may fail if there is insufficient space available. + + 3. The TPM_OSAP allows the binding of an authorization to a specific entity. This allows the + caller to continue to send in authorization data for each command but not have to request the + information or cache the actual authorization data. + + 4. When TPM_OSAP is wrapped in an encrypted transport session, no input or output parameters are + encrypted + + 5. If the owner pointer is pointing to a delegate row, the TPM internally MUST treat the OSAP + session as a DSAP session + + 6. TPM_ET_SRK or TPM_ET_KEYHANDLE with a value of TPM_KH_SRK MUST specify the SRK. + + 7. If the entity is tied to PCR values, the PCR's are not validated during the TPM_OSAP ordinal + session creation. The PCR's are validated when the OSAP session is used. +*/ + +TPM_RESULT TPM_Process_OSAP(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_ENTITY_TYPE entityType; /* The type of entity in use */ + uint32_t entityValue = 0; /* The selection value based on entityType, e.g. a + keyHandle # */ + TPM_NONCE nonceOddOSAP; /* The nonce generated by the caller associated with + the shared secret. */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_AUTH_SESSION_DATA *authSession; /* the empty structure to be filled */ + TPM_BOOL got_handle = FALSE; + TPM_SECRET *authData; /* usageAuth for the entity */ + TPM_DIGEST *entityDigest = NULL; /* digest of the entity establishing the OSAP + session, initialize to silence compiler */ + TPM_KEY *authKey; /* key to authorize */ + TPM_BOOL parentPCRStatus; + TPM_COUNTER_VALUE *counterValue; /* associated with entityValue */ + TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; /* associated with entityValue */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_AUTHHANDLE authHandle = 0; /* Handle that TPM creates that points to the authorization + state. */ + TPM_NONCE nonceEvenOSAP; /* Nonce generated by TPM and associated with shared + secret. */ + + printf("TPM_Process_OSAP: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* get entityType */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&entityType, &command, ¶mSize); + } + /* get entityValue */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OSAP: entityType %04hx\n", entityType); + returnCode = TPM_Load32(&entityValue, &command, ¶mSize); + } + /* get nonceOddOSAP */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OSAP: entityValue %08x\n", entityValue); + returnCode = TPM_Nonce_Load(nonceOddOSAP, &command, ¶mSize); + } + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_OWNER | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_OSAP: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM creates S1 a storage area that keeps track of the information associated with the + authorization. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetNewHandle(&authSession, + &authHandle, + tpm_state->tpm_stclear_data.authSessions); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OSAP: Using authHandle %08x\n", authHandle); + got_handle = TRUE; + /* 2. S1 MUST track the following information: */ + /* a. Protocol identification */ + authSession->protocolID = TPM_PID_OSAP; /* save protocol identification */ + authSession->entityTypeByte = entityType & 0x00ff; /* save entity type LSB */ + /* b. nonceEven */ + /* i. Initialized to the next value from the TPM RNG */ + TPM_Nonce_Generate(authSession->nonceEven); + /* c. shared secret NOTE: determined below */ + /* d. ADIP encryption scheme from TPM_ENTITY_TYPE entityType */ + authSession->adipEncScheme = (entityType >> 8) & 0x00ff; /* save entity type MSB */ + /* e. Any other internal TPM state the TPM needs to manage the session */ + /* 3. The TPM MUST create and MAY track the following information */ + /* a. nonceEvenOSAP */ + /* i. Initialized to the next value from the TPM RNG */ + TPM_Nonce_Generate(nonceEvenOSAP); + /* 4. HMAC, shared secret NOTE: determined below */ + /* 5. Check if the ADIP encryption scheme specified by entityType is supported, if not + return TPM_INAPPROPRIATE_ENC. */ + returnCode = TPM_AuthSessionData_CheckEncScheme(authSession->adipEncScheme, + tpm_state->tpm_permanent_flags.FIPS); + } + if (returnCode == TPM_SUCCESS) { + switch (authSession->entityTypeByte) { + case TPM_ET_KEYHANDLE: + /* 6. If entityType = TPM_ET_KEYHANDLE */ + /* a. The entity to authorize is a key held in the TPM. entityValue contains the + keyHandle that holds the key. */ + /* b. If entityValue is TPM_KH_OPERATOR return TPM_BAD_HANDLE */ + if (returnCode == TPM_SUCCESS) { + if (entityValue == TPM_KH_OPERATOR) { + printf("TPM_Process_OSAP: Error, " + "entityType TPM_ET_KEYHANDLE entityValue TPM_KH_OPERATOR\n"); + returnCode = TPM_BAD_HANDLE; + } + } + /* look up and get the TPM_KEY authorization data */ + if (returnCode == TPM_SUCCESS) { + /* get the TPM_KEY, entityValue is the handle */ + printf("TPM_Process_OSAP: entityType TPM_ET_KEYHANDLE entityValue %08x\n", + entityValue); + /* TPM_KeyHandleEntries_GetKey() does the mapping from TPM_KH_SRK to the SRK */ + returnCode = TPM_KeyHandleEntries_GetKey(&authKey, + &parentPCRStatus, + tpm_state, + entityValue, + TRUE, /* read only */ + TRUE, /* ignore PCRs */ + FALSE); /* cannot use EK */ + } + if (returnCode == TPM_SUCCESS) { + /* get the entityDigest for the key */ + entityDigest = &(authKey->tpm_store_asymkey->pubDataDigest); + /* get the usageAuth for the key */ + returnCode = TPM_Key_GetUsageAuth(&authData, authKey); + } + break; + case TPM_ET_OWNER: + /* 7. else if entityType = TPM_ET_OWNER */ + /* a. This value indicates that the entity is the TPM owner. entityValue is ignored. */ + /* b. The HMAC key is the secret pointed to by ownerReference (owner secret or delegated + secret) */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OSAP: entityType TPM_ET_OWNER, ownerReference %08x\n", + tpm_state->tpm_stclear_data.ownerReference); + /* verify that an owner is installed */ + if (!tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_Process_OSAP: Error, no owner\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + /* owner reference is owner, use the owner authorization data */ + if (tpm_state->tpm_stclear_data.ownerReference == TPM_KH_OWNER) { + entityDigest = &(tpm_state->tpm_permanent_data.ownerAuth); + authData = &(tpm_state->tpm_permanent_data.ownerAuth); + } + /* Description 5. If the owner pointer is pointing to a delegate row, the TPM + internally MUST treat the OSAP session as a DSAP session */ + else { + returnCode = TPM_OSAPDelegate(&entityDigest, + &authData, + authSession, + tpm_state, + tpm_state->tpm_stclear_data.ownerReference); + } + } + break; + case TPM_ET_SRK: + /* 8. else if entityType = TPM_ET_SRK */ + /* a. The entity to authorize is the SRK. entityValue is ignored. */ + printf("TPM_Process_OSAP: entityType TPM_ET_SRK\n"); + entityDigest = &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); + returnCode = TPM_Key_GetUsageAuth(&authData, &(tpm_state->tpm_permanent_data.srk)); + break; + case TPM_ET_COUNTER: + /* 9. else if entityType = TPM_ET_COUNTER */ + /* a. The entity is a monotonic counter, entityValue contains the counter handle */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OSAP: entityType TPM_ET_COUNTER entityValue %08x\n", + entityValue); + returnCode = + TPM_Counters_GetCounterValue(&counterValue, + tpm_state->tpm_permanent_data.monotonicCounter, + entityValue); + } + if (returnCode == TPM_SUCCESS) { + /* get the entityDigest for the counter */ + entityDigest = &(counterValue->digest); + /* get the authData for the counter */ + authData = &(counterValue->authData); + } + break; + case TPM_ET_NV: + /* 10. else if entityType = TPM_ET_NV + a. The entity is a NV index, entityValue contains the NV index */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_OSAP: entityType TPM_ET_NV\n"); + returnCode = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, + &(tpm_state->tpm_nv_index_entries), + entityValue); + } + if (returnCode == TPM_SUCCESS) { + /* get the entityDigest for the NV data */ + entityDigest = &(tpm_nv_data_sensitive->digest); + /* get the authData for the NV data */ + authData = &(tpm_nv_data_sensitive->authValue); + } + break; + default: + /* 11. else return TPM_INVALID_PARAMETER */ + printf("TPM_Process_OSAP: Error, unknown entityType %04x\n", entityType); + returnCode = TPM_BAD_PARAMETER; + break; + } + } + /* 2.c. shared secret */ + /* 4. The TPM calculates the shared secret using an HMAC calculation. The key for the HMAC + calculation is the secret AuthData assigned to the key handle identified by entityValue. + The input to the HMAC calculation is the concatenation of nonces nonceEvenOSAP and + nonceOddOSAP. The output of the HMAC calculation is the shared secret which is saved in + the authorization area associated with authHandle */ + if (returnCode == TPM_SUCCESS) { + TPM_Digest_Copy(authSession->entityDigest, *entityDigest); + TPM_PrintFour("TPM_Process_OSAP: entityDigest", *entityDigest); + TPM_PrintFour("TPM_Process_OSAP: authData", *authData); + TPM_PrintFour("TPM_Process_OSAP: nonceEvenOSAP", nonceEvenOSAP); + TPM_PrintFour("TPM_Process_OSAP: nonceOddOSAP", nonceOddOSAP); + returnCode = TPM_HMAC_Generate(authSession->sharedSecret, + *authData, /* HMAC key */ + TPM_NONCE_SIZE, nonceEvenOSAP, + TPM_NONCE_SIZE, nonceOddOSAP, + 0, NULL); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_OSAP: sharedSecret", authSession->sharedSecret); + } + /* 12. On each subsequent use of the OSAP session the TPM MUST generate a new nonce value. + NOTE: Done as the response is generated. */ + /* 13. The TPM MUST ensure that OSAP shared secret is only available while the OSAP session is + valid. + */ + /* 14. The session MUST terminate upon any of the following conditions: + a. The command that uses the session returns an error + NOTE Done by command + b. The resource is evicted from the TPM or otherwise invalidated + NOTE Done by evict or flush + c. The session is used in any command for which the shared secret is used to encrypt an + input parameter (TPM_ENCAUTH) + NOTE Done by the command + d. The TPM Owner is cleared + NOTE Done by owner clear + e. TPM_ChangeAuthOwner is executed and this session is attached to the owner authorization + NOTE Done by TPM_ChangeAuthOwner + f. The session explicitly terminated with continueAuth, TPM_Reset or TPM_FlushSpecific + NOTE Done by the ordinal processing + g. All OSAP sessions associated with the delegation table MUST be invalidated when any of the + following commands execute: + i. TPM_Delegate_Manage + ii. TPM_Delegate_CreateOwnerDelegation with Increment==TRUE + iii. TPM_Delegate_LoadOwnerDelegation + NOTE Done by the ordinal processing + */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_OSAP: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + /* append authHandle */ + returnCode = TPM_Sbuffer_Append32(response, authHandle); + } + /* append nonceEven */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Store(response, authSession->nonceEven); + } + /* append nonceEvenOSAP */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Store(response, nonceEvenOSAP); + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if the handle is not being returned, it should be terminated */ + if (((returnCode != 0) || (rcf != 0)) && got_handle) { + TPM_AuthSessionData_Delete(authSession); + } + /* + cleanup + */ + return rcf; +} + +/* 18.3 TPM_DSAP rev 106 + + The TPM_DSAP command creates the authorization session handle using a delegated AuthData value + passed into the command as an encrypted blob or from the internal delegation table. It can be + used to start an authorization session for a user key or the owner. + + As in TPM_OSAP, it generates a shared secret and generates nonceEven and nonceEvenOSAP. + + 1. The TPM_DSAP command allows the creation of an authorization session handle and the tracking + of the handle by the TPM. The TPM generates the handle, nonceEven and nonceEvenOSAP. + + 2. The TPM has an internal limit on the number of handles that may be open at one time, so the + request for a new handle may fail if there is insufficient space available. + + 3. The TPM_DSAP allows the binding of a delegated authorization to a specific entity. This allows + the caller to continue to send in AuthData for each command but not have to request the + information or cache the actual AuthData. + + 4. On each subsequent use of the DSAP session the TPM MUST generate a new nonce value and check if + the ordinal to be executed has delegation to execute. The TPM MUST ensure that the DSAP shared + secret is only available while the DSAP session is valid. + + 5. When TPM_DSAP is wrapped in an encrypted transport session + a. For input the only parameter encrypted or logged is entityValue + b. For output no parameters are encrypted or logged + + 6. The DSAP session MUST terminate under any of the following conditions + + a. The command that uses the session returns an error + b. If attached to a key, when the key is evicted from the TPM or otherwise invalidated + c. The session is used in any command for which the shared secret is used to encrypt an + input parameter (TPM_ENCAUTH) + d. The TPM Owner is cleared + e. TPM_ChangeAuthOwner is executed and this session is attached to the owner + authorization + f. The session explicitly terminated with continueAuth, TPM_Reset or TPM_FlushSpecific + g. All DSAP sessions MUST be invalidated when any of the following commands execute: + + i. TPM_Delegate_CreateOwnerDelegation + (1) When Increment is TRUE + ii. TPM_Delegate_LoadOwnerDelegation + iii. TPM_Delegate_Manage + + NOTE Done by the ordinal processing + + entityType = TPM_ET_DEL_OWNER_BLOB + The entityValue parameter contains a delegation blob structure. + entityType = TPM_ET_DEL_ROW + The entityValue parameter contains a row number in the nv Delegation table which should be + used for the AuthData value. +*/ + +TPM_RESULT TPM_Process_DSAP(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_ENTITY_TYPE entityType; /* The type of delegation information to use */ + TPM_KEY_HANDLE keyHandle = 0; /* Key for which delegated authority corresponds, or 0 if + delegated owner activity. Only relevant if entityValue + equals TPM_DELEGATE_USEKEY_BLOB */ + TPM_NONCE nonceOddDSAP; /* The nonce generated by the caller associated with the + shared secret. */ + TPM_SIZED_BUFFER entityValue; /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB or + index. MUST not be empty. If entityType is TPM_ET_DEL_ROW + then entityValue is a TPM_DELEGATE_INDEX */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_AUTH_SESSION_DATA *authSession; /* the empty structure to be filled */ + unsigned char *stream; /* temp input stream */ + uint32_t stream_size; + TPM_DELEGATE_OWNER_BLOB b1DelegateOwnerBlob; + TPM_DELEGATE_KEY_BLOB k1DelegateKeyBlob; + TPM_KEY *delKey; /* key corresponding to keyHandle */ + TPM_BOOL parentPCRStatus; + TPM_DELEGATE_SENSITIVE s1DelegateSensitive; + uint32_t delegateRowIndex; + TPM_DELEGATE_TABLE_ROW *d1DelegateTableRow; + TPM_SECRET *a1AuthValue = NULL; + TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ + + TPM_BOOL got_handle = FALSE; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_AUTHHANDLE authHandle = 0; /* Handle that TPM creates that points to the authorization + state. */ + TPM_NONCE nonceEvenDSAP; /* Nonce generated by TPM and associated with shared + secret. */ + + printf("TPM_Process_DSAP: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&entityValue); /* freed @1 */ + TPM_DelegateOwnerBlob_Init(&b1DelegateOwnerBlob); /* freed @2 */ + TPM_DelegateKeyBlob_Init(&k1DelegateKeyBlob); /* freed @3 */ + TPM_DelegateSensitive_Init(&s1DelegateSensitive); /* freed @4 */ + /* + get inputs + */ + /* get entityType */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&entityType, &command, ¶mSize); + } + /* get keyHandle */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DSAP: entityType %04hx\n", entityType); + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* get nonceOddDSAP */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DSAP: keyHandle %08x\n", keyHandle); + returnCode = TPM_Nonce_Load(nonceOddDSAP, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command + sizeof(uint32_t); /* audit entityValue but not entityValueSize */ + /* get entityValue */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&entityValue, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_OWNER | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DSAP: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + /* use a temporary copy so the original values are not moved */ + stream = entityValue.buffer; + stream_size = entityValue.size; + switch (entityType & 0x00ff) { /* entity type LSB is the actual entity type */ + case TPM_ET_DEL_OWNER_BLOB: + /* 1. If entityType == TPM_ET_DEL_OWNER_BLOB */ + /* a. Map entityValue to B1 a TPM_DELEGATE_OWNER_BLOB */ + /* b. Validate that B1 is a valid TPM_DELEGATE_OWNER_BLOB, return TPM_WRONG_ENTITYTYPE + on error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateOwnerBlob_Load(&b1DelegateOwnerBlob, + &stream, &stream_size); + if (returnCode != TPM_SUCCESS) { + returnCode = TPM_WRONG_ENTITYTYPE; + } + } + /* c. Locate B1 -> pub -> familyID in the TPM_FAMILY_TABLE and set familyRow to + indicate row, return TPM_BADINDEX if not found */ + /* d. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ + /* e. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_FamilyTable_GetEnabledEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + b1DelegateOwnerBlob.pub.familyID); + } + /* f. Verify that B1->verificationCount equals FR -> verificationCount. */ + if (returnCode == TPM_SUCCESS) { + if (b1DelegateOwnerBlob.pub.verificationCount != familyRow->verificationCount) { + printf("TPM_Process_DSAP: Error, verificationCount mismatch %u %u\n", + b1DelegateOwnerBlob.pub.verificationCount, familyRow->verificationCount); + returnCode = TPM_FAMILYCOUNT; + } + } + /* g. Validate the integrity of the blob */ + /* i. Copy B1 -> integrityDigest to H2 */ + /* ii. Set B1 -> integrityDigest to NULL */ + /* iii. Create H3 the HMAC of B1 using tpmProof as the secret */ + /* iv. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &b1DelegateOwnerBlob, /* structure */ + b1DelegateOwnerBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store,/* store function */ + TPM_AUTHFAIL); /* error code */ + } + /* h. Create S1 a TPM_DELEGATE_SENSITIVE by decrypting B1 -> sensitiveArea using + TPM_DELEGATE_KEY */ + /* i. Validate S1 values */ + /* i. S1 -> tag is TPM_TAG_DELEGATE_SENSITIVE */ + /* ii. Return TPM_BAD_DELEGATE on error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateSensitive_DecryptEncData + (&s1DelegateSensitive, /* decrypted data */ + &(b1DelegateOwnerBlob.sensitiveArea), + tpm_state->tpm_permanent_data.delegateKey); + } + /* j. Set A1 to S1 -> authValue */ + if (returnCode == TPM_SUCCESS) { + a1AuthValue = &(s1DelegateSensitive.authValue); + } + break; + case TPM_ET_DEL_ROW: + /* 2. Else if entityType == TPM_ET_DEL_ROW */ + /* a. Verify that entityValue points to a valid row in the delegation table. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&delegateRowIndex, &stream, &stream_size); + } + /* b. Set D1 to the delegation information in the row. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_DelegateTable_GetValidRow(&d1DelegateTableRow, + &(tpm_state->tpm_permanent_data.delegateTable), + delegateRowIndex); + } + if (returnCode == TPM_SUCCESS) { + /* c. Set A1 to D1->authValue. */ + a1AuthValue = &d1DelegateTableRow->authValue; + /* d. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate + that row, return TPM_BADINDEX if not found */ + /* e. Set FR to TPM_FAMILY_TABLE.FamTableRow[familyRow] */ + /* f. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ + returnCode = + TPM_FamilyTable_GetEnabledEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + d1DelegateTableRow->pub.familyID); + } + /* g. Verify that D1->verificationCount equals FR -> verificationCount. */ + if (returnCode == TPM_SUCCESS) { + if (d1DelegateTableRow->pub.verificationCount != familyRow->verificationCount) { + printf("TPM_Process_DSAP: Error, verificationCount mismatch %u %u\n", + d1DelegateTableRow->pub.verificationCount, familyRow->verificationCount); + returnCode = TPM_FAMILYCOUNT; + } + } + break; + case TPM_ET_DEL_KEY_BLOB: + /* 3. Else if entityType == TPM_ET_DEL_KEY_BLOB */ + /* a. Map entityValue to K1 a TPM_DELEGATE_KEY_BLOB */ + /* b. Validate that K1 is a valid TPM_DELEGATE_KEY_BLOB, return TPM_WRONG_ENTITYTYPE on + error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateKeyBlob_Load(&k1DelegateKeyBlob, &stream, &stream_size); + if (returnCode != TPM_SUCCESS) { + returnCode = TPM_WRONG_ENTITYTYPE; + } + } + /* c. Locate K1 -> pub -> familyID in the TPM_FAMILY_TABLE and set familyRow to + indicate that row, return TPM_BADINDEX if not found */ + /* d. Set FR to TPM_FAMILY_TABLE.FamTableRow[familyRow] */ + /* e. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_FamilyTable_GetEnabledEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + k1DelegateKeyBlob.pub.familyID); + } + /* f. Verify that K1 -> pub -> verificationCount equals FR -> verificationCount. */ + if (returnCode == TPM_SUCCESS) { + if (k1DelegateKeyBlob.pub.verificationCount != familyRow->verificationCount) { + printf("TPM_Process_DSAP: Error, verificationCount mismatch %u %u\n", + k1DelegateKeyBlob.pub.verificationCount, familyRow->verificationCount); + returnCode = TPM_FAMILYCOUNT; + } + } + /* g. Validate the integrity of the blob */ + /* i. Copy K1 -> integrityDigest to H2 */ + /* ii. Set K1 -> integrityDigest to NULL */ + /* iii. Create H3 the HMAC of K1 using tpmProof as the secret */ + /* iv. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &k1DelegateKeyBlob, /* structure */ + k1DelegateKeyBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store, /* store function */ + TPM_AUTHFAIL); /* error code */ + } + /* h. Validate that K1 -> pubKeyDigest identifies keyHandle, return TPM_KEYNOTFOUND on + error */ + /* get the TPM_KEY corresponding to keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&delKey, + &parentPCRStatus, + tpm_state, + keyHandle, + TRUE, /* read only */ + TRUE, /* ignore PCRs at setup */ + FALSE); /* cannot use EK */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_CheckStructure(k1DelegateKeyBlob.pubKeyDigest, + &(delKey->pubKey), + (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store, + TPM_KEYNOTFOUND); + } + /* i. Create S1 a TPM_DELEGATE_SENSITIVE by decrypting K1 -> sensitiveArea using + TPM_DELEGATE_KEY */ + /* j. Validate S1 values */ + /* i. S1 -> tag is TPM_TAG_DELEGATE_SENSITIVE */ + /* ii. Return TPM_BAD_DELEGATE on error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_DelegateSensitive_DecryptEncData + (&s1DelegateSensitive, /* decrypted data */ + &(k1DelegateKeyBlob.sensitiveArea), + tpm_state->tpm_permanent_data.delegateKey); + } + /* k. Set A1 to S1 -> authValue */ + if (returnCode == TPM_SUCCESS) { + a1AuthValue = &(s1DelegateSensitive.authValue); + } + break; + default: + /* 4. Else return TPM_BAD_PARAMETER */ + printf("TPM_Process_DSAP: Error, bad entityType %04hx\n", entityType); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 5. Generate a new authorization session handle and reserve space to save protocol + identification, shared secret, pcrInfo, both nonces, ADIP encryption scheme, delegated + permission bits and any other information the TPM needs to manage the session. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetNewHandle(&authSession, + &authHandle, + tpm_state->tpm_stclear_data.authSessions); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DSAP: Using authHandle %08x\n", authHandle); + got_handle = TRUE; + /* save protocol identification */ + authSession->protocolID = TPM_PID_DSAP; + /* save the ADIP encryption scheme */ + authSession->adipEncScheme = (entityType >> 8) & 0x00ff; + /* NOTE: added: Check if the ADIP encryption scheme specified by entityType is supported, if + not return TPM_INAPPROPRIATE_ENC. */ + returnCode = TPM_AuthSessionData_CheckEncScheme(authSession->adipEncScheme, + tpm_state->tpm_permanent_flags.FIPS); + } + if (returnCode == TPM_SUCCESS) { + if (entityType == TPM_ET_DEL_KEY_BLOB) { + /* map the entity type to a key */ + authSession->entityTypeByte = TPM_ET_KEYHANDLE; + /* Save the entityDigest for comparison during use. */ + TPM_Digest_Copy(authSession->entityDigest, delKey->tpm_store_asymkey->pubDataDigest); + /* Save the TPM_DELEGATE_PUBLIC to check the permissions and pcrInfo at DSAP session + use. */ + returnCode =TPM_DelegatePublic_Copy(&(authSession->pub), &(k1DelegateKeyBlob.pub)); + } + else { + /* owner or blob or delegate row are both owner auth */ + authSession->entityTypeByte = TPM_ET_OWNER; + /* Save the entityDigest for comparison during use. */ + TPM_Digest_Copy(authSession->entityDigest, tpm_state->tpm_permanent_data.ownerAuth); + /* Save the TPM_DELEGATE_PUBLIC to check the permissions and pcrInfo at DSAP session + use. */ + if (entityType == TPM_ET_DEL_OWNER_BLOB) { + returnCode = TPM_DelegatePublic_Copy(&(authSession->pub), + &(b1DelegateOwnerBlob.pub)); + } + else { /* TPM_ET_DEL_ROW */ + returnCode = TPM_DelegatePublic_Copy(&(authSession->pub), + &(d1DelegateTableRow->pub)); + } + } + /* 6. Read two new values from the RNG to generate nonceEven and nonceEvenOSAP. */ + TPM_Nonce_Generate(authSession->nonceEven); + TPM_Nonce_Generate(nonceEvenDSAP); + } + /* 7. The TPM calculates the shared secret using an HMAC calculation. The key for the HMAC + calculation is A1. The input to the HMAC calculation is the concatenation of nonces + nonceEvenOSAP and nonceOddOSAP. The output of the HMAC calculation is the shared secret + which is saved in the authorization area associated with authHandle. */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_DSAP: authData", *a1AuthValue); + TPM_PrintFour("TPM_Process_DSAP: nonceEvenOSAP", nonceEvenDSAP); + TPM_PrintFour("TPM_Process_DSAP: nonceOddOSAP", nonceOddDSAP); + returnCode = TPM_HMAC_Generate(authSession->sharedSecret, + *a1AuthValue, /* HMAC key */ + TPM_NONCE_SIZE, nonceEvenDSAP, + TPM_NONCE_SIZE, nonceOddDSAP, + 0, NULL); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DSAP: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + /* append authHandle */ + returnCode = TPM_Sbuffer_Append32(response, authHandle); + } + /* append nonceEven */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Store(response, authSession->nonceEven); + } + /* append nonceEvenDSAP */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Store(response, nonceEvenDSAP); + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if the handle is not being returned, it should be terminated */ + if (((returnCode != 0) || (rcf != 0)) && got_handle) { + TPM_AuthSessionData_Delete(authSession); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&entityValue); /* @1 */ + TPM_DelegateOwnerBlob_Delete(&b1DelegateOwnerBlob); /* @2 */ + TPM_DelegateKeyBlob_Delete(&k1DelegateKeyBlob); /* @3 */ + TPM_DelegateSensitive_Delete(&s1DelegateSensitive); /* @4 */ + return rcf; +} + +/* TPM_DSAPDelegate() implements the actions common to TPM_DSAP and TPM_OSAP with + ownerReference pointing to a delegate row. + + 'entityDigest' and 'authData' are returned, as they are used by common code. + authSession. + + protocolID is changed to DSAP. + the TPM_DELEGATE_PUBLIC blob is copied to the OSAP/DSAP session structure. +*/ + +static TPM_RESULT TPM_OSAPDelegate(TPM_DIGEST **entityDigest, + TPM_SECRET **authData, + TPM_AUTH_SESSION_DATA *authSession, + tpm_state_t *tpm_state, + uint32_t delegateRowIndex) +{ + TPM_RESULT rc = 0; + TPM_DELEGATE_TABLE_ROW *d1DelegateTableRow; + TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ + + printf("TPM_DSAPCommon: Index %u\n", delegateRowIndex); + /* 2. Else if entityType == TPM_ET_DEL_ROW */ + /* a. Verify that entityValue points to a valid row in the delegation table. */ + /* b. Set d1 to the delegation information in the row. */ + if (rc == TPM_SUCCESS) { + rc = TPM_DelegateTable_GetValidRow(&d1DelegateTableRow, + &(tpm_state->tpm_permanent_data.delegateTable), + delegateRowIndex); + } + if (rc == TPM_SUCCESS) { + /* d. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate that + row, return TPM_BADINDEX if not found */ + /* e. Set FR to TPM_FAMILY_TABLE.FamTableRow[familyRow] */ + /* f. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ + rc = TPM_FamilyTable_GetEnabledEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + d1DelegateTableRow->pub.familyID); + } + /* g. Verify that d1->verificationCount equals FR -> verificationCount. */ + if (rc == TPM_SUCCESS) { + if (d1DelegateTableRow->pub.verificationCount != familyRow->verificationCount) { + printf("TPM_DSAPCommon: Error, verificationCount mismatch %u %u\n", + d1DelegateTableRow->pub.verificationCount, familyRow->verificationCount); + rc = TPM_FAMILYCOUNT; + } + } + if (rc == TPM_SUCCESS) { + /* c. Set a1 to d1->authValue. */ + *authData = &d1DelegateTableRow->authValue; /* use owner delegate authorization value */ + /* indicate later that the entity is the 'owner'. Use the real owner auth because the + ordinal doesn't know about the delegation */ + *entityDigest = &(tpm_state->tpm_permanent_data.ownerAuth); + authSession->protocolID = TPM_PID_DSAP; /* change from OSAP to DSAP */ + /* Save the TPM_DELEGATE_PUBLIC to check the permissions and pcrInfo at DSAP session + use. */ + rc = TPM_DelegatePublic_Copy(&(authSession->pub), + &(d1DelegateTableRow->pub)); + } + return rc; +} + +/* 18.4 TPM_SetOwnerPointer rev 109 + + This command will set a reference to which secret the TPM will use when executing an owner secret + related OIAP or OSAP session. + + This command should only be used to provide an owner delegation function for legacy code that + does not itself support delegation. Normally, TPM_STCLEAR_DATA->ownerReference points to + TPM_KH_OWNER, indicating that OIAP and OSAP sessions should use the owner authorization. This + command allows ownerReference to point to an index in the delegation table, indicating that + OIAP and OSAP sessions should use the delegation authorization. + + In use, a TSS supporting delegation would create and load the owner delegation and set the owner + pointer to that delegation. From then on, a legacy TSS application would use its OIAP and OSAP + sessions with the delegated owner authorization. + + Since this command is not authorized, the ownerReference is open to DoS attacks. Applications can + attempt to recover from a failing owner authorization by resetting ownerReference to an + appropriate value. + + This command intentionally does not clear OSAP sessions. A TPM 1.1 application gets the benefit + of owner delegation, while the original owner can use a pre-existing OSAP session with the actual + owner authorization. +*/ + +TPM_RESULT TPM_Process_SetOwnerPointer(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) + +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_ENTITY_TYPE entityType; /* The type of entity in use */ + uint32_t entityValue = 0; /* The selection value based on entityType */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_STCLEAR_DATA *v1StClearData; + TPM_DELEGATE_TABLE_ROW *b1DelegateTableRow; /* delegate row indicated by entityValue */ + TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SetOwnerPointer: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get entityType */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&entityType, &command, ¶mSize); + } + /* get entityValue */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SetOwnerPointer: entityType %04hx\n", entityType); + returnCode = TPM_Load32(&entityValue, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SetOwnerPointer: entityValue %08x\n", entityValue); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SetOwnerPointer: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Map TPM_STCLEAR_DATA to V1 */ + if (returnCode == TPM_SUCCESS) { + v1StClearData = &(tpm_state->tpm_stclear_data); + /* 2. If entityType = TPM_ET_DEL_ROW */ + if (entityType == TPM_ET_DEL_ROW) { + /* a. This value indicates that the entity is a delegate row. entityValue is a delegate + index in the delegation table. */ + /* b. Validate that entityValue points to a legal row within the delegate table stored + within the TPM. If not return TPM_BADINDEX */ + /* i. Set D1 to the delegation information in the row. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_DelegateTable_GetValidRow(&b1DelegateTableRow, + &(tpm_state->tpm_permanent_data.delegateTable), + entityValue); + + } + /* c. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate that + row, return TPM_BADINDEX if not found. */ + /* d. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ + /* e. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_FamilyTable_GetEnabledEntry(&familyRow, + &(tpm_state->tpm_permanent_data.familyTable), + b1DelegateTableRow->pub.familyID); + } + /* f. Verify that B1->verificationCount equals FR -> verificationCount. */ + if (returnCode == TPM_SUCCESS) { + if (b1DelegateTableRow->pub.verificationCount != familyRow->verificationCount) { + printf("TPM_Process_SetOwnerPointer: Error, " + "verificationCount mismatch %u %u\n", + b1DelegateTableRow->pub.verificationCount, familyRow->verificationCount); + returnCode = TPM_FAMILYCOUNT; + } + } + /* g. The TPM sets V1-> ownerReference to entityValue */ + /* h. Return TPM_SUCCESS */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SetOwnerPointer: Setting ownerReference to %08x\n", + entityValue); + v1StClearData->ownerReference = entityValue; + } + } + /* 3. else if entityType = TPM_ET_OWNER */ + else if (entityType == TPM_ET_OWNER) { + /* a. This value indicates that the entity is the TPM owner. entityValue is ignored. */ + /* b. The TPM sets V1-> ownerReference to TPM_KH_OWNER */ + /* c. Return TPM_SUCCESS */ + printf("TPM_Process_SetOwnerPointer: Setting ownerReference to %08x\n", TPM_KH_OWNER); + v1StClearData->ownerReference = TPM_KH_OWNER; + } + /* 4. Return TPM_BAD_PARAMETER */ + else { + printf("TPM_Process_SetOwnerPointer: Error, bad entityType\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SetOwnerPointer: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + return rcf; +} + +/* 27.1.2 TPM_Terminate_Handle rev 87 + + This allows the TPM manager to clear out information in a session handle. + + The TPM may maintain the authorization session even though a key attached to it has been unloaded + or the authorization session itself has been unloaded in some way. When a command is executed + that requires this session, it is the responsibility of the external software to load both the + entity and the authorization session information prior to command execution. + + The TPM SHALL terminate the session and destroy all data associated with the session indicated. +*/ + +TPM_RESULT TPM_Process_TerminateHandle(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_TerminateHandle: Ordinal Entry\n"); + /* + get inputs + */ + /* get handle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&authHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_TerminateHandle: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* terminate the handle */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TerminateHandle: Using authHandle %08x\n", authHandle); + returnCode = TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, + authHandle); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_TerminateHandle: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 22.1 TPM_FlushSpecific rev 104 + + TPM_FlushSpecific flushes from the TPM a specific handle. + + TPM_FlushSpecific releases the resources associated with the given handle. +*/ + +TPM_RESULT TPM_Process_FlushSpecific(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_HANDLE handle; /* The handle of the item to flush */ + TPM_RESOURCE_TYPE resourceType = 0; /* The type of resource that is being flushed */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + uint32_t r1Resource; /* the context resource being flushed */ + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* key table entry for the handle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_FlushSpecific: Ordinal Entry\n"); + /* + get inputs + */ + /* get handle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&handle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get resourceType parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_FlushSpecific: Handle %08x\n", handle); + returnCode = TPM_Load32(&resourceType, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_FlushSpecific: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + switch (resourceType) { + case TPM_RT_CONTEXT: + /* 1. If resourceType is TPM_RT_CONTEXT */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_FlushSpecific: Flushing context count %08x\n", handle); + /* a. The handle for a context is not a handle but the "context count" value. The + TPM uses the "context count" value to locate the proper contextList entry and + sets R1 to the contextList entry */ + returnCode = TPM_ContextList_GetEntry(&r1Resource, /* index into + contextList[] */ + tpm_state->tpm_stclear_data.contextList, + handle); + /* 7. Validate that R1 determined by resourceType and handle points to a valid + allocated resource. Return TPM_BAD_PARAMETER on error. */ + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_FlushSpecific: Error, context count %08x not found\n", + handle); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 8. Invalidate R1 and all internal resources allocated to R1 */ + /* a. Resources include authorization sessions */ + if (returnCode == TPM_SUCCESS) { + /* setting the entry to 0 prevents the session from being reloaded. */ + tpm_state->tpm_stclear_data.contextList[r1Resource] = 0; + } + break; + case TPM_RT_KEY: + /* 2. Else if resourceType is TPM_RT_KEY */ + /* a. Set R1 to the key pointed to by handle */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_FlushSpecific: Flushing key handle %08x\n", handle); + returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_state->tpm_key_handle_entries, + handle); + /* 7. Validate that R1 determined by resourceType and handle points to a valid + allocated resource. Return TPM_BAD_PARAMETER on error. */ + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_FlushSpecific: Error, key handle %08x not found\n", + handle); + returnCode = TPM_BAD_PARAMETER; + } + } + /* b. If R1 -> ownerEvict is TRUE return TPM_KEY_OWNER_CONTROL */ + if (returnCode == TPM_SUCCESS) { + if (tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) { + printf("TPM_Process_FlushSpecific: Error, keyHandle specifies owner evict\n"); + returnCode = TPM_KEY_OWNER_CONTROL; + } + } + /* 8. Invalidate R1 and all internal resources allocated to R1 */ + /* a. Resources include authorization sessions */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntry_FlushSpecific(tpm_state, tpm_key_handle_entry); + } + break; + case TPM_RT_AUTH: + /* NOTE replaces deprecated TPM_Terminate_Handle */ + /* 3. Else if resourceType is TPM_RT_AUTH */ + /* a. Set R1 to the authorization session pointed to by handle */ + /* 7. Validate that R1 determined by resourceType and handle points to a valid allocated + resource. Return TPM_BAD_PARAMETER on error. */ + /* 8. Invalidate R1 and all internal resources allocated to R1 */ + /* a. Resources include authorization sessions */ + printf("TPM_Process_FlushSpecific: Flushing authorization session handle %08x\n", + handle); + returnCode = TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, + handle); + break; + case TPM_RT_TRANS: + /* 4. Else if resourceType is TPM_RT_TRANS */ + /* a. Set R1 to the transport session pointed to by handle */ + /* 7. Validate that R1 determined by resourceType and handle points to a valid allocated + resource. Return TPM_BAD_PARAMETER on error. */ + /* 8. Invalidate R1 and all internal resources allocated to R1 */ + /* a. Resources include authorization sessions */ + printf("TPM_Process_FlushSpecific: Flushing transport session handle %08x\n", handle); + returnCode = TPM_TransportSessions_TerminateHandle + (tpm_state->tpm_stclear_data.transSessions, + handle, + &(tpm_state->tpm_stany_flags.transportExclusive)); + break; + case TPM_RT_DAA_TPM: + /* 5. Else if resourceType is TPM_RT_DAA_TPM */ + /* a. Set R1 to the DAA session pointed to by handle */ + /* 7. Validate that R1 determined by resourceType and handle points to a valid allocated + resource. Return TPM_BAD_PARAMETER on error. */ + /* 8. Invalidate R1 and all internal resources allocated to R1 */ + /* a. Resources include authorization sessions */ + printf("TPM_Process_FlushSpecific: Flushing DAA session handle %08x\n", handle); + returnCode = TPM_DaaSessions_TerminateHandle(tpm_state->tpm_stclear_data.daaSessions, + handle); + break; + default: + /* 6. Else return TPM_INVALID_RESOURCE */ + printf("TPM_Process_FlushSpecific: Error, invalid resourceType %08x\n", resourceType); + returnCode = TPM_INVALID_RESOURCE; + break; + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_FlushSpecific: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 21.2 TPM_SaveContext rev 107 + + SaveContext saves a loaded resource outside the TPM. After successful execution of the command the + TPM automatically releases the internal memory for sessions but leaves keys in place. + + The caller of the function uses the label field to add additional sequencing, anti-replay or other + items to the blob. The information does not need to be confidential but needs to be part of the + blob integrity. +*/ + +TPM_RESULT TPM_Process_SaveContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_HANDLE handle; /* Handle of the resource being saved. */ + TPM_RESOURCE_TYPE resourceType = 0; /* The type of resource that is being saved */ + BYTE label[TPM_CONTEXT_LABEL_SIZE]; /* Label for identification purposes */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_STORE_BUFFER b1_sbuffer; /* serialization of b1 */ + TPM_STCLEAR_DATA *v1StClearData = NULL; + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* key table entry for the handle */ + TPM_AUTH_SESSION_DATA *tpm_auth_session_data = NULL; /* session table entry for the handle */ + TPM_TRANSPORT_INTERNAL *tpm_transport_internal; /* transport table entry for the handle */ + TPM_DAA_SESSION_DATA *tpm_daa_session_data; /* daa session table entry for the handle */ + TPM_NONCE *n1ContextNonce = NULL; + TPM_SYMMETRIC_KEY_TOKEN k1ContextKey = NULL; + TPM_STORE_BUFFER r1ContextSensitive; /* serialization of sensitive data clear text */ + TPM_CONTEXT_SENSITIVE c1ContextSensitive; + TPM_CONTEXT_BLOB b1ContextBlob; + TPM_STORE_BUFFER c1_sbuffer; /* serialization of c1ContextSensitive */ + uint32_t contextIndex = 0; /* free index in context list */ + uint32_t space; /* free space in context list */ + TPM_BOOL isZero; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SaveContext: Ordinal Entry\n"); + TPM_Sbuffer_Init(&b1_sbuffer); /* freed @1 */ + TPM_Sbuffer_Init(&r1ContextSensitive); /* freed @2 */ + TPM_ContextBlob_Init(&b1ContextBlob); /* freed @3 */ + TPM_ContextSensitive_Init(&c1ContextSensitive); /* freed @4 */ + TPM_Sbuffer_Init(&c1_sbuffer); /* freed @6 */ + /* + get inputs + */ + /* get handle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&handle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get resourceType */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveContext: handle %08x\n", handle); + returnCode = TPM_Load32(&resourceType, &command, ¶mSize); + } + /* get label */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveContext: resourceType %08x\n", resourceType); + returnCode = TPM_Loadn(label, TPM_CONTEXT_LABEL_SIZE, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_SaveContext: label", label); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SaveContext: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Map V1 to TPM_STANY_DATA NOTE MAY be TPM_STCLEAR_DATA */ + if (returnCode == TPM_SUCCESS) { + v1StClearData = &(tpm_state->tpm_stclear_data); + } + /* 2. Validate that handle points to resource that matches resourceType, return + TPM_INVALID_RESOURCE on error */ + /* 3. Validate that resourceType is a resource from the following list if not return + TPM_INVALID_RESOURCE */ + if (returnCode == TPM_SUCCESS) { + switch (resourceType) { + case TPM_RT_KEY: + /* a. TPM_RT_KEY */ + printf("TPM_Process_SaveContext: Resource is key handle %08x\n", handle); + /* check if the key handle is valid */ + returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_state->tpm_key_handle_entries, + handle); + break; + case TPM_RT_AUTH: + /* b. TPM_RT_AUTH */ + printf("TPM_Process_SaveContext: Resource is session handle %08x\n", handle); + returnCode = TPM_AuthSessions_GetEntry(&tpm_auth_session_data, + v1StClearData->authSessions, + handle); + break; + case TPM_RT_TRANS: + /* c. TPM_RT_TRANS */ + printf("TPM_Process_SaveContext: Resource is transport handle %08x\n", handle); + returnCode = TPM_TransportSessions_GetEntry(&tpm_transport_internal, + v1StClearData->transSessions, + handle); + break; + case TPM_RT_DAA_TPM: + /* d. TPM_RT_DAA_TPM */ + printf("TPM_Process_SaveContext: Resource is DAA handle %08x\n", handle); + returnCode = TPM_DaaSessions_GetEntry(&tpm_daa_session_data, + v1StClearData->daaSessions, + handle); + break; + default: + printf("TPM_Process_SaveContext: Error, invalid resourceType %08x\n", resourceType); + returnCode = TPM_INVALID_RESOURCE; + break; + } + if (returnCode != 0) { + printf("TPM_Process_SaveContext: Error, handle %08x not found\n", handle); + returnCode = TPM_INVALID_RESOURCE; + } + } + /* 4. Locate the correct nonce */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveContext: Locating nonce\n"); + /* a. If resourceType is TPM_RT_KEY */ + if (resourceType == TPM_RT_KEY) { + if (returnCode == TPM_SUCCESS) { + /* i. If TPM_STCLEAR_DATA -> contextNonceKey is NULLS */ + TPM_Nonce_IsZero(&isZero, tpm_state->tpm_stclear_data.contextNonceKey); + if (isZero) { + /* (1) Set TPM_STCLEAR_DATA -> contextNonceKey to the next value from the TPM + RNG */ + returnCode = TPM_Nonce_Generate(tpm_state->tpm_stclear_data.contextNonceKey); + } + } + if (returnCode == TPM_SUCCESS) { + /* ii. Map N1 to TPM_STCLEAR_DATA -> contextNonceKey */ + n1ContextNonce = &(tpm_state->tpm_stclear_data.contextNonceKey); + /* iii. If the key has TPM_KEY_CONTROL_OWNER_EVICT set then return TPM_OWNER_CONTROL + */ + if (tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) { + printf("TPM_Process_SaveContext: Error, key under owner control\n"); + returnCode = TPM_OWNER_CONTROL; + } + } + } + /* b. Else (resource not TPM_RT_KEY) */ + else { + if (returnCode == TPM_SUCCESS) { + /* i. If V1 -> contextNonceSession is NULLS */ + TPM_Nonce_IsZero(&isZero, v1StClearData->contextNonceSession); + if (isZero) { + /* (1) Set V1 -> contextNonceSession to the next value from the TPM RNG */ + returnCode = TPM_Nonce_Generate(v1StClearData->contextNonceSession); + } + } + /* ii. Map N1 to V1 -> contextNonceSession */ + if (returnCode == TPM_SUCCESS) { + n1ContextNonce = &(v1StClearData->contextNonceSession); + } + } + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveContext: Building sensitive data\n"); + /* 5. Set K1 to TPM_PERMANENT_DATA -> contextKey */ + k1ContextKey = tpm_state->tpm_permanent_data.contextKey; + /* 6. Create R1 by putting the sensitive part of the resource pointed to by handle into a + structure. The structure is a TPM manufacturer option. The TPM MUST ensure that ALL + sensitive information of the resource is included in R1. */ + /* NOTE Since the contextKey is a symmetric key, the entire resource is put into the + sensitiveData */ + switch (resourceType) { + case TPM_RT_KEY: + returnCode = TPM_KeyHandleEntry_Store(&r1ContextSensitive, tpm_key_handle_entry); + break; + case TPM_RT_AUTH: + returnCode = TPM_AuthSessionData_Store(&r1ContextSensitive, tpm_auth_session_data); + break; + case TPM_RT_TRANS: + returnCode = TPM_TransportInternal_Store(&r1ContextSensitive, tpm_transport_internal); + break; + case TPM_RT_DAA_TPM: + returnCode = TPM_DaaSessionData_Store(&r1ContextSensitive, tpm_daa_session_data); + break; + default: + printf("TPM_Process_SaveContext: Error, invalid resourceType %08x", resourceType); + returnCode = TPM_INVALID_RESOURCE; + break; + } + } + /* 7. Create C1 a TPM_CONTEXT_SENSITIVE structure */ + /* NOTE Done at TPM_ContextSensitive_Init() */ + /* a. C1 forms the inner encrypted wrapper for the blob. All saved context blobs MUST include a + TPM_CONTEXT_SENSITIVE structure and the TPM_CONTEXT_SENSITIVE structure MUST be encrypted. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveContext: Building TPM_CONTEXT_SENSITIVE\n"); + /* b. Set C1 -> contextNonce to N1 */ + TPM_Nonce_Copy(c1ContextSensitive.contextNonce, *n1ContextNonce); + /* c. Set C1 -> internalData to R1 */ + returnCode = TPM_SizedBuffer_SetFromStore(&(c1ContextSensitive.internalData), + &r1ContextSensitive); + } + /* 8. Create B1 a TPM_CONTEXT_BLOB */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveContext: Building TPM_CONTEXT_BLOB\n"); + /* a. Set B1 -> tag to TPM_TAG_CONTEXTBLOB */ + /* NOTE Done at TPM_ContextBlob_Init() */ + /* b. Set B1 -> resourceType to resourceType */ + b1ContextBlob.resourceType = resourceType; + /* c. Set B1 -> handle to handle */ + b1ContextBlob.handle = handle; + /* d. Set B1 -> integrityDigest to NULL */ + /* NOTE Done at TPM_ContextBlob_Init() */ + /* e. Set B1 -> label to label */ + memcpy(b1ContextBlob.label, label, TPM_CONTEXT_LABEL_SIZE); + + } + /* f. Set B1 -> additionalData to information determined by the TPM manufacturer. This data will + help the TPM to reload and reset context. This area MUST NOT hold any data that is sensitive + (symmetric IV are fine, prime factors of an RSA key are not). */ + /* i. For OSAP sessions, and for DSAP sessions attached to keys, the hash of the entity MUST be + included in additionalData */ + /* NOTE Included in TPM_AUTH_SESSION_DATA. This is implementation defined, and the manufacturer + can put everything in sensitive data. */ + /* g. Set B1 -> additionalSize to the size of additionalData */ + /* NOTE Initialized by TPM_ContextBlob_Init() */ + /* h. Set B1 -> sensitiveSize to the size of C1 */ + /* i. Set B1 -> sensitiveData to C1 */ + /* serialize C1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextSensitive_Store(&c1_sbuffer, &c1ContextSensitive); + } + /* Here the clear text goes into TPM_CONTEXT_BLOB->sensitiveData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_SetFromStore(&(b1ContextBlob.sensitiveData), &c1_sbuffer); + } + if (returnCode == TPM_SUCCESS) { + /* 9. If resourceType is TPM_RT_KEY */ + if (resourceType == TPM_RT_KEY) { + /* a. Set B1 -> contextCount to 0 */ + b1ContextBlob.contextCount = 0; + } + /* 10. Else */ + else { + printf("TPM_Process_SaveContext: Processing session context count\n"); + if (returnCode == TPM_SUCCESS) { + /* a. If V1 -> contextCount > 2^32-2 then */ + if (v1StClearData->contextCount > 0xfffffffe) { + /* i. Return with TPM_TOOMANYCONTEXTS */ + printf("TPM_Process_SaveContext: Error, too many contexts\n"); + returnCode = TPM_TOOMANYCONTEXTS; + } + } + /* b. Else */ + if (returnCode == TPM_SUCCESS) { + /* i. Validate that the TPM can still manage the new count value */ + /* (1) If the distance between the oldest saved context and the contextCount is + too large return TPM_CONTEXT_GAP */ + /* Since contextCount is uint32_t, this is not applicable here. From email: Does + the TPM have the ability to keep track of the context delta. It is possible to + keep track of things with just a byte or so internally, if this is done a gap of + greater than 2^16 or so might be too large, hence the context gap message */ + } + /* ii. Find contextIndex such that V1 -> contextList[contextIndex] equals 0. If not + found exit with TPM_NOCONTEXTSPACE */ + if (returnCode == TPM_SUCCESS) { + TPM_ContextList_GetSpace(&space, &contextIndex, v1StClearData->contextList); + if (space == 0) { + printf("TPM_Process_SaveContext: Error, no space in context list\n"); + returnCode = TPM_NOCONTEXTSPACE; + } + } + if (returnCode == TPM_SUCCESS) { + /* iii. Increment V1 -> contextCount by 1 */ + v1StClearData->contextCount++; + /* iv. Set V1-> contextList[contextIndex] to V1 -> contextCount */ + v1StClearData->contextList[contextIndex] = v1StClearData->contextCount; + /* v. Set B1 -> contextCount to V1 -> contextCount */ + b1ContextBlob.contextCount = v1StClearData->contextCount; + } + /* c. The TPM MUST invalidate all information regarding the resource except for + information needed for reloading */ + if (returnCode == TPM_SUCCESS) { + switch (resourceType) { + case TPM_RT_AUTH: + returnCode = TPM_AuthSessions_TerminateHandle(v1StClearData->authSessions, + handle); + break; + case TPM_RT_TRANS: + returnCode = TPM_TransportSessions_TerminateHandle + (v1StClearData->transSessions, + handle, + &(tpm_state->tpm_stany_flags.transportExclusive)); + break; + case TPM_RT_DAA_TPM: + returnCode = TPM_DaaSessions_TerminateHandle(v1StClearData->daaSessions, + handle); + break; + default: + printf("TPM_Process_SaveContext: Error, invalid resourceType %08x", + resourceType); + returnCode = TPM_INVALID_RESOURCE; + break; + } + } + } + } + /* 11. Calculate B1 -> integrityDigest the HMAC of B1 using TPM_PERMANENT_DATA -> tpmProof as + the secret. NOTE It is calculated on the cleartext data */ + if (returnCode == TPM_SUCCESS) { + /* This is a bit circular. It's safe since the TPM_CONTEXT_BLOB is serialized before the + HMAC is generated. The result is put back into the structure. */ + printf("TPM_Process_SaveContext: Digesting TPM_CONTEXT_BLOB\n"); + returnCode = TPM_HMAC_GenerateStructure + (b1ContextBlob.integrityDigest, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &b1ContextBlob, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store); /* store function */ + } + /* 12. Create E1 by encrypting C1 using K1 as the key */ + /* a. Set B1 -> sensitiveSize to the size of E1 */ + /* b. Set B1 -> sensitiveData to E1 */ + if (returnCode == TPM_SUCCESS) { + /* The cleartext went into sensitiveData for the integrityDigest calculation. Free it now, + before the encrypted data is stored there. */ + TPM_SizedBuffer_Delete(&(b1ContextBlob.sensitiveData)); + returnCode = TPM_SymmetricKeyData_EncryptSbuffer(&(b1ContextBlob.sensitiveData), + &c1_sbuffer, + k1ContextKey); + } + /* 13. Set contextSize to the size of B1 */ + /* 14. Return B1 in contextBlob */ + /* Since the redundant size parameter must be returned, the TPM_CONTEXT_BLOB is serialized + first. Later, rather than the usual _Store to the response, the already serialized buffer is + stored. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextBlob_Store(&b1_sbuffer, &b1ContextBlob); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SaveContext: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return contextSize and contextBlob */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &b1_sbuffer); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&b1_sbuffer); /* @1 */ + TPM_Sbuffer_Delete(&r1ContextSensitive); /* @2 */ + TPM_ContextBlob_Delete(&b1ContextBlob); /* @3 */ + TPM_ContextSensitive_Delete(&c1ContextSensitive); /* @4 */ + TPM_Sbuffer_Delete(&c1_sbuffer); /* @6 */ + return rcf; +} + +/* 21.3 TPM_LoadContext rev 107 + + TPM_LoadContext loads into the TPM a previously saved context. The command returns the handle. +*/ + +TPM_RESULT TPM_Process_LoadContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_HANDLE entityHandle; /* The handle the TPM MUST use to locate the entity ties + to the OSAP/DSAP session */ + TPM_BOOL keepHandle; /* Indication if the handle MUST be preserved */ + uint32_t contextSize; /* The size of the following context blob */ + TPM_CONTEXT_BLOB b1ContextBlob; /* The context blob */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL key_added = FALSE; /* key has been added to handle list */ + TPM_BOOL auth_session_added = FALSE; + TPM_BOOL trans_session_added = FALSE; + TPM_BOOL daa_session_added = FALSE; + TPM_STCLEAR_DATA *v1StClearData = NULL; + unsigned char *m1Decrypt; /* decrypted sensitive data */ + uint32_t m1_length; /* actual data in m1 */ + unsigned char *stream; + uint32_t stream_size; + TPM_CONTEXT_SENSITIVE c1ContextSensitive; + TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; + TPM_AUTH_SESSION_DATA tpm_auth_session_data; /* loaded authorization session */ + TPM_TRANSPORT_INTERNAL tpm_transport_internal; /* loaded transport session */ + TPM_DAA_SESSION_DATA tpm_daa_session_data; /* loaded daa session */ + TPM_DIGEST entityDigest; /* digest of the entity corresponding to + entityHandle */ + uint32_t contextIndex; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_LoadContext: Ordinal Entry\n"); + TPM_ContextBlob_Init(&b1ContextBlob); /* freed @1 */ + TPM_KeyHandleEntry_Init(&tpm_key_handle_entry); /* no free */ + m1Decrypt = NULL; /* freed @2 */ + TPM_ContextSensitive_Init(&c1ContextSensitive); /* freed @3 */ + TPM_AuthSessionData_Init(&tpm_auth_session_data); /* freed @4 */ + TPM_TransportInternal_Init(&tpm_transport_internal); /* freed @5 */ + TPM_DaaSessionData_Init(&tpm_daa_session_data); /* freed @6 */ + /* + get inputs + */ + /* get parameter entityHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&entityHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get keepHandle parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadContext: entityHandle %08x\n", entityHandle); + returnCode = TPM_LoadBool(&keepHandle, &command, ¶mSize); + } + /* get contextSize parameter (redundant, not used) */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadContext: keepHandle %02x\n", keepHandle); + returnCode = TPM_Load32(&contextSize, &command, ¶mSize); + } + /* get contextBlob parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextBlob_Load(&b1ContextBlob, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_LoadContext: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Map contextBlob to B1, a TPM_CONTEXT_BLOB structure */ + /* NOTE Done by TPM_ContextBlob_Load() */ + if (returnCode == TPM_SUCCESS) { + /* 2. Map V1 to TPM_STANY_DATA NOTE MAY be TPM_STCLEAR_DATA */ + v1StClearData = &(tpm_state->tpm_stclear_data); + /* 3. Create M1 by decrypting B1 -> sensitiveData using TPM_PERMANENT_DATA -> contextKey */ + printf("TPM_Process_LoadContext: Decrypting sensitiveData\n"); + returnCode = TPM_SymmetricKeyData_Decrypt(&m1Decrypt, /* decrypted data */ + &m1_length, /* length decrypted data */ + b1ContextBlob.sensitiveData.buffer, /* encrypt */ + b1ContextBlob.sensitiveData.size, + tpm_state->tpm_permanent_data.contextKey); + } + /* 4. Create C1 and R1 by splitting M1 into a TPM_CONTEXT_SENSITIVE structure and internal + resource data */ + /* NOTE R1 is manufacturer specific data that might be part of the blob. This implementation + does not use R1 */ + if (returnCode == TPM_SUCCESS) { + stream = m1Decrypt; + stream_size = m1_length; + returnCode = TPM_ContextSensitive_Load(&c1ContextSensitive, &stream, &stream_size); + } + /* Parse the TPM_CONTEXT_SENSITIVE -> internalData depending on the resource type */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadContext: Parsing TPM_CONTEXT_SENSITIVE -> internalData\n"); + stream = c1ContextSensitive.internalData.buffer; + stream_size = c1ContextSensitive.internalData.size; + switch (b1ContextBlob.resourceType) { + case TPM_RT_KEY: + printf("TPM_Process_LoadContext: Loading TPM_KEY_HANDLE_ENTRY\n"); + returnCode = TPM_KeyHandleEntry_Load(&tpm_key_handle_entry, &stream, &stream_size); + break; + case TPM_RT_AUTH: + printf("TPM_Process_LoadContext: Loading TPM_AUTH_SESSION_DATA\n"); + returnCode = TPM_AuthSessionData_Load(&tpm_auth_session_data, &stream, &stream_size); + printf("TPM_Process_LoadContext: protocolID %02x entityTypeByte %02x\n", + tpm_auth_session_data.protocolID, tpm_auth_session_data.entityTypeByte); + break; + case TPM_RT_TRANS: + printf("TPM_Process_LoadContext: Loading TPM_TRANSPORT_INTERNAL\n"); + returnCode = TPM_TransportInternal_Load(&tpm_transport_internal, + &stream, &stream_size); + break; + case TPM_RT_DAA_TPM: + printf("TPM_Process_LoadContext: Loading TPM_DAA_SESSION_DATA\n"); + returnCode = TPM_DaaSessionData_Load(&tpm_daa_session_data, &stream, &stream_size); + printf("TPM_Process_LoadContext: stage %u\n", + tpm_daa_session_data.DAA_session.DAA_stage); + break; + default: + printf("TPM_Process_LoadContext: Error, invalid resourceType %08x", + b1ContextBlob.resourceType); + returnCode = TPM_INVALID_RESOURCE; + break; + } + } + /* 5. Check contextNonce */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadContext: Checking contextNonce\n"); + /* a. If B1 -> resourceType is NOT TPM_RT_KEY */ + if (b1ContextBlob.resourceType != TPM_RT_KEY) { + /* i. If C1 -> contextNonce does not equal V1 -> contextNonceSession return + TPM_BADCONTEXT */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Compare(v1StClearData->contextNonceSession, + c1ContextSensitive.contextNonce); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_LoadContext: Error comparing non-key contextNonce\n"); + returnCode = TPM_BADCONTEXT; + } + } + /* ii. Validate that the resource pointed to by the context is loaded (i.e. for OSAP the + key referenced is loaded and DSAP connected to the key) return TPM_RESOURCEMISSING */ + /* (1) For OSAP sessions and for DSAP sessions attached to keys, the TPM MUST validate + that the hash of the entity matches the entity held by the TPM */ + /* (2) For OSAP and DSAP sessions referring to a key, verify that entityHandle + identifies the key linked to this OSAP/DSAP session, if not return TPM_BAD_HANDLE. */ + if ((returnCode == TPM_SUCCESS) && (b1ContextBlob.resourceType == TPM_RT_AUTH)) { + if ((tpm_auth_session_data.protocolID == TPM_PID_OSAP) || + (tpm_auth_session_data.protocolID == TPM_PID_DSAP)) { + /* check that the entity is loaded, and get the entity's digest */ + switch (tpm_auth_session_data.entityTypeByte) { + case TPM_ET_KEYHANDLE: + returnCode = TPM_LoadContext_CheckKeyLoaded(tpm_state, + entityHandle, + entityDigest); + break; + case TPM_ET_OWNER: + returnCode = TPM_LoadContext_CheckOwnerLoaded(tpm_state, + entityDigest); + break; + case TPM_ET_SRK: + returnCode = TPM_LoadContext_CheckSrkLoaded(tpm_state, + entityDigest); + break; + case TPM_ET_COUNTER: + returnCode = TPM_LoadContext_CheckCounterLoaded(tpm_state, + entityHandle, + entityDigest); + break; + case TPM_ET_NV: + returnCode = TPM_LoadContext_CheckNvLoaded(tpm_state, + entityHandle, + entityDigest); + break; + default: + printf("TPM_Process_LoadContext: Error, invalid session entityType %02x\n", + tpm_auth_session_data.entityTypeByte); + returnCode = TPM_WRONG_ENTITYTYPE; + break; + } + if (returnCode == TPM_SUCCESS) { + returnCode= TPM_Digest_Compare(entityDigest, + tpm_auth_session_data.entityDigest); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_LoadContext: Error, " + "OSAP or DSAP entityDigest mismatch\n"); + returnCode = TPM_RESOURCEMISSING; + } + } + } + } + } + /* b. Else (TPM_RT_KEY) */ + else { + /* i. If C1 -> internalData -> parentPCRStatus is FALSE and C1 -> internalData -> + isVolatile is FALSE */ + /* NOTE parentPCRStatus and keyFlags are not security sensitive data, could be in + additionalData */ + /* (1) Ignore C1 -> contextNonce */ + if (returnCode == TPM_SUCCESS) { + if (tpm_key_handle_entry.parentPCRStatus || + (tpm_key_handle_entry.key->keyFlags & TPM_ISVOLATILE)) { + /* ii. else */ + /* (1) If C1 -> contextNonce does not equal TPM_STCLEAR_DATA -> contextNonceKey + return TPM_BADCONTEXT */ + returnCode = TPM_Nonce_Compare(v1StClearData->contextNonceKey, + c1ContextSensitive.contextNonce); + if (returnCode != 0) { + printf("TPM_Process_LoadContext: Error comparing contextNonceKey\n"); + returnCode = TPM_BADCONTEXT; + } + } + } + } + } + /* 6. Validate the structure */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadContext: Checking integrityDigest\n"); + /* a. Set H1 to B1 -> integrityDigest */ + /* NOTE Done by TPM_HMAC_CheckStructure() */ + /* b. Set B1 -> integrityDigest to all zeros */ + /* NOTE Done by TPM_HMAC_CheckStructure() */ + /* c. Copy M1 to B1 -> sensitiveData (integrityDigest HMAC uses cleartext) */ + returnCode = TPM_SizedBuffer_Set(&(b1ContextBlob.sensitiveData), m1_length, m1Decrypt); + } + /* d. Create H2 the HMAC of B1 using TPM_PERMANENT_DATA -> tpmProof as the HMAC key */ + /* e. If H2 does not equal H1 return TPM_BADCONTEXT */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &b1ContextBlob, /* structure */ + b1ContextBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store, /* store function */ + TPM_BADCONTEXT); /* error code */ + } + /* 9. If B1 -> resourceType is NOT TPM_RT_KEY */ + if ((returnCode == TPM_SUCCESS) && (b1ContextBlob.resourceType != TPM_RT_KEY)) { + printf("TPM_Process_LoadContext: Checking contextCount\n"); + /* a. Find contextIndex such that V1 -> contextList[contextIndex] equals B1 -> + TPM_CONTEXT_BLOB -> contextCount */ + /* b. If not found then return TPM_BADCONTEXT */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextList_GetEntry(&contextIndex, + v1StClearData->contextList, + b1ContextBlob.contextCount); + } + /* c. Set V1 -> contextList[contextIndex] to 0 */ + if (returnCode == TPM_SUCCESS) { + v1StClearData->contextList[contextIndex] = 0; + } + } + /* 10. Process B1 to return the resource back into TPM use */ + /* restore the entity, try to keep the handle as 'handle' */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadContext: Adding entry to table\n"); + switch (b1ContextBlob.resourceType) { + case TPM_RT_KEY: + returnCode = TPM_KeyHandleEntries_AddEntry(&(b1ContextBlob.handle), + keepHandle, + tpm_state->tpm_key_handle_entries, + &tpm_key_handle_entry); + key_added = TRUE; + break; + case TPM_RT_AUTH: + returnCode = TPM_AuthSessions_AddEntry(&(b1ContextBlob.handle), /* input/output */ + keepHandle, + v1StClearData->authSessions, + &tpm_auth_session_data); + auth_session_added = TRUE; + break; + case TPM_RT_TRANS: + returnCode = TPM_TransportSessions_AddEntry(&(b1ContextBlob.handle), /* input/output */ + keepHandle, + v1StClearData->transSessions, + &tpm_transport_internal); + trans_session_added = TRUE; + break; + case TPM_RT_DAA_TPM: + returnCode = TPM_DaaSessions_AddEntry(&(b1ContextBlob.handle), /* input/output */ + keepHandle, + v1StClearData->daaSessions, + &tpm_daa_session_data); + daa_session_added = TRUE; + break; + default: + printf("TPM_Process_LoadContext: Error, invalid resourceType %08x\n", + b1ContextBlob.resourceType); + returnCode = TPM_INVALID_RESOURCE; + break; + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_LoadContext: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* return handle */ + returnCode = TPM_Sbuffer_Append32(response, b1ContextBlob.handle); + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + /* if there was a failure, roll back */ + if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { + TPM_Key_Delete(tpm_key_handle_entry.key); /* free on error */ + free(tpm_key_handle_entry.key); /* free on error */ + if (key_added) { + /* if there was a failure and inKey was stored in the handle list, free the handle. + Ignore errors, since only one error code can be returned. */ + TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, + b1ContextBlob.handle); + } + if (auth_session_added) { + TPM_AuthSessions_TerminateHandle(v1StClearData->authSessions, b1ContextBlob.handle); + } + if (trans_session_added) { + TPM_TransportSessions_TerminateHandle(v1StClearData->transSessions, + b1ContextBlob.handle, + &(tpm_state->tpm_stany_flags.transportExclusive)); + } + if (daa_session_added) { + TPM_DaaSessions_TerminateHandle(v1StClearData->daaSessions, b1ContextBlob.handle); + } + } + TPM_ContextBlob_Delete(&b1ContextBlob); /* @1 */ + free(m1Decrypt); /* @2 */ + TPM_ContextSensitive_Delete(&c1ContextSensitive); /* @3 */ + TPM_AuthSessionData_Delete(&tpm_auth_session_data); /* @4 */ + TPM_TransportInternal_Delete(&tpm_transport_internal); /* @5 */ + TPM_DaaSessionData_Delete(&tpm_daa_session_data); /* @6 */ + return rcf; +} + +/* TPM_LoadContext_CheckKeyLoaded() validates that the key associated with a loading authorization + context is loaded. + + It returns the key pubDataDigest for comparison with the digest of the loading context. +*/ + +static TPM_RESULT TPM_LoadContext_CheckKeyLoaded(tpm_state_t *tpm_state, + TPM_HANDLE entityHandle, + TPM_DIGEST entityDigest) +{ + TPM_RESULT rc = 0; + TPM_KEY_HANDLE_ENTRY *key_handle_entry; + + printf("TPM_LoadContext_CheckKeyLoaded: handle %08x\n", entityHandle); + /* get the key associated with entityHandle */ + /* special case, SRK is not in the key handle list */ + if (entityHandle == TPM_KH_SRK) { + if (tpm_state->tpm_permanent_data.ownerInstalled) { + TPM_Digest_Copy(entityDigest, + tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); + } + else { + printf("TPM_LoadContext_CheckKeyLoaded: Error, ownerInstalled is FALSE\n"); + rc = TPM_NOSRK; + } + } + /* normal case, key is in the key handle list */ + else { + rc = TPM_KeyHandleEntries_GetEntry(&key_handle_entry, + tpm_state->tpm_key_handle_entries, + entityHandle); + if (rc == 0) { + TPM_Digest_Copy(entityDigest, key_handle_entry->key->tpm_store_asymkey->pubDataDigest); + } + else { + printf("TPM_LoadContext_CheckKeyLoaded: Error, key handle %08x not found\n", + entityHandle); + rc = TPM_BAD_HANDLE; + } + } + return rc; +} + +/* TPM_LoadContext_CheckKeyLoadedByDigest() validates that the key associated with a loading + authorization context is loaded. + + It compares the key the pubDataDigest to the digest of the loading context. +*/ + +static TPM_RESULT TPM_LoadContext_CheckKeyLoadedByDigest(tpm_state_t *tpm_state, + TPM_DIGEST entityDigest) +{ + TPM_RESULT rc = TPM_RETRY; /* any non-zero value will do */ + size_t start; + size_t current; + TPM_KEY_HANDLE_ENTRY *key_handle_entry; + + printf("TPM_LoadContext_CheckKeyLoadedByDigest:\n"); + /* get the key associated with entityDigest */ + start = 0; + /* iterate through all keys in the key handle table */ + while ((rc != 0) && /* a match sets rc to 0, terminates loop */ + /* returns TPM_RETRY when at the end of the table, terminates loop */ + (TPM_KeyHandleEntries_GetNextEntry(&key_handle_entry, + ¤t, + tpm_state->tpm_key_handle_entries, + start)) == 0) { + + + start = current + 1; + rc = TPM_Digest_Compare(entityDigest, + key_handle_entry->key->tpm_store_asymkey->pubDataDigest); + } + /* if that failed, check the SRK */ + if (rc != 0) { + if (tpm_state->tpm_permanent_data.ownerInstalled) { + rc = TPM_Digest_Compare + (entityDigest, + tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); + } + } + if (rc != 0) { + printf("TPM_LoadContext_CheckKeyLoadedByDigest: " + "Error, OSAP or DSAP entityDigest mismatch\n"); + rc = TPM_RESOURCEMISSING; + } + return rc; +} + +/* TPM_LoadContext_CheckOwnerLoaded() validates that the owner is loaded. + + It returns the owner authorization for comparison with the digest of the loading context. +*/ + +static TPM_RESULT TPM_LoadContext_CheckOwnerLoaded(tpm_state_t *tpm_state, + TPM_DIGEST entityDigest) +{ + TPM_RESULT rc = 0; + + printf("TPM_LoadContext_CheckOwnerLoaded:\n"); + /* verify that an owner is installed */ + if (rc == 0) { + if (!tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_LoadContext_CheckOwnerLoaded: Error, no owner\n"); + rc = TPM_RESOURCEMISSING; + } + } + if (rc == 0) { + TPM_Digest_Copy(entityDigest, tpm_state->tpm_permanent_data.ownerAuth); + } + return rc; +} + +/* TPM_LoadContext_CheckSrkLoaded() validates that the SRK is loaded. + + It returns the SRK pubDataDigest for comparison with the digest of the loading context. +*/ + +static TPM_RESULT TPM_LoadContext_CheckSrkLoaded(tpm_state_t *tpm_state, + TPM_DIGEST entityDigest) +{ + TPM_RESULT rc = 0; + + printf("TPM_LoadContext_CheckSrkLoaded:\n"); + /* verify that an owner is installed */ + if (rc == 0) { + if (!tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_LoadContext_CheckSrkLoaded: Error, no SRK\n"); + rc = TPM_RESOURCEMISSING; + } + } + if (rc == 0) { + TPM_Digest_Copy(entityDigest, + tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); + } + return rc; +} + +/* TPM_LoadContext_CheckCounterLoaded() validates that the counter associated with a loading + authorization context is loaded. + + It returns the counter authorization for comparison with the digest of the loading context. +*/ + +static TPM_RESULT TPM_LoadContext_CheckCounterLoaded(tpm_state_t *tpm_state, + TPM_HANDLE entityHandle, + TPM_DIGEST entityDigest) +{ + TPM_RESULT rc = 0; + TPM_COUNTER_VALUE *counterValue; /* associated with entityHandle */ + + printf("TPM_LoadContext_CheckCounterLoaded: handle %08x\n", entityHandle); + if (rc == 0) { + rc = TPM_Counters_GetCounterValue(&counterValue, + tpm_state->tpm_permanent_data.monotonicCounter, + entityHandle); + if (rc != 0) { + printf("TPM_LoadContext_CheckCounterLoaded: Error, no counter\n"); + rc = TPM_RESOURCEMISSING; + } + } + if (rc == 0) { + TPM_Digest_Copy(entityDigest, counterValue->digest); + } + return rc; +} + +/* TPM_LoadContext_CheckNvLoaded() validates that the NV space associated with a loading + authorization context exists. +*/ + +static TPM_RESULT TPM_LoadContext_CheckNvLoaded(tpm_state_t *tpm_state, + TPM_HANDLE entityHandle, + TPM_DIGEST entityDigest) +{ + + TPM_RESULT rc = 0; + TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; /* associated with entityValue */ + + printf(" TPM_LoadContext_CheckNvLoaded: handle %08x\n", entityHandle); + if (rc == 0) { + rc = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, + &(tpm_state->tpm_nv_index_entries), + entityHandle); + if (rc != 0) { + printf("TPM_LoadContext_CheckNvLoaded: Error, no NV at index %08x\n", entityHandle); + rc = TPM_RESOURCEMISSING; + } + } + if (rc == 0) { + TPM_Digest_Copy(entityDigest, tpm_nv_data_sensitive->digest); + } + return rc; +} + +/* 21.1 TPM_KeyControlOwner rev 116 + + This command controls some attributes of keys that are stored within the TPM key cache. + + 1. Set an internal bit within the key cache that controls some attribute of a loaded key. + + 2.When a key is set to ownerEvict, the key handle value remains the same as long as the key + remains ownerEvict. The key handle value persists through TPM_Startup. + + OwnerEvict: If this bit is set to true, this key remains in the TPM non-volatile storage + through all TPM_Startup events. The only way to evict this key is for the TPM Owner to + execute this command again, setting the owner control bit to false and then executing + TPM_FlushSpecific. + + The key handle does not reference an authorized entity and is not validated. + + The check for two remaining key slots ensures that users can load the two keys required to + execute many commands. Since only the owner can flush owner evict keys, non-owner commands + could be blocked if this test was not performed. +*/ + +TPM_RESULT TPM_Process_KeyControlOwner(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The handle of a loaded key. */ + TPM_PUBKEY pubKey; /* The public key associated with the loaded key */ + TPM_KEY_CONTROL bitName = 0; /* The name of the bit to be modified */ + TPM_BOOL bitValue = FALSE; /* The value to set the bit to */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner + authentication. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA ownerAuth; /* HMAC authorization: key ownerAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* entry for keyHandle */ + TPM_BOOL isSpace; + TPM_BOOL oldOwnerEvict; /* original owner evict state */ + uint16_t ownerEvictCount; /* current number of owner evict keys */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_KeyControlOwner: Ordinal Entry\n"); + TPM_Pubkey_Init(&pubKey); /* freed @1 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get pubKey parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_KeyControlOwner: keyHandle %08x\n", keyHandle); + returnCode = TPM_Pubkey_Load(&pubKey, &command, ¶mSize); + } + /* get bitName parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&bitName, &command, ¶mSize); + } + /* get bitValue parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load8(&bitValue, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_KeyControlOwner: bitName %08x bitValue %02x\n", bitName, bitValue); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + ownerAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_KeyControlOwner: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. Validate the AuthData using the owner authentication value, on error return TPM_AUTHFAIL + */ + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_OWNER, + ordinal, + NULL, + &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ + tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* owner HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* 2. Validate that keyHandle refers to a loaded key, return TPM_INVALID_KEYHANDLE on error. */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_state->tpm_key_handle_entries, + keyHandle); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_KeyControlOwner: Error, key handle not loaded\n"); + returnCode = TPM_INVALID_KEYHANDLE; + } + } + /* If the keyUsage field of the key indicated by keyHandle does not have the value + TPM_KEY_SIGNING, TPM_KEY_STORAGE, TPM_KEY_IDENTITY, TPM_KEY_BIND, or TPM_KEY_LEGACY, the TPM + must return the error code TPM_INVALID_KEYUSAGE. */ + if (returnCode == TPM_SUCCESS) { + if ((tpm_key_handle_entry->key->keyUsage != TPM_KEY_SIGNING) && + (tpm_key_handle_entry->key->keyUsage != TPM_KEY_STORAGE) && + (tpm_key_handle_entry->key->keyUsage != TPM_KEY_IDENTITY) && + (tpm_key_handle_entry->key->keyUsage != TPM_KEY_BIND) && + (tpm_key_handle_entry->key->keyUsage != TPM_KEY_LEGACY)) { + printf("TPM_Process_KeyControlOwner: Error, invalid key keyUsage %04hx\n", + tpm_key_handle_entry->key->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. Validate that pubKey matches the key held by the TPM pointed to by keyHandle, return + TPM_BAD_PARAMETER on mismatch */ + /* a. This check is added so that virtualization of the keyHandle does not result in attacks, as + the keyHandle is not associated with an authorization value */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_ComparePubkey(tpm_key_handle_entry->key, &pubKey); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_KeyControlOwner: Error comparing pubKey\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 4. Validate that bitName is valid, return TPM_BAD_MODE on error. NOTE Valid means a legal + TPM_KEY_CONTROL value */ + if (returnCode == TPM_SUCCESS) { + switch(bitName) { + /* 5. If bitName == TPM_KEY_CONTROL_OWNER_EVICT */ + case TPM_KEY_CONTROL_OWNER_EVICT: + /* save the old value to determine if NVRAM update is necessary */ + oldOwnerEvict = tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT; + /* a. If bitValue == TRUE */ + if (bitValue) { + printf("TPM_Process_KeyControlOwner: setting key owner evict\n"); + if (!oldOwnerEvict) { /* if the key is not owner evict */ + /* i. Verify that after this operation at least two key slots will be present + within the TPM that can store any type of key both of which do NOT have the + OwnerEvict bit set, on error return TPM_NOSPACE */ + if (returnCode == TPM_SUCCESS) { + TPM_KeyHandleEntries_IsEvictSpace(&isSpace, + tpm_state->tpm_key_handle_entries, + 2); /* minSpace */ + if (!isSpace) { + printf("TPM_Process_KeyControlOwner: Error, " + "Need 2 non-evict slots\n"); + returnCode = TPM_NOSPACE; + } + } + /* ii. Verify that for this key handle, parentPCRStatus is FALSE and isVolatile + is FALSE. Return TPM_BAD_PARAMETER on error. */ + if (returnCode == TPM_SUCCESS) { + if (tpm_key_handle_entry->parentPCRStatus || + tpm_key_handle_entry->key->keyFlags & TPM_ISVOLATILE) { + printf("TPM_Process_KeyControlOwner: Error, " + "parentPCRStatus or Volatile\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* check the current number of occupied owner evict key slots */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_OwnerEvictGetCount + (&ownerEvictCount, + tpm_state->tpm_key_handle_entries); + } + /* check that the number of owner evict key slots will not be exceeded */ + if (returnCode == TPM_SUCCESS) { + if (ownerEvictCount == TPM_OWNER_EVICT_KEY_HANDLES) { + printf("TPM_Process_KeyControlOwner: Error, " + "no evict space, only %u evict slots\n", + TPM_OWNER_EVICT_KEY_HANDLES); + returnCode = TPM_NOSPACE; + } + } + /* iii. Set ownerEvict within the internal key storage structure to TRUE. */ + if (returnCode == TPM_SUCCESS) { + tpm_key_handle_entry->keyControl |= TPM_KEY_CONTROL_OWNER_EVICT; + } + /* if the old value was FALSE, write the entry to NVRAM */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PermanentAll_NVStore(tpm_state, + TRUE, /* write NV */ + 0); /* no roll back */ + } + } + else { /* if the key is already owner evict, nothing to do */ + printf("TPM_Process_KeyControlOwner: key is already owner evict\n"); + } + } + /* b. Else if bitValue == FALSE */ + else { + if (oldOwnerEvict) { /* if the key is currently owner evict */ + printf("TPM_Process_KeyControlOwner: setting key not owner evict\n"); + /* i. Set ownerEvict within the internal key storage structure to FALSE. */ + if (returnCode == TPM_SUCCESS) { + tpm_key_handle_entry->keyControl &= ~TPM_KEY_CONTROL_OWNER_EVICT; + } + /* if the old value was TRUE, delete the entry from NVRAM */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PermanentAll_NVStore(tpm_state, + TRUE, /* write NV */ + 0); /* no roll back */ + } + } + else { /* if the key is already not owner evict, nothing to do */ + printf("TPM_Process_KeyControlOwner: key is already not owner evict\n"); + } + } + break; + default: + printf("TPM_Process_KeyControlOwner: Invalid bitName %08x\n", bitName); + returnCode = TPM_BAD_MODE; + break; + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_KeyControlOwner: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_Pubkey_Delete(&pubKey); /* @1 */ + return rcf; +} + +/* 27.2 Context management + + The 1.1 context commands were written for specific resource types. The 1.2 commands are generic + for all resource types. So the Savexxx commands are replaced by TPM_SaveContext and the LoadXXX + commands by TPM_LoadContext. +*/ + +/* 27.2.1 TPM_SaveKeyContext rev 87 + + SaveKeyContext saves a loaded key outside the TPM. After creation of the key context blob the TPM + automatically releases the internal memory used by that key. The format of the key context blob is + specific to a TPM. +*/ + +TPM_RESULT TPM_Process_SaveKeyContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The key which will be kept outside the TPM */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* key table entry for the key handle */ + TPM_BOOL isZero; /* contextNonceKey not set yet */ + TPM_CONTEXT_SENSITIVE contextSensitive; + TPM_STORE_BUFFER contextSensitive_sbuffer; /* serialization of contextSensitive */ + TPM_CONTEXT_BLOB contextBlob; + TPM_STORE_BUFFER contextBlob_sbuffer; /* serialization of contextBlob */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SaveKeyContext: Ordinal Entry\n"); + TPM_ContextSensitive_Init(&contextSensitive); /* freed @1 */ + TPM_Sbuffer_Init(&contextSensitive_sbuffer); /* freed @2 */ + TPM_ContextBlob_Init(&contextBlob); /* freed @3 */ + TPM_Sbuffer_Init(&contextBlob_sbuffer); /* freed @4 */ + /* + get inputs + */ + /* get keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SaveKeyContext: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. This command allows saving a loaded key outside the TPM. After creation of the + KeyContextBlob, the TPM automatically releases the internal memory used by that key. The + format of the key context blob is specific to a TPM. + + 2. A TPM protected capability belonging to the TPM that created a key context blob MUST be + the only entity that can interpret the contents of that blob. If a cryptographic technique is + used for this purpose, the level of security provided by that technique SHALL be at least as + secure as a 2048 bit RSA algorithm. Any secrets (such as keys) used in such a cryptographic + technique MUST be generated using the TPM's random number generator. Any symmetric key MUST + be used within the power-on session during which it was created, only. + + 3. A key context blob SHALL enable verification of the integrity of the contents of the blob + by a TPM protected capability. + + 4. A key context blob SHALL enable verification of the session validity of the contents of + the blob by a TPM protected capability. The method SHALL ensure that all key context blobs + are rendered invalid if power to the TPM is interrupted. + */ + /* check if the key handle is valid */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveKeyContext: Handle %08x\n", keyHandle); + returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, + tpm_state->tpm_key_handle_entries, + keyHandle); + } + /* use the contextNonceKey to invalidate a blob at power up */ + if (returnCode == TPM_SUCCESS) { + /* If TPM_STCLEAR_DATA -> contextNonceKey is NULLS */ + TPM_Nonce_IsZero(&isZero, tpm_state->tpm_stclear_data.contextNonceKey); + if (isZero) { + /* Set TPM_STCLEAR_DATA -> contextNonceKey to the next value from the TPM RNG */ + returnCode = TPM_Nonce_Generate(tpm_state->tpm_stclear_data.contextNonceKey); + } + } + /* Create internalData by putting the sensitive part of the resource pointed to by handle into a + structure. The structure is a TPM manufacturer option. The TPM MUST ensure that ALL sensitive + information of the resource is included in internalData. For a key, the sensitive part is + the TPM_STORE_ASYMKEY */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveKeyContext: Building TPM_CONTEXT_SENSITIVE\n"); + returnCode = TPM_SizedBuffer_SetStructure(&(contextSensitive.internalData), + tpm_key_handle_entry, + (TPM_STORE_FUNCTION_T)TPM_KeyHandleEntry_Store); + } + if (returnCode == TPM_SUCCESS) { + /* TPM_CONTEXT_SENSITIVE -> contextNonce */ + TPM_Nonce_Copy(contextSensitive.contextNonce, tpm_state->tpm_stclear_data.contextNonceKey); + /* TPM_CONTEXT_BLOB -> resourceType, handle, integrityDigest */ + printf("TPM_Process_SaveKeyContext: Building TPM_CONTEXT_BLOB\n"); + contextBlob.resourceType = TPM_RT_KEY; + contextBlob.handle = keyHandle; + contextBlob.contextCount = 0; + } + /* TPM_CONTEXT_BLOB -> sensitiveData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextSensitive_Store(&contextSensitive_sbuffer, &contextSensitive); + } + /* Here the clear text goes into TPM_CONTEXT_BLOB->sensitiveData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_SetFromStore(&(contextBlob.sensitiveData), + &contextSensitive_sbuffer); + } + /* Calculate TPM_CONTEXT_BLOB -> integrityDigest, the HMAC of TPM_CONTEXT_BLOB using + TPM_PERMANENT_DATA -> tpmProof as the secret */ + if (returnCode == TPM_SUCCESS) { + /* This is a bit circular. It's safe since the TPM_CONTEXT_BLOB is serialized before the + HMAC is generated. The result is put back into the structure. */ + printf("TPM_Process_SaveKeyContext: Digesting TPM_CONTEXT_BLOB\n"); + returnCode = TPM_HMAC_GenerateStructure + (contextBlob.integrityDigest, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &contextBlob, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store); /* store function */ + } + /* encrypt TPM_CONTEXT_SENSITIVE using as TPM_PERMANENT_DATA -> contextKey the key. Store the + result in TPM_CONTEXT_BLOB -> sensitiveData */ + if (returnCode == TPM_SUCCESS) { + /* The cleartext went into sensitiveData for the integrityDigest calculation. Free it now, + before the encrypted data is stored there. */ + TPM_SizedBuffer_Delete(&(contextBlob.sensitiveData)); + printf("TPM_Process_SaveKeyContext: Encrypting TPM_CONTEXT_SENSITIVE\n"); + returnCode = + TPM_SymmetricKeyData_EncryptSbuffer(&(contextBlob.sensitiveData), + &contextSensitive_sbuffer, + tpm_state->tpm_permanent_data.contextKey); + } + /* serialize TPM_CONTEXT_BLOB */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextBlob_Store(&contextBlob_sbuffer, &contextBlob); + } + /* invalidate the key handle and delete the key */ + if (returnCode == TPM_SUCCESS) { + /* free the key resources, free the key itself, and remove entry from the key handle entries + list */ + TPM_KeyHandleEntry_Delete(tpm_key_handle_entry); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SaveKeyContext: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return keyContextSize and keyContextBlob */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &contextBlob_sbuffer); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_ContextSensitive_Delete(&contextSensitive); /* @1 */ + TPM_Sbuffer_Delete(&contextSensitive_sbuffer); /* @2 */ + TPM_ContextBlob_Delete(&contextBlob); /* @3 */ + TPM_Sbuffer_Delete(&contextBlob_sbuffer); /* @4 */ + return rcf; +} + +/* 27.2.2 TPM_LoadKeyContext rev 87 + + LoadKeyContext loads a key context blob into the TPM previously retrieved by a SaveKeyContext + call. After successful completion the handle returned by this command can be used to access the + key. +*/ + +TPM_RESULT TPM_Process_LoadKeyContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + uint32_t keyContextSize; /* The size of the following key context blob */ + TPM_CONTEXT_BLOB keyContextBlob; /* The key context blob */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + unsigned char *stream; + uint32_t stream_size; + unsigned char *contextSensitiveBuffer; /* decrypted sensitive data */ + uint32_t contextSensitiveBuffer_length; /* actual data in contextSensitiveBuffer */ + TPM_CONTEXT_SENSITIVE contextSensitive; + TPM_KEY_HANDLE_ENTRY *used_key_handle_entry; + TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; + TPM_RESULT getRc; /* is the handle value free */ + TPM_BOOL isSpace; + uint32_t index; /* free space index */ + TPM_BOOL key_added = FALSE; /* key has been added to handle list */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_KEY_HANDLE keyHandle; /* The handle assigned to the key after it has been + successfully loaded. */ + + printf("TPM_Process_LoadKeyContext: Ordinal Entry\n"); + TPM_ContextBlob_Init(&keyContextBlob); /* freed @1 */ + contextSensitiveBuffer = NULL; /* freed @2 */ + TPM_ContextSensitive_Init(&contextSensitive); /* freed @3 */ + TPM_KeyHandleEntry_Init(&tpm_key_handle_entry); /* no free */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get keyContextSize parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyContextSize, &command, ¶mSize); + } + /* get keyContextBlob parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextBlob_Load(&keyContextBlob, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_LoadKeyContext: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. This command allows loading a key context blob into the TPM previously retrieved by a + TPM_SaveKeyContext call. After successful completion the handle returned by this command can + be used to access the key. + + 2. The contents of a key context blob SHALL be discarded unless the contents have passed an + integrity test. This test SHALL (statistically) prove that the contents of the blob are the + same as when the blob was created. + + 3. The contents of a key context blob SHALL be discarded unless the contents have passed a + session validity test. This test SHALL (statistically) prove that the blob was created by + this TPM during this power-on session. + */ + if (returnCode == TPM_SUCCESS) { + if (keyContextBlob.resourceType != TPM_RT_KEY) { + printf("TPM_Process_LoadKeyContext: Error, resourceType %08x should be TPM_RT_KEY\n", + keyContextBlob.resourceType); + returnCode =TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Decrypting TPM_CONTEXT_SENSITIVE stream\n"); + returnCode = + TPM_SymmetricKeyData_Decrypt(&contextSensitiveBuffer, /* decrypted data */ + &contextSensitiveBuffer_length, /* length decrypted data */ + keyContextBlob.sensitiveData.buffer, /* encrypted */ + keyContextBlob.sensitiveData.size, + tpm_state->tpm_permanent_data.contextKey); + } + /* deserialize TPM_CONTEXT_SENSITIVE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Creating TPM_CONTEXT_SENSITIVE\n"); + stream = contextSensitiveBuffer; + stream_size = contextSensitiveBuffer_length; + returnCode = TPM_ContextSensitive_Load(&contextSensitive, &stream, &stream_size); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Loading TPM_KEY_HANDLE_ENTRY from internalData\n"); + stream = contextSensitive.internalData.buffer; + stream_size = contextSensitive.internalData.size; + returnCode = TPM_KeyHandleEntry_Load(&tpm_key_handle_entry, &stream, &stream_size); + } + /* check contextNonce */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Checking TPM_CONTEXT_SENSITIVE -> contextNonce\n"); + returnCode = TPM_Nonce_Compare(tpm_state->tpm_stclear_data.contextNonceKey, + contextSensitive.contextNonce); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Error comparing contextNonceKey\n"); + returnCode = TPM_BADCONTEXT; + } + } + /* Move decrypted data back to keyContextBlob for integrityDigest check. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Set(&(keyContextBlob.sensitiveData), + contextSensitiveBuffer_length, contextSensitiveBuffer); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Checking integrityDigest\n"); + /* make a copy of integrityDigest, because it needs to be 0 for the HMAC calculation */ + /* NOTE Done by TPM_HMAC_CheckStructure() */ + /* b. Set B1 -> integrityDigest to NULL */ + /* NOTE Done by TPM_HMAC_CheckStructure() */ + /* verify the integrityDigest HMAC of TPM_CONTEXT_BLOB using TPM_PERMANENT_DATA -> tpmProof + as the HMAC key */ + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &keyContextBlob, /* structure */ + keyContextBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store, /* store function */ + TPM_BADCONTEXT); /* error code */ + } + /* try to use the saved handle value when possible */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Checking if suggested handle %08x is free\n", + keyContextBlob.handle); + /* check if the key handle is free */ + getRc = TPM_KeyHandleEntries_GetEntry(&used_key_handle_entry, + tpm_state->tpm_key_handle_entries, + keyContextBlob.handle); + /* GetEntry TPM_SUCCESS means the handle is already used */ + if (getRc == TPM_SUCCESS) { + keyHandle = 0; /* no suggested handle */ + } + /* not success means that the handle value is not currently used */ + else { + keyHandle = keyContextBlob.handle; + } + } + /* check that there is space in the key handle entries */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Checking for table space\n"); + TPM_KeyHandleEntries_IsSpace(&isSpace, &index, + tpm_state->tpm_key_handle_entries); + /* if there is no space, return error */ + if (!isSpace) { + printf("TPM_Process_LoadKeyContext: Error, no room in table\n"); + returnCode = TPM_RESOURCES; + } + } + /* restore the entity, try to keep the handle as 'handle' */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKeyContext: Adding entry to table\n"); + returnCode = TPM_KeyHandleEntries_AddEntry(&keyHandle, + FALSE, /* keep handle */ + tpm_state->tpm_key_handle_entries, + &tpm_key_handle_entry); + key_added = TRUE; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_LoadKeyContext: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* return keyHandle */ + returnCode = TPM_Sbuffer_Append32(response, keyHandle); + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_ContextBlob_Delete(&keyContextBlob); /* @1 */ + free(contextSensitiveBuffer); /* @2 */ + TPM_ContextSensitive_Delete(&contextSensitive); /* @3 */ + /* if there was a failure, roll back */ + if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { + TPM_Key_Delete(tpm_key_handle_entry.key); /* @5 */ + free(tpm_key_handle_entry.key); /* @5 */ + if (key_added) { + /* if there was a failure and a key was stored in the handle list, free the handle. + Ignore errors, since only one error code can be returned. */ + TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, keyHandle); + } + } + return rcf; +} + +/* 27.2.3 TPM_SaveAuthContext rev 87 + + SaveAuthContext saves a loaded authorization session outside the TPM. After creation of the + authorization context blob, the TPM automatically releases the internal memory used by that + session. The format of the authorization context blob is specific to a TPM. +*/ + +TPM_RESULT TPM_Process_SaveAuthContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_AUTHHANDLE authHandle; /* Authorization session which will be kept outside the TPM + */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_AUTH_SESSION_DATA *tpm_auth_session_data; /* session table entry for the handle */ + TPM_BOOL isZero; /* contextNonceSession not set yet */ + TPM_STCLEAR_DATA *v1StClearData = NULL; + uint32_t contextIndex = 0; /* free index in context list */ + uint32_t space; /* free space in context list */ + TPM_CONTEXT_SENSITIVE contextSensitive; + TPM_STORE_BUFFER contextSensitive_sbuffer; /* serialization of contextSensitive */ + TPM_CONTEXT_BLOB contextBlob; + TPM_STORE_BUFFER contextBlob_sbuffer; /* serialization of contextBlob */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SaveAuthContext: Ordinal Entry\n"); + TPM_ContextSensitive_Init(&contextSensitive); /* freed @1 */ + TPM_Sbuffer_Init(&contextSensitive_sbuffer); /* freed @2 */ + TPM_ContextBlob_Init(&contextBlob); /* freed @3 */ + TPM_Sbuffer_Init(&contextBlob_sbuffer); /* freed @4 */ + /* + get inputs + */ + /* get authHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&authHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveAuthContext: authHandle %08x\n", authHandle); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SaveAuthContext: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* This command allows saving a loaded authorization session outside the TPM. After creation of + the authContextBlob, the TPM automatically releases the internal memory used by that + session. The format of the authorization context blob is specific to a TPM. + + A TPM protected capability belonging to the TPM that created an authorization context blob + MUST be the only entity that can interpret the contents of that blob. If a cryptographic + technique is used for this purpose, the level of security provided by that technique SHALL be + at least as secure as a 2048 bit RSA algorithm. Any secrets (such as keys) used in such a + cryptographic technique MUST be generated using the TPM's random number generator. Any + symmetric key MUST be used within the power-on session during which it was created, only. + + An authorization context blob SHALL enable verification of the integrity of the contents of + the blob by a TPM protected capability. + + An authorization context blob SHALL enable verification of the session validity of the + contents of the blob by a TPM protected capability. The method SHALL ensure that all + authorization context blobs are rendered invalid if power to the TPM is interrupted. + */ + /* 1. Map V1 to TPM_STANY_DATA NOTE MAY be TPM_STCLEAR_DATA */ + if (returnCode == TPM_SUCCESS) { + v1StClearData = &(tpm_state->tpm_stclear_data); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveAuthContext: Handle %08x\n", authHandle); + returnCode = TPM_AuthSessions_GetEntry(&tpm_auth_session_data, + v1StClearData->authSessions, + authHandle); + } + if (returnCode == TPM_SUCCESS) { + /* If TPM_STANY_DATA -> contextNonceSession is NULLS */ + TPM_Nonce_IsZero(&isZero, v1StClearData->contextNonceSession); + if (isZero) { + /* Set TPM_STANY_DATA -> contextNonceSession to the next value from the TPM RNG */ + returnCode = TPM_Nonce_Generate(v1StClearData->contextNonceSession); + } + } + /* Create internalData by putting the sensitive part of the resource pointed to by handle into a + structure. The structure is a TPM manufacturer option. The TPM MUST ensure that ALL sensitive + information of the resource is included in internalData. For a session, the entire structure + can fit in the sensitive part. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveAuthContext: Building TPM_CONTEXT_SENSITIVE\n"); + returnCode = TPM_SizedBuffer_SetStructure(&(contextSensitive.internalData), + tpm_auth_session_data, + (TPM_STORE_FUNCTION_T)TPM_AuthSessionData_Store); + } + if (returnCode == TPM_SUCCESS) { + } + if (returnCode == TPM_SUCCESS) { + /* TPM_CONTEXT_SENSITIVE -> contextNonce */ + TPM_Nonce_Copy(contextSensitive.contextNonce, v1StClearData->contextNonceSession); + /* TPM_CONTEXT_BLOB -> resourceType, handle, integrityDigest */ + printf("TPM_Process_SaveAuthContext: Building TPM_CONTEXT_BLOB\n"); + contextBlob.resourceType = TPM_RT_AUTH; + contextBlob.handle = authHandle; + TPM_Digest_Init(contextBlob.integrityDigest); + } + /* TPM_CONTEXT_BLOB -> sensitiveData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextSensitive_Store(&contextSensitive_sbuffer, &contextSensitive); + } + /* Here the clear text goes into TPM_CONTEXT_BLOB->sensitiveData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_SetFromStore(&(contextBlob.sensitiveData), + &contextSensitive_sbuffer); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_SaveAuthContext: Processing session context count\n"); + /* a. If V1 -> contextCount > 2^32-2 then */ + if (v1StClearData->contextCount > 0xfffffffe) { + /* i. Return with TPM_TOOMANYCONTEXTS */ + printf("TPM_Process_SaveAuthContext: Error, too many contexts\n"); + returnCode = TPM_TOOMANYCONTEXTS; + } + } + /* b. Else */ + if (returnCode == TPM_SUCCESS) { + /* i. Increment V1 -> contextCount by 1 */ + v1StClearData->contextCount++; + /* ii. Validate that the TPM can still manage the new count value */ + /* (1) If the distance between the oldest saved context and the contextCount is + too large return TPM_CONTEXT_GAP */ + /* Since contextCount is uint32_t, this is not applicable here. From email: Does the + TPM have the ability to keep track of the context delta. It is possible to keep + track of things with just a byte or so internally, if this is done a gap of + greater than 2^16 or so might be too large, hence the context gap message */ + } + /* iii. Find contextIndex such that V1 -> contextList[contextIndex] equals 0. If not + found exit with TPM_NOCONTEXTSPACE */ + if (returnCode == TPM_SUCCESS) { + TPM_ContextList_GetSpace(&space, &contextIndex, v1StClearData->contextList); + if (space == 0) { + printf("TPM_Process_SaveAuthContext: Error, no space in context list\n"); + returnCode = TPM_NOCONTEXTSPACE; + } + } + if (returnCode == TPM_SUCCESS) { + /* iv. Set V1-> contextList[contextIndex] to V1 -> contextCount */ + v1StClearData->contextList[contextIndex] = v1StClearData->contextCount; + /* v. Set B1 -> contextCount to V1 -> contextCount */ + contextBlob.contextCount = v1StClearData->contextCount; + } + /* c. The TPM MUST invalidate all information regarding the resource except for information + needed for reloading */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_TerminateHandle(v1StClearData->authSessions, authHandle); + } + /* Calculate TPM_CONTEXT_BLOB -> integrityDigest, the HMAC of TPM_CONTEXT_BLOB using + TPM_PERMANENT_DATA -> tpmProof as the secret */ + if (returnCode == TPM_SUCCESS) { + /* This is a bit circular. It's safe since the TPM_CONTEXT_BLOB is serialized before the + HMAC is generated. The result is put back into the structure. */ + printf("TPM_Process_SaveAuthContext: Digesting TPM_CONTEXT_BLOB\n"); + returnCode = TPM_HMAC_GenerateStructure + (contextBlob.integrityDigest, /* HMAC */ + tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ + &contextBlob, /* structure */ + (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store); /* store function */ + } + /* encrypt TPM_CONTEXT_SENSITIVE using as TPM_PERMANENT_DATA -> contextKey the key. Store the + result in TPM_CONTEXT_BLOB -> sensitiveData */ + if (returnCode == TPM_SUCCESS) { + /* The cleartext went into sensitiveData for the integrityDigest calculation. Free it now, + before the encrypted data is stored there. */ + TPM_SizedBuffer_Delete(&(contextBlob.sensitiveData)); + printf("TPM_Process_SaveAuthContext: Encrypting TPM_CONTEXT_SENSITIVE\n"); + returnCode = + TPM_SymmetricKeyData_EncryptSbuffer(&(contextBlob.sensitiveData), + &contextSensitive_sbuffer, + tpm_state->tpm_permanent_data.contextKey); + } + /* serialize TPM_CONTEXT_BLOB */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextBlob_Store(&contextBlob_sbuffer, &contextBlob); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SaveAuthContext: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return authContextSize and authContextBlob */ + returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &contextBlob_sbuffer); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_ContextSensitive_Delete(&contextSensitive); /* @1 */ + TPM_Sbuffer_Delete(&contextSensitive_sbuffer); /* @2 */ + TPM_ContextBlob_Delete(&contextBlob); /* @3 */ + TPM_Sbuffer_Delete(&contextBlob_sbuffer); /* @4 */ + return rcf; +} + +/* 27.2.4 TPM_LoadAuthContext rev 106 + + LoadAuthContext loads an authorization context blob into the TPM previously retrieved by a + SaveAuthContext call. After successful completion, the handle returned by this command can be used + to access the authorization session. +*/ + +TPM_RESULT TPM_Process_LoadAuthContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + uint32_t authContextSize; /* The size of the following auth context blob */ + TPM_CONTEXT_BLOB authContextBlob; /* The auth context blob */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + unsigned char *stream; + uint32_t stream_size; + unsigned char *contextSensitiveBuffer; /* decrypted sensitive data */ + uint32_t contextSensitiveBuffer_length; /* actual data in contextSensitiveBuffer */ + TPM_CONTEXT_SENSITIVE contextSensitive; + TPM_AUTH_SESSION_DATA tpm_auth_session_data; + TPM_AUTH_SESSION_DATA *used_auth_session_data; + TPM_RESULT getRc; /* is the handle value free */ + TPM_BOOL isSpace; + uint32_t index; /* free space index */ + TPM_BOOL auth_session_added = FALSE; /* session key has been added to handle list */ + TPM_STCLEAR_DATA *v1StClearData = NULL; + uint32_t contextIndex; + TPM_DIGEST entityDigest; /* digest of the entity used to set up the + OSAP or DSAP session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_KEY_HANDLE authHandle; /* The handle assigned to the authorization session after it + has been successfully loaded. */ + + printf("TPM_Process_LoadAuthContext: Ordinal Entry\n"); + TPM_ContextBlob_Init(&authContextBlob); /* freed @1 */ + contextSensitiveBuffer = NULL; /* freed @2 */ + TPM_ContextSensitive_Init(&contextSensitive); /* freed @3 */ + TPM_AuthSessionData_Init(&tpm_auth_session_data); /* freed @4 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get authContextSize parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&authContextSize, &command, ¶mSize); + } + /* get authContextBlob parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_ContextBlob_Load(&authContextBlob, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: handle %08x\n", authContextBlob.handle); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_LoadAuthContext: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* This command allows loading an authorization context blob into the TPM previously retrieved + by a TPM_SaveAuthContext call. After successful completion, the handle returned by this + command can be used to access the authorization session. + + The contents of an authorization context blob SHALL be discarded unless the contents have + passed an integrity test. This test SHALL (statistically) prove that the contents of the blob + are the same as when the blob was created. + + The contents of an authorization context blob SHALL be discarded unless the contents have + passed a session validity test. This test SHALL (statistically) prove that the blob was + created by this TPM during this power-on session. + + For an OSAP authorization context blob referring to a key, verify that the key linked to this + session is resident in the TPM. + */ + if (returnCode == TPM_SUCCESS) { + /* 2. Map V1 to TPM_STANY_DATA NOTE MAY be TPM_STCLEAR_DATA */ + v1StClearData = &(tpm_state->tpm_stclear_data); + if (authContextBlob.resourceType != TPM_RT_AUTH) { + printf("TPM_Process_LoadAuthContext: Error, resourceType %08x should be TPM_RT_AUTH\n", + authContextBlob.resourceType); + returnCode = TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: Decrypting TPM_CONTEXT_SENSITIVE stream\n"); + returnCode = + TPM_SymmetricKeyData_Decrypt(&contextSensitiveBuffer, /* decrypted data */ + &contextSensitiveBuffer_length, /* length decrypted data */ + authContextBlob.sensitiveData.buffer, /* encrypted */ + authContextBlob.sensitiveData.size, + tpm_state->tpm_permanent_data.contextKey); + } + /* deserialize TPM_CONTEXT_SENSITIVE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: Creating TPM_CONTEXT_SENSITIVE\n"); + stream = contextSensitiveBuffer; + stream_size = contextSensitiveBuffer_length; + returnCode = TPM_ContextSensitive_Load(&contextSensitive, + &stream, + &stream_size); + } + /* Parse the TPM_CONTEXT_SENSITIVE -> internalData to TPM_AUTH_SESSION_DATA */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: Loading TPM_AUTH_SESSION_DATA from internalData\n"); + stream = contextSensitive.internalData.buffer; + stream_size = contextSensitive.internalData.size; + returnCode = TPM_AuthSessionData_Load(&tpm_auth_session_data, &stream, &stream_size); + } + /* check contextNonce */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: protocolID %04x entityTypeByte %02x\n", + tpm_auth_session_data.protocolID, tpm_auth_session_data.entityTypeByte); + printf("TPM_Process_LoadAuthContext: Checking TPM_CONTEXT_SENSITIVE -> contextNonce\n"); + returnCode = TPM_Nonce_Compare(v1StClearData->contextNonceSession, + contextSensitive.contextNonce); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: Error comparing contextNonceSession\n"); + returnCode = TPM_BADCONTEXT; + } + } + if (returnCode == TPM_SUCCESS) { + if ((tpm_auth_session_data.protocolID == TPM_PID_OSAP) || + (tpm_auth_session_data.protocolID == TPM_PID_DSAP)) { + /* check that the entity is loaded, and that the entity's digest equals that of the OSAP + or DSAP session */ + switch (tpm_auth_session_data.entityTypeByte) { + case TPM_ET_OWNER: + printf("TPM_Process_LoadAuthContext: Owner OSAP/DSAP session\n"); + /* check for owner */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadContext_CheckOwnerLoaded(tpm_state, entityDigest); + } + /* compare entity digest */ + if (returnCode == TPM_SUCCESS) { + returnCode= TPM_Digest_Compare(entityDigest, + tpm_auth_session_data.entityDigest); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: " + "Error, OSAP or DSAP entityDigest mismatch\n"); + returnCode = TPM_RESOURCEMISSING; + } + } + break; + case TPM_ET_SRK: + printf("TPM_Process_LoadAuthContext: SRK OSAP/DSAP session\n"); + /* check for SRK */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadContext_CheckSrkLoaded(tpm_state, entityDigest); + } + /* compare entity digest */ + if (returnCode == TPM_SUCCESS) { + returnCode= TPM_Digest_Compare(entityDigest, + tpm_auth_session_data.entityDigest); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: " + "Error, OSAP or DSAP entityDigest mismatch\n"); + returnCode = TPM_RESOURCEMISSING; + } + } + break; + case TPM_ET_KEYHANDLE: + printf("TPM_Process_LoadAuthContext: Key OSAP/DSAP session\n"); + /* for keys */ + returnCode = + TPM_LoadContext_CheckKeyLoadedByDigest(tpm_state, + tpm_auth_session_data.entityDigest); + break; + case TPM_ET_COUNTER: + printf("TPM_Process_LoadAuthContext: Counter OSAP/DSAP session\n"); +#if 0 /* TPM_LoadAuthContext is a deprecated 1.1 command, where there was no counter */ + returnCode = + TPM_LoadContext_CheckCounterLoaded(tpm_state, + entityHandle, + entityDigest); +#endif + break; + case TPM_ET_NV: + printf("TPM_Process_LoadAuthContext: NV OSAP/DSAP session\n"); +#if 0 /* TPM_LoadAuthContext is a deprecated 1.1 command, where there was no NV space */ + returnCode = + TPM_LoadContext_CheckNvLoaded(tpm_state, + entityHandle, + entityDigest); +#endif + break; + default: + printf("TPM_Process_LoadAuthContext: Error, invalid session entityType %02x\n", + tpm_auth_session_data.entityTypeByte); + returnCode = TPM_WRONG_ENTITYTYPE; + break; + } + } + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: Checking integrityDigest\n"); + /* b. Set B1 -> integrityDigest to NULL */ + /* NOTE Done by TPM_HMAC_CheckStructure() */ + /* c. Copy M1 to B1 -> sensitiveData (integrityDigest HMAC uses cleartext) */ + returnCode = TPM_SizedBuffer_Set(&(authContextBlob.sensitiveData), + contextSensitiveBuffer_length, contextSensitiveBuffer); + /* verify the integrityDigest HMAC of TPM_CONTEXT_BLOB using TPM_PERMANENT_DATA -> tpmProof + as the HMAC key */ + returnCode = TPM_HMAC_CheckStructure + (tpm_state->tpm_permanent_data.tpmProof, /* key */ + &authContextBlob, /* structure */ + authContextBlob.integrityDigest, /* expected */ + (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store, /* store function */ + TPM_BADCONTEXT); /* error code */ + } + /* try to use the saved handle value when possible */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: Checking if suggested handle %08x is free\n", + authContextBlob.handle); + /* check if the auth handle is free */ + getRc = TPM_AuthSessions_GetEntry(&used_auth_session_data, + tpm_state->tpm_stclear_data.authSessions, + authContextBlob.handle); + /* GetEntry TPM_SUCCESS means the handle is already used */ + if (getRc == TPM_SUCCESS) { + authHandle = 0; /* no suggested handle */ + } + /* not success means that the handle value is not currently used */ + else { + authHandle = authContextBlob.handle; + } + } + /* check that there is space in the authorization handle entries */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: Checking for table space\n"); + TPM_AuthSessions_IsSpace(&isSpace, &index, + tpm_state->tpm_stclear_data.authSessions); + /* if there is no space, return error */ + if (!isSpace) { + printf("TPM_Process_LoadAuthContext: Error, no room in table\n"); + TPM_AuthSessions_Trace(tpm_state->tpm_stclear_data.authSessions); + returnCode = TPM_RESOURCES; + } + } + /* a. Find contextIndex such that V1 -> contextList[contextIndex] equals B1 -> + TPM_CONTEXT_BLOB -> contextCount */ + /* b. If not found then return TPM_BADCONTEXT */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadAuthContext: Checking contextCount\n"); + returnCode = TPM_ContextList_GetEntry(&contextIndex, + v1StClearData->contextList, + authContextBlob.contextCount); + } + /* c. Set V1 -> contextList[contextIndex] to 0 */ + if (returnCode == TPM_SUCCESS) { + v1StClearData->contextList[contextIndex] = 0; + } + /* restore the entity, try to keep the handle as 'handle' */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_AddEntry(&authHandle, /* input/output */ + FALSE, /* keepHandle */ + v1StClearData->authSessions, + &tpm_auth_session_data); + auth_session_added = TRUE; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_LoadAuthContext: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* return authHandle */ + returnCode = TPM_Sbuffer_Append32(response, authHandle); + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + TPM_ContextBlob_Delete(&authContextBlob); /* @1 */ + free(contextSensitiveBuffer); /* @2 */ + TPM_ContextSensitive_Delete(&contextSensitive); /* @3 */ + TPM_AuthSessionData_Delete(&tpm_auth_session_data); /* @4 */ + /* if there was a failure, roll back */ + if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { + if (auth_session_added) { + TPM_AuthSessionData_Delete(&tpm_auth_session_data); + } + } + return rcf; +} diff --git a/src/tpm12/tpm_session.h b/src/tpm12/tpm_session.h new file mode 100644 index 0000000..a7c9c6d --- /dev/null +++ b/src/tpm12/tpm_session.h @@ -0,0 +1,276 @@ +/********************************************************************************/ +/* */ +/* TPM Sessions Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_session.h 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_SESSION_H +#define TPM_SESSION_H + +#include "tpm_global.h" +#include "tpm_store.h" +#include "tpm_types.h" + +/* + TPM_AUTH_SESSION_DATA (the entire array) +*/ + +void TPM_AuthSessions_Init(TPM_AUTH_SESSION_DATA *authSessions); +TPM_RESULT TPM_AuthSessions_Load(TPM_AUTH_SESSION_DATA *authSessions, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_AuthSessions_Store(TPM_STORE_BUFFER *sbuffer, + TPM_AUTH_SESSION_DATA *authSessions); +void TPM_AuthSessions_Delete(TPM_AUTH_SESSION_DATA *authSessions); + + +void TPM_AuthSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, + TPM_AUTH_SESSION_DATA *authSessions); +void TPM_AuthSessions_Trace(TPM_AUTH_SESSION_DATA *authSessions); +void TPM_AuthSessions_GetSpace(uint32_t *space, + TPM_AUTH_SESSION_DATA *authSessions); +TPM_RESULT TPM_AuthSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, + TPM_AUTH_SESSION_DATA *authSessions); +TPM_RESULT TPM_AuthSessions_GetNewHandle(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, + TPM_AUTHHANDLE *authHandle, + TPM_AUTH_SESSION_DATA *authSessions); +TPM_RESULT TPM_AuthSessions_GetEntry(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, + TPM_AUTH_SESSION_DATA *authSessions, + TPM_AUTHHANDLE authHandle); +TPM_RESULT TPM_AuthSessions_AddEntry(TPM_HANDLE *tpm_handle, + TPM_BOOL keepHandle, + TPM_AUTH_SESSION_DATA *authSessions, + TPM_AUTH_SESSION_DATA *tpm_auth_session_data); +TPM_RESULT TPM_AuthSessions_GetData(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, + TPM_SECRET **hmacKey, + tpm_state_t *tpm_state, + TPM_AUTHHANDLE authHandle, + TPM_PROTOCOL_ID protocolID, + TPM_ENT_TYPE entityType, + TPM_COMMAND_CODE ordinal, + TPM_KEY *tpmKey, + TPM_SECRET *entityAuth, + TPM_DIGEST entityDigest); + +TPM_RESULT TPM_AuthSessions_TerminateHandle(TPM_AUTH_SESSION_DATA *authSessions, + TPM_AUTHHANDLE authHandle); +void TPM_AuthSessions_TerminateEntity(TPM_BOOL *continueAuthSession, + TPM_AUTHHANDLE authHandle, + TPM_AUTH_SESSION_DATA *authSessions, + TPM_ENT_TYPE entityType, + TPM_DIGEST *entityDigest); +void TPM_AuthSessions_TerminatexSAP(TPM_BOOL *continueAuthSession, + TPM_AUTHHANDLE authHandle, + TPM_AUTH_SESSION_DATA *authSessions); + +/* + TPM_AUTH_SESSION_DATA (one element of the array) +*/ + + +void TPM_AuthSessionData_Init(TPM_AUTH_SESSION_DATA *tpm_auth_session_data); +TPM_RESULT TPM_AuthSessionData_Load(TPM_AUTH_SESSION_DATA *tpm_auth_session_data, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_AuthSessionData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_AUTH_SESSION_DATA *tpm_auth_session_data); +void TPM_AuthSessionData_Delete(TPM_AUTH_SESSION_DATA *tpm_auth_session_data); + + +void TPM_AuthSessionData_Copy(TPM_AUTH_SESSION_DATA *dest_auth_session_data, + TPM_HANDLE tpm_handle, + TPM_AUTH_SESSION_DATA *src_auth_session_data); +TPM_RESULT TPM_AuthSessionData_GetDelegatePublic(TPM_DELEGATE_PUBLIC **delegatePublic, + TPM_AUTH_SESSION_DATA *auth_session_data); +TPM_RESULT TPM_AuthSessionData_CheckEncScheme(TPM_ADIP_ENC_SCHEME adipEncScheme, + TPM_BOOL FIPS); +TPM_RESULT TPM_AuthSessionData_Decrypt(TPM_DIGEST a1Even, + TPM_DIGEST a1Odd, + TPM_ENCAUTH encAuthEven, + TPM_AUTH_SESSION_DATA *tpm_auth_session_data, + TPM_NONCE nonceOdd, + TPM_ENCAUTH encAuthOdd, + TPM_BOOL odd); + +/* + Context List +*/ + +void TPM_ContextList_Init(uint32_t *contextList); +TPM_RESULT TPM_ContextList_Load(uint32_t *contextList, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_ContextList_Store(TPM_STORE_BUFFER *sbuffer, + const uint32_t *contextList); + +TPM_RESULT TPM_ContextList_StoreHandles(TPM_STORE_BUFFER *sbuffer, + const uint32_t *contextList); +void TPM_ContextList_GetSpace(uint32_t *space, + uint32_t *entry, + const uint32_t *contextList); +TPM_RESULT TPM_ContextList_GetEntry(uint32_t *entry, + const uint32_t *contextList, + uint32_t value); + +/* + TPM_CONTEXT_BLOB +*/ + +void TPM_ContextBlob_Init(TPM_CONTEXT_BLOB *tpm_context_blob); +TPM_RESULT TPM_ContextBlob_Load(TPM_CONTEXT_BLOB *tpm_context_blob, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_ContextBlob_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CONTEXT_BLOB *tpm_context_blob); +void TPM_ContextBlob_Delete(TPM_CONTEXT_BLOB *tpm_context_blob); + +/* + TPM_CONTEXT_SENSITIVE +*/ + +void TPM_ContextSensitive_Init(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive); +TPM_RESULT TPM_ContextSensitive_Load(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_ContextSensitive_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CONTEXT_SENSITIVE *tpm_context_sensitive); +void TPM_ContextSensitive_Delete(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive); + +/* + Processing Functions +*/ + +TPM_RESULT TPM_Process_OIAP(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_OSAP(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_DSAP(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_SetOwnerPointer(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_TerminateHandle(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +TPM_RESULT TPM_Process_FlushSpecific(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_SaveContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_LoadContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_KeyControlOwner(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_SaveKeyContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_LoadKeyContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_SaveAuthContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_LoadAuthContext(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + + + + + +#endif diff --git a/src/tpm12/tpm_sizedbuffer.c b/src/tpm12/tpm_sizedbuffer.c new file mode 100644 index 0000000..046ad43 --- /dev/null +++ b/src/tpm12/tpm_sizedbuffer.c @@ -0,0 +1,374 @@ +/********************************************************************************/ +/* */ +/* TPM Sized Buffer Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_sizedbuffer.c 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_memory.h" +#include "tpm_process.h" +#include "tpm_types.h" + +#include "tpm_sizedbuffer.h" + +void TPM_SizedBuffer_Init(TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + tpm_sized_buffer->size = 0; + tpm_sized_buffer->buffer = NULL; + return; +} + +/* TPM_SizedBuffer_Load() allocates and sets a sized buffer from a stream. A sized buffer structure + has two members: + + - 4 bytes size + - pointer to array of 'size' + + This structure is typically a cast from a subset of a larger TPM structure. Two members - a 4 + bytes size followed by a 4 bytes pointer to the data is a common TPM structure idiom. + + This function correctly handles a 'size' of 0. + + Call TPM_SizedBuffer_Init() before first use + Call TPM_SizedBuffer_Delete() after use +*/ + +TPM_RESULT TPM_SizedBuffer_Load(TPM_SIZED_BUFFER *tpm_sized_buffer, /* result */ + unsigned char **stream, /* pointer to next parameter */ + uint32_t *stream_size) /* stream size left */ +{ + TPM_RESULT rc = 0; + + printf(" TPM_SizedBuffer_Load:\n"); + if (rc == 0) { + rc = TPM_Load32(&(tpm_sized_buffer->size), stream, stream_size); + } + /* if the size is not 0 */ + if ((rc == 0) && (tpm_sized_buffer->size > 0)) { + /* allocate memory for the buffer */ + if (rc == 0) { + rc = TPM_Malloc(&(tpm_sized_buffer->buffer), tpm_sized_buffer->size); + } + /* copy the buffer */ + if (rc == 0) { + rc = TPM_Loadn(tpm_sized_buffer->buffer, tpm_sized_buffer->size, stream, stream_size); + } + } + return rc; +} + +/* TPM_SizedBuffer_Set() reallocs a sized buffer and copies 'size' bytes of 'data' into it. + + If the sized buffer already has data, the buffer is realloc'ed. + + This function correctly handles a 'size' of 0. + + Call TPM_SizedBuffer_Delete() to free the buffer +*/ + +TPM_RESULT TPM_SizedBuffer_Set(TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t size, + const unsigned char *data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SizedBuffer_Set:\n"); + /* allocate memory for the buffer, and copy the buffer */ + if (rc == 0) { + if (size > 0) { + rc = TPM_Realloc(&(tpm_sized_buffer->buffer), + size); + if (rc == 0) { + tpm_sized_buffer->size = size; + memcpy(tpm_sized_buffer->buffer, data, size); + } + } + /* if size is zero */ + else { + TPM_SizedBuffer_Delete(tpm_sized_buffer); + } + } + return rc; +} + +/* TPM_SizedBuffer_SetFromStore() reallocs a sized buffer and copies 'sbuffer" data into it. + + This function correctly handles an 'sbuffer' of 0 length. + */ + +TPM_RESULT TPM_SizedBuffer_SetFromStore(TPM_SIZED_BUFFER *tpm_sized_buffer, + TPM_STORE_BUFFER *sbuffer) +{ + TPM_RESULT rc = 0; + const unsigned char *data; + uint32_t size; + + if (rc == 0) { + /* get the stream and its size from the TPM_STORE_BUFFER */ + TPM_Sbuffer_Get(sbuffer, &data, &size); + rc = TPM_SizedBuffer_Set(tpm_sized_buffer, size, data); + } + return rc; +} + +/* TPM_SizedBuffer_SetStructure() serializes the structure 'tpmStructure' using the function + 'storeFunction', storing the result in a TPM_SIZED_BUFFER. +*/ + +TPM_RESULT TPM_SizedBuffer_SetStructure(TPM_SIZED_BUFFER *tpm_sized_buffer, + void *tpmStructure, + TPM_STORE_FUNCTION_T storeFunction) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ + + printf(" TPM_SizedBuffer_SetStructure:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize the structure */ + if (rc == 0) { + if (tpmStructure != NULL) { + rc = storeFunction(&sbuffer, tpmStructure); + } + } + /* copy to TPM_SIZED_BUFFER */ + if (rc == 0) { + rc = TPM_SizedBuffer_SetFromStore(tpm_sized_buffer, &sbuffer); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +TPM_RESULT TPM_SizedBuffer_Copy(TPM_SIZED_BUFFER *tpm_sized_buffer_dest, + TPM_SIZED_BUFFER *tpm_sized_buffer_src) +{ + TPM_RESULT rc = 0; + rc = TPM_SizedBuffer_Set(tpm_sized_buffer_dest, + tpm_sized_buffer_src->size, + tpm_sized_buffer_src->buffer); + return rc; +} + + +/* TPM_SizedBuffer_Store() serializes a TPM_SIZED_BUFFER into a TPM_STORE_BUFFER + */ + +TPM_RESULT TPM_SizedBuffer_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SizedBuffer_Store:\n"); + /* append the size */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_sized_buffer->size); + } + /* append the data */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_sized_buffer->buffer, tpm_sized_buffer->size); + } + return rc; +} + +void TPM_SizedBuffer_Delete(TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + printf(" TPM_SizedBuffer_Delete:\n"); + if (tpm_sized_buffer != NULL) { + free(tpm_sized_buffer->buffer); + TPM_SizedBuffer_Init(tpm_sized_buffer); + } + return; +} + +/* TPM_SizedBuffer_Allocate() allocates 'size' bytes of memory and sets the TPM_SIZED_BUFFER + members. + + The buffer data is not initialized. +*/ + +TPM_RESULT TPM_SizedBuffer_Allocate(TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SizedBuffer_Allocate: Size %u\n", size); + tpm_sized_buffer->size = size; + rc = TPM_Malloc(&(tpm_sized_buffer->buffer), size); + return rc; +} + +/* TPM_SizedBuffer_GetBool() converts from a TPM_SIZED_BUFFER to a TPM_BOOL. + + If the size does not indicate a TPM_BOOL, an error is returned. +*/ + +TPM_RESULT TPM_SizedBuffer_GetBool(TPM_BOOL *tpm_bool, + TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + + if (tpm_sized_buffer->size == sizeof(TPM_BOOL)) { + *tpm_bool = *(TPM_BOOL *)tpm_sized_buffer->buffer; + printf(" TPM_SizedBuffer_GetBool: bool %02x\n", *tpm_bool); + } + else { + printf("TPM_SizedBuffer_GetBool: Error, buffer size %08x is not a BOOL\n", + tpm_sized_buffer->size); + rc = TPM_BAD_PARAMETER; + } + return rc; +} + +/* TPM_SizedBuffer_GetUint32() converts from a TPM_SIZED_BUFFER to a uint32_t. + + If the size does not indicate a uint32_t, an error is returned. +*/ + +TPM_RESULT TPM_SizedBuffer_GetUint32(uint32_t *uint32, + TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + + if (rc == 0) { + if (tpm_sized_buffer->size != sizeof(uint32_t)) { + printf("TPM_GetUint32: Error, buffer size %08x is not a uint32_t\n", + tpm_sized_buffer->size); + rc = TPM_BAD_PARAMETER; + } + } + if (rc == 0) { + stream = tpm_sized_buffer->buffer; + stream_size = tpm_sized_buffer->size; + rc = TPM_Load32(uint32, &stream, &stream_size); + } + return rc; +} + +/* TPM_SizedBuffer_Append32() appends a uint32_t to a TPM_SIZED_BUFFER + +*/ + +TPM_RESULT TPM_SizedBuffer_Append32(TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t uint32) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SizedBuffer_Append32: Current size %u uint32 %08x\n", + tpm_sized_buffer->size, uint32); + /* allocate space for another uint32_t */ + if (rc == 0) { + rc = TPM_Realloc(&(tpm_sized_buffer->buffer), + tpm_sized_buffer->size + sizeof(uint32_t)); + } + if (rc == 0) { + uint32_t ndata = htonl(uint32); /* convert to network byte order */ + memcpy(tpm_sized_buffer->buffer + tpm_sized_buffer->size, /* append at end */ + (char *)&ndata, /* cast safe after conversion */ + sizeof(uint32_t)); + tpm_sized_buffer->size += sizeof(uint32_t); + } + return rc; +} + +/* TPM_SizedBuffer_Remove32() removes the uint32_t with value from a TPM_SIZED_BUFFER + +*/ + +TPM_RESULT TPM_SizedBuffer_Remove32(TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t uint32) +{ + TPM_RESULT rc = 0; + unsigned char *stream; + uint32_t stream_size; + uint32_t bufferValue; + TPM_BOOL found = FALSE; + unsigned char *from; + unsigned char *to; + + printf(" TPM_SizedBuffer_Remove32: Current size %u uint32 %08x\n", + tpm_sized_buffer->size, uint32); + + stream = tpm_sized_buffer->buffer; + stream_size = tpm_sized_buffer->size; + + /* search for the uint32 */ + while ((rc == 0) && (stream_size != 0) && !found) { + /* get the next value */ + if (rc == 0) { + rc = TPM_Load32(&bufferValue, &stream, &stream_size); + } + /* if the value is the one to be removed */ + if (rc == 0) { + if (bufferValue == uint32) { + found = TRUE; + /* shift the reset of the buffer down by a uint32_t */ + for (from = stream, to = (stream - sizeof(uint32_t)) ; + /* go to the end of the buffer */ + from < (tpm_sized_buffer->buffer + tpm_sized_buffer->size) ; + from++, to++) { + *to = *from; + } + /* adjust the size */ + tpm_sized_buffer->size -= sizeof(uint32_t); + } + } + } + if (!found) { + printf("TPM_SizedBuffer_Remove32: Error, value not found\n"); + rc = TPM_BAD_HANDLE; + } + return rc; +} + +/* TPM_SizedBuffer_Zero() overwrites all data in the buffer with zeros + + */ + +void TPM_SizedBuffer_Zero(TPM_SIZED_BUFFER *tpm_sized_buffer) +{ + printf(" TPM_SizedBuffer_Zero:\n"); + if (tpm_sized_buffer->buffer != NULL) { + memset(tpm_sized_buffer->buffer, 0, tpm_sized_buffer->size); + } + return; +} diff --git a/src/tpm12/tpm_sizedbuffer.h b/src/tpm12/tpm_sizedbuffer.h new file mode 100644 index 0000000..a92c3e9 --- /dev/null +++ b/src/tpm12/tpm_sizedbuffer.h @@ -0,0 +1,75 @@ +/********************************************************************************/ +/* */ +/* TPM Sized Buffer Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_sizedbuffer.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_SIZEDBUFFER_H +#define TPM_SIZEDBUFFER_H + +#include "tpm_digest.h" +#include "tpm_store.h" + +void TPM_SizedBuffer_Init(TPM_SIZED_BUFFER *tpm_sized_buffer); +TPM_RESULT TPM_SizedBuffer_Load(TPM_SIZED_BUFFER *tpm_sized_buffer, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_SizedBuffer_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SIZED_BUFFER *tpm_sized_buffer); +TPM_RESULT TPM_SizedBuffer_Set(TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t size, + const unsigned char *data); +TPM_RESULT TPM_SizedBuffer_SetFromStore(TPM_SIZED_BUFFER *tpm_sized_buffer, + TPM_STORE_BUFFER *sbuffer); +TPM_RESULT TPM_SizedBuffer_SetStructure(TPM_SIZED_BUFFER *tpm_sized_buffer, + void *tpmStructure, + TPM_STORE_FUNCTION_T storeFunction); +TPM_RESULT TPM_SizedBuffer_Copy(TPM_SIZED_BUFFER *tpm_sized_buffer_dest, + TPM_SIZED_BUFFER *tpm_sized_buffer_src); +void TPM_SizedBuffer_Delete(TPM_SIZED_BUFFER *tpm_sized_buffer); +TPM_RESULT TPM_SizedBuffer_Allocate(TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t size); +TPM_RESULT TPM_SizedBuffer_GetBool(TPM_BOOL *tpm_bool, + TPM_SIZED_BUFFER *tpm_sized_buffer); +TPM_RESULT TPM_SizedBuffer_GetUint32(uint32_t *uint32, + TPM_SIZED_BUFFER *tpm_sized_buffer); +TPM_RESULT TPM_SizedBuffer_Append32(TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t uint32); +TPM_RESULT TPM_SizedBuffer_Remove32(TPM_SIZED_BUFFER *tpm_sized_buffer, + uint32_t uint32); +void TPM_SizedBuffer_Zero(TPM_SIZED_BUFFER *tpm_sized_buffer); + +#endif diff --git a/src/tpm12/tpm_startup.c b/src/tpm12/tpm_startup.c new file mode 100644 index 0000000..25b9e08 --- /dev/null +++ b/src/tpm12/tpm_startup.c @@ -0,0 +1,1446 @@ +/********************************************************************************/ +/* */ +/* TPM Admin Startup and State */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_startup.c 4533 2011-03-30 19:50:41Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_constants.h" +#include "tpm_commands.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_digest.h" +#include "tpm_init.h" +#include "tpm_key.h" +#include "tpm_nonce.h" +#include "tpm_nvfile.h" +#include "tpm_nvfilename.h" +#include "tpm_nvram.h" +#include "tpm_pcr.h" +#include "tpm_process.h" +#include "tpm_session.h" + +#include "tpm_startup.h" + +/* + Save State +*/ + +/* TPM_SaveState_Load() restores the TPM state from a stream created by TPM_SaveState_Store() + + The two functions must be kept in sync. +*/ + +TPM_RESULT TPM_SaveState_Load(tpm_state_t *tpm_state, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + unsigned char *stream_start = *stream; /* copy for integrity check */ + uint32_t stream_size_start = *stream_size; + + printf(" TPM_SaveState_Load:\n"); + if (rc == 0) { + printf(" TPM_SaveState_Load: Loading PCR's\n"); + } + /* 1. Store PCR contents except for */ + /* a. If the PCR attribute pcrReset is TRUE */ + /* b. Any platform identified debug PCR */ + /* NOTE Done by TPM_StclearData_Load() */ + /* 2. The auditDigest MUST be handled according to the audit requirements as reported by + TPM_GetCapability */ + /* NOTE Moved to TPM_STCLEAR_DATA */ + /* 3. All values in TPM_STCLEAR_DATA MUST be preserved */ + if (rc == 0) { + rc = TPM_StclearData_Load(&(tpm_state->tpm_stclear_data), stream, stream_size, + tpm_state->tpm_permanent_data.pcrAttrib); + } + /* 4. All values in TPM_STCLEAR_FLAGS MUST be preserved */ + if (rc == 0) { + rc = TPM_StclearFlags_Load(&(tpm_state->tpm_stclear_flags), stream, stream_size); + } + /* 5. The contents of any key that is currently loaded SHOULD be preserved if the key's + parentPCRStatus indicator is TRUE. */ + /* 6. The contents of any key that has TPM_KEY_CONTROL_OWNER_EVICT set MUST be preserved */ + /* 7. The contents of any key that is currently loaded MAY be preserved as reported by + TPM_GetCapability */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_Load(tpm_state, stream, stream_size); + } + /* 8. The contents of sessions (authorization, transport etc.) MAY be preserved as reported by + TPM_GetCapability */ + /* NOTE Done at TPM_StclearData_Load() */ + /* load the NV volatile flags */ + if (rc == 0) { + rc = TPM_NVIndexEntries_LoadVolatile(&(tpm_state->tpm_nv_index_entries), + stream, stream_size); + } + /* sanity check the stream size */ + if (rc == 0) { + if (*stream_size != TPM_DIGEST_SIZE) { + printf("TPM_SaveState_Load: Error (fatal) stream size %u not %u\n", + *stream_size, TPM_DIGEST_SIZE); + rc = TPM_FAIL; + } + } + /* check the integrity digest */ + if (rc == 0) { + printf(" TPM_SaveState_Load: Checking integrity digest\n"); + rc = TPM_SHA1_Check(*stream, /* currently points to integrity digest */ + stream_size_start - TPM_DIGEST_SIZE, stream_start, + 0, NULL); + } + /* remove the integrity digest from the stream */ + if (rc == 0) { + *stream_size -= TPM_DIGEST_SIZE; + } + return rc; +} + +/* TPM_SaveState_Store() stores the TPM state to a stream that can be restored through + TPM_SaveState_Load(). + + The two functions must be kept in sync. +*/ + +TPM_RESULT TPM_SaveState_Store(TPM_STORE_BUFFER *sbuffer, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + const unsigned char *buffer; /* elements of sbuffer */ + uint32_t length; + TPM_DIGEST tpm_digest; + + printf(" TPM_SaveState_Store:\n"); + if (rc == 0) { + printf(" TPM_SaveState_Store: Storing PCR's\n"); + } + /* NOTE: Actions from TPM_SaveState */ + /* 1. Store TPM_STCLEAR_DATA -> PCR contents except for */ + /* a. If the PCR attribute pcrReset is TRUE */ + /* b. Any platform identified debug PCR */ + /* NOTE Done by TPM_StclearData_Store() */ + /* 2. The auditDigest MUST be handled according to the audit requirements as reported by + TPM_GetCapability */ + /* NOTE Moved to TPM_STCLEAR_DATA */ + /* a. If the ordinalAuditStatus is TRUE for the TPM_SaveState ordinal and the auditDigest is + being stored in the saved state, the saved auditDigest MUST include the TPM_SaveState input + parameters and MUST NOT include the output parameters. */ + /* NOTE Done naturally because this function is called between input and output audit. */ + /* 3. All values in TPM_STCLEAR_DATA MUST be preserved */ + if (rc == 0) { + rc = TPM_StclearData_Store(sbuffer, &(tpm_state->tpm_stclear_data), + tpm_state->tpm_permanent_data.pcrAttrib); + } + /* 4. All values in TPM_STCLEAR_FLAGS MUST be preserved */ + if (rc == 0) { + rc = TPM_StclearFlags_Store(sbuffer, &(tpm_state->tpm_stclear_flags)); + } + /* 5. The contents of any key that is currently loaded SHOULD be preserved if the key's + parentPCRStatus indicator is TRUE. */ + /* 6. The contents of any key that has TPM_KEY_CONTROL_OWNER_EVICT set MUST be preserved */ + /* 7. The contents of any key that is currently loaded MAY be preserved as reported by + TPM_GetCapability */ + /* NOTE This implementation saves all keys. Owner evict keys are not saved in the state blob, + as they are already saved in the file system */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_Store(sbuffer, tpm_state); + } + /* 8. The contents of sessions (authorization, transport etc.) MAY be preserved as reported by + TPM_GetCapability */ + /* NOTE Done by TPM_StclearData_Store() */ + /* store the NV volatile flags */ + if (rc == 0) { + rc = TPM_NVIndexEntries_StoreVolatile(sbuffer, + &(tpm_state->tpm_nv_index_entries)); + } + if (rc == 0) { + /* get the current serialized buffer and its length */ + TPM_Sbuffer_Get(sbuffer, &buffer, &length); + /* generate the integrity digest */ + rc = TPM_SHA1(tpm_digest, + length, buffer, + 0, NULL); + } + /* append the integrity digest to the stream */ + if (rc == 0) { + printf(" TPM_SaveState_Store: Appending integrity digest\n"); + rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE); + } + return rc; +} + +/* TPM_SaveState_IsSaveKey() determines which keys are saved as part of the saved state. + + According to Ryan, all keys must be saved for this to be of use. +*/ + +void TPM_SaveState_IsSaveKey(TPM_BOOL *save, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) +{ + *save = FALSE; + /* 5. The contents of any key that is currently loaded SHOULD be preserved if the key's + parentPCRStatus indicator is TRUE. */ + /* 6. The contents of any key that has TPM_KEY_CONTROL_OWNER_EVICT set MUST be preserved */ + /* 7. The contents of any key that is currently loaded MAY be preserved as reported by + TPM_GetCapability */ + /* NOTE Owner evict keys are not saved in the state blob, as they are already saved in the file + system */ + if (!(tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { + *save = TRUE; + } + else { + *save = FALSE; + } + if (*save) { + printf(" TPM_SaveState_IsSaveKey: Save key handle %08x\n", tpm_key_handle_entry->handle); + } + return; +} + +/* TPM_SaveState_NVLoad() deserializes the saved state data from the NV file TPM_SAVESTATE_NAME + + 0 on success. + Returns TPM_RETRY on non-existent file + TPM_FAIL on failure to load (fatal), since it should never occur +*/ + +TPM_RESULT TPM_SaveState_NVLoad(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + unsigned char *stream = NULL; + unsigned char *stream_start = NULL; + uint32_t stream_size; + + printf(" TPM_SaveState_NVLoad:\n"); + if (rc == 0) { + /* load from NVRAM. Returns TPM_RETRY on non-existent file. */ + rc = TPM_NVRAM_LoadData(&stream, /* freed @1 */ + &stream_size, + tpm_state->tpm_number, + TPM_SAVESTATE_NAME); + } + /* deserialize from stream */ + if (rc == 0) { + stream_start = stream; /* save starting point for free() */ + rc = TPM_SaveState_Load(tpm_state, &stream, &stream_size); + if (rc != 0) { + printf("TPM_SaveState_NVLoad: Error (fatal) loading deserializing saved state\n"); + rc = TPM_FAIL; + } + } + free(stream_start); /* @1 */ + return rc; +} + +/* TPM_SaveState_NVStore() serializes saved state data and stores it in the NV file + TPM_SAVESTATE_NAME +*/ + +TPM_RESULT TPM_SaveState_NVStore(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ + const unsigned char *buffer; + uint32_t length; + + printf(" TPM_SaveState_NVStore:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize relevant data from tpm_state to be written to NV */ + if (rc == 0) { + rc = TPM_SaveState_Store(&sbuffer, tpm_state); + /* get the serialized buffer and its length */ + TPM_Sbuffer_Get(&sbuffer, &buffer, &length); + } + /* validate the length of the stream */ + if (rc == 0) { + printf(" TPM_SaveState_NVStore: Require %u bytes\n", length); + if (length > TPM_MAX_SAVESTATE_SPACE) { + printf("TPM_SaveState_NVStore: Error, No space, need %u max %u\n", + length, TPM_MAX_SAVESTATE_SPACE); + rc = TPM_NOSPACE; + } + } + if (rc == 0) { + /* store the buffer in NVRAM */ + rc = TPM_NVRAM_StoreData(buffer, + length, + tpm_state->tpm_number, + TPM_SAVESTATE_NAME); + tpm_state->tpm_stany_flags.stateSaved = TRUE; /* mark the state as stored */ + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_SaveState_NVDelete() deletes the NV file + + If mustExist is TRUE, returns an error if the file does not exist. + If mustExist is FALSE, returns success if the file does not exist. +*/ + +TPM_RESULT TPM_SaveState_NVDelete(tpm_state_t *tpm_state, + TPM_BOOL mustExist) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SaveState_NVDelete:\n"); + if (rc == 0) { + /* remove the saved state */ + rc = TPM_NVRAM_DeleteName(tpm_state->tpm_number, + TPM_SAVESTATE_NAME, + mustExist); + tpm_state->tpm_stany_flags.stateSaved = FALSE; /* mark the state as deleted */ + } + return rc; +} + +/* Volatile state includes all the tpm_state structure volatile members. It is a superset of Saved + state, used when the entire TPM state must be saved and restored +*/ + +/* TPM_VolatileAll_Load() restores the TPM state from a stream created by TPM_VolatileAll_Store() + + The two functions must be kept in sync. +*/ + +TPM_RESULT TPM_VolatileAll_Load(tpm_state_t *tpm_state, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + TPM_PCR_ATTRIBUTES pcrAttrib[TPM_NUM_PCR]; + size_t i; + unsigned char *stream_start = *stream; /* copy for integrity check */ + uint32_t stream_size_start = *stream_size; + + printf(" TPM_VolatileAll_Load:\n"); + /* check format tag */ + /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' + on the tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_VSTATE_V1, stream, stream_size); + } + /* compiled in TPM parameters */ + if (rc == 0) { + rc = TPM_Parameters_Load(stream, stream_size); + } + /* V1 is the TCG standard returned by the getcap. It's unlikely that this will change */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_STCLEAR_FLAGS_V1, stream, stream_size); + } + /* TPM_STCLEAR_FLAGS */ + if (rc == 0) { + rc = TPM_StclearFlags_Load(&(tpm_state->tpm_stclear_flags), stream, stream_size); + } + /* TPM_STANY_FLAGS */ + if (rc == 0) { + rc = TPM_StanyFlags_Load(&(tpm_state->tpm_stany_flags), stream, stream_size); + } + /* TPM_STCLEAR_DATA */ + /* normally, resettable PCRs are not restored. "All" means to restore everything */ + for (i = 0 ; (rc == 0) && (i < TPM_NUM_PCR) ; i++) { + pcrAttrib[i].pcrReset = FALSE; + } + /* TPM_STCLEAR_DATA */ + if (rc == 0) { + rc = TPM_StclearData_Load(&(tpm_state->tpm_stclear_data), stream, stream_size, + (TPM_PCR_ATTRIBUTES *)&pcrAttrib); + } + /* TPM_STANY_DATA */ + if (rc == 0) { + rc = TPM_StanyData_Load(&(tpm_state->tpm_stany_data), stream, stream_size); + } + /* TPM_KEY_HANDLE_ENTRY */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_Load(tpm_state, stream, stream_size); + } + /* Context for SHA1 functions */ + if (rc == 0) { + printf(" TPM_VolatileAll_Load: Loading SHA ordinal context\n"); + rc = TPM_Sha1Context_Load(&(tpm_state->sha1_context), stream, stream_size); + } + /* Context for TIS SHA1 functions */ + if (rc == 0) { + printf(" TPM_VolatileAll_Load: Loading TIS context\n"); + rc = TPM_Sha1Context_Load(&(tpm_state->sha1_context_tis), stream, stream_size); + } + /* TPM_TRANSHANDLE */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_state->transportHandle), stream, stream_size); + } + /* testState */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_state->testState), stream, stream_size); + } + /* load the NV volatile flags */ + if (rc == 0) { + rc = TPM_NVIndexEntries_LoadVolatile(&(tpm_state->tpm_nv_index_entries), + stream, stream_size); + } + /* sanity check the stream size */ + if (rc == 0) { + if (*stream_size != TPM_DIGEST_SIZE) { + printf("TPM_VolatileAll_Load: Error (fatal) stream size %u not %u\n", + *stream_size, TPM_DIGEST_SIZE); + rc = TPM_FAIL; + } + } + /* check the integrity digest */ + if (rc == 0) { + printf(" TPM_VolatileAll_Load: Checking integrity digest\n"); + rc = TPM_SHA1_Check(*stream, /* currently points to integrity digest */ + stream_size_start - TPM_DIGEST_SIZE, stream_start, + 0, NULL); + } + /* remove the integrity digest from the stream */ + if (rc == 0) { + *stream_size -= TPM_DIGEST_SIZE; + } + return rc; +} + +/* TPM_VolatileAll_Store() stores the TPM state to a stream that can be restored through + TPM_VolatileAll_Load(). + + The two functions must be kept in sync. +*/ + +TPM_RESULT TPM_VolatileAll_Store(TPM_STORE_BUFFER *sbuffer, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_PCR_ATTRIBUTES pcrAttrib[TPM_NUM_PCR]; + size_t i; + const unsigned char *buffer; /* elements of sbuffer */ + uint32_t length; + TPM_DIGEST tpm_digest; + + printf(" TPM_VolatileAll_Store:\n"); + /* overall format tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_VSTATE_V1); + } + /* compiled in TPM parameters */ + if (rc == 0) { + rc = TPM_Parameters_Store(sbuffer); + } + /* V1 is the TCG standard returned by the getcap. It's unlikely that this will change */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STCLEAR_FLAGS_V1); + } + /* TPM_STCLEAR_FLAGS */ + if (rc == 0) { + rc = TPM_StclearFlags_Store(sbuffer, &(tpm_state->tpm_stclear_flags)); + } + /* TPM_STANY_FLAGS */ + if (rc == 0) { + rc = TPM_StanyFlags_Store(sbuffer, &(tpm_state->tpm_stany_flags)); + } + /* TPM_STCLEAR_DATA */ + /* normally, resettable PCRs are not restored. "All" means to restore everything */ + for (i = 0 ; (rc == 0) && (i < TPM_NUM_PCR) ; i++) { + pcrAttrib[i].pcrReset = FALSE; + } + /* TPM_STCLEAR_DATA */ + if (rc == 0) { + rc = TPM_StclearData_Store(sbuffer, &(tpm_state->tpm_stclear_data), + (TPM_PCR_ATTRIBUTES *)&pcrAttrib); + } + /* TPM_STANY_DATA */ + if (rc == 0) { + rc = TPM_StanyData_Store(sbuffer, &(tpm_state->tpm_stany_data)); + } + /* TPM_KEY_HANDLE_ENTRY */ + if (rc == 0) { + rc = TPM_KeyHandleEntries_Store(sbuffer, tpm_state); + } + /* Context for SHA1 functions */ + if (rc == 0) { + printf(" TPM_VolatileAll_Store: Storing SHA ordinal context\n"); + rc = TPM_Sha1Context_Store(sbuffer, tpm_state->sha1_context); + } + /* Context for TIS SHA1 functions */ + if (rc == 0) { + printf(" TPM_VolatileAll_Store: Storing TIS context\n"); + rc = TPM_Sha1Context_Store(sbuffer, tpm_state->sha1_context_tis); + } + /* TPM_TRANSHANDLE */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_state->transportHandle); + } + /* testState */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_state->testState); + } + /* store the NV volatile flags */ + if (rc == 0) { + rc = TPM_NVIndexEntries_StoreVolatile(sbuffer, + &(tpm_state->tpm_nv_index_entries)); + } + if (rc == 0) { + /* get the current serialized buffer and its length */ + TPM_Sbuffer_Get(sbuffer, &buffer, &length); + /* generate the integrity digest */ + rc = TPM_SHA1(tpm_digest, + length, buffer, + 0, NULL); + } + /* append the integrity digest to the stream */ + if (rc == 0) { + printf(" TPM_VolatileAll_Store: Appending integrity digest\n"); + rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE); + } + return rc; +} + +/* TPM_VolatileAll_NVLoad() deserializes the entire volatile state data from the NV file + TPM_VOLATILESTATE_NAME. + + If the file does not exist (a normal startup), returns success. + + 0 on success or non-existent file + TPM_FAIL on failure to load (fatal), since it should never occur +*/ + +TPM_RESULT TPM_VolatileAll_NVLoad(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_BOOL done = FALSE; + unsigned char *stream = NULL; + unsigned char *stream_start = NULL; + uint32_t stream_size; + + printf(" TPM_VolatileAll_NVLoad:\n"); + if (rc == 0) { + /* load from NVRAM. Returns TPM_RETRY on non-existent file. */ + rc = TPM_NVRAM_LoadData(&stream, /* freed @1 */ + &stream_size, + tpm_state->tpm_number, + TPM_VOLATILESTATE_NAME); + /* if the file does not exist, leave the volatile state initial values */ + if (rc == TPM_RETRY) { + done = TRUE; + rc = 0; + } + else if (rc != 0) { + printf("TPM_VolatileAll_NVLoad: Error (fatal) loading %s\n", TPM_VOLATILESTATE_NAME); + rc = TPM_FAIL; + } + } + /* deserialize from stream */ + if ((rc == 0) && !done) { + stream_start = stream; /* save starting point for free() */ + rc = TPM_VolatileAll_Load(tpm_state, &stream, &stream_size); + if (rc != 0) { + printf("TPM_VolatileAll_NVLoad: Error (fatal) loading deserializing state\n"); + rc = TPM_FAIL; + } + } + if (rc != 0) { + printf(" TPM_VolatileAll_NVLoad: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + + } + free(stream_start); /* @1 */ + return rc; +} + +/* TPM_VolatileAll_NVStore() serializes the entire volatile state data and stores it in the NV file + TPM_VOLATILESTATE_NAME +*/ + +TPM_RESULT TPM_VolatileAll_NVStore(tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ + const unsigned char *buffer; + uint32_t length; + + printf(" TPM_VolatileAll_NVStore:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize relevant data from tpm_state to be written to NV */ + if (rc == 0) { + rc = TPM_VolatileAll_Store(&sbuffer, tpm_state); + /* get the serialized buffer and its length */ + TPM_Sbuffer_Get(&sbuffer, &buffer, &length); + } + /* validate the length of the stream */ + if (rc == 0) { + printf(" TPM_VolatileAll_NVStore: Require %u bytes\n", length); + if (length > TPM_MAX_VOLATILESTATE_SPACE) { + printf("TPM_VolatileAll_NVStore: Error, No space, need %u max %u\n", + length, TPM_MAX_VOLATILESTATE_SPACE); + rc = TPM_NOSPACE; + } + } + if (rc == 0) { + /* store the buffer in NVRAM */ + rc = TPM_NVRAM_StoreData(buffer, + length, + tpm_state->tpm_number, + TPM_VOLATILESTATE_NAME); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* + Compiled in TPM Parameters +*/ + +TPM_RESULT TPM_Parameters_Load(unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Parameters_Load:\n"); + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_TPM_PARAMETERS_V1, + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check8(TPM_MAJOR, "TPM_MAJOR", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check8(TPM_MINOR, "TPM_MINOR", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_PCCLIENT, "TPM_PCCLIENT", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_NUM_PCR, "TPM_NUM_PCR", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_RSA_KEY_LENGTH_MAX, "TPM_RSA_KEY_LENGTH_MAX", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_KEY_HANDLES, "TPM_KEY_HANDLES", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_OWNER_EVICT_KEY_HANDLES, "TPM_OWNER_EVICT_KEY_HANDLES", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_NUM_FAMILY_TABLE_ENTRY_MIN, + "TPM_NUM_FAMILY_TABLE_ENTRY_MIN", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_NUM_DELEGATE_TABLE_ENTRY_MIN, + "TPM_NUM_DELEGATE_TABLE_ENTRY_MIN", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_MIN_AUTH_SESSIONS, "TPM_MIN_AUTH_SESSIONS", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_MIN_TRANS_SESSIONS, "TPM_MIN_TRANS_SESSIONS", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_MIN_DAA_SESSIONS, "TPM_MIN_DAA_SESSIONS", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_MIN_COUNTERS, "TPM_MIN_COUNTERS", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check16(TPM_MIN_SESSION_LIST, "TPM_MIN_SESSION_LIST", + stream, stream_size); + } + if (rc == 0) { + rc = TPM_Parameters_Check32(TPM_MAX_NV_SPACE, "TPM_MAX_NV_SPACE", + stream, stream_size); + } + return rc; +} + +TPM_RESULT TPM_Parameters_Check8(uint8_t expected, + const char *parameter, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint8_t tmp8; + + if (rc == 0) { + rc = TPM_Load8(&tmp8, stream, stream_size); + if (tmp8 != expected) { + printf("TPM_Parameters_Check8: Error (fatal) %s received %u expect %u\n", + parameter, tmp8, expected); + rc = TPM_FAIL; + } + } + return rc; +} + +TPM_RESULT TPM_Parameters_Check16(uint16_t expected, + const char *parameter, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint16_t tmp16; + + if (rc == 0) { + rc = TPM_Load16(&tmp16, stream, stream_size); + if (tmp16 != expected) { + printf("TPM_Parameters_Check16: Error (fatal) %s received %u expect %u\n", + parameter, tmp16, expected); + rc = TPM_FAIL; + } + } + return rc; +} + +TPM_RESULT TPM_Parameters_Check32(uint32_t expected, + const char *parameter, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t tmp32; + + if (rc == 0) { + rc = TPM_Load32(&tmp32, stream, stream_size); + if (tmp32 != expected) { + printf("TPM_Parameters_Check32: Error (fatal) %s received %u expect %u\n", + parameter, tmp32, expected); + rc = TPM_FAIL; + } + } + return rc; +} + +TPM_RESULT TPM_Parameters_Store(TPM_STORE_BUFFER *sbuffer) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Parameters_Store:\n"); + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TPM_PARAMETERS_V1); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append8(sbuffer, TPM_MAJOR); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append8(sbuffer, TPM_MINOR); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_PCCLIENT); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_NUM_PCR); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_RSA_KEY_LENGTH_MAX); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_KEY_HANDLES); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_OWNER_EVICT_KEY_HANDLES); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_NUM_FAMILY_TABLE_ENTRY_MIN); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_AUTH_SESSIONS); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_TRANS_SESSIONS); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_DAA_SESSIONS); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_COUNTERS); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_SESSION_LIST); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, TPM_MAX_NV_SPACE); + } + return rc; +} + + +/* 27.5 TPM_Reset rev 105 + + Releases all resources associated with existing authorization sessions. This is useful if a TSS + driver has lost track of the state in the TPM. + + This is a deprecated command in V1.2. This command in 1.1 only referenced authorization sessions + and is not upgraded to affect any other TPM entity in 1.2 +*/ + +TPM_RESULT TPM_Process_Reset(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_Reset: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Reset: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM invalidates all resources allocated to authorization sessions as per version 1.1 + extant in the TPM */ + /* a. This includes structures created by TPM_SaveAuthContext and TPM_SaveKeyContext */ + /* b.The TPM MUST invalidate OSAP sessions */ + /* c.The TPM MAY invalidate DSAP sessions */ + /* d. The TPM MUST NOT invalidate structures created by TPM_SaveContext */ + if (returnCode == TPM_SUCCESS) { + TPM_StclearData_AuthSessionDelete(&(tpm_state->tpm_stclear_data)); + } + /* 2. The TPM does not reset any PCR or DIR values. */ + /* 3. The TPM does not reset any flags in the TPM_STCLEAR_FLAGS structure. */ + /* 4. The TPM does not reset or invalidate any keys */ + /* + response + */ + if (rcf == 0) { + printf("TPM_Process_Reset: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + return rcf; +} + +/* 3.2 TPM_Startup rev 101 + + TPM_Startup is always preceded by TPM_Init, which is the physical indication (a system-wide + reset) that TPM initialization is necessary. + + There are many events on a platform that can cause a reset and the response to these events can + require different operations to occur on the TPM. The mere reset indication does not contain + sufficient information to inform the TPM as to what type of reset is occurring. Additional + information known by the platform initialization code needs transmitting to the TPM. The + TPM_Startup command provides the mechanism to transmit the information. + + The TPM can startup in three different modes: + + A "clear" start where all variables go back to their default or non-volatile set state + + A "save" start where the TPM recovers appropriate information and restores various values based + on a prior TPM_SaveState. This recovery requires an invocation of TPM_Init to be successful. + + A failing "save" start must shut down the TPM. The CRTM cannot leave the TPM in a state where an + untrusted upper software layer could issue a "clear" and then extend PCR's and thus mimic the + CRTM. + + A "deactivated" start where the TPM turns itself off and requires another TPM_Init before the TPM + will execute in a fully operational state. The TPM can startup in three different modes: +*/ + +TPM_RESULT TPM_Process_Startup(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + TPM_RESULT returnCode1 = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_STARTUP_TYPE startupType; + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_Startup: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get startupType parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&startupType, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Startup: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* TPM_CheckState() can check for the normal case where postInitialise TRUE is an error. This + is the only command where FALSE is the error. */ + if (returnCode == TPM_SUCCESS) { + /* 1. If TPM_STANY_FLAGS -> postInitialise is FALSE, */ + if (!(tpm_state->tpm_stany_flags.postInitialise)) { + /* a. Then the TPM MUST return TPM_INVALID_POSTINIT, and exit this capability */ + printf("TPM_Process_Startup: Error, postInitialise is FALSE\n"); + returnCode = TPM_INVALID_POSTINIT; + } + } + if (returnCode == TPM_SUCCESS) { + /* 1. If the TPM is in failure mode */ + if (tpm_state->testState == TPM_TEST_STATE_FAILURE) { + /* a. TPM_STANY_FLAGS -> postInitialize is still set to FALSE */ + tpm_state->tpm_stany_flags.postInitialise = FALSE; + printf("TPM_Process_Startup: Error, shutdown is TRUE\n"); + /* b. The TPM returns TPM_FAILEDSELFTEST */ + returnCode = TPM_FAILEDSELFTEST; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + switch (startupType) { + case TPM_ST_CLEAR: /* The TPM is starting up from a clean state */ + returnCode = TPM_Startup_Clear(tpm_state); + break; + case TPM_ST_STATE: /* The TPM is starting up from a saved state */ + returnCode = TPM_Startup_State(tpm_state); + break; + case TPM_ST_DEACTIVATED: /* The TPM is to startup and set the deactivated flag to + TRUE */ + returnCode = TPM_Startup_Deactivated(tpm_state); + break; + default: + returnCode = TPM_BAD_PARAMETER; + break; + } + } + /* TPM_STANY_FLAGS MUST reset on TPM_Startup(any) */ + if (returnCode == TPM_SUCCESS) { + TPM_StanyFlags_Init(&(tpm_state->tpm_stany_flags)); + } + /* 5. The TPM MUST ensure that state associated with TPM_SaveState is invalidated */ + returnCode1 = TPM_SaveState_NVDelete(tpm_state, + FALSE); /* Ignore errors if the state does not + exist. */ + if (returnCode == TPM_SUCCESS) { /* previous error takes precedence */ + returnCode = returnCode1; + } + /* 6. The TPM MUST set TPM_STANY_FLAGS -> postInitialise to FALSE */ + tpm_state->tpm_stany_flags.postInitialise = FALSE; + /* + response + */ + if (rcf == 0) { + printf("TPM_Process_Startup: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + return rcf; +} + +/* 3.2 TPM_Startup(TPM_ST_CLEAR) rev 99 +*/ + +TPM_RESULT TPM_Startup_Clear(tpm_state_t *tpm_state) +{ + TPM_RESULT returnCode = TPM_SUCCESS; + + printf("TPM_Startup_Clear:\n"); + /* 2. If stType = TPM_ST_CLEAR */ + if (returnCode == TPM_SUCCESS) { + /* a. Ensure that sessions associated with resources TPM_RT_CONTEXT, TPM_RT_AUTH, + TPM_RT_DAA_TPM, and TPM_RT_TRANS are invalidated */ + /* NOTE TPM_RT_CONTEXT - + contextNonceKey cleared by TPM_Global_Init() -> TPM_StanyData_Init() + contextNonceSession cleared by TPM_Global_Init() -> TPM_StanyData_Init() + */ + /* NOTE TPM_RT_AUTH - TPM_AuthSessions_Init() called by TPM_Global_Init() -> + TPM_StanyData_Init() */ + /* TPM_RT_TRANS - TPM_TransportSessions_Init() called by TPM_Global_Init() -> + TPM_StanyData_Init()*/ + /* TPM_RT_DAA_TPM - TPM_DaaSessions_Init() called by TPM_Global_Init() -> + TPM_StanyData_Init()*/ + /* b. Reset PCR values to each correct default value */ + /* i. pcrReset is FALSE, set to 0x00..00 */ + /* ii. pcrReset is TRUE, set to 0xFF..FF */ + /* NOTE done by TPM_MainInit() -> TPM_Global_Init() */ + /* c. Set the following TPM_STCLEAR_FLAGS to their default state + i. PhysicalPresence + ii. PhysicalPresenceLock + iii. disableForceClear + */ + /* NOTE Done by TPM_Global_Init() -> TPM_StclearFlags_Init() */ + /* d. The TPM MAY initialize auditDigest to all zeros + i. If not initialized to all zeros the TPM SHALL ensure that auditDigest contains a valid + value + ii. If initialization fails the TPM SHALL set auditDigest to all zeros and SHALL set the + internal TPM state so that the TPM returns TPM_FAILEDSELFTEST to all subsequent + commands. + */ + /* NOTE Done by TPM_Global_Init() ->TPM_StanyData_Init() */ + /* e. The TPM SHALL set TPM_STCLEAR_FLAGS -> deactivated to the same state as + TPM_PERMANENT_FLAGS -> deactivated + */ + tpm_state->tpm_stclear_flags.deactivated = tpm_state->tpm_permanent_flags.deactivated; + /* f. The TPM MUST set the TPM_STANY_DATA fields to: */ + /* i. TPM_STANY_DATA->contextNonceSession is set to all zeros */ + /* ii. TPM_STANY_DATA->contextCount is set to 0 */ + /* iii. TPM_STANY_DATA->contextList is set to 0 */ + /* NOTE Done by TPM_Global_Init() ->TPM_StanyData_Init() */ + /* g. The TPM MUST set TPM_STCLEAR_DATA fields to: */ + /* i. Invalidate contextNonceKey */ + /* ii. countID to zero */ + /* iii. OwnerReference to TPM_KH_OWNER */ + /* NOTE Done by TPM_Global_Init() -> TPM_StclearData_Init() */ + /* h. The TPM MUST set the following TPM_STCLEAR_FLAGS to */ + /* i. bGlobalLock to FALSE */ + /* NOTE Done by TPM_Global_Init() -> TPM_StclearFlags_Init() */ + /* i. Determine which keys should remain in the TPM */ + /* i. For each key that has a valid preserved value in the TPM */ + /* (1) if parentPCRStatus is TRUE then call TPM_FlushSpecific(keyHandle) */ + /* (2) if isVolatile is TRUE then call TPM_FlushSpecific(keyHandle) */ + /* NOTE Since TPM_Global_Init() calls TPM_KeyHandleEntries_Init(), there are no keys + remaining. Since this TPM implementation loads keys into volatile memory, not NVRAM, no + keys are preserved at ST_CLEAR. */ + /* ii. Keys under control of the OwnerEvict flag MUST stay resident in the TPM */ + /* NOTE Done by TPM_PermanentAll_NVLoad() */ + /* bReadSTClear and bWriteSTClear are volatile, in that they are set FALSE at + TPM_Startup(ST_Clear) */ + TPM_NVIndexEntries_StClear(&(tpm_state->tpm_nv_index_entries)); + } + return returnCode; +} + +/* 3.2 TPM_Startup(TPM_ST_STATE) rev 100 + */ + +TPM_RESULT TPM_Startup_State(tpm_state_t *tpm_state) +{ + TPM_RESULT returnCode = TPM_SUCCESS; + + printf("TPM_Startup_State:\n"); + if (returnCode == TPM_SUCCESS) { + /* a. If the TPM has no state to restore the TPM MUST set the internal state such that it + returns TPM_FAILEDSELFTEST to all subsequent commands */ + /* b. The TPM MAY determine for each session type (authorization, transport, DAA, ...) to + release or maintain the session information. The TPM reports how it manages sessions in + the TPM_GetCapability command. */ + /* c. The TPM SHALL take all necessary actions to ensure that all PCRs contain valid + preserved values. If the TPM is unable to successfully complete these actions, it SHALL + enter the TPM failure mode. */ + /* i. For resettable PCR the TPM MUST set the value of TPM_STCLEAR_DATA -> PCR[] to the + resettable PCR default value. The TPM MUST NOT restore a resettable PCR to a preserved + value */ + /* d. The TPM MAY initialize auditDigest to all zeros */ + /* i. Otherwise, the TPM SHALL take all actions necessary to ensure that auditDigest + contains a valid value. If the TPM is unable to successfully complete these actions, the + TPM SHALL initialize auditDigest to all zeros and SHALL set the internal state such that + the TPM returns TPM_FAILEDSELFTEST to all subsequent commands. */ + /* e. The TPM MUST restore the following flags to their preserved states: */ + /* i. All values in TPM_STCLEAR_FLAGS */ + /* ii. All values in TPM_STCLEAR_DATA */ + /* f. The TPM MUST restore all keys that have a valid preserved value */ + /* NOTE Owner evict keys are loaded at TPM_PermanentAll_NVLoad() */ + returnCode = TPM_SaveState_NVLoad(tpm_state); /* returns TPM_RETRY on non-existent file */ + } + /* g. The TPM resumes normal operation. If the TPM is unable to resume normal operation, it + SHALL enter the TPM failure mode. */ + if (returnCode != TPM_SUCCESS) { + printf("TPM_Startup_State: Error restoring state\n"); + returnCode = TPM_FAILEDSELFTEST; + printf(" TPM_Startup_State: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + return returnCode; +} + +/* 3.2 TPM_Startup(TPM_ST_DEACTIVATED) rev 97 + */ + +TPM_RESULT TPM_Startup_Deactivated(tpm_state_t *tpm_state) +{ + TPM_RESULT returnCode = TPM_SUCCESS; + + printf("TPM_Startup_Deactivated:\n"); + if (returnCode == TPM_SUCCESS) { + /* a. Invalidate sessions */ + /* i. Ensure that all resources associated with saved and active sessions are invalidated */ + /* NOTE Done at TPM_MainInit() */ + /* b. The TPM MUST set TPM_STCLEAR_FLAGS -> deactivated to TRUE */ + tpm_state->tpm_stclear_flags.deactivated = TRUE; + } + return returnCode; +} + +#if 0 +/* TPM_Startup_Any() rev 96 + + Handles Actions common to all TPM_Startup options. +*/ + +TPM_RESULT TPM_Startup_Any(tpm_state_t *tpm_state) +{ + TPM_RESULT returnCode = TPM_SUCCESS; + + printf("TPM_Startup_Any:\n"); + /* TPM_STANY_FLAGS MUST reset on TPM_Startup(any) */ + TPM_StanyFlags_Init(&(tpm_state->tpm_stany_flags)); + /* 5. The TPM MUST ensure that state associated with TPM_SaveState is invalidated */ + returnCode = TPM_SaveState_NVDelete(tpm_state, + FALSE); /* Ignore errors if the state does not exist. */ + /* 6. The TPM MUST set TPM_STANY_FLAGS -> postInitialise to FALSE */ + tpm_state->tpm_stany_flags.postInitialise = FALSE; + return returnCode; +} +#endif + +/* 3.3 TPM_SaveState rev 111 + + This warns a TPM to save some state information. + + If the relevant shielded storage is non-volatile, this command need have no effect. + + If the relevant shielded storage is volatile and the TPM alone is unable to detect the loss of + external power in time to move data to non-volatile memory, this command should be presented + before the TPM enters a low or no power state. + + Resettable PCRs are tied to platform state that does not survive a sleep state. If the PCRs did + not reset, they would falsely indicate that the platform state was already present when it came + out of sleep. Since some setup is required first, there would be a gap where PCRs indicated the + wrong state. Therefore, the PCRs must be recreated. +*/ + +TPM_RESULT TPM_Process_SaveState(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_SaveState: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | + TPM_CHECK_NO_LOCKOUT)); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_SaveState: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Preserved values MUST be non-volatile. */ + /* 2. If data is never stored in a volatile medium, that data MAY be used as preserved data. In + such cases, no explicit action may be required to preserve that data. */ + /* 3. If an explicit action is required to preserve data, it MUST be possible for the TPM to + determine whether preserved data is valid. */ + /* 4. If the parameter mirrored by a preserved value is altered, all preserved values MUST be + declared invalid. */ + if (returnCode == TPM_SUCCESS) { + /* Determine if TPM_SaveState was called from within a transport session. The TPM MAY save + transport sessions as part of the saved state. Since this TPM implements that option, + there's no point in saving the state, because it would be immediately invalidated during + the transport response. Return an error to indicate that the state was not saved. */ + if (transportInternal != NULL) { + printf("TPM_Process_SaveState: Error, called from transport session\n"); + returnCode = TPM_NO_WRAP_TRANSPORT; + } + } + /* Audit Generation Corner cases 3.a. TPM_SaveState: Only the input parameters are audited, and + the audit occurs before the state is saved. If an error occurs while or after the state is + saved, the audit still occurs. + */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* 5. The TPM MAY declare all preserved value is invalid in response to any command other that + TPM_Init. */ + /* NOTE Done by TPM_GetInParamDigest(), which is called by all ordinals */ + /* 1. Store TPM_STCLEAR_DATA -> PCR contents except for */ + /* a. If the PCR attribute pcrReset is TRUE */ + /* b. Any platform identified debug PCR */ + /* 2. The auditDigest MUST be handled according to the audit requirements as reported by + TPM_GetCapability */ + /* a. If the ordinalAuditStatus is TRUE for the TPM_SaveState ordinal and the auditDigest is + being stored in the saved state, the saved auditDigest MUST include the TPM_SaveState input + parameters and MUST NOT include the output parameters. */ + /* 3. All values in TPM_STCLEAR_DATA MUST be preserved */ + /* 4. All values in TPM_STCLEAR_FLAGS MUST be preserved */ + /* 5. The contents of any key that is currently loaded SHOULD be preserved if the key's + parentPCRStatus indicator is TRUE. */ + /* 6. The contents of any key that has TPM_KEY_CONTROL_OWNER_EVICT set MUST be preserved */ + /* 7. The contents of any key that is currently loaded MAY be preserved */ + /* 8. The contents of sessions (authorization, transport, DAA etc.) MAY be preserved as reported + by TPM_GetCapability */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SaveState_NVStore(tpm_state); + } + /* store the state in NVRAM */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_SaveState: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* Special case, no output parameter audit */ + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + return rcf; +} diff --git a/src/tpm12/tpm_startup.h b/src/tpm12/tpm_startup.h new file mode 100644 index 0000000..bc72328 --- /dev/null +++ b/src/tpm12/tpm_startup.h @@ -0,0 +1,136 @@ +/********************************************************************************/ +/* */ +/* TPM Admin Startup and State */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_startup.h 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_STARTUP_H +#define TPM_STARTUP_H + +#include "tpm_global.h" +#include "tpm_store.h" +#include "tpm_types.h" + +/* + Startup +*/ + +TPM_RESULT TPM_Startup_Clear(tpm_state_t *tpm_state); +TPM_RESULT TPM_Startup_State(tpm_state_t *tpm_state); +TPM_RESULT TPM_Startup_Deactivated(tpm_state_t *tpm_state); +#if 0 +TPM_RESULT TPM_Startup_Any(tpm_state_t *tpm_state); +#endif + +/* + Save State +*/ + +TPM_RESULT TPM_SaveState_Load(tpm_state_t *tpm_state, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_SaveState_Store(TPM_STORE_BUFFER *sbuffer, + tpm_state_t *tpm_state); + +TPM_RESULT TPM_SaveState_NVLoad(tpm_state_t *tpm_state); +TPM_RESULT TPM_SaveState_NVStore(tpm_state_t *tpm_state); +TPM_RESULT TPM_SaveState_NVDelete(tpm_state_t *tpm_state, + TPM_BOOL mustExist); + +void TPM_SaveState_IsSaveKey(TPM_BOOL *save, + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); + +/* + Volatile State +*/ + +TPM_RESULT TPM_VolatileAll_Load(tpm_state_t *tpm_state, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_VolatileAll_Store(TPM_STORE_BUFFER *sbuffer, + tpm_state_t *tpm_state); +TPM_RESULT TPM_VolatileAll_NVLoad(tpm_state_t *tpm_state); +TPM_RESULT TPM_VolatileAll_NVStore(tpm_state_t *tpm_state); + +/* + Compiled in TPM Parameters +*/ + +TPM_RESULT TPM_Parameters_Load(unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Parameters_Store(TPM_STORE_BUFFER *sbuffer); +TPM_RESULT TPM_Parameters_Check8(uint8_t expected, + const char *parameter, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Parameters_Check16(uint16_t expected, + const char *parameter, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Parameters_Check32(uint32_t expected, + const char *parameter, + unsigned char **stream, + uint32_t *stream_size); + +/* + Processing Functions +*/ + +TPM_RESULT TPM_Process_Reset(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_Startup(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +TPM_RESULT TPM_Process_SaveState(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +#endif diff --git a/src/tpm12/tpm_storage.c b/src/tpm12/tpm_storage.c new file mode 100644 index 0000000..c3cd1ac --- /dev/null +++ b/src/tpm12/tpm_storage.c @@ -0,0 +1,3593 @@ +/********************************************************************************/ +/* */ +/* Storage Functions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_storage.c 4442 2011-02-14 20:20:01Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_auth.h" +#include "tpm_cryptoh.h" +#include "tpm_crypto.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_pcr.h" +#include "tpm_process.h" +#include "tpm_secret.h" +#include "tpm_structures.h" +#include "tpm_ver.h" + +#include "tpm_storage.h" + +/* local function prototypes */ + +static TPM_RESULT TPM_SealCryptCommon(BYTE **o1, + TPM_ADIP_ENC_SCHEME adipEncScheme, + TPM_SIZED_BUFFER *inData, + TPM_AUTH_SESSION_DATA *auth_session_data, + TPM_NONCE nonceOdd); + +static TPM_RESULT TPM_LoadKeyCommon(TPM_KEY_HANDLE *inKeyHandle, + TPM_BOOL *key_added, + TPM_SECRET **hmacKey, + TPM_AUTH_SESSION_DATA **auth_session_data, + tpm_state_t *tpm_state, + TPM_TAG tag, + TPM_COMMAND_CODE ordinal, + TPM_KEY_HANDLE parentHandle, + TPM_KEY *inKey, + TPM_DIGEST inParamDigest, + TPM_AUTHHANDLE authHandle, + TPM_NONCE nonceOdd, + TPM_BOOL continueAuthSession, + TPM_AUTHDATA parentAuth); + +/* + TPM_BOUND_DATA +*/ + +/* TPM_BoundData_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_BoundData_Init(TPM_BOUND_DATA *tpm_bound_data) +{ + printf(" TPM_BoundData_Init:\n"); + TPM_StructVer_Init(&(tpm_bound_data->ver)); + tpm_bound_data->payload = TPM_PT_BIND; + tpm_bound_data->payloadDataSize = 0; + tpm_bound_data->payloadData = NULL; + return; +} + +/* TPM_BoundData_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_BoundData_Init() + After use, call TPM_BoundData_Delete() to free memory +*/ + +TPM_RESULT TPM_BoundData_Load(TPM_BOUND_DATA *tpm_bound_data, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_BoundData_Load:\n"); + if (rc == 0) { + rc = TPM_StructVer_Load(&(tpm_bound_data->ver), stream, stream_size); + } + /* check ver immediately to ease debugging */ + if (rc == 0) { + rc = TPM_StructVer_CheckVer(&(tpm_bound_data->ver)); + } + if (rc == 0) { + rc = TPM_Load8(&(tpm_bound_data->payload), stream, stream_size); + } + if ((rc == 0) && (*stream_size > 0)){ + /* There is no payloadData size in the serialized data. Assume it consumes the rest of the + stream */ + tpm_bound_data->payloadDataSize = *stream_size; + rc = TPM_Malloc(&(tpm_bound_data->payloadData), tpm_bound_data->payloadDataSize); + } + if ((rc == 0) && (*stream_size > 0)){ + memcpy(tpm_bound_data->payloadData, *stream, tpm_bound_data->payloadDataSize); + *stream += tpm_bound_data->payloadDataSize; + *stream_size -= tpm_bound_data->payloadDataSize; + } + return rc; +} + +#if 0 +/* TPM_BoundData_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + This structure serialization assumes that the payloadDataSize member indicates the size of + payloadData. +*/ + +TPM_RESULT TPM_BoundData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_BOUND_DATA *tpm_bound_data) +{ + TPM_RESULT rc = 0; + + printf(" TPM_BoundData_Store:\n"); + if (rc == 0) { + rc = TPM_StructVer_Store(sbuffer, &(tpm_bound_data->ver)); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_bound_data->payload), sizeof(TPM_PAYLOAD_TYPE)); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, tpm_bound_data->payloadData, + tpm_bound_data->payloadDataSize); + } + return rc; +} +#endif + +/* TPM_BoundData_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the bound_data + sets pointers to NULL + calls TPM_BoundData_Init to set members back to default values + The bound_data itself is not freed +*/ + +void TPM_BoundData_Delete(TPM_BOUND_DATA *tpm_bound_data) +{ + printf(" TPM_BoundData_Delete:\n"); + if (tpm_bound_data != NULL) { + free(tpm_bound_data->payloadData); + TPM_BoundData_Init(tpm_bound_data); + } + return; +} + +/* + TPM_SEALED_DATA +*/ + +/* TPM_SealedData_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_SealedData_Init(TPM_SEALED_DATA *tpm_sealed_data) +{ + printf(" TPM_SealedData_Init:\n"); + tpm_sealed_data->payload = TPM_PT_SEAL; + TPM_Secret_Init(tpm_sealed_data->authData); + TPM_Secret_Init(tpm_sealed_data->tpmProof); + TPM_Digest_Init(tpm_sealed_data->storedDigest); + TPM_SizedBuffer_Init(&(tpm_sealed_data->data)); + return; +} + +/* TPM_SealedData_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_SealedData_Init() + After use, call TPM_SealedData_Delete() to free memory +*/ + +TPM_RESULT TPM_SealedData_Load(TPM_SEALED_DATA *tpm_sealed_data, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_SealedData_Load:\n"); + /* load payload */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_sealed_data->payload), stream, stream_size); + } + /* load authData */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_sealed_data->authData, stream, stream_size); + } + /* load tpmProof */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_sealed_data->tpmProof, stream, stream_size); + } + /* load storedDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_sealed_data->storedDigest, stream, stream_size); + } + /* load dataSize and data */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_sealed_data->data), stream, stream_size); + } + return rc; +} + +/* TPM_SealedData_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_SealedData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SEALED_DATA *tpm_sealed_data) +{ + TPM_RESULT rc = 0; + printf(" TPM_SealedData_Store:\n"); + /* store payload */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_sealed_data->payload), sizeof(TPM_PAYLOAD_TYPE)); + } + /* store authData */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_sealed_data->authData); + } + /* store tpmProof */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_sealed_data->tpmProof); + } + /* store storedDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_sealed_data->storedDigest); + } + /* store dataSize and data */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_sealed_data->data)); + } + return rc; +} + +/* TPM_SealedData_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_SealedData_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_SealedData_Delete(TPM_SEALED_DATA *tpm_sealed_data) +{ + printf(" TPM_SealedData_Delete:\n"); + if (tpm_sealed_data != NULL) { + TPM_SizedBuffer_Delete(&(tpm_sealed_data->data)); + TPM_SealedData_Init(tpm_sealed_data); + } + return; +} + +/* TPM_SealedData_GenerateEncData() generates an enc_data structure by serializing the + TPM_SEALED_DATA structure and encrypting the result using the public key. +*/ + +TPM_RESULT TPM_SealedData_GenerateEncData(TPM_SIZED_BUFFER *enc_data, + const TPM_SEALED_DATA *tpm_sealed_data, + TPM_KEY *tpm_key) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* TPM_SEALED_DATA serialization */ + + printf(" TPM_SealedData_GenerateEncData\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize the TPM_SEALED_DATA */ + if (rc == 0) { + rc = TPM_SealedData_Store(&sbuffer, tpm_sealed_data); + } + /* encrypt the TPM_SEALED_DATA serialization buffer with the public key, and place + the result in the encData members */ + if (rc == 0) { + rc = TPM_RSAPublicEncryptSbuffer_Key(enc_data, &sbuffer, tpm_key); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* TPM_SealedData_DecryptEncData() decrypts the enc_data using the private key. The + result is deserialized and stored in the TPM_SEALED_DATA structure. + +*/ + +TPM_RESULT TPM_SealedData_DecryptEncData(TPM_SEALED_DATA *tpm_sealed_data, /* result */ + TPM_SIZED_BUFFER *enc_data, /* encrypted input */ + TPM_KEY *tpm_key) /* key for decrypting */ +{ + TPM_RESULT rc = 0; + unsigned char *decryptData = NULL; /* freed @1 */ + uint32_t decryptDataLength = 0; /* actual valid data */ + unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_SealedData_DecryptEncData:\n"); + /* allocate space for the decrypted data */ + if (rc == 0) { + rc = TPM_RSAPrivateDecryptMalloc(&decryptData, /* decrypted data */ + &decryptDataLength, /* actual size of decrypted data */ + enc_data->buffer, /* encrypted data */ + enc_data->size, /* encrypted data size */ + tpm_key); + } + /* load the TPM_SEALED_DATA structure from the decrypted data stream */ + if (rc == 0) { + /* use temporary variables, because TPM_SealedData_Load() moves the stream */ + stream = decryptData; + stream_size = decryptDataLength; + rc = TPM_SealedData_Load(tpm_sealed_data, &stream, &stream_size); + } + free(decryptData); /* @1 */ + return rc; +} + + +/* + TPM_STORED_DATA +*/ + +/* TPM_StoredData_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_StoredData_Init(TPM_STORED_DATA *tpm_stored_data, + unsigned int version) +{ + printf(" TPM_StoredData_Init: v%u\n", version); + if (version == 1) { + TPM_StructVer_Init(&(tpm_stored_data->ver)); + } + else { + ((TPM_STORED_DATA12 *)tpm_stored_data)->tag = TPM_TAG_STORED_DATA12; + ((TPM_STORED_DATA12 *)tpm_stored_data)->et = 0x0000; + } + TPM_SizedBuffer_Init(&(tpm_stored_data->sealInfo)); + TPM_SizedBuffer_Init(&(tpm_stored_data->encData)); + tpm_stored_data->tpm_seal_info = NULL; + return; +} + +/* TPM_StoredData_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_StoredData_Init() + After use, call TPM_StoredData_Delete() to free memory + + This function handles both TPM_STORED_DATA and TPM_STORED_DATA12 and returns the 'version'. +*/ + +TPM_RESULT TPM_StoredData_Load(TPM_STORED_DATA *tpm_stored_data, + unsigned int *version, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + /* Peek at the first byte to guess the version number. The data is verified later. + TPM_STORED_DATA is 01,01,00,00 TPM_STORED_DATA12 is 00,16,00,00 */ + if ((rc == 0) && (*stream_size > 0)) { + if (**stream == 0x01) { + *version = 1; + } + else { + *version = 2; + } + printf(" TPM_StoredData_Load: v%u\n", *version); + } + /* 1.1 load ver */ + if ((rc == 0) && (*version == 1)) { + rc = TPM_StructVer_Load(&(tpm_stored_data->ver), stream, stream_size); + } + /* 1.2 load tag */ + if ((rc == 0) && (*version != 1)) { + rc = TPM_Load16(&(((TPM_STORED_DATA12 *)tpm_stored_data)->tag), stream, stream_size); + } + /* 1.2 load et */ + if ((rc == 0) && (*version != 1)) { + rc = TPM_Load16(&(((TPM_STORED_DATA12 *)tpm_stored_data)->et), stream, stream_size); + } + /* check the TPM_STORED_DATA structure version */ + if ((rc == 0) && (*version == 1)) { + rc = TPM_StructVer_CheckVer(&(tpm_stored_data->ver)); + } + /* check the TPM_STORED_DATA12 structure tag */ + if ((rc == 0) && (*version != 1)) { + rc = TPM_StoredData_CheckTag((TPM_STORED_DATA12 *)tpm_stored_data); + } + /* load sealInfoSize and sealInfo */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_stored_data->sealInfo), stream, stream_size); + } + /* load the TPM_PCR_INFO or TPM_PCR_INFO_LONG cache */ + if (rc == 0) { + if (*version == 1) { + rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_stored_data->tpm_seal_info), + &(tpm_stored_data->sealInfo)); + } + else { + rc = TPM_PCRInfoLong_CreateFromBuffer + (&(((TPM_STORED_DATA12 *)tpm_stored_data)->tpm_seal_info_long), + &(tpm_stored_data->sealInfo)); + } + } + /* load encDataSize and encData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Load(&(tpm_stored_data->encData), stream, stream_size); + } + return rc; +} + +/* TPM_StoredData_StoreClearData() serializes a TPM_STORED_DATA structure, excluding encData, + appending results to 'sbuffer'. + + Before serializing, it serializes tpm_seal_info to sealInfoSize and sealInfo. + + This function handles both TPM_STORED_DATA and TPM_STORED_DATA12. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_StoredData_StoreClearData(TPM_STORE_BUFFER *sbuffer, + TPM_STORED_DATA *tpm_stored_data, + unsigned int version) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StoredData_StoreClearData: v%u\n", version); + /* 1.1 store ver */ + if ((rc == 0) && (version == 1)) { + rc = TPM_StructVer_Store(sbuffer, &(tpm_stored_data->ver)); + } + /* 1.2 store tag */ + if ((rc == 0) && (version != 1)) { + rc = TPM_Sbuffer_Append16(sbuffer, ((TPM_STORED_DATA12 *)tpm_stored_data)->tag); + } + /* 1.2 store et */ + if ((rc == 0) && (version != 1)) { + rc = TPM_Sbuffer_Append16(sbuffer, ((TPM_STORED_DATA12 *)tpm_stored_data)->et); + } + /* store sealInfoSize and sealInfo */ + if (rc == 0) { + /* copy cache to sealInfoSize and sealInfo */ + if (version == 1) { + rc = TPM_SizedBuffer_SetStructure(&(tpm_stored_data->sealInfo), + tpm_stored_data->tpm_seal_info, + (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store); + } + else { + rc = TPM_SizedBuffer_SetStructure(&(tpm_stored_data->sealInfo), + tpm_stored_data->tpm_seal_info, + (TPM_STORE_FUNCTION_T)TPM_PCRInfoLong_Store); + } + } + /* copy sealInfoSize and sealInfo to sbuffer */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_stored_data->sealInfo)); + } + return rc; +} + +/* TPM_StoredData_Store() + + Before serializing, it serializes tpm_seal_info to sealInfoSize and sealInfo. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_StoredData_Store(TPM_STORE_BUFFER *sbuffer, + TPM_STORED_DATA *tpm_stored_data, + unsigned int version) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StoredData_Store: v%u\n", version); + if (rc == 0) { + rc = TPM_StoredData_StoreClearData(sbuffer, tpm_stored_data, version); + } + /* store encDataSize and encData */ + if (rc == 0) { + rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_stored_data->encData)); + } + return rc; +} + +/* TPM_StoredData_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_StoredData_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_StoredData_Delete(TPM_STORED_DATA *tpm_stored_data, + unsigned int version) +{ + printf(" TPM_StoredData_Delete: v%u\n", version); + if (tpm_stored_data != NULL) { + TPM_SizedBuffer_Delete(&(tpm_stored_data->sealInfo)); + TPM_SizedBuffer_Delete(&(tpm_stored_data->encData)); + if (version == 1) { + TPM_PCRInfo_Delete(tpm_stored_data->tpm_seal_info); + free(tpm_stored_data->tpm_seal_info); + } + else { + TPM_PCRInfoLong_Delete((TPM_PCR_INFO_LONG *)tpm_stored_data->tpm_seal_info); + free(tpm_stored_data->tpm_seal_info); + } + TPM_StoredData_Init(tpm_stored_data, version); + } + return; +} + +/* TPM_StoredData_CheckTag() verifies the tag and et members of a TPM_STORED_DATA12 structure + + */ + +TPM_RESULT TPM_StoredData_CheckTag(TPM_STORED_DATA12 *tpm_stored_data12) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StoredData_CheckTag:\n"); + if (rc == 0) { + if (tpm_stored_data12->tag != TPM_TAG_STORED_DATA12) { + printf("TPM_StoredData_CheckTag: Error, tag expected %04x found %04hx\n", + TPM_TAG_STORED_DATA12, tpm_stored_data12->tag); + rc = TPM_BAD_VERSION; + } + } + return rc; +} + +/* TPM_StoredData_GenerateDigest() generates a TPM_DIGEST over the TPM_STORED_DATA structure + excluding the encDataSize and encData members. +*/ + +TPM_RESULT TPM_StoredData_GenerateDigest(TPM_DIGEST tpm_digest, + TPM_STORED_DATA *tpm_stored_data, + unsigned int version) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; /* TPM_STORED_DATA serialization */ + + printf(" TPM_StoredData_GenerateDigest:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize the TPM_STORED_DATA excluding the encData fields */ + if (rc == 0) { + rc = TPM_StoredData_StoreClearData(&sbuffer, tpm_stored_data, version); + } + if (rc == 0) { + rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* + Processing Functions +*/ + +/* TPM_SealCryptCommon() rev 98 + + Handles the encrypt/decrypt actions common to TPM_Sealx and TPM_Unseal + + 'encrypt TRUE for encryption, FALSE for decryption + + The output o1 must be freed by the caller. +*/ + +static TPM_RESULT TPM_SealCryptCommon(BYTE **o1, /* freed by caller */ + TPM_ADIP_ENC_SCHEME adipEncScheme, + TPM_SIZED_BUFFER *inData, + TPM_AUTH_SESSION_DATA *auth_session_data, + TPM_NONCE nonceOdd) +{ + TPM_RESULT rc = 0; + BYTE *x1; /* XOR string, MGF1 output */ + TPM_DIGEST ctr; /* symmetric key algorithm CTR */ + + printf(" TPM_SealCryptCommon:\n"); + x1 = NULL; /* freed @1 */ + + /* allocate for the output o1 */ + if (rc == TPM_SUCCESS) { + rc = TPM_Malloc(o1, inData->size); /* freed by caller */ + } + if (rc == TPM_SUCCESS) { + TPM_PrintFourLimit(" TPM_SealCryptCommon: input data", inData->buffer, inData->size); + } + switch (adipEncScheme) { + case TPM_ET_XOR: + printf(" TPM_SealCryptCommon: TPM_ET_XOR\n"); + if (rc == TPM_SUCCESS) { + /* i. Use MGF1 to create string X1 of length sealedDataSize. The inputs to MGF1 are; + authLastnonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four + concatenated values form the Z value that is the seed for MFG1. */ + rc = TPM_MGF1_GenerateArray(&x1, /* MGF1 array */ + inData->size, /* MGF1 array length */ + + TPM_NONCE_SIZE + + TPM_NONCE_SIZE + + sizeof("XOR") -1 + + TPM_DIGEST_SIZE, /* seed length */ + + TPM_NONCE_SIZE, auth_session_data->nonceEven, + TPM_NONCE_SIZE, nonceOdd, + sizeof("XOR") -1, "XOR", + TPM_DIGEST_SIZE, auth_session_data->sharedSecret, + 0, NULL); + } + /* ii. Create o1 by XOR of d1 -> data and X1 */ + if (rc == TPM_SUCCESS) { + TPM_PrintFour(" TPM_SealCryptCommon: XOR key", x1); + TPM_XOR(*o1, inData->buffer, x1, inData->size); + } + break; + case TPM_ET_AES128_CTR: + printf(" TPM_SealCryptCommon: TPM_ET_AES128_CTR\n"); + /* i. Create o1 by encrypting d1 -> data using the algorithm indicated by inData -> + et */ + /* ii. Key is from authHandle -> sharedSecret */ + /* iii. IV is SHA-1 of (authLastNonceEven || nonceOdd) */ + if (rc == TPM_SUCCESS) { + rc = TPM_SHA1(ctr, + TPM_NONCE_SIZE, auth_session_data->nonceEven, + TPM_NONCE_SIZE, nonceOdd, + 0, NULL); + } + if (rc == TPM_SUCCESS) { + TPM_PrintFour(" TPM_SealCryptCommon: AES key", auth_session_data->sharedSecret); + TPM_PrintFour(" TPM_SealCryptCommon: CTR", ctr); + rc = TPM_SymmetricKeyData_CtrCrypt(*o1, /* output data */ + inData->buffer, /* input data */ + inData->size, /* data size */ + auth_session_data->sharedSecret, /* key */ + TPM_SECRET_SIZE, /* key size */ + ctr, /* CTR */ + TPM_DIGEST_SIZE); /* CTR size */ + } + break; + default: + printf("TPM_SealCryptCommon: Error, unsupported adipEncScheme %02x\n", adipEncScheme); + rc = TPM_INAPPROPRIATE_ENC; + break; + } + if (rc == 0) { + TPM_PrintFour(" TPM_SealCryptCommon: output data", *o1); + + } + free(x1); /* @1 */ + return rc; +} + +/* 10.1 TPM_Seal rev 110 + + The SEAL operation allows software to explicitly state the future "trusted" configuration that + the platform must be in for the secret to be revealed. The SEAL operation also implicitly + includes the relevant platform configuration (PCR-values) when the SEAL operation was + performed. The SEAL operation uses the tpmProof value to BIND the blob to an individual TPM. + + TPM_Seal is used to encrypt private objects that can only be decrypted using TPM_Unseal. +*/ + +TPM_RESULT TPM_Process_Seal(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* Handle of a loaded key that can perform seal + operations. */ + TPM_ENCAUTH encAuth; /* The encrypted authorization data for the sealed data. */ + TPM_SIZED_BUFFER pcrInfo; /* The PCR selection information. The caller MAY use + TPM_PCR_INFO_LONG. */ + TPM_SIZED_BUFFER inData; /* The data to be sealed to the platform and any specified + PCRs */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle + authorization. Must be an OS_AP session for this + command. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA pubAuth; /* The authorization digest for inputs and keyHandle. HMAC + key: key.usageAuth. */ + + /* processing */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_KEY *key = NULL; /* the key specified by keyHandle */ + TPM_SECRET *keyUsageAuth; + TPM_BOOL parentPCRStatus; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + unsigned int v1PcrVersion = 1; /* pcrInfo version */ + TPM_STORED_DATA12 *s1_12; + TPM_PCR_INFO tpm_pcr_info; /* deserialized pcrInfo v1 */ + TPM_PCR_INFO_LONG tpm_pcr_info_long; /* deserialized pcrInfo v2 */ + unsigned char *stream; + uint32_t stream_size; + TPM_DIGEST a1Auth; + TPM_SEALED_DATA s2SealedData; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORED_DATA s1StoredData; /* Encrypted, integrity-protected data object that is the + result of the TPM_Seal operation. Returned as + SealedData */ + + printf("TPM_Process_Seal: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&pcrInfo); /* freed @1 */ + TPM_SizedBuffer_Init(&inData); /* freed @2 */ + TPM_StoredData_Init(&s1StoredData, v1PcrVersion); /* freed @3, default is v1 */ + TPM_PCRInfo_Init(&tpm_pcr_info); /* freed @4 */ + TPM_PCRInfoLong_Init(&tpm_pcr_info_long); /* freed @5 */ + TPM_SealedData_Init(&s2SealedData); /* freed @6 */ + s1_12 = (TPM_STORED_DATA12 *)&s1StoredData; /* to avoid casts */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get encAuth parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Seal: keyHandle %08x\n", keyHandle); + returnCode = TPM_Authdata_Load(encAuth, &command, ¶mSize); + } + /* get pcrInfo parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&pcrInfo, &command, ¶mSize); + } + /* get inData parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Seal: Sealing %u bytes\n", inData.size); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + pubAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Seal: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not r/o, using to encrypt */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get keyHandle -> usageAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); + } + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_KEYHANDLE, + ordinal, + key, + NULL, /* OIAP */ + key->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 1. Validate the authorization to use the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + pubAuth); /* Authorization digest for input */ + } + /* 2. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (inData.size == 0) { + printf("TPM_Process_Seal: Error, inDataSize is 0\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 3. If the keyUsage field of the key indicated by keyHandle does not have the value + TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE. */ + if (returnCode == TPM_SUCCESS) { + if (key->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_Seal: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n", + key->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. If the keyHandle points to a migratable key then the TPM MUST return the error code + TPM_INVALID_KEY_USAGE. */ + if (returnCode == TPM_SUCCESS) { + if (key->keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_Seal: Error, key keyFlags %08x indicates migratable\n", + key->keyFlags); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 5. Determine the version of pcrInfo */ + if (returnCode == TPM_SUCCESS) { + /* a. If pcrInfoSize is 0 */ + if (pcrInfo.size == 0) { + v1PcrVersion = 1; /* i. set V1 to 1 */ + } + else { /* b. Else */ + /* i. Point X1 as TPM_PCR_INFO_LONG structure to pcrInfo */ + /* ii. If X1 -> tag is TPM_TAG_PCR_INFO_LONG */ + if (htons(*(uint16_t *)(pcrInfo.buffer)) == TPM_TAG_PCR_INFO_LONG) { + v1PcrVersion = 2; /* (1) Set V1 to 2 */ + } + else { /* iii. Else */ + v1PcrVersion = 1; /* (1) Set V1 to 1 */ + } + } + /* 6. If V1 is 1 then */ + /* a. Create S1 a TPM_STORED_DATA structure */ + /* 7. else */ + /* a. Create S1 a TPM_STORED_DATA12 structure */ + /* b. Set S1 -> et to 0 */ + /* 8. Set S1 -> encDataSize to 0 */ + /* 9. Set S1 -> encData to all zeros */ + printf("TPM_Process_Seal: V%u\n", v1PcrVersion); + TPM_StoredData_Init(&s1StoredData, v1PcrVersion); + /* 10. Set S1 -> sealInfoSize to pcrInfoSize */ + /* NOTE This step is unnecessary. If pcrInfoSize is 0, sealInfoSize is already initialized + to 0. If pcrInfoSize is non-zero, sealInfoSize is the result of serialization of the + tpm_seal_info member, which is either a TPM_PCR_INFO or a TPM_PCR_INFO_LONG */ + } + /* 11. If pcrInfoSize is not 0 then */ + if ((returnCode == TPM_SUCCESS) && (pcrInfo.size != 0)) { + printf("TPM_Process_Seal: Creating PCR digest\n"); + /* assign the stream, so pcrInfo is not altered */ + stream = pcrInfo.buffer; + stream_size = pcrInfo.size; + /* a. if V1 is 1 then */ + if (v1PcrVersion == 1) { + /* i. Validate pcrInfo as a valid TPM_PCR_INFO structure, return TPM_BADINDEX on + error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRInfo_Load(&tpm_pcr_info, &stream, &stream_size); + if (returnCode != 0) { + returnCode = TPM_BADINDEX; + } + } + /* build the TPM_STORED_DATA S1 structure */ + if (returnCode == TPM_SUCCESS) { + /* ii. Set S1 -> sealInfo -> pcrSelection to pcrInfo -> pcrSelection */ + returnCode = TPM_PCRInfo_CreateFromBuffer(&(s1StoredData.tpm_seal_info), &pcrInfo); + } + /* iii. Create h1 the composite hash of the PCR selected by pcrInfo -> pcrSelection */ + /* iv. Set S1 -> sealInfo -> digestAtCreation to h1 */ + /* NOTE hash directly to destination. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_PCRSelection_GenerateDigest(s1StoredData.tpm_seal_info->digestAtCreation, + &(tpm_pcr_info.pcrSelection), + tpm_state->tpm_stclear_data.PCRS); + } + /* v. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */ + /* NOTE digestAtRelease copied during TPM_PCRInfo_CreateFromBuffer() */ + } + /* b. else (v1 is 2) */ + else { + /* i. Validate pcrInfo as a valid TPM_PCR_INFO_LONG structure, return TPM_BADINDEX + on error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRInfoLong_Load(&tpm_pcr_info_long, &stream, &stream_size); + if (returnCode != 0) { + returnCode = TPM_BADINDEX; + } + } + /* build the TPM_STORED_DATA S1 structure */ + if (returnCode == TPM_SUCCESS) { + /* ii. Set S1 -> sealInfo -> creationPCRSelection to pcrInfo -> creationPCRSelection + */ + /* iii. Set S1 -> sealInfo -> releasePCRSelection to pcrInfo -> releasePCRSelection + */ + /* iv. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */ + /* v. Set S1 -> sealInfo -> localityAtRelease to pcrInfo -> localityAtRelease */ + /* NOTE copied during TPM_PCRInfoLong_CreateFromBuffer() */ + returnCode = TPM_PCRInfoLong_CreateFromBuffer(&(s1_12->tpm_seal_info_long), + &pcrInfo); + } + if (returnCode == TPM_SUCCESS) { + /* vi. Create h2 the composite hash of the PCR selected by pcrInfo -> + creationPCRSelection */ + /* vii. Set S1 -> sealInfo -> digestAtCreation to h2 */ + /* NOTE hash directly to destination. */ + returnCode = + TPM_PCRSelection_GenerateDigest(s1_12->tpm_seal_info_long->digestAtCreation, + &(tpm_pcr_info_long.creationPCRSelection), + tpm_state->tpm_stclear_data.PCRS); + } + /* viii. Set S1 -> sealInfo -> localityAtCreation to TPM_STANY_FLAGS -> + localityModifier */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Locality_Set(&(s1_12->tpm_seal_info_long->localityAtCreation), + tpm_state->tpm_stany_flags.localityModifier); + } + } + } + /* 12. Create a1 by decrypting encAuth according to the ADIP indicated by authHandle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessionData_Decrypt(a1Auth, + NULL, + encAuth, + auth_session_data, + NULL, + NULL, + FALSE); /* even and odd */ + } + /* 13. The TPM provides NO validation of a1. Well-known values (like all zeros) are valid and + possible. */ + /* 14. Create S2 a TPM_SEALED_DATA structure */ + if (returnCode == TPM_SUCCESS) { + /* a. Set S2 -> payload to TPM_PT_SEAL */ + /* NOTE: Done at TPM_SealedData_Init() */ + /* b. Set S2 -> tpmProof to TPM_PERMANENT_DATA -> tpmProof */ + TPM_Secret_Copy(s2SealedData.tpmProof, tpm_state->tpm_permanent_data.tpmProof); + /* c. Create h3 the SHA-1 of S1 */ + /* d. Set S2 -> storedDigest to h3 */ + returnCode = TPM_StoredData_GenerateDigest(s2SealedData.storedDigest, + &s1StoredData, v1PcrVersion); + } + if (returnCode == TPM_SUCCESS) { + /* e. Set S2 -> authData to a1 */ + TPM_Secret_Copy(s2SealedData.authData, a1Auth); + /* f. Set S2 -> dataSize to inDataSize */ + /* g. Set S2 -> data to inData */ + returnCode = TPM_SizedBuffer_Copy(&(s2SealedData.data), &inData); + } + /* 15. Validate that the size of S2 can be encrypted by the key pointed to by keyHandle, return + TPM_BAD_DATASIZE on error */ + /* 16. Create s3 the encryption of S2 using the key pointed to by keyHandle */ + /* 17. Set continueAuthSession to FALSE */ + if (returnCode == TPM_SUCCESS) { + continueAuthSession = FALSE; + } + /* 18. Set S1 -> encDataSize to the size of s3 */ + /* 19. Set S1 -> encData to s3 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SealedData_GenerateEncData(&(s1StoredData.encData), &s2SealedData, key); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_Seal: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 20. Return S1 as sealedData */ + returnCode = TPM_StoredData_Store(response, &s1StoredData, v1PcrVersion); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&pcrInfo); /* @1 */ + TPM_SizedBuffer_Delete(&inData); /* @2 */ + TPM_StoredData_Delete(&s1StoredData, v1PcrVersion); /* @3 */ + TPM_PCRInfo_Delete(&tpm_pcr_info); /* @4 */ + TPM_PCRInfoLong_Delete(&tpm_pcr_info_long); /* @5 */ + TPM_SealedData_Delete(&s2SealedData); /* @6 */ + return rcf; +} + +/* 10.7 TPM_Sealx rev 110 + + The TPM_Sealx command works exactly like the TPM_Seal command with the additional requirement of + encryption for the inData parameter. This command also places in the sealed blob the information + that the TPM_Unseal also requires encryption. + + TPM_Sealx requires the use of 1.2 data structures. The actions are the same as TPM_Seal without + the checks for 1.1 data structure usage. +*/ + +TPM_RESULT TPM_Process_Sealx(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* Handle of a loaded key that can perform seal + operations. */ + TPM_ENCAUTH encAuth; /* The encrypted authorization data for the sealed data */ + TPM_SIZED_BUFFER pcrInfo; /* If 0 there are no PCR registers in use. pcrInfo MUST use + TPM_PCR_INFO_LONG */ + TPM_SIZED_BUFFER inData; /* The data to be sealed to the platform and any specified + PCRs */ + + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle + authorization. Must be an OSAP session for this command. + */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA pubAuth; /* The authorization digest for inputs and keyHandle. HMAC + key: key.usageAuth. */ + + /* processing */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_KEY *key = NULL; /* the key specified by keyHandle */ + TPM_SECRET *keyUsageAuth; + TPM_BOOL parentPCRStatus; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_STORED_DATA12 s1StoredData; /* Encrypted, integrity-protected data object that + is the result of the TPM_Seal operation. Returned + as SealedData */ + TPM_STORED_DATA *s1_11; /* 1.1 version to avoid casts */ + TPM_SEALED_DATA s2SealedData; + TPM_DIGEST a1Auth; + BYTE *o1DecryptedData; + + printf("TPM_Process_Sealx: Ordinal Entry\n"); + s1_11 = (TPM_STORED_DATA *)&s1StoredData; /* 1.1 version to avoid casts */ + TPM_SizedBuffer_Init(&pcrInfo); /* freed @1 */ + TPM_SizedBuffer_Init(&inData); /* freed @2 */ + TPM_StoredData_Init(s1_11, 2); /* freed @3 */ + TPM_SealedData_Init(&s2SealedData); /* freed @4 */ + o1DecryptedData = NULL; /* freed @5 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get encAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Load(encAuth, &command, ¶mSize); + } + /* get pcrInfo parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&pcrInfo, &command, ¶mSize); + } + /* get inData parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Sealx: Sealing %u bytes\n", inData.size); + TPM_PrintFourLimit("TPM_Process_Sealx: Sealing data", inData.buffer, inData.size); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + pubAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Sealx: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not r/o, using to encrypt */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get keyHandle -> usageAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); + } + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_KEYHANDLE, + ordinal, + key, + NULL, /* OIAP */ + key->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 1. Validate the authorization to use the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + pubAuth); /* Authorization digest for input */ + } + /* 2. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (inData.size == 0) { + printf("TPM_Process_Sealx: Error, inDataSize is 0\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 3. If the keyUsage field of the key indicated by keyHandle does not have the value + TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE. */ + if (returnCode == TPM_SUCCESS) { + if (key->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_Sealx: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n", + key->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. If the keyHandle points to a migratable key then the TPM MUST return the error code + TPM_INVALID_KEY_USAGE. */ + if (returnCode == TPM_SUCCESS) { + if (key->keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_Sealx: Error, key keyFlags %08x indicates migratable\n", + key->keyFlags); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 5. Create S1 a TPM_STORED_DATA12 structure */ + /* 6. Set S1 -> encDataSize to 0 */ + /* 7. Set S1 -> encData to all zeros */ + /* NOTE: Done by TPM_StoredData_Init() */ + /* 8. Set S1 -> sealInfoSize to pcrInfoSize */ + /* NOTE This step is unnecessary. If pcrInfoSize is 0, sealInfoSize is already initialized + to 0. If pcrInfoSize is non-zero, sealInfoSize is the result of serialization of the + tpm_seal_info member, which is a TPM_PCR_INFO_LONG */ + /* 9. If pcrInfoSize is not 0 then */ + if ((returnCode == TPM_SUCCESS) && (pcrInfo.size != 0)) { + printf("TPM_Process_Sealx: Setting sealInfo to pcrInfo\n"); + /* initializing the s -> TPM_PCR_INFO_LONG cache to the contents of pcrInfo */ + /* a. Validate pcrInfo as a valid TPM_PCR_INFO_LONG structure, return TPM_BADINDEX on + error */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRInfoLong_CreateFromBuffer(&(s1StoredData.tpm_seal_info_long), + &pcrInfo); + if (returnCode != TPM_SUCCESS) { + returnCode = TPM_BADINDEX; + } + } + /* b. Set S1 -> sealInfo -> creationPCRSelection to pcrInfo -> creationPCRSelection */ + /* c. Set S1 -> sealInfo -> releasePCRSelection to pcrInfo -> releasePCRSelection */ + /* d. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */ + /* e. Set S1 -> sealInfo -> localityAtRelease to pcrInfo -> localityAtRelease */ + /* NOTE copied during TPM_PCRInfoLong_CreateFromBuffer() */ + /* f. Create h2 the composite hash of the PCR selected by pcrInfo -> creationPCRSelection */ + /* g. Set S1 -> sealInfo -> digestAtCreation to h2 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_PCRSelection_GenerateDigest + (s1StoredData.tpm_seal_info_long->digestAtCreation, + &(s1StoredData.tpm_seal_info_long->creationPCRSelection), + tpm_state->tpm_stclear_data.PCRS); + } + /* h. Set S1 -> sealInfo -> localityAtCreation to TPM_STANY_DATA -> localityModifier */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Locality_Set(&(s1StoredData.tpm_seal_info_long->localityAtCreation), + tpm_state->tpm_stany_flags.localityModifier); + } + } + /* 10. Create S2 a TPM_SEALED_DATA structure */ + /* NOTE: Done at TPM_SealedData_Init() */ + /* 11.Create a1 by decrypting encAuth according to the ADIP indicated by authHandle. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Sealx: Decrypting encAuth\n"); + returnCode = TPM_AuthSessionData_Decrypt(a1Auth, /* a1 even */ + NULL, /* a1 odd (2nd encAuth) */ + encAuth, /* encAuthEven */ + auth_session_data, + NULL, /* nonceOdd */ + NULL, /* encAuthOdd */ + FALSE); /* even and odd */ + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_Sealx: Decrypted Auth", a1Auth); + /* a. If authHandle indicates XOR encryption for the AuthData secrets */ + if (auth_session_data->adipEncScheme == TPM_ET_XOR) { + /* i. Set S1 -> et to TPM_ET_XOR || TPM_ET_KEY */ + /* (1) TPM_ET_KEY is added because TPM_Unseal uses zero as a special value indicating no + encryption. */ + s1StoredData.et = TPM_ET_XOR | TPM_ET_KEY; + } + /* b. Else */ + else { + /* i. Set S1 -> et to algorithm indicated by authHandle */ + s1StoredData.et = auth_session_data->adipEncScheme << 8; + } + } + /* 12. The TPM provides NO validation of a1. Well-known values (like all zeros) are valid and + possible. */ + /* 13. If authHandle indicates XOR encryption */ + /* a. Use MGF1 to create string X2 of length inDataSize. The inputs to MGF1 are; + authLastNonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four concatenated + values form the Z value that is the seed for MFG1. */ + /* b. Create o1 by XOR of inData and x2 */ + /* 14. Else */ + /* a. Create o1 by decrypting inData using the algorithm indicated by authHandle */ + /* b. Key is from authHandle -> sharedSecret */ + /* c. CTR is SHA-1 of (authLastNonceEven || nonceOdd) */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Sealx: decrypting inData\n"); + returnCode = TPM_SealCryptCommon(&o1DecryptedData, /* freed by caller */ + auth_session_data->adipEncScheme, + &inData, + auth_session_data, + nonceOdd); + + } + /* 15. Create S2 a TPM_SEALED_DATA structure */ + if (returnCode == TPM_SUCCESS) { + /* a. Set S2 -> payload to TPM_PT_SEAL */ + /* NOTE: Done at TPM_SealedData_Init() */ + /* b. Set S2 -> tpmProof to TPM_PERMANENT_DATA -> tpmProof */ + TPM_Secret_Copy(s2SealedData.tpmProof, tpm_state->tpm_permanent_data.tpmProof); + /* c. Create h3 the SHA-1 of S1 */ + /* d. Set S2 -> storedDigest to h3 */ + returnCode = TPM_StoredData_GenerateDigest(s2SealedData.storedDigest, s1_11, 2); + } + /* e. Set S2 -> authData to a1 */ + if (returnCode == TPM_SUCCESS) { + TPM_Secret_Copy(s2SealedData.authData, a1Auth); + /* f. Set S2 -> dataSize to inDataSize */ + /* g. Set S2 -> data to o1 */ + returnCode = TPM_SizedBuffer_Set(&(s2SealedData.data), inData.size, o1DecryptedData); + } + /* 16. Validate that the size of S2 can be encrypted by the key pointed to by keyHandle, return + */ + /* TPM_BAD_DATASIZE on error */ + /* 17. Create s3 the encryption of S2 using the key pointed to by keyHandle */ + /* 18. Set continueAuthSession to FALSE */ + if (returnCode == TPM_SUCCESS) { + continueAuthSession = FALSE; + } + /* 19. Set S1 -> encDataSize to the size of s3 */ + /* 20. Set S1 -> encData to s3 */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Sealx: Encrypting sealed data\n"); + returnCode = TPM_SealedData_GenerateEncData(&(s1StoredData.encData), &s2SealedData, key); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_Sealx: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 21. Return S1 as sealedData */ + returnCode = TPM_StoredData_Store(response, s1_11, 2); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&pcrInfo); /* @1 */ + TPM_SizedBuffer_Delete(&inData); /* @2 */ + TPM_StoredData_Delete(s1_11, 2); /* @3 */ + TPM_SealedData_Delete(&s2SealedData); /* @4 */ + free(o1DecryptedData); /* @5 */ + return rcf; +} + +/* 10.2 TPM_Unseal rev 110 + + The TPM_Unseal operation will reveal TPM_Sealed data only if it was encrypted on this platform + and the current configuration (as defined by the named PCR contents) is the one named as + qualified to decrypt it. Internally, TPM_Unseal accepts a data blob generated by a TPM_Seal + operation. TPM_Unseal decrypts the structure internally, checks the integrity of the resulting + data, and checks that the PCR named has the value named during TPM_Seal. Additionally, the + caller must supply appropriate authorization data for blob and for the key that was used to seal + that data. + + If the integrity, platform configuration and authorization checks succeed, the sealed data is + returned to the caller; otherwise, an error is generated. +*/ + +TPM_RESULT TPM_Process_Unseal(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can unseal the data. */ + TPM_STORED_DATA inData; /* The encrypted data generated by TPM_Seal. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and + parentHandle. HMAC key: parentKey.usageAuth. */ + TPM_AUTHHANDLE dataAuthHandle; /* The authorization handle used to authorize inData. */ + TPM_NONCE datanonceOdd; /* Nonce generated by system associated with + entityAuthHandle */ + TPM_BOOL continueDataSession = TRUE; /* Continue usage flag for dataAuthHandle. */ + TPM_AUTHDATA dataAuth; /* The authorization digest for the encrypted entity. HMAC + key: entity.usageAuth. */ + + /* processing */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_BOOL dataAuthHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_AUTH_SESSION_DATA *data_auth_session_data = NULL; /* session data for dataAuthHandle + */ + TPM_SECRET *hmacKey; + TPM_SECRET *dataHmacKey; + unsigned int v1StoredDataVersion = 1; /* version of TPM_STORED_DATA + inData */ + TPM_KEY *parentKey; + TPM_BOOL parentPCRStatus; + TPM_SECRET *parentUsageAuth; + TPM_SEALED_DATA d1SealedData; + TPM_DIGEST h1StoredDataDigest; + TPM_STORED_DATA12 *s2StoredData; + BYTE *o1Encrypted; /* For ADIP encryption */ + TPM_ADIP_ENC_SCHEME adipEncScheme; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + uint32_t secretSize = 0; /* Decrypted data that had been sealed */ + BYTE *secret = NULL; + + printf("TPM_Process_Unseal: Ordinal Entry\n"); + TPM_StoredData_Init(&inData, v1StoredDataVersion); /* freed @1, default is v1 */ + TPM_SealedData_Init(&d1SealedData); /* freed @2 */ + o1Encrypted = NULL; /* freed @3 */ + s2StoredData = (TPM_STORED_DATA12 *)&inData; /* inData when it's a TPM_STORED_DATA12 + structure */ + /* + get inputs + */ + /* get parentHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get inData parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Unseal: parentHandle %08x\n", parentHandle); + returnCode = TPM_StoredData_Load(&inData, &v1StoredDataVersion, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Unseal: inData is v%u\n", v1StoredDataVersion); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag21(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + parentAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + printf("TPM_Process_Unseal: authHandle %08x\n", authHandle); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&dataAuthHandle, + &dataAuthHandleValid, + datanonceOdd, + &continueDataSession, + dataAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Unseal: dataAuthHandle %08x\n", dataAuthHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_Unseal: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + dataAuthHandleValid = FALSE; + } + /* + Processing + */ + /* Verify that parentHandle points to a valid key. Get the TPM_KEY associated with parentHandle + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* not r/o, using to decrypt */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get parentHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); + } + /* get the first session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + parentUsageAuth, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* 1. The TPM MUST validate that parentAuth authorizes the use of the key in parentHandle, on + error return TPM_AUTHFAIL */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + parentAuth); /* Authorization digest for input */ + } + /* if there are no parent auth parameters */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { + if (parentKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_Unseal: Error, parent key authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* 2. If the keyUsage field of the key indicated by parentHandle does not have the value + TPM_KEY_STORAGE, the TPM MUST return the error code TPM_INVALID_KEYUSAGE. */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_Unseal: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n", + parentKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. The TPM MUST check that the TPM_KEY_FLAGS -> Migratable flag has the value FALSE in the + key indicated by parentKeyHandle. If not, the TPM MUST return the error code + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_Unseal: Error, key keyFlags %08x indicates migratable\n", + parentKey->keyFlags); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. Determine the version of inData */ + /* a. If inData -> tag = TPM_TAG_STORED_DATA12 */ + /* i. Set V1 to 2 */ + /* ii. Map S2 a TPM_STORED_DATA12 structure to inData */ + /* b. Else If inData -> ver = 1.1 */ + /* i. Set V1 to 1 */ + /* ii. Map S2 a TPM_STORED_DATA structure to inData */ + /* c. Else */ + /* i. Return TPM_BAD_VERSION */ + /* NOTE: Done during TPM_StoredData_Load() */ + /* The extra indent of error checking is required because the next steps all return + TPM_NOTSEALED_BLOB on error */ + if (returnCode == TPM_SUCCESS) { + /* 5. Create d1 by decrypting S2 -> encData using the key pointed to by parentHandle */ + printf("TPM_Process_Unseal: Decrypting encData\n"); + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SealedData_DecryptEncData(&d1SealedData, /* TPM_SEALED_DATA */ + &(inData.encData), + parentKey); + } + /* 6. Validate d1 */ + /* a. d1 MUST be a TPM_SEALED_DATA structure */ + /* NOTE Done during TPM_SealedData_DecryptEncData() */ + /* b. d1 -> tpmProof MUST match TPM_PERMANENT_DATA -> tpmProof */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Unseal: Sealed data size %u\n", d1SealedData.data.size); + TPM_PrintFour("TPM_Process_Unseal: Sealed data", d1SealedData.data.buffer); + printf("TPM_Process_Unseal: Checking tpmProof\n"); + returnCode = TPM_Secret_Compare(d1SealedData.tpmProof, + tpm_state->tpm_permanent_data.tpmProof); + } + if (returnCode == TPM_SUCCESS) { + /* c. Set S2 -> encDataSize to 0 */ + /* d. Set S2 -> encData to all zeros */ + /* NOTE: This would be done at cleanup */ + TPM_SizedBuffer_Delete(&(inData.encData)); + /* e. Create h1 the SHA-1 of S2 */ + returnCode = TPM_StoredData_GenerateDigest(h1StoredDataDigest, + &inData, v1StoredDataVersion); + } + /* f. d1 -> storedDigest MUST match h1 */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Unseal: Checking storedDigest\n"); + returnCode = TPM_Digest_Compare(d1SealedData.storedDigest, h1StoredDataDigest); + } + /* g. d1 -> payload MUST be TPM_PT_SEAL */ + if (returnCode == TPM_SUCCESS) { + if (d1SealedData.payload != TPM_PT_SEAL) { + printf("TPM_Process_Unseal: Error, payload %02x not TPM_PT_SEAL\n", + d1SealedData.payload); + returnCode = TPM_NOTSEALED_BLOB; + } + } + /* h. Any failure MUST return TPM_NOTSEALED_BLOB */ + if (returnCode != TPM_SUCCESS) { + returnCode = TPM_NOTSEALED_BLOB; + } + } + /* 7. If S2 -> sealInfo is not 0 then */ + /* NOTE: Done by _CheckDigest() */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_Unseal: Checking PCR digest\n"); + /* a. If V1 is 1 then */ + if (v1StoredDataVersion == 1) { + /* i. Validate that S2 -> pcrInfo is a valid TPM_PCR_INFO structure */ + /* NOTE: Done during TPM_StoredData_Load() */ + /* ii. Create h2 the composite hash of the PCR selected by S2 -> pcrInfo -> pcrSelection + */ + /* c. Compare h2 with S2 -> pcrInfo -> digestAtRelease, on mismatch return + TPM_WRONGPCRVALUE */ + returnCode = TPM_PCRInfo_CheckDigest(inData.tpm_seal_info, + tpm_state->tpm_stclear_data.PCRS); /* PCR array */ + } + /* b. If V1 is 2 then */ + else { + /* i. Validate that S2 -> pcrInfo is a valid TPM_PCR_INFO_LONG structure */ + /* NOTE: Done during TPM_StoredData_Load() */ + /* ii. Create h2 the composite hash of the PCR selected by S2 -> pcrInfo -> + releasePCRSelection */ + /* iii. Check that S2 -> pcrInfo -> localityAtRelease for TPM_STANY_DATA -> + localityModifier is TRUE */ + /* (1) For example if TPM_STANY_DATA -> localityModifier was 2 then S2 -> pcrInfo -> + localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ + /* c. Compare h2 with S2 -> pcrInfo -> digestAtRelease, on mismatch return + TPM_WRONGPCRVALUE */ + returnCode = + TPM_PCRInfoLong_CheckDigest(s2StoredData->tpm_seal_info_long, + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + tpm_state->tpm_stany_flags.localityModifier); + } + } + /* 8. The TPM MUST validate authorization to use d1 by checking that the HMAC calculation + using d1 -> authData as the shared secret matches the dataAuth. Return TPM_AUTHFAIL on + mismatch. */ + /* get the second session data */ + /* NOTE: While OSAP isn't specifically excluded, there is currently no way to set up an OSAP + session using TPM_SEALED_DATA as the entity */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&data_auth_session_data, + &dataHmacKey, + tpm_state, + dataAuthHandle, + TPM_PID_OIAP, /* currently require OIAP */ + 0, /* OSAP entity type */ + ordinal, + NULL, + &(d1SealedData.authData), /* OIAP */ + NULL); /* OSAP */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Auth2data_Check(tpm_state, + *dataHmacKey, /* HMAC key */ + inParamDigest, + data_auth_session_data, /* authorization session */ + datanonceOdd, /* Nonce generated by system + associated with authHandle */ + continueDataSession, + dataAuth); /* Authorization digest for input */ + } + if (returnCode == TPM_SUCCESS) { + /* 9. If V1 is 2 and S2 -> et specifies encryption (i.e. is not all zeros) then */ + if ((v1StoredDataVersion == 2) && (s2StoredData->et != 0x0000)) { + /* a. If tag is not TPM_TAG_RQU_AUTH2_COMMAND, return TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + if (tag != TPM_TAG_RQU_AUTH2_COMMAND) { + printf("TPM_Process_Unseal: Error, sealed with encryption but auth-1\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* b. Verify that the authHandle session type is TPM_PID_OSAP or TPM_PID_DSAP, return + TPM_BAD_MODE on error. */ + if (returnCode == TPM_SUCCESS) { + if ((auth_session_data->protocolID != TPM_PID_OSAP) && + (auth_session_data->protocolID != TPM_PID_DSAP)) { + printf("TPM_Process_Unseal: Error, sealed with encryption but OIAP\n"); + returnCode = TPM_BAD_MODE; + } + } + /* c. If MSB of S2 -> et is TPM_ET_XOR */ + /* i. Use MGF1 to create string X1 of length sealedDataSize. The inputs to MGF1 are; + authLastnonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four + concatenated values form the Z value that is the seed for MFG1. */ + /* d. Else */ + /* i. Create o1 by encrypting d1 -> data using the algorithm indicated by inData -> + et */ + /* ii. Key is from authHandle -> sharedSecret */ + /* iii. IV is SHA-1 of (authLastNonceEven || nonceOdd) */ + if (returnCode == TPM_SUCCESS) { + /* entity type MSB is ADIP encScheme */ + adipEncScheme = (s2StoredData->et >> 8) & 0x00ff; + printf("TPM_Process_Unseal: Encrypting the output, encScheme %02x\n", + adipEncScheme); + returnCode = TPM_SealCryptCommon(&o1Encrypted, + adipEncScheme, + &(d1SealedData.data), + auth_session_data, + nonceOdd); + secretSize = d1SealedData.data.size; + secret = o1Encrypted; + } + /* e. Set continueAuthSession to FALSE */ + continueAuthSession = FALSE; + } + /* 10. else */ + else { + printf("TPM_Process_Unseal: No output encryption\n"); + /* a. Set o1 to d1 -> data */ + secretSize = d1SealedData.data.size; + secret = d1SealedData.data.buffer; + } + } + /* 11. Set the return secret as o1 */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_Unseal: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return secretSize */ + returnCode = TPM_Sbuffer_Append32(response, secretSize); + } + if (returnCode == TPM_SUCCESS) { + /* return secret */ + returnCode = TPM_Sbuffer_Append(response, secret, secretSize); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *dataHmacKey, /* HMAC key */ + data_auth_session_data, + outParamDigest, + datanonceOdd, + continueDataSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueDataSession) && + dataAuthHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, dataAuthHandle); + } + /* + cleanup + */ + TPM_StoredData_Delete(&inData, v1StoredDataVersion); /* @1 */ + TPM_SealedData_Delete(&d1SealedData); /* @2 */ + free(o1Encrypted); /* @3 */ + return rcf; +} + +/* 10.3 TPM_UnBind rev 87 + + TPM_UnBind takes the data blob that is the result of a Tspi_Data_Bind command and decrypts it + for export to the User. The caller must authorize the use of the key that will decrypt the + incoming blob. + + UnBind operates on a block-by-block basis, and has no notion of any relation between one block + and another. + + UnBind SHALL operate on a single block only. +*/ + +TPM_RESULT TPM_Process_UnBind(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform + UnBind operations. */ + TPM_SIZED_BUFFER inData; /* Encrypted blob to be decrypted */ + TPM_AUTHHANDLE authHandle; /* The handle used for keyHandle authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA privAuth; /* The authorization digest that authorizes the inputs and + use of keyHandle. HMAC key: key.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_KEY *key = NULL; /* the key specified by keyHandle */ + TPM_SECRET *keyUsageAuth; + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; /* for key */ + TPM_BOOL parentPCRStatus; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + uint32_t decrypt_data_size; /* resulting decrypted data size */ + BYTE *decrypt_data = NULL; /* The resulting decrypted data. */ + unsigned char *stream; + uint32_t stream_size; + TPM_BOUND_DATA tpm_bound_data; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + size_t outDataSize = 0; /* The length of the returned decrypted data */ + BYTE *outData = NULL; /* The resulting decrypted data. */ + + printf("TPM_Process_UnBind: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&inData); /* freed @1 */ + TPM_BoundData_Init(&tpm_bound_data); /* freed @3 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get areaToSignSize and areaToSign parameters */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_UnBind: keyHandle %08x\n", keyHandle); + returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_UnBind: UnBinding %u bytes\n", inData.size); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_UnBind: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* 1. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (inData.size == 0) { + printf("TPM_Process_UnBind: Error, inDataSize is 0\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ + if (key->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_UnBind: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + key, + keyUsageAuth, /* OIAP */ + key->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 2. Validate the authorization to use the key pointed to by keyHandle */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + /* 3. If the keyUsage field of the key referenced by keyHandle does not have the value + TPM_KEY_BIND or TPM_KEY_LEGACY, the TPM must return the error code TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if ((key->keyUsage != TPM_KEY_BIND) && (key->keyUsage != TPM_KEY_LEGACY)) { + printf("TPM_Process_UnBind: Error, invalid keyUsage %04hx\n", (key->keyUsage)); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* Get the TPM_RSA_KEY_PARMS associated with key */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, &(key->algorithmParms)); + } + /* 4. Decrypt the inData using the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_RSAPrivateDecryptMalloc(&decrypt_data, /* decrypted data, freed @2 */ + &decrypt_data_size, /* actual size of decrypted data + data */ + inData.buffer, + inData.size, + key); + } + if (returnCode == TPM_SUCCESS) { + /* 5. if (keyHandle -> encScheme does not equal TPM_ES_RSAESOAEP_SHA1_MGF1) and (keyHandle + -> keyUsage equals TPM_KEY_LEGACY), */ + if ((key->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) && + (key->keyUsage == TPM_KEY_LEGACY)) { + printf("TPM_Process_UnBind: Legacy key\n"); + /* a. The payload does not have TPM specific markers to validate, so no consistency + check can be performed. */ + /* b. Set the output parameter outData to the value of the decrypted value of + inData. (Padding associated with the encryption wrapping of inData SHALL NOT be + returned.) */ + outData = decrypt_data; + /* c. Set the output parameter outDataSize to the size of outData, as deduced from the + decryption process. */ + outDataSize = decrypt_data_size; + } + /* 6. else */ + else { + printf("TPM_Process_UnBind: Payload is TPM_BOUND_DATA structure\n"); + /* a. Interpret the decrypted data under the assumption that it is a TPM_BOUND_DATA + structure, and validate that the payload type is TPM_PT_BIND */ + if (returnCode == TPM_SUCCESS) { + stream = decrypt_data; + stream_size = decrypt_data_size; + returnCode = TPM_BoundData_Load(&tpm_bound_data, + &stream, + &stream_size); + } + if (returnCode == TPM_SUCCESS) { + if (tpm_bound_data.payload != TPM_PT_BIND) { + printf("TPM_Process_UnBind: Error, " + "TPM_BOUND_DATA->payload %02x not TPM_PT_BIND\n", + tpm_bound_data.payload); + returnCode = TPM_INVALID_STRUCTURE; + } + } + /* b. Set the output parameter outData to the value of TPM_BOUND_DATA -> + payloadData. (Other parameters of TPM_BOUND_DATA SHALL NOT be returned. Padding + associated with the encryption wrapping of inData SHALL NOT be returned.) */ + if (returnCode == TPM_SUCCESS) { + outData = tpm_bound_data.payloadData; + /* c. Set the output parameter outDataSize to the size of outData, as deduced from + the decryption process and the interpretation of TPM_BOUND_DATA. */ + outDataSize = tpm_bound_data.payloadDataSize; + } + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_UnBind: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 10. Return the computed outData */ + /* append outDataSize */ + returnCode = TPM_Sbuffer_Append32(response, outDataSize); + } + if (returnCode == TPM_SUCCESS) { + /* append outData */ + returnCode = TPM_Sbuffer_Append(response, outData, outDataSize); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&inData); /* @1 */ + free(decrypt_data); /* @2 */ + TPM_BoundData_Delete(&tpm_bound_data); /* @3 */ + return rcf; +} + +/* 10.4 TPM_CreateWrapKey rev 114 + + The TPM_CreateWrapKey command both generates and creates a secure storage bundle for asymmetric + keys. + + The newly created key can be locked to a specific PCR value by specifying a set of PCR registers. +*/ + +TPM_RESULT TPM_Process_CreateWrapKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can perform key wrapping. */ + TPM_ENCAUTH dataUsageAuth; /* Encrypted usage authorization data for the key. */ + TPM_ENCAUTH dataMigrationAuth; /* Encrypted migration authorization data for the + key.*/ + TPM_KEY keyInfo; /* Information about key to be created, pubkey.keyLength and + keyInfo.encData elements are 0. MAY be TPM_KEY12 */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for parent key + authorization. Must be an OSAP session. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA pubAuth; /* The authorization digest that authorizes the use of the + public key in parentHandle. HMAC key: + parentKey.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_KEY *parentKey = NULL; /* the key specified by parentHandle */ + TPM_BOOL parentPCRStatus; + TPM_RSA_KEY_PARMS *keyInfoRSAParms = NULL; /* substructure of keyInfo */ + TPM_SECRET du1UsageAuth; + TPM_SECRET dm1MigrationAuth; + TPM_STORE_ASYMKEY *wrappedStoreAsymkey; /* substructure of wrappedKey */ + TPM_PCR_INFO wrappedPCRInfo; + int ver; /* TPM_KEY or TPM_KEY12 */ + + /* output parameters */ + TPM_KEY wrappedKey; /* The TPM_KEY structure which includes the public and + encrypted private key. MAY be TPM_KEY12 */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_CreateWrapKey: Ordinal Entry\n"); + TPM_Key_Init(&keyInfo); + TPM_Key_Init(&wrappedKey); + TPM_PCRInfo_Init(&wrappedPCRInfo); + /* + get inputs + */ + /* get parentHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get dataUsageAuth parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateWrapKey: parentHandle %08x\n", parentHandle); + returnCode = TPM_Authdata_Load(dataUsageAuth, &command, ¶mSize); + } + /* get dataMigrationAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Authdata_Load(dataMigrationAuth, &command, ¶mSize); + } + /* get keyInfo parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_Load(&keyInfo, &command, ¶mSize); /* freed @1 */ + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + pubAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_CreateWrapKey: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the parentHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, + parentHandle, + FALSE, /* not r/o, using to encrypt w/public key */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* get the session data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OSAP, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + NULL, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ + } + /* 1. Validate the authorization to use the key pointed to by parentHandle. Return TPM_AUTHFAIL + on any error. */ + /* 2. Validate the session type for parentHandle is OSAP. */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_CreateWrapKey: sharedSecret", auth_session_data->sharedSecret); + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle + */ + continueAuthSession, + pubAuth); /* Authorization digest for input */ + } + /* 3. If the TPM is not designed to create a key of the type requested in keyInfo, return the + error code TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateWrapKey: Checking key properties\n"); + returnCode = TPM_Key_CheckProperties(&ver, &keyInfo, 0, + tpm_state->tpm_permanent_flags.FIPS); + } + /* Get the TPM_RSA_KEY_PARMS associated with keyInfo */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateWrapKey: key parameters v = %d\n", ver); + returnCode = TPM_KeyParms_GetRSAKeyParms(&keyInfoRSAParms, &(keyInfo.algorithmParms)); + } + /* 4. Verify that parentHandle->keyUsage equals TPM_KEY_STORAGE */ + if (returnCode == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_CreateWrapKey: Error, parent keyUsage not TPM_KEY_STORAGE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 5. If parentHandle -> keyFlags -> migratable is TRUE and keyInfo -> keyFlags -> migratable is + FALSE then return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if ((parentKey->keyFlags & TPM_MIGRATABLE) && !(keyInfo.keyFlags & TPM_MIGRATABLE)) { + printf("TPM_Process_CreateWrapKey: Error, parent not migratable\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 6. Validate key parameters */ + /* a. keyInfo -> keyUsage MUST NOT be TPM_KEY_IDENTITY or TPM_KEY_AUTHCHANGE. If it is, return + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if ((keyInfo.keyUsage == TPM_KEY_IDENTITY) || + (keyInfo.keyUsage == TPM_KEY_AUTHCHANGE)) { + printf("TPM_Process_CreateWrapKey: Error, Invalid key usage %04x\n", + keyInfo.keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* b. If keyInfo -> keyFlags -> migrateAuthority is TRUE then return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (keyInfo.keyFlags & TPM_MIGRATEAUTHORITY) { + printf("TPM_Process_CreateWrapKey: Error, Invalid key flags %08x\n", + keyInfo.keyFlags); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 7. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then + a. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS + b. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS + c. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return TPM_NOTFIPS + NOTE Done in step 3 TPM_Key_CheckProperties() + */ + /* 8. If keyInfo -> keyUsage equals TPM_KEY_STORAGE or TPM_KEY_MIGRATE + i. algorithmID MUST be TPM_ALG_RSA + ii. encScheme MUST be TPM_ES_RSAESOAEP_SHA1_MGF1 + iii. sigScheme MUST be TPM_SS_NONE + iv. key size MUST be 2048 + v. exponentSize MUST be 0 + NOTE Done in step 3 TPM_Key_CheckProperties() + */ + /* 9. Determine the version of key + a.If keyInfo -> ver is 1.1 + i. Set V1 to 1 + ii. Map wrappedKey to a TPM_KEY structure + iii. Validate all remaining TPM_KEY structures + b. Else if keyInfo -> tag is TPM_TAG_KEY12 + i. Set V1 to 2 + ii. Map wrappedKey to a TPM_KEY12 structure + iii. Validate all remaining TPM_KEY12 structures + NOTE Check done by TPM_Key_CheckProperties() + NOTE Map done by TPM_Key_GenerateRSA() + */ + /* 10..Create DU1 by decrypting dataUsageAuth according to the ADIP indicated by authHandle */ + /* 11. Create DM1 by decrypting dataMigrationAuth according to the ADIP indicated by + authHandle */ + if (returnCode == TPM_SUCCESS) { + TPM_AuthSessionData_Decrypt(du1UsageAuth, + dm1MigrationAuth, + dataUsageAuth, /* even encAuth */ + auth_session_data, + nonceOdd, + dataMigrationAuth, /* odd encAuth */ + TRUE); + } + /* 12. Set continueAuthSession to FALSE */ + if (returnCode == TPM_SUCCESS) { + continueAuthSession = FALSE; + } + /* 13. Generate asymmetric key according to algorithm information in keyInfo */ + /* 14. Fill in the wrappedKey structure with information from the newly generated key. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_CreateWrapKey: Generating key\n"); + returnCode = TPM_Key_GenerateRSA(&wrappedKey, + tpm_state, + parentKey, + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + ver, + keyInfo.keyUsage, + keyInfo.keyFlags, + keyInfo.authDataUsage, /* TPM_AUTH_DATA_USAGE */ + &(keyInfo.algorithmParms), /* TPM_KEY_PARMS */ + keyInfo.tpm_pcr_info, /* TPM_PCR_INFO */ + keyInfo.tpm_pcr_info_long); /* TPM_PCR_INFO_LONG */ + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GetStoreAsymkey(&wrappedStoreAsymkey, + &wrappedKey); + } + if (returnCode == TPM_SUCCESS) { + /* a. Set wrappedKey -> encData -> usageAuth to DU1 */ + TPM_Secret_Copy(wrappedStoreAsymkey->usageAuth, du1UsageAuth); + /* b. If the KeyFlags -> migratable bit is set to 1, the wrappedKey -> encData -> + migrationAuth SHALL contain the decrypted value from dataMigrationAuth. */ + if (wrappedKey.keyFlags & TPM_MIGRATABLE) { + TPM_Secret_Copy(wrappedStoreAsymkey->migrationAuth, dm1MigrationAuth); + } + /* c. If the KeyFlags -> migratable bit is set to 0, the wrappedKey -> encData -> + migrationAuth SHALL be set to the value tpmProof */ + else { + TPM_Secret_Copy(wrappedStoreAsymkey->migrationAuth, + tpm_state->tpm_permanent_data.tpmProof); + } + printf("TPM_Process_CreateWrapKey: wrappedKey.PCRInfoSize %d\n", wrappedKey.pcrInfo.size); + } + /* 15. If keyInfo->PCRInfoSize is non-zero. */ + /* a. If V1 is 1 */ + /* i. Set wrappedKey -> pcrInfo to a TPM_PCR_INFO structure using the pcrSelection to + indicate the PCR's in use */ + /* b. Else */ + /* i. Set wrappedKey -> pcrInfo to a TPM_PCR_INFO_LONG structure */ + /* c. Set wrappedKey -> pcrInfo to keyInfo -> pcrInfo */ + /* d. Set wrappedKey -> digestAtCreation to the TPM_COMPOSITE_HASH indicated by + creationPCRSelection */ + /* e. If V1 is 2 set wrappedKey -> localityAtCreation to TPM_STANY_DATA -> locality */ + /* NOTE Done by TPM_Key_GenerateRSA() */ + /* 16. Encrypt the private portions of the wrappedKey structure using the key in parentHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_GenerateEncData(&wrappedKey, parentKey); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_CreateWrapKey: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 17. Return the newly generated key in the wrappedKey parameter */ + returnCode = TPM_Key_Store(response, &wrappedKey); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* cleanup */ + TPM_Key_Delete(&keyInfo); /* @1 */ + TPM_Key_Delete(&wrappedKey); /* @2 */ + TPM_PCRInfo_Delete(&wrappedPCRInfo); /* @3 */ + return rcf; +} + +/* 27.8 TPM_LoadKey rev 114 + + Version 1.2 deprecates LoadKey due to the HMAC of the new keyhandle on return. The wrapping makes + use of the handle difficult in an environment where the TSS, or other management entity, is + changing the TPM handle to a virtual handle. + + Software using loadKey on a 1.2 TPM can have a collision with the returned handle as the 1.2 TPM + uses random values in the lower three bytes of the handle. All new software must use LoadKey2 to + allow management software the ability to manage the key handle. + + Before the TPM can use a key to either wrap, unwrap, bind, unbind, seal, unseal, sign or perform + any other action, it needs to be present in the TPM. The TPM_LoadKey function loads the key into + the TPM for further use. +*/ + +TPM_RESULT TPM_Process_LoadKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* TPM handle of parent key. */ + TPM_KEY *inKey; /* Incoming key structure, both encrypted private and clear + public portions. MAY be TPM_KEY12 */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle + authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = FALSE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and + parentHandle. HMAC key: parentKey.usageAuth. */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_BOOL key_added = FALSE; /* key has been added to handle list */ + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_KEY_HANDLE inKeyHandle; /* Internal TPM handle where decrypted key was loaded. */ + + printf("TPM_Process_LoadKey: Ordinal Entry\n"); + inKey = NULL; /* freed @1 */ + /* + get inputs + */ + /* get parentHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* Allocate space for inKey. The key cannot be a local variable, since it persists in key + storage after the command completes. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKey: parentHandle %08x\n", parentHandle); + returnCode = TPM_Malloc((unsigned char **)&inKey, sizeof(TPM_KEY)); /* freed @1 */ + } + /* get inKey parameter */ + if (returnCode == TPM_SUCCESS) { + TPM_Key_Init(inKey); /* freed @2 */ + returnCode = TPM_Key_Load(inKey, &command, ¶mSize); /* freed @2 */ + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_LoadKey: inKey n", inKey->pubKey.buffer); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + parentAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_LoadKey: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadKeyCommon(&inKeyHandle, /* output */ + &key_added, /* output */ + &hmacKey, /* output */ + &auth_session_data, /* output */ + tpm_state, + tag, + ordinal, + parentHandle, + inKey, + inParamDigest, + authHandle, /*uninitialized*/ + nonceOdd, + continueAuthSession, + parentAuth); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_LoadKey: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return the key handle */ + returnCode = TPM_Sbuffer_Append32(response, inKeyHandle); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + /* if there was a failure, delete inKey */ + if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { + TPM_Key_Delete(inKey); /* @2 */ + free(inKey); /* @1 */ + if (key_added) { + /* if there was a failure and inKey was stored in the handle list, free the handle. + Ignore errors, since only one error code can be returned. */ + TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, inKeyHandle); + } + } + return rcf; +} + +/* 10.5 TPM_LoadKey2 rev 107 + + Before the TPM can use a key to either wrap, unwrap, unbind, seal, unseal, sign or perform any + other action, it needs to be present in the TPM. The TPM_LoadKey2 function loads the key into + the TPM for further use. + + The TPM assigns the key handle. The TPM always locates a loaded key by use of the handle. The + assumption is that the handle may change due to key management operations. It is the + responsibility of upper level software to maintain the mapping between handle and any label used + by external software. + + This command has the responsibility of enforcing restrictions on the use of keys. For example, + when attempting to load a STORAGE key it will be checked for the restrictions on a storage key + (2048 size etc.). + + The load command must maintain a record of whether any previous key in the key hierarchy was + bound to a PCR using parentPCRStatus. + + The flag parentPCRStatus enables the possibility of checking that a platform passed through some + particular state or states before finishing in the current state. A grandparent key could be + linked to state-1, a parent key could linked to state-2, and a child key could be linked to + state-3, for example. The use of the child key then indicates that the platform passed through + states 1 and 2 and is currently in state 3, in this example. TPM_Startup with stType == + TPM_ST_CLEAR indicates that the platform has been reset, so the platform has not passed through + the previous states. Hence keys with parentPCRStatus==TRUE must be unloaded if TPM_Startup is + issued with stType == TPM_ST_CLEAR. + + If a TPM_KEY structure has been decrypted AND the integrity test using "pubDataDigest" has passed + AND the key is non-migratory, the key must have been created by the TPM. So there is every reason + to believe that the key poses no security threat to the TPM. While there is no known attack from + a rogue migratory key, there is a desire to verify that a loaded migratory key is a real key, + arising from a general sense of unease about execution of arbitrary data as a key. Ideally a + consistency check would consist of an encrypt/decrypt cycle, but this may be expensive. For RSA + keys, it is therefore suggested that the consistency test consists of dividing the supposed RSA + product by the supposed RSA prime, and checking that there is no remainder. +*/ + +TPM_RESULT TPM_Process_LoadKey2(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE parentHandle; /* TPM handle of parent key. */ + TPM_KEY *inKey; /* Incoming key structure, both encrypted private and clear + public portions. MAY be TPM_KEY12 */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle + authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = FALSE; /* The continue use flag for the authorization + handle */ + TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and + parentHandle. HMAC key: parentKey.usageAuth. */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_BOOL key_added = FALSE; /* key has been added to handle list */ + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_KEY_HANDLE inKeyHandle; /* Internal TPM handle where decrypted key was loaded. */ + + printf("TPM_Process_LoadKey2: Ordinal Entry\n"); + inKey = NULL; /* freed @1 */ + /* + get inputs + */ + /* get parentHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* Allocate space for inKey. The key cannot be a local variable, since it persists in key + storage after the command completes. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_LoadKey2: parentHandle %08x\n", parentHandle); + returnCode = TPM_Malloc((unsigned char **)&inKey, sizeof(TPM_KEY)); /* freed @1 */ + } + /* get inKey parameter */ + if (returnCode == TPM_SUCCESS) { + TPM_Key_Init(inKey); /* freed @2 */ + returnCode = TPM_Key_Load(inKey, &command, ¶mSize); /* freed @2 */ + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_LoadKey2: inKey n", inKey->pubKey.buffer); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + parentAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_LoadKey2: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_LoadKeyCommon(&inKeyHandle, /* output */ + &key_added, /* output */ + &hmacKey, /* output */ + &auth_session_data, /* output */ + tpm_state, + tag, + ordinal, + parentHandle, + inKey, + inParamDigest, + authHandle, /* uninitialized */ + nonceOdd, + continueAuthSession, + parentAuth); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_LoadKey2: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + /* In TPM_LoadKey2, the inKeyHandle is not part of the output HMAC */ + /* return the key handle */ + returnCode = TPM_Sbuffer_Append32(response, inKeyHandle); + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + /* if there was a failure, delete inKey */ + if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { + TPM_Key_Delete(inKey); /* @2 */ + free(inKey); /* @1 */ + if (key_added) { + /* if there was a failure and inKey was stored in the handle list, free the handle. + Ignore errors, since only one error code can be returned. */ + TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, inKeyHandle); + } + } + return rcf; +} + +/* TPM_LoadKeyCommon rev 114 + + Code common to TPM_LoadKey and TPM_LoadKey2. They differ only in whether the key handle is + included in the response HMAC calculation. +*/ + +static TPM_RESULT TPM_LoadKeyCommon(TPM_KEY_HANDLE *inKeyHandle, /* output */ + TPM_BOOL *key_added, /* output */ + TPM_SECRET **hmacKey, /* output */ + TPM_AUTH_SESSION_DATA **auth_session_data, /* output */ + tpm_state_t *tpm_state, + TPM_TAG tag, + TPM_COMMAND_CODE ordinal, + TPM_KEY_HANDLE parentHandle, + TPM_KEY *inKey, + TPM_DIGEST inParamDigest, + TPM_AUTHHANDLE authHandle, + TPM_NONCE nonceOdd, + TPM_BOOL continueAuthSession, + TPM_AUTHDATA parentAuth) +{ + TPM_RESULT rc = 0; + TPM_KEY *parentKey; /* the key specified by parentHandle */ + TPM_SECRET *parentUsageAuth; + TPM_BOOL parentPCRStatus; + TPM_BOOL parentPCRUsage; + int ver; + + printf("TPM_LoadKeyCommon:\n"); + *key_added = FALSE; /* key has been added to handle list */ + /* Verify that parentHandle points to a valid key. Get the TPM_KEY associated with parentHandle + */ + if (rc == TPM_SUCCESS) { + rc = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, + tpm_state, parentHandle, + FALSE, /* not r/o, using to decrypt */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* check TPM_AUTH_DATA_USAGE authDataUsage */ + if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (parentKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_LoadKeyCommon: Error, authorization required\n"); + rc = TPM_AUTHFAIL; + } + } + /* get parentHandle -> usageAuth */ + if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + rc = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); + } + /* get the session data */ + if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + rc = TPM_AuthSessions_GetData(auth_session_data, + hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + parentKey, + parentUsageAuth, /* OIAP */ + parentKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 1. Validate the command and the parameters using parentAuth and parentHandle -> usageAuth */ + if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + rc = TPM_Authdata_Check(tpm_state, + **hmacKey, /* HMAC key */ + inParamDigest, + *auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + parentAuth); /* Authorization digest for input */ + } + /* 2. If parentHandle -> keyUsage is NOT TPM_KEY_STORAGE return TPM_INVALID_KEYUSAGE */ + if (rc == TPM_SUCCESS) { + if (parentKey->keyUsage != TPM_KEY_STORAGE) { + printf("TPM_LoadKeyCommon: Error, " + "parentHandle -> keyUsage should be TPM_KEY_STORAGE, is %04x\n", + parentKey->keyUsage); + rc = TPM_INVALID_KEYUSAGE; + } + } + /* 3. If the TPM is not designed to operate on a key of the type specified by inKey, return the + error code TPM_BAD_KEY_PROPERTY. */ + if (rc == TPM_SUCCESS) { + rc = TPM_Key_CheckProperties(&ver, inKey, 0, tpm_state->tpm_permanent_flags.FIPS); + printf("TPM_LoadKeyCommon: key parameters v = %d\n", ver); + } + /* 4. The TPM MUST handle both TPM_KEY and TPM_KEY12 structures. + This step is done at TPM_Key_Load() + */ + /* 5. Decrypt the inKey -> privkey to obtain TPM_STORE_ASYMKEY structure using the key in + parentHandle. + */ + if (rc == TPM_SUCCESS) { + rc = TPM_Key_DecryptEncData(inKey, parentKey); + } + /* 6. Validate the integrity of inKey and decrypted TPM_STORE_ASYMKEY + a. Reproduce inKey -> TPM_STORE_ASYMKEY -> pubDataDigest using the fields of inKey, and check + that the reproduced value is the same as pubDataDigest + */ + if (rc == TPM_SUCCESS) { + rc = TPM_Key_CheckPubDataDigest(inKey); + } + /* 7. Validate the consistency of the key and it's key usage. */ + /* a. If inKey -> keyFlags -> migratable is TRUE, the TPM SHALL verify consistency of the public + and private components of the asymmetric key pair. If inKey -> keyFlags -> migratable is + FALSE, the TPM MAY verify consistency of the public and private components of the asymmetric + key pair. The consistency of an RSA key pair MAY be verified by dividing the supposed (P*Q) + product by a supposed prime and checking that there is no remainder. + + This step is done at TPM_Key_Load() + */ + /* b. If inKey -> keyUsage is TPM_KEY_IDENTITY, verify that inKey->keyFlags->migratable is + FALSE. If it is not, return TPM_INVALID_KEYUSAGE + */ + if (rc == TPM_SUCCESS) { + if ((inKey->keyUsage == TPM_KEY_IDENTITY) && + (inKey->keyFlags & TPM_MIGRATABLE)) { + printf("TPM_LoadKeyCommon: Error, identity key is migratable\n"); + rc = TPM_INVALID_KEYUSAGE; + } + } + /* c. If inKey -> keyUsage is TPM_KEY_AUTHCHANGE, return TPM_INVALID_KEYUSAGE */ + if (rc == TPM_SUCCESS) { + if (inKey->keyUsage == TPM_KEY_AUTHCHANGE) { + printf("TPM_LoadKeyCommon: Error, keyUsage is TPM_KEY_AUTHCHANGE\n"); + rc = TPM_INVALID_KEYUSAGE; + } + } + /* d. If inKey -> keyFlags -> migratable equals 0 then verify that TPM_STORE_ASYMKEY -> + migrationAuth equals TPM_PERMANENT_DATA -> tpmProof */ + if (rc == TPM_SUCCESS) { + if (!(inKey->keyFlags & TPM_MIGRATABLE)) { + rc = TPM_Secret_Compare(tpm_state->tpm_permanent_data.tpmProof, + inKey->tpm_store_asymkey->migrationAuth); + if (rc != 0) { + printf("TPM_LoadKeyCommon: Error, tpmProof mismatch\n"); + rc = TPM_INVALID_KEYUSAGE; + } + } + } + /* e. Validate the mix of encryption and signature schemes + f. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then + i. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS + ii. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return + TPM_NOTFIPS + iii. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return + TPM_NOTFIPS + g. If inKey -> keyUsage is TPM_KEY_STORAGE or TPM_KEY_MIGRATE + i. algorithmID MUST be TPM_ALG_RSA + ii. Key size MUST be 2048 + iii. exponentSize MUST be 0 + iv. sigScheme MUST be TPM_SS_NONE + h. If inKey -> keyUsage is TPM_KEY_IDENTITY + i. algorithmID MUST be TPM_ALG_RSA + ii. Key size MUST be 2048 + iv. exponentSize MUST be 0 + iii. encScheme MUST be TPM_ES_NONE + NOTE Done in step 3. + */ + if (rc == TPM_SUCCESS) { + /* i. If the decrypted inKey -> pcrInfo is NULL, */ + /* i. The TPM MUST set the internal indicator to indicate that the key is not using any PCR + registers. */ + /* j. Else */ + /* i. The TPM MUST store pcrInfo in a manner that allows the TPM to calculate a composite + hash whenever the key will be in use */ + /* ii. The TPM MUST handle both version 1.1 TPM_PCR_INFO and 1.2 TPM_PCR_INFO_LONG + structures according to the type of TPM_KEY structure */ + /* (1) The TPM MUST validate the TPM_PCR_INFO or TPM_PCR_INFO_LONG structures for legal + values. However, the digestAtRelease and localityAtRelease are not validated for + authorization until use time.*/ + /* NOTE TPM_Key_Load() loads the TPM_PCR_INFO or TPM_PCR_INFO_LONG cache */ + } + /* 8. Perform any processing necessary to make TPM_STORE_ASYMKEY key available for + operations. */ + /* NOTE Done at TPM_Key_Load() */ + /* 9. Load key and key information into internal memory of the TPM. If insufficient memory + exists return error TPM_NOSPACE. */ + /* 10. Assign inKeyHandle according to internal TPM rules. */ + /* 11. Set InKeyHandle -> parentPCRStatus to parentHandle -> parentPCRStatus. */ + if (rc == TPM_SUCCESS) { + *inKeyHandle = 0; /* no preferred value */ + rc = TPM_KeyHandleEntries_AddKeyEntry(inKeyHandle, /* output */ + tpm_state->tpm_key_handle_entries, /* input */ + inKey, /* input */ + parentPCRStatus, + 0); /* keyControl */ + } + if (rc == TPM_SUCCESS) { + printf(" TPM_LoadKeyCommon: Loaded key handle %08x\n", *inKeyHandle); + /* remember that the handle has been added to handle list, so it can be deleted on error */ + *key_added = TRUE; + + } + /* 12. If parentHandle indicates it is using PCR registers then set inKeyHandle -> + parentPCRStatus to TRUE. */ + if (rc == TPM_SUCCESS) { + rc = TPM_Key_GetPCRUsage(&parentPCRUsage, parentKey, 0); + } + if (rc == TPM_SUCCESS) { + if (parentPCRUsage) { + rc = TPM_KeyHandleEntries_SetParentPCRStatus(tpm_state->tpm_key_handle_entries, + *inKeyHandle, TRUE); + } + } + return rc; +} + +/* 10.6 TPM_GetPubKey rev 102 + + The owner of a key may wish to obtain the public key value from a loaded key. This information + may have privacy concerns so the command must have authorization from the key owner. +*/ + +TPM_RESULT TPM_Process_GetPubKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* TPM handle of key. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle + authorization. */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /*The continue use flag for the authorization + handle */ + TPM_AUTHDATA keyAuth; /* Authorization HMAC key: key.usageAuth. */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_SECRET *hmacKey; + TPM_KEY *key = NULL; /* the key specified by keyHandle */ + TPM_BOOL parentPCRStatus; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_SECRET *keyUsageAuth; + TPM_STORE_BUFFER pubkeyStream; + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + const unsigned char *pubkeyStreamBuffer; /* output */ + uint32_t pubkeyStreamLength; + + printf("TPM_Process_GetPubKey: Ordinal Entry\n"); + TPM_Sbuffer_Init(&pubkeyStream); /* freed @1 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetPubKey: keyHandle %08x\n", keyHandle); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + keyAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetPubKey: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_GetPubKey: Key handle %08x\n", keyHandle); + returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, + TRUE, /* read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* 1. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */ + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + key, + keyUsageAuth, /* OIAP */ + key->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + + + /* a. Validate the command parameters using keyHandle -> usageAuth, on error return + TPM_AUTHFAIL */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + keyAuth); /* Authorization digest for input */ + } + /* 2. Else */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ + /* a. Verify that keyHandle -> authDataUsage is TPM_NO_READ_PUBKEY_AUTH or TPM_AUTH_NEVER, + on error return TPM_AUTHFAIL */ +#ifdef TPM_V12 + if ((key->authDataUsage != TPM_NO_READ_PUBKEY_AUTH) && + (key->authDataUsage != TPM_AUTH_NEVER)) { + printf("TPM_Process_GetPubKey: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } +#else /* TPM 1.1 does not have TPM_NO_READ_PUBKEY_AUTH */ + if (key->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_GetPubKey: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } +#endif + } +#ifdef TPM_V12 /* TPM 1.1 does not have readSRKPub */ + if (returnCode == TPM_SUCCESS) { + /* 3. If keyHandle == TPM_KH_SRK then */ + if ((keyHandle == TPM_KH_SRK) && + /* a. If TPM_PERMANENT_FLAGS -> readSRKPub is FALSE then return TPM_INVALID_KEYHANDLE */ + !tpm_state->tpm_permanent_flags.readSRKPub) { + printf("TPM_Process_GetPubKey: " + "Error, keyHandle is TPM_KH_SRK and readSRKPub is FALSE\n"); + returnCode = TPM_INVALID_KEYHANDLE; + } + } +#endif + /* 4. If keyHandle -> pcrInfoSize is not 0 */ + /* a. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */ + /* i. Create a digestAtRelease according to the specified PCR registers and compare + to keyHandle -> digestAtRelease and if a mismatch return TPM_WRONGPCRVAL */ + /* ii. If specified validate any locality requests */ + /* NOTE: Done at TPM_KeyHandleEntries_GetKey() */ + /* 5. Create a TPM_PUBKEY structure and return */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_StorePubkey(&pubkeyStream, /* output */ + &pubkeyStreamBuffer, /* output */ + &pubkeyStreamLength, /* output */ + key); /* input */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_GetPubKey: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* TPM_PUBKEY structure */ + returnCode = TPM_Sbuffer_Append(response, pubkeyStreamBuffer, pubkeyStreamLength); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_Sbuffer_Delete(&pubkeyStream); /* @1 */ + return rcf; +} diff --git a/src/tpm12/tpm_storage.h b/src/tpm12/tpm_storage.h new file mode 100644 index 0000000..060e44f --- /dev/null +++ b/src/tpm12/tpm_storage.h @@ -0,0 +1,167 @@ +/********************************************************************************/ +/* */ +/* Storage Functions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_storage.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_STORAGE_H +#define TPM_STORAGE_H + +#include "tpm_global.h" +#include "tpm_store.h" +#include "tpm_types.h" + +/* + TPM_BOUND_DATA +*/ + +void TPM_BoundData_Init(TPM_BOUND_DATA *tpm_bound_data); +TPM_RESULT TPM_BoundData_Load(TPM_BOUND_DATA *tpm_bound_data, + unsigned char **stream, + uint32_t *stream_size); +#if 0 +TPM_RESULT TPM_BoundData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_BOUND_DATA *tpm_bound_data); +#endif +void TPM_BoundData_Delete(TPM_BOUND_DATA *tpm_bound_data); + +/* + TPM_SEALED_DATA +*/ + +void TPM_SealedData_Init(TPM_SEALED_DATA *tpm_sealed_data); +TPM_RESULT TPM_SealedData_Load(TPM_SEALED_DATA *tpm_sealed_data, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_SealedData_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_SEALED_DATA *tpm_sealed_data); +void TPM_SealedData_Delete(TPM_SEALED_DATA *tpm_sealed_data); + +TPM_RESULT TPM_SealedData_DecryptEncData(TPM_SEALED_DATA *tpm_sealed_data, + TPM_SIZED_BUFFER *enc_data, + TPM_KEY *tpm_key); +TPM_RESULT TPM_SealedData_GenerateEncData(TPM_SIZED_BUFFER *enc_data, + const TPM_SEALED_DATA *tpm_sealed_data, + TPM_KEY *tpm_key); + +/* + TPM_STORED_DATA +*/ + +void TPM_StoredData_Init(TPM_STORED_DATA *tpm_stored_data, + unsigned int version); +TPM_RESULT TPM_StoredData_Load(TPM_STORED_DATA *tpm_stored_data, + unsigned int *version, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_StoredData_Store(TPM_STORE_BUFFER *sbuffer, + TPM_STORED_DATA *tpm_stored_data, + unsigned int version); +void TPM_StoredData_Delete(TPM_STORED_DATA *tpm_stored_data, + unsigned int version); + +TPM_RESULT TPM_StoredData_CheckTag(TPM_STORED_DATA12 *tpm_stored_data12); +TPM_RESULT TPM_StoredData_StoreClearData(TPM_STORE_BUFFER *sbuffer, + TPM_STORED_DATA *tpm_stored_data, + unsigned int version); +TPM_RESULT TPM_StoredData_GenerateDigest(TPM_DIGEST tpm_digest, + TPM_STORED_DATA *tpm_stored_data, + unsigned int version); + +/* + Processing functions +*/ + +TPM_RESULT TPM_Process_Seal(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_Sealx(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_Unseal(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_UnBind(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_CreateWrapKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_LoadKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_LoadKey2(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_GetPubKey(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + + +#endif diff --git a/src/tpm12/tpm_store.c b/src/tpm12/tpm_store.c new file mode 100644 index 0000000..ce79190 --- /dev/null +++ b/src/tpm12/tpm_store.c @@ -0,0 +1,598 @@ +/********************************************************************************/ +/* */ +/* Safe Storage Buffer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_store.c 4668 2012-01-25 21:16:48Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* Generally useful utilities to serialize structures to a stream */ + +#include +#include +#include + +#include "tpm_commands.h" +#include "tpm_constants.h" +#include "tpm_crypto.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_memory.h" +#include "tpm_process.h" + +#include "tpm_store.h" + +/* + ->buffer; beginning of buffer + ->buffer_current; first empty position in buffer + ->buffer_end; one past last valid position in buffer +*/ + +/* local prototypes */ + +static void TPM_Sbuffer_AdjustParamSize(TPM_STORE_BUFFER *sbuffer); +static TPM_RESULT TPM_Sbuffer_AdjustReturnCode(TPM_STORE_BUFFER *sbuffer, TPM_RESULT returnCode); + + +/* TPM_Sbuffer_Init() sets up a new serialize buffer. It should be called before the first use. */ + +void TPM_Sbuffer_Init(TPM_STORE_BUFFER *sbuffer) +{ + sbuffer->buffer = NULL; + sbuffer->buffer_current = NULL; + sbuffer->buffer_end = NULL; +} + +/* TPM_Sbuffer_Load() loads TPM_STORE_BUFFER that has been serialized using + TPM_Sbuffer_AppendAsSizedBuffer(), as a size plus stream. +*/ + +TPM_RESULT TPM_Sbuffer_Load(TPM_STORE_BUFFER *sbuffer, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t length; + + /* get the length of the stream to be loaded */ + if (rc == 0) { + rc = TPM_Load32(&length, stream, stream_size); + } + /* check stream_size */ + if (rc == 0) { + if (*stream_size < length) { + printf("TPM_Sbuffer_Load: Error, stream_size %u less than %u\n", + *stream_size, length); + rc = TPM_BAD_PARAM_SIZE; + } + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, *stream, length); + *stream += length; + *stream_size -= length; + } + return rc; +} + +/* TPM_Sbuffer_Store() cannot simply store the elements, as they are pointers. Rather, the + TPM_Sbuffer_AppendAsSizedBuffer() function is used. +*/ + +/* TPM_Sbuffer_Delete() frees an existing buffer and reinitializes it. It must be called when a + TPM_STORE_BUFFER is no longer required, to avoid a memory leak. The buffer can be reused, but in + that case TPM_Sbuffer_Clear would be a better choice. */ + +void TPM_Sbuffer_Delete(TPM_STORE_BUFFER *sbuffer) +{ + free(sbuffer->buffer); + TPM_Sbuffer_Init(sbuffer); +} + +/* TPM_Sbuffer_Clear() removes all data from an existing buffer, allowing reuse. Memory is NOT + freed. */ + +void TPM_Sbuffer_Clear(TPM_STORE_BUFFER *sbuffer) +{ + sbuffer->buffer_current = sbuffer->buffer; + return; +} + +/* TPM_Sbuffer_Get() gets the resulting byte buffer and its size. */ + +void TPM_Sbuffer_Get(TPM_STORE_BUFFER *sbuffer, + const unsigned char **buffer, + uint32_t *length) +{ + *length = sbuffer->buffer_current - sbuffer->buffer; + *buffer = sbuffer->buffer; + return; +} + +/* TPM_Sbuffer_GetAll() gets the resulting byte buffer and its size, as well as the total size. */ + +void TPM_Sbuffer_GetAll(TPM_STORE_BUFFER *sbuffer, + unsigned char **buffer, + uint32_t *length, + uint32_t *total) +{ + *length = sbuffer->buffer_current - sbuffer->buffer; + *total = sbuffer->buffer_end - sbuffer->buffer; + *buffer = sbuffer->buffer; + return; +} + +/* TPM_Sbuffer_Set() creates a TPM_STORE_BUFFER from + + 'buffer' - pointer to a buffer that was allocated (can be NULL) + + 'total' - the total number of allocated bytes (ignored if buffer is NULL) + + 'length' - the number of valid bytes in buffer (ignored if buffer is NULL, can be 0, cannot be + greater than total. +*/ + +TPM_RESULT TPM_Sbuffer_Set(TPM_STORE_BUFFER *sbuffer, + unsigned char *buffer, + const uint32_t length, + const uint32_t total) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + if (sbuffer == NULL) { + printf("TPM_Sbuffer_Set: Error (fatal), sbuffer is NULL\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + if (buffer != NULL) { + if (rc == 0) { + if (length > total) { + printf("TPM_Sbuffer_Set: Error (fatal), length %u > total %u\n", + length, total); + rc = TPM_FAIL; + } + } + if (rc == 0) { + sbuffer->buffer = buffer; + sbuffer->buffer_current = buffer + length; + sbuffer->buffer_end = buffer + total; + } + } + else { /* buffer == NULL */ + sbuffer->buffer = NULL; + sbuffer->buffer_current = NULL; + sbuffer->buffer_end = NULL; + } + } + return rc; +} + +/* TPM_Sbuffer_Append() is the basic function to append 'data' of size 'data_length' to the + TPM_STORE_BUFFER + + Returns 0 if success, TPM_SIZE if the buffer cannot be allocated. +*/ + +TPM_RESULT TPM_Sbuffer_Append(TPM_STORE_BUFFER *sbuffer, + const unsigned char *data, + size_t data_length) +{ + TPM_RESULT rc = 0; + size_t free_length; /* length of free bytes in current buffer */ + size_t current_size; /* size of current buffer */ + size_t current_length; /* bytes in current buffer */ + size_t new_size; /* size of new buffer */ + + /* can data fit? */ + if (rc == 0) { + /* cast safe as end is always greater than current */ + free_length = (size_t)(sbuffer->buffer_end - sbuffer->buffer_current); + /* if data cannot fit in buffer as sized */ + if (free_length < data_length) { + /* This test will fail long before the add uint32_t overflow */ + if (rc == 0) { + /* cast safe as current is always greater than start */ + current_length = (size_t)(sbuffer->buffer_current - sbuffer->buffer); + if ((current_length + data_length) > TPM_ALLOC_MAX) { + printf("TPM_Sbuffer_Append: " + "Error, size %lu + %lu greater than maximum allowed\n", + (unsigned long)current_length, (unsigned long)data_length); + rc = TPM_SIZE; + } + } + if (rc == 0) { + /* cast safe as end is always greater than start */ + current_size = (size_t)(sbuffer->buffer_end - sbuffer->buffer); + /* optimize realloc's by rounding up data_length to the next increment */ + new_size = current_size + /* currently used */ + ((((data_length - 1)/TPM_STORE_BUFFER_INCREMENT) + 1) * + TPM_STORE_BUFFER_INCREMENT); + /* but not greater than maximum buffer size */ + if (new_size > TPM_ALLOC_MAX) { + new_size = TPM_ALLOC_MAX; + } + printf(" TPM_Sbuffer_Append: data_length %lu, growing from %lu to %lu\n", + (unsigned long)data_length, + (unsigned long)current_size, + (unsigned long)new_size); + rc = TPM_Realloc(&(sbuffer->buffer), new_size); + } + if (rc == 0) { + sbuffer->buffer_end = sbuffer->buffer + new_size; /* end */ + sbuffer->buffer_current = sbuffer->buffer + current_length; /* new empty position */ + } + } + } + /* append the data */ + if (rc == 0) { + if (data_length > 0) { /* libtpms added (ubsan) */ + memcpy(sbuffer->buffer_current, data, data_length); + sbuffer->buffer_current += data_length; + } + } + return rc; +} + +/* TPM_Sbuffer_Append8() is a special append that appends a uint8_t + */ + +TPM_RESULT TPM_Sbuffer_Append8(TPM_STORE_BUFFER *sbuffer, uint8_t data) +{ + TPM_RESULT rc = 0; + + rc = TPM_Sbuffer_Append(sbuffer, (const unsigned char *)(&data), sizeof(uint8_t)); + return rc; +} + +/* TPM_Sbuffer_Append16() is a special append that converts a uint16_t to big endian (network byte + order) and appends. */ + +TPM_RESULT TPM_Sbuffer_Append16(TPM_STORE_BUFFER *sbuffer, uint16_t data) +{ + TPM_RESULT rc = 0; + + uint16_t ndata = htons(data); + rc = TPM_Sbuffer_Append(sbuffer, (const unsigned char *)(&ndata), sizeof(uint16_t)); + return rc; +} + +/* TPM_Sbuffer_Append32() is a special append that converts a uint32_t to big endian (network byte + order) and appends. */ + +TPM_RESULT TPM_Sbuffer_Append32(TPM_STORE_BUFFER *sbuffer, uint32_t data) +{ + TPM_RESULT rc = 0; + + uint32_t ndata = htonl(data); + rc = TPM_Sbuffer_Append(sbuffer, (const unsigned char *)(&ndata), sizeof(uint32_t)); + return rc; +} + +/* TPM_Sbuffer_AppendAsSizedBuffer() appends the source to the destination using the + TPM_SIZED_BUFFER idiom. That is, for a uint32_t size is stored. Then the data is stored. + + Use this function when the stream is not self-describing and a size must be prepended. +*/ + +TPM_RESULT TPM_Sbuffer_AppendAsSizedBuffer(TPM_STORE_BUFFER *destSbuffer, + TPM_STORE_BUFFER *srcSbuffer) +{ + TPM_RESULT rc = 0; + const unsigned char *buffer; + uint32_t length; + + if (rc == 0) { + TPM_Sbuffer_Get(srcSbuffer, &buffer, &length); + rc = TPM_Sbuffer_Append32(destSbuffer, length); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(destSbuffer, buffer, length); + } + return rc; +} + +/* TPM_Sbuffer_AppendSBuffer() appends the source to the destination. The size is not prepended, so + the stream must be self-describing. +*/ + +TPM_RESULT TPM_Sbuffer_AppendSBuffer(TPM_STORE_BUFFER *destSbuffer, + TPM_STORE_BUFFER *srcSbuffer) +{ + TPM_RESULT rc = 0; + const unsigned char *buffer; + uint32_t length; + + if (rc == 0) { + TPM_Sbuffer_Get(srcSbuffer, &buffer, &length); + rc = TPM_Sbuffer_Append(destSbuffer, buffer, length); + } + return rc; +} + +/* TPM_Sbuffer_StoreInitialResponse() is a special purpose append specific to a TPM response. + + It appends the first 3 standard response parameters: + - response_tag + - parameter size + - return code + + For some TPM commands, this is the entire response. Other times, additional parameters + will be appended. See TPM_Sbuffer_StoreFinalResponse(). + + Returns: + 0 success + TPM_SIZE response could not fit in buffer +*/ + +TPM_RESULT TPM_Sbuffer_StoreInitialResponse(TPM_STORE_BUFFER *response, + TPM_TAG request_tag, + TPM_RESULT returnCode) +{ + TPM_RESULT rc = 0; + TPM_TAG response_tag; + + printf(" TPM_Sbuffer_StoreInitialResponse: returnCode %08x\n", returnCode); + if (rc == 0) { + if (request_tag == TPM_TAG_RQU_COMMAND) { + response_tag = TPM_TAG_RSP_COMMAND; + } + else if (request_tag == TPM_TAG_RQU_AUTH1_COMMAND) { + response_tag = TPM_TAG_RSP_AUTH1_COMMAND; + } + else if (request_tag == TPM_TAG_RQU_AUTH2_COMMAND) { + response_tag = TPM_TAG_RSP_AUTH2_COMMAND; + } + /* input tag error, returnCode is handled by caller TPM_CheckRequestTag() */ + else { + response_tag = TPM_TAG_RSP_COMMAND; + } + } + /* tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(response, response_tag); + } + /* paramSize */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(response, + sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT)); + } + /* returnCode */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(response, returnCode); + } + return rc; +} + +/* TPM_Sbuffer_StoreFinalResponse() is a special purpose append specific to a TPM response. + + It is used after TPM_Sbuffer_StoreInitialResponse() and all additional parameters are appended. + + 1 - If the additional parameters were successfully appended, this function adjusts the + preliminary parameter size set by TPM_Sbuffer_StoreInitialResponse() to reflect the additional + appends. + + 2 - If there was a failure during the additional appends, this function adjusts the return code + and removes the additional appends. +*/ + +TPM_RESULT TPM_Sbuffer_StoreFinalResponse(TPM_STORE_BUFFER *sbuffer, + TPM_RESULT returnCode, + tpm_state_t *tpm_state) +{ + TPM_RESULT rc = 0; + const unsigned char *buffer; + uint32_t length; + + printf(" TPM_Sbuffer_StoreFinalResponse: returnCode %08x\n", returnCode); + /* determine whether the response would exceed the output buffer size */ + TPM_Sbuffer_Get(sbuffer, &buffer, &length); + if (length > TPM12_GetBufferSize()) { + printf("TPM_Sbuffer_StoreFinalResponse: Error, response buffer %u exceeds max %u\n", + length, TPM12_GetBufferSize()); + returnCode = TPM_SIZE; + } + if (returnCode == TPM_SUCCESS) { + TPM_Sbuffer_AdjustParamSize(sbuffer); + } + else { + /* TPM_FAIL is reserved for "should never occur" errors that indicate a software or hardware + failure */ + if ((returnCode == TPM_FAIL) && (tpm_state != NULL)) { + printf(" TPM_Sbuffer_StoreFinalResponse: Set testState to %u \n", + TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + rc = TPM_Sbuffer_AdjustReturnCode(sbuffer, returnCode); + } + return rc; +} + +/* TPM_Sbuffer_AdjustParamSize() is a special purpose function to go back and adjust the response + paramSize after the response buffer is complete +*/ + +static void TPM_Sbuffer_AdjustParamSize(TPM_STORE_BUFFER *sbuffer) +{ + uint32_t paramSize; /* the correct paramsize */ + uint32_t nParamSize; /* the correct paramsize, in network byte order */ + uint32_t paramSizeOffset; + + /* actual size */ + paramSize = sbuffer->buffer_current - sbuffer->buffer; + paramSizeOffset = sizeof(TPM_TAG); + nParamSize = htonl(paramSize); /* network byte order */ + /* overwrite the original size */ + memcpy(sbuffer->buffer + paramSizeOffset, &nParamSize, sizeof(uint32_t)); + return; +} + +/* TPM_Sbuffer_AdjustReturnCode() is a special function to go back and adjust the response tag and + returnCode if there was a failure while appending the rest of the parameters. + + This should never fail, because sbuffer was allocated during TPM_Sbuffer_StoreInitialResponse(). +*/ + +static TPM_RESULT TPM_Sbuffer_AdjustReturnCode(TPM_STORE_BUFFER *sbuffer, TPM_RESULT returnCode) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + /* erase the previous result without freeing the buffer */ + sbuffer->buffer_current = sbuffer->buffer; + /* error tag */ + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_RSP_COMMAND); + } + /* paramSize */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT)); + } + /* returnCode */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, returnCode); + } + return rc; +} + +#if 0 +/* Test appending to the TPM_STORE_BUFFER up to the limit */ + +TPM_RESULT TPM_Sbuffer_Test(void) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; + size_t total_count; + unsigned char count; + unsigned char data[256]; /* dummy data */ + + printf(" TPM_Sbuffer_Test:\n"); + TPM_Sbuffer_Init(&sbuffer); + total_count = 0; + while ((total_count != TPM_ALLOC_MAX) && rc == 0) { + if (rc == 0) { + rc = TPM_Random(&count, 1); + } + if (rc == 0) { + printf(" TPM_Sbuffer_Test: count %u\n", count); + /* last time through */ + if (total_count + count > TPM_ALLOC_MAX) { + count = TPM_ALLOC_MAX - total_count; + } + rc = TPM_Sbuffer_Append(&sbuffer,data, count); + } + if (rc == 0) { + total_count += count; + } + printf(" TPM_Sbuffer_Test: total_count %lu\n", (unsigned long)total_count); + } + TPM_Sbuffer_Delete(&sbuffer); + return rc; +} +#endif + +/* type to byte stream */ +void STORE32(unsigned char *buffer, unsigned int offset, uint32_t value) +{ + buffer[offset + 0] = value >> 24; + buffer[offset + 1] = value >> 16; + buffer[offset + 2] = value >> 8; + buffer[offset + 3] = value >> 0; +} + +void STORE16(unsigned char *buffer, unsigned int offset, uint16_t value) +{ + buffer[offset + 0] = value >> 8; + buffer[offset + 1] = value >> 0; +} + +void STORE8(unsigned char *buffer, unsigned int offset, uint8_t value) + +{ + buffer[offset + 0] = value >> 0; +} + +/* TPM_Bitmap_Load() is a safe loading of a TPM_BOOL from a bitmap. + + If 'pos' is >= 32, the function fails. + TPM_BOOL is TRUE. if The bit at pos is set + 'pos' is incremented after the load. +*/ + +TPM_RESULT TPM_Bitmap_Load(TPM_BOOL *tpm_bool, + uint32_t tpm_bitmap, + uint32_t *pos) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + if ((*pos) >= (sizeof(uint32_t) * CHAR_BIT)) { + printf("TPM_Bitmap_Load: Error (fatal), loading from position %u\n", *pos); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + *tpm_bool = (tpm_bitmap & (1 << (*pos))) != 0; + (*pos)++; + } + return rc; +} + +/* TPM_Bitmap_Store() is a safe storing of a TPM_BOOL into a bitmap. + + If 'pos' is >= 32, the function fails. + The bit at pos is set if the TPM_BOOL is TRUE. + 'pos' is incremented after the store. +*/ + +TPM_RESULT TPM_Bitmap_Store(uint32_t *tpm_bitmap, + TPM_BOOL tpm_bool, + uint32_t *pos) +{ + TPM_RESULT rc = 0; + + if (rc == 0) { + if ((*pos) >= (sizeof(uint32_t) * CHAR_BIT)) { + printf("TPM_Bitmap_Store: Error (fatal), storing to position %u\n", *pos); + rc = TPM_FAIL; /* should never occur */ + } + } + if (rc == 0) { + if (tpm_bool) { + *tpm_bitmap |= (1 << (*pos)); + } + (*pos)++; + } + return rc; +} + diff --git a/src/tpm12/tpm_store.h b/src/tpm12/tpm_store.h new file mode 100644 index 0000000..8b6fefd --- /dev/null +++ b/src/tpm12/tpm_store.h @@ -0,0 +1,111 @@ +/********************************************************************************/ +/* */ +/* Safe Storage Buffer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_store.h 4668 2012-01-25 21:16:48Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_STORE_H +#define TPM_STORE_H + +#include "tpm_global.h" +#include "tpm_load.h" +#include "tpm_types.h" + +void TPM_Sbuffer_Init(TPM_STORE_BUFFER *sbuffer); +TPM_RESULT TPM_Sbuffer_Load(TPM_STORE_BUFFER *sbuffer, + unsigned char **stream, + uint32_t *stream_size); +/* TPM_Sbuffer_Store(): See TPM_Sbuffer_AppendAsSizedBuffer() */ +void TPM_Sbuffer_Delete(TPM_STORE_BUFFER *sbuffer); + +void TPM_Sbuffer_Clear(TPM_STORE_BUFFER *sbuffer); +void TPM_Sbuffer_Get(TPM_STORE_BUFFER *sbuffer, + const unsigned char **buffer, + uint32_t *length); +void TPM_Sbuffer_GetAll(TPM_STORE_BUFFER *sbuffer, + unsigned char **buffer, + uint32_t *length, + uint32_t *total); +TPM_RESULT TPM_Sbuffer_Set(TPM_STORE_BUFFER *sbuffer, + unsigned char *buffer, + const uint32_t length, + const uint32_t total); + +TPM_RESULT TPM_Sbuffer_Append(TPM_STORE_BUFFER *sbuffer, + const unsigned char *data, + size_t data_length); + +TPM_RESULT TPM_Sbuffer_Append8(TPM_STORE_BUFFER *sbuffer, uint8_t data); +TPM_RESULT TPM_Sbuffer_Append16(TPM_STORE_BUFFER *sbuffer, uint16_t data); +TPM_RESULT TPM_Sbuffer_Append32(TPM_STORE_BUFFER *sbuffer, uint32_t data); +TPM_RESULT TPM_Sbuffer_AppendAsSizedBuffer(TPM_STORE_BUFFER *destSbuffer, + TPM_STORE_BUFFER *srcSbuffer); +TPM_RESULT TPM_Sbuffer_AppendSBuffer(TPM_STORE_BUFFER *destSbuffer, + TPM_STORE_BUFFER *srcSbuffer); + + +TPM_RESULT TPM_Sbuffer_StoreInitialResponse(TPM_STORE_BUFFER *response, + TPM_TAG response_tag, + TPM_RESULT returnCode); +TPM_RESULT TPM_Sbuffer_StoreFinalResponse(TPM_STORE_BUFFER *sbuffer, + TPM_RESULT returnCode, + tpm_state_t *tpm_state); + +#if 0 +TPM_RESULT TPM_Sbuffer_Test(void); +#endif + +/* type to byte stream */ + +void STORE32(unsigned char *buffer, unsigned int offset, uint32_t value); +void STORE16(unsigned char *buffer, unsigned int offset, uint16_t value); +void STORE8 (unsigned char *buffer, unsigned int offset, uint8_t value); + +/* load and store to bitmap */ + +TPM_RESULT TPM_Bitmap_Load(TPM_BOOL *tpm_bool, + uint32_t tpm_bitmap, + uint32_t *pos); +TPM_RESULT TPM_Bitmap_Store(uint32_t *tpm_bitmap, + TPM_BOOL tpm_bool, + uint32_t *pos); + +/* generic function prototype for a structure store callback function */ + +typedef TPM_RESULT (*TPM_STORE_FUNCTION_T )(TPM_STORE_BUFFER *sbuffer, + const void *tpm_structure); + +#endif diff --git a/src/tpm12/tpm_structures.h b/src/tpm12/tpm_structures.h new file mode 100644 index 0000000..1552126 --- /dev/null +++ b/src/tpm12/tpm_structures.h @@ -0,0 +1,2630 @@ +/********************************************************************************/ +/* */ +/* TPM Structures */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_structures.h 4528 2011-03-29 22:16:28Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_STRUCTURES_H +#define TPM_STRUCTURES_H + +#include +#include "tpm_constants.h" +#include "tpm_memory.h" +#include "tpm_types.h" +#include "tpm_nvram_const.h" + +/* Sanity check on build macros are centralized here, since any TPM will use this header */ + +#if !defined (TPM_POSIX) && !defined (TPM_WINDOWS) && !defined(TPM_SYSTEM_P) +#error "Must define either TPM_POSIX or TPM_WINDOWS or TPM_SYSTEM_P" +#endif + +#if defined (TPM_NV_XCRYPTO_FLASH) && defined (TPM_NV_DISK) +#error "Cannot define TPM_NV_XCRYPTO_FLASH and TPM_NV_DISK" +#endif + +#if defined (TPM_WINDOWS) && defined (TPM_UNIX_DOMAIN_SOCKET) +#error "Cannot define TPM_WINDOWS and TPM_UNIX_DOMAIN_SOCKET" +#endif + +#if defined (TPM_USE_CHARDEV) && defined (TPM_UNIX_DOMAIN_SOCKET) +#error "Cannot define TPM_USE_CHARDEV and TPM_UNIX_DOMAIN_SOCKET" +#endif + +#if defined (TPM_NV_XCRYPTO_FLASH) && defined (TPM_UNIX_DOMAIN_SOCKET) +#error "Cannot define TPM_NV_XCRYPTO_FLASH and TPM_UNIX_DOMAIN_SOCKET" +#endif + +#if defined (TPM_XCRYPTO_USE_HW) && !defined(TPM_NV_XCRYPTO_FLASH) +#error "TPM_XCRYPTO_USE_HW requires TPM_NV_XCRYPTO_FLASH" +#endif + +#if defined (TPM_VTPM) && defined (TPM_UNIX_DOMAIN_SOCKET) +#error "Cannot define TPM_VTPM and TPM_UNIX_DOMAIN_SOCKET" +#endif + + + +#if defined (TPM_V11) && defined (TPM_V12) +#error "Cannot define TPM_V12 and TPM_V11" +#endif + +#if !defined (TPM_V11) && !defined (TPM_V12) +#error "Must define either TPM_V12 or TPM_V11" +#endif + +#if defined (TPM_DES) && defined (TPM_AES) +#error "Cannot define TPM_DES and TPM_AES" +#endif +#if !defined (TPM_DES) && !defined (TPM_AES) +#error "Must define either TPM_DES or TPM_AES" +#endif + +/* This structure is typically a cast from a subset of a larger TPM structure. Two members - a 4 + bytes size followed by a 4 bytes pointer to the data is a common TPM structure idiom. */ + +typedef struct tdTPM_SIZED_BUFFER { + uint32_t size; + BYTE *buffer; +} TPM_SIZED_BUFFER; + +/* This structure implements a safe storage buffer, used throughout the code when serializing + structures to a stream. +*/ + +typedef struct tdTPM_STORE_BUFFER { + unsigned char *buffer; /* beginning of buffer */ + unsigned char *buffer_current; /* first empty position in buffer */ + unsigned char *buffer_end; /* one past last valid position in buffer */ +} TPM_STORE_BUFFER; + +/* 5.1 TPM_STRUCT_VER rev 100 + + This indicates the version of the structure or TPM. + + Version 1.2 deprecates the use of this structure in all other structures. The structure is not + deprecated as many of the structures that contain this structure are not deprecated. +*/ + +#define TPM_MAJOR 0x01 + +#if defined TPM_V12 +#define TPM_MINOR 0x02 +#endif + +#if defined TPM_V11 +#define TPM_MINOR 0x01 +#endif + +typedef struct tdTPM_STRUCT_VER { + BYTE major; /* This SHALL indicate the major version of the structure. MUST be 0x01 */ + BYTE minor; /* This SHALL indicate the minor version of the structure. MUST be 0x01 */ + BYTE revMajor; /* This MUST be 0x00 on output, ignored on input */ + BYTE revMinor; /* This MUST be 0x00 on output, ignored on input */ +} TPM_STRUCT_VER; + +/* 5.2 TPM_VERSION_BYTE rev 87 + + Allocating a byte for the version information is wasteful of space. The current allocation does + not provide sufficient resolution to indicate completely the version of the TPM. To allow for + backwards compatibility the size of the structure does not change from 1.1. + + To enable minor version, or revision, numbers with 2-digit resolution, the byte representing a + version splits into two BDC encoded nibbles. The ordering of the low and high order provides + backwards compatibility with existing numbering. + + An example of an implementation of this is; a version of 1.23 would have the value 2 in bit + positions 3-0 and the value 3 in bit positions 7-4. + + TPM_VERSION_BYTE is a byte. The byte is broken up according to the following rule + + 7-4 leastSigVer Least significant nibble of the minor version. MUST be values within the range of + 0000-1001 + 3-0 mostSigVer Most significant nibble of the minor version. MUST be values within the range of + 0000-1001 +*/ + +/* 5.3 TPM_VERSION rev 116 + + This structure provides information relative the version of the TPM. This structure should only + be in use by TPM_GetCapability to provide the information relative to the TPM. +*/ + +typedef struct tdTPM_VERSION { + TPM_VERSION_BYTE major; /* This SHALL indicate the major version of the TPM, mostSigVer MUST + be 0x1, leastSigVer MUST be 0x0 */ + TPM_VERSION_BYTE minor; /* This SHALL indicate the minor version of the TPM, mostSigVer MUST + be 0x1 or 0x2, leastSigVer MUST be 0x0 */ + BYTE revMajor; /* This SHALL be the value of the TPM_PERMANENT_DATA -> revMajor */ + BYTE revMinor; /* This SHALL be the value of the TPM_PERMANENT_DATA -> revMinor */ +} TPM_VERSION; + +/* 5.4 TPM_DIGEST rev 111 + + The digest value reports the result of a hash operation. + + In version 1 the hash algorithm is SHA-1 with a resulting hash result being 20 bytes or 160 bits. + + It is understood that algorithm agility is lost due to fixing the hash at 20 bytes and on + SHA-1. The reason for fixing is due to the internal use of the digest. It is the authorization + values, it provides the secrets for the HMAC and the size of 20 bytes determines the values that + can be stored and encrypted. For this reason, the size is fixed and any changes to this value + require a new version of the specification. + + The digestSize parameter MUST indicate the block size of the algorithm and MUST be 20 or greater. + + For all TPM v1 hash operations, the hash algorithm MUST be SHA-1 and the digestSize parameter is + therefore equal to 20. +*/ + +#define TPM_DIGEST_SIZE 20 +typedef BYTE TPM_DIGEST[TPM_DIGEST_SIZE]; + +#if 0 +/* kgold - This was designed as a structure with one element. Changed to a simple BYTE array, like + TPM_SECRET. */ +typedef struct tdTPM_DIGEST { + BYTE digest[TPM_DIGEST_SIZE]; /* This SHALL be the actual digest information */ +} TPM_DIGEST; +#endif + +/* Redefinitions */ + +typedef TPM_DIGEST TPM_CHOSENID_HASH; /* This SHALL be the digest of the chosen identityLabel and + privacyCA for a new TPM identity.*/ + +typedef TPM_DIGEST TPM_COMPOSITE_HASH; /* This SHALL be the hash of a list of PCR indexes and PCR + values that a key or data is bound to. */ + +typedef TPM_DIGEST TPM_DIRVALUE; /* This SHALL be the value of a DIR register */ + +typedef TPM_DIGEST TPM_HMAC; /* This shall be the output of the HMAC algorithm */ + +typedef TPM_DIGEST TPM_PCRVALUE; /* The value inside of the PCR */ + +typedef TPM_DIGEST TPM_AUDITDIGEST; /* This SHALL be the value of the current internal audit + state */ + +/* 5.5 TPM_NONCE rev 99 + + A nonce is a random value that provides protection from replay and other attacks. Many of the + commands and protocols in the specification require a nonce. This structure provides a consistent + view of what a nonce is. +*/ + +#define TPM_NONCE_SIZE 20 +typedef BYTE TPM_NONCE[TPM_NONCE_SIZE]; + +#if 0 +/* kgold - This was designed as a structure with one element. Changed to a simple BYTE array, like + TPM_SECRET. */ +typedef struct tdTPM_NONCE { + BYTE nonce[TPM_NONCE_SIZE]; /* This SHALL be the 20 bytes of random data. When created by the + TPM the value MUST be the next 20 bytes from the RNG */ +} TPM_NONCE; +#endif + +typedef TPM_NONCE TPM_DAA_TPM_SEED; /* This SHALL be a random value generated by a TPM + immediately after the EK is installed in that TPM, + whenever an EK is installed in that TPM */ +typedef TPM_NONCE TPM_DAA_CONTEXT_SEED; /* This SHALL be a random value */ + +/* 5.6 TPM_AUTHDATA rev 87 + + The authorization data is the information that is saved or passed to provide proof of ownership + of an entity. For version 1 this area is always 20 bytes. +*/ + +#define TPM_AUTHDATA_SIZE 20 +typedef BYTE TPM_AUTHDATA[TPM_AUTHDATA_SIZE]; + +#define TPM_SECRET_SIZE 20 +typedef BYTE TPM_SECRET[TPM_SECRET_SIZE]; + +#if 0 /* kgold - define TPM_SECRET directly, so the size can be defined */ +typedef TPM_AUTHDATA TPM_SECRET; /* A secret plain text value used in the authorization process. */ +#endif + +typedef TPM_AUTHDATA TPM_ENCAUTH; /* A cipher text (encrypted) version of authorization data. The + encryption mechanism depends on the context. */ + +/* 5.7 TPM_KEY_HANDLE_LIST rev 87 + + TPM_KEY_HANDLE_LIST is a structure used to describe the handles of all keys currently loaded into + a TPM. +*/ + +#if 0 /* This is the version from the specification part 2 */ +typedef struct tdTPM_KEY_HANDLE_LIST { + uint16_t loaded; /* The number of keys currently loaded in the TPM. */ + [size_is(loaded)] TPM_KEY_HANDLE handle[]; /* An array of handles, one for each key currently + loaded in the TPM */ +} TPM_KEY_HANDLE_LIST; +#endif + +/* 5.11 TPM_CHANGEAUTH_VALIDATE rev 87 + + This structure provides an area that will stores the new authorization data and the challenger's + nonce. +*/ + +typedef struct tdTPM_CHANGEAUTH_VALIDATE { + TPM_SECRET newAuthSecret; /* This SHALL be the new authorization data for the target entity */ + TPM_NONCE n1; /* This SHOULD be a nonce, to enable the caller to verify that the + target TPM is on-line. */ +} TPM_CHANGEAUTH_VALIDATE; + + + +/* PCR */ + +/* NOTE: The TPM requires and the code assumes a multiple of CHAR_BIT (8). 48 registers (6 bytes) + may be a bad number, as it makes TPM_PCR_INFO and TPM_PCR_INFO_LONG indistinguishable in the + first two bytes. */ + +#if defined TPM_V11 +#define TPM_NUM_PCR 16 /* Use PC Client specification values */ +#endif + +#if defined TPM_V12 +#define TPM_NUM_PCR 24 /* Use PC Client specification values */ +#endif + +#if (CHAR_BIT != 8) +#error "CHAR_BIT must be 8" +#endif + +#if ((TPM_NUM_PCR % 8) != 0) +#error "TPM_NUM_PCR must be a multiple of 8" +#endif + +/* 8.1 TPM_PCR_SELECTION rev 110 + + This structure provides a standard method of specifying a list of PCR registers. +*/ + +typedef struct tdTPM_PCR_SELECTION { + uint16_t sizeOfSelect; /* The size in bytes of the pcrSelect structure */ + BYTE pcrSelect[TPM_NUM_PCR/CHAR_BIT]; /* This SHALL be a bit map that indicates if a PCR + is active or not */ +} TPM_PCR_SELECTION; + +/* 8.2 TPM_PCR_COMPOSITE rev 97 + + The composite structure provides the index and value of the PCR register to be used when creating + the value that SEALS an entity to the composite. +*/ + +typedef struct tdTPM_PCR_COMPOSITE { + TPM_PCR_SELECTION select; /* This SHALL be the indication of which PCR values are active */ +#if 0 + uint32_t valueSize; /* This SHALL be the size of the pcrValue field (not the number of + PCR's) */ + TPM_PCRVALUE *pcrValue; /* This SHALL be an array of TPM_PCRVALUE structures. The values + come in the order specified by the select parameter and are + concatenated into a single blob */ +#endif + TPM_SIZED_BUFFER pcrValue; +} TPM_PCR_COMPOSITE; + +/* 8.3 TPM_PCR_INFO rev 87 + + The TPM_PCR_INFO structure contains the information related to the wrapping of a key or the + sealing of data, to a set of PCRs. +*/ + +typedef struct tdTPM_PCR_INFO { + TPM_PCR_SELECTION pcrSelection; /* This SHALL be the selection of PCRs to which the + data or key is bound. */ + TPM_COMPOSITE_HASH digestAtRelease; /* This SHALL be the digest of the PCR indices and + PCR values to verify when revealing Sealed Data + or using a key that was wrapped to PCRs. NOTE: + This is passed in by the host, and used as + authorization to use the key */ + TPM_COMPOSITE_HASH digestAtCreation; /* This SHALL be the composite digest value of the + PCR values, at the time when the sealing is + performed. NOTE: This is generated at key + creation, but is just informative to the host, + not used for authorization */ +} TPM_PCR_INFO; + +/* 8.6 TPM_LOCALITY_SELECTION rev 87 + + When used with localityAtCreation only one bit is set and it corresponds to the locality of the + command creating the structure. + + When used with localityAtRelease the bits indicate which localities CAN perform the release. +*/ + +typedef BYTE TPM_LOCALITY_SELECTION; + +#define TPM_LOC_FOUR 0x10 /* Locality 4 */ +#define TPM_LOC_THREE 0x08 /* Locality 3 */ +#define TPM_LOC_TWO 0x04 /* Locality 2 */ +#define TPM_LOC_ONE 0x02 /* Locality 1 */ +#define TPM_LOC_ZERO 0x01 /* Locality 0. This is the same as the legacy interface. */ + +#define TPM_LOC_ALL 0x1f /* kgold - added all localities */ +#define TPM_LOC_MAX 4 /* kgold - maximum value for TPM_MODIFIER_INDICATOR */ + + +/* 8.4 TPM_PCR_INFO_LONG rev 109 + + The TPM_PCR_INFO structure contains the information related to the wrapping of a key or the + sealing of data, to a set of PCRs. + + The LONG version includes information necessary to properly define the configuration that creates + the blob using the PCR selection. +*/ + +typedef struct tdTPM_PCR_INFO_LONG { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_PCR_INFO_LONG */ +#endif + TPM_LOCALITY_SELECTION localityAtCreation; /* This SHALL be the locality modifier of the + function that creates the PCR info structure */ + TPM_LOCALITY_SELECTION localityAtRelease; /* This SHALL be the locality modifier required to + reveal Sealed Data or use a key that was wrapped + to PCRs */ + TPM_PCR_SELECTION creationPCRSelection; /* This SHALL be the selection of PCRs active when + the blob is created */ + TPM_PCR_SELECTION releasePCRSelection; /* This SHALL be the selection of PCRs to which the + data or key is bound. */ + TPM_COMPOSITE_HASH digestAtCreation; /* This SHALL be the composite digest value of the + PCR values, at the time when the sealing is + performed. */ + TPM_COMPOSITE_HASH digestAtRelease; /* This SHALL be the digest of the PCR indices and + PCR values to verify when revealing Sealed Data + or using a key that was wrapped to PCRs. */ +} TPM_PCR_INFO_LONG; + +/* 8.5 TPM_PCR_INFO_SHORT rev 87 + + This structure is for defining a digest at release when the only information that is necessary is + the release configuration. +*/ + +typedef struct tdTPM_PCR_INFO_SHORT { + TPM_PCR_SELECTION pcrSelection; /* This SHALL be the selection of PCRs that specifies the + digestAtRelease */ + TPM_LOCALITY_SELECTION localityAtRelease; /* This SHALL be the locality modifier required to + release the information. This value must not be + zero (0). */ + TPM_COMPOSITE_HASH digestAtRelease; /* This SHALL be the digest of the PCR indices and + PCR values to verify when revealing auth data */ +} TPM_PCR_INFO_SHORT; + +/* 8.8 TPM_PCR_ATTRIBUTES rev 107 + + These attributes are available on a per PCR basis. + + The TPM is not required to maintain this structure internally to the TPM. + + When a challenger evaluates a PCR an understanding of this structure is vital to the proper + understanding of the platform configuration. As this structure is static for all platforms of the + same type the structure does not need to be reported with each quote. +*/ + +typedef struct tdTPM_PCR_ATTRIBUTES { + TPM_BOOL pcrReset; /* A value of TRUE SHALL indicate that the PCR register can be reset + using the TPM_PCR_RESET command. */ + TPM_LOCALITY_SELECTION pcrExtendLocal; /* An indication of which localities can perform + extends on the PCR. */ + TPM_LOCALITY_SELECTION pcrResetLocal; /* An indication of which localities can reset the + PCR */ +} TPM_PCR_ATTRIBUTES; + +/* + 9. Storage Structures +*/ + +/* 9.1 TPM_STORED_DATA rev 87 + + The definition of this structure is necessary to ensure the enforcement of security properties. + + This structure is in use by the TPM_Seal and TPM_Unseal commands to identify the PCR index and + values that must be present to properly unseal the data. + + This structure only provides 1.1 data store and uses PCR_INFO + + 1. This structure is created during the TPM_Seal process. The confidential data is encrypted + using a nonmigratable key. When the TPM_Unseal decrypts this structure the TPM_Unseal uses the + public information in the structure to validate the current configuration and release the + decrypted data + + 2. When sealInfoSize is not 0 sealInfo MUST be TPM_PCR_INFO +*/ + +typedef struct tdTPM_STORED_DATA { + TPM_STRUCT_VER ver; /* This MUST be 1.1.0.0 */ + TPM_SIZED_BUFFER sealInfo; +#if 0 + uint32_t sealInfoSize; /* Size of the sealInfo parameter */ + BYTE* sealInfo; /* This SHALL be a structure of type TPM_PCR_INFO or a 0 length + array if the data is not bound to PCRs. */ +#endif + TPM_SIZED_BUFFER encData; +#if 0 + uint32_t encDataSize; /* This SHALL be the size of the encData parameter */ + BYTE* encData; /* This shall be an encrypted TPM_SEALED_DATA structure containing + the confidential part of the data. */ +#endif + /* NOTE: kgold - Added this structure, a cache of PCRInfo when not NULL */ + TPM_PCR_INFO *tpm_seal_info; +} TPM_STORED_DATA; + + +/* 9.2 TPM_STORED_DATA12 rev 101 + + The definition of this structure is necessary to ensure the enforcement of security properties. + This structure is in use by the TPM_Seal and TPM_Unseal commands to identify the PCR index and + values that must be present to properly unseal the data. + + 1. This structure is created during the TPM_Seal process. The confidential data is encrypted + using a nonmigratable key. When the TPM_Unseal decrypts this structure the TPM_Unseal uses the + public information in the structure to validate the current configuration and release the + decrypted data. + + 2. If sealInfoSize is not 0 then sealInfo MUST be TPM_PCR_INFO_LONG +*/ + +typedef struct tdTPM_STORED_DATA12 { + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_STORED_DATA12 */ + TPM_ENTITY_TYPE et; /* The type of blob */ + TPM_SIZED_BUFFER sealInfo; +#if 0 + uint32_t sealInfoSize; /* Size of the sealInfo parameter */ + BYTE* sealInfo; /* This SHALL be a structure of type TPM_PCR_INFO_LONG or a 0 length + array if the data is not bound to PCRs. */ +#endif + TPM_SIZED_BUFFER encData; +#if 0 + uint32_t encDataSize; /* This SHALL be the size of the encData parameter */ + BYTE* encData; /* This shall be an encrypted TPM_SEALED_DATA structure containing + the confidential part of the data. */ +#endif + /* NOTE: kgold - Added this structure, a cache of PCRInfo when not NULL */ + TPM_PCR_INFO_LONG *tpm_seal_info_long; +} TPM_STORED_DATA12; + +/* 9.3 TPM_SEALED_DATA rev 87 + + This structure contains confidential information related to sealed data, including the data + itself. + + 1. To tie the TPM_STORED_DATA structure to the TPM_SEALED_DATA structure this structure contains + a digest of the containing TPM_STORED_DATA structure. + + 2. The digest calculation does not include the encDataSize and encData parameters. +*/ + +typedef struct tdTPM_SEALED_DATA { + TPM_PAYLOAD_TYPE payload; /* This SHALL indicate the payload type of TPM_PT_SEAL */ + TPM_SECRET authData; /* This SHALL be the authorization data for this value */ + TPM_SECRET tpmProof; /* This SHALL be a copy of TPM_PERMANENT_FLAGS -> tpmProof */ + TPM_DIGEST storedDigest; /* This SHALL be a digest of the TPM_STORED_DATA structure, + excluding the fields TPM_STORED_DATA -> encDataSize and + TPM_STORED_DATA -> encData. */ + TPM_SIZED_BUFFER data; /* This SHALL be the data to be sealed */ +#if 0 + uint32_t dataSize; /* This SHALL be the size of the data parameter */ + BYTE* data; /* This SHALL be the data to be sealed */ +#endif +} TPM_SEALED_DATA; + + +/* 9.4 TPM_SYMMETRIC_KEY rev 87 + + This structure describes a symmetric key, used during the process "Collating a Request for a + Trusted Platform Module Identity". +*/ + +typedef struct tdTPM_SYMMETRIC_KEY { + TPM_ALGORITHM_ID algId; /* This SHALL be the algorithm identifier of the symmetric key. */ + TPM_ENC_SCHEME encScheme; /* This SHALL fully identify the manner in which the key will be + used for encryption operations. */ + uint16_t size; /* This SHALL be the size of the data parameter in bytes */ + BYTE* data; /* This SHALL be the symmetric key data */ + /* NOTE Cannot make this a TPM_SIZED_BUFFER because uint16_t */ +} TPM_SYMMETRIC_KEY; + +/* 9.5 TPM_BOUND_DATA rev 87 + + This structure is defined because it is used by a TPM_UnBind command in a consistency check. + + The intent of TCG is to promote "best practice" heuristics for the use of keys: a signing key + shouldn't be used for storage, and so on. These heuristics are used because of the potential + threats that arise when the same key is used in different ways. The heuristics minimize the + number of ways in which a given key can be used. + + One such heuristic is that a key of type TPM_KEY_BIND, and no other type of key, should always be + used to create the blob that is unwrapped by TPM_UnBind. Binding is not a TPM function, so the + only choice is to perform a check for the correct payload type when a blob is unwrapped by a key + of type TPM_KEY_BIND. This requires the blob to have internal structure. + + Even though payloadData has variable size, TPM_BOUND_DATA deliberately does not include the size + of payloadData. This is to maximise the size of payloadData that can be encrypted when + TPM_BOUND_DATA is encrypted in a single block. When using TPM-UnBind to obtain payloadData, the + size of payloadData is deduced as a natural result of the (RSA) decryption process. + + 1. This structure MUST be used for creating data when (wrapping with a key of type TPM_KEY_BIND) + or (wrapping using the encryption algorithm TPM_ES_RSAESOAEP_SHA1_MGF1). If it is not, the + TPM_UnBind command will fail. +*/ + +typedef struct tdTPM_BOUND_DATA { + TPM_STRUCT_VER ver; /* This MUST be 1.1.0.0 */ + TPM_PAYLOAD_TYPE payload; /* This SHALL be the value TPM_PT_BIND */ + uint32_t payloadDataSize; /* NOTE: added, not part of serialization */ + BYTE *payloadData; /* The bound data */ +} TPM_BOUND_DATA; + +/* + 10. TPM_KEY Complex +*/ + +/* 10.1.1 TPM_RSA_KEY_PARMS rev 87 + + This structure describes the parameters of an RSA key. +*/ + +/* TPM_RSA_KEY_LENGTH_MAX restricts the maximum size of an RSA key. It has two uses: + - bounds the size of the TPM state + - protects against a denial of service attack where the attacker creates a very large key +*/ + +#ifdef TPM_RSA_KEY_LENGTH_MAX /* if the builder defines a value */ +#if ((TPM_RSA_KEY_LENGTH_MAX % 16) != 0) +#error "TPM_RSA_KEY_LENGTH_MAX must be a multiple of 16" +#endif +#if (TPM_RSA_KEY_LENGTH_MAX < 2048) +#error "TPM_RSA_KEY_LENGTH_MAX must be at least 2048" +#endif +#endif /* TPM_RSA_KEY_LENGTH_MAX */ + +#ifndef TPM_RSA_KEY_LENGTH_MAX /* default if the builder does not define a value */ +#define TPM_RSA_KEY_LENGTH_MAX 2048 +#endif + +typedef struct tdTPM_RSA_KEY_PARMS { + uint32_t keyLength; /* This specifies the size of the RSA key in bits */ + uint32_t numPrimes; /* This specifies the number of prime factors used by this RSA key. */ +#if 0 + uint32_t exponentSize; /* This SHALL be the size of the exponent. If the key is using the + default exponent then the exponentSize MUST be 0. */ + BYTE *exponent; /* The public exponent of this key */ +#endif + TPM_SIZED_BUFFER exponent; /* The public exponent of this key */ + +} TPM_RSA_KEY_PARMS; + + +/* 10.1 TPM_KEY_PARMS rev 87 + + This provides a standard mechanism to define the parameters used to generate a key pair, and to + store the parts of a key shared between the public and private key parts. +*/ + +typedef struct tdTPM_KEY_PARMS { + TPM_ALGORITHM_ID algorithmID; /* This SHALL be the key algorithm in use */ + TPM_ENC_SCHEME encScheme; /* This SHALL be the encryption scheme that the key uses to encrypt + information */ + TPM_SIG_SCHEME sigScheme; /* This SHALL be the signature scheme that the key uses to perform + digital signatures */ +#if 0 + uint32_t parmSize; /* This SHALL be the size of the parms field in bytes */ + BYTE* parms; /* This SHALL be the parameter information dependent upon the key + algorithm. */ +#endif + TPM_SIZED_BUFFER parms; /* This SHALL be the parameter information dependent upon the key + algorithm. */ + /* NOTE: kgold - Added this structure. It acts as a cache of the result of parms and parmSize + deserialization when non-NULL. */ + TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; +} TPM_KEY_PARMS; + +/* 10.1.2 TPM_SYMMETRIC_KEY_PARMS rev 87 + + This structure describes the parameters for symmetric algorithms +*/ + +typedef struct tdTPM_SYMMETRIC_KEY_PARMS { + uint32_t keyLength; /* This SHALL indicate the length of the key in bits */ + uint32_t blockSize; /* This SHALL indicate the block size of the algorithm*/ + uint32_t ivSize; /* This SHALL indicate the size of the IV */ + BYTE *IV; /* The initialization vector */ +} TPM_SYMMETRIC_KEY_PARMS; + +#if 0 +/* 10.4 TPM_STORE_PUBKEY rev 99 + + This structure can be used in conjunction with a corresponding TPM_KEY_PARMS to construct a + public key which can be unambiguously used. +*/ + +typedef struct tdTPM_STORE_PUBKEY { + uint32_t keyLength; /* This SHALL be the length of the key field. */ + BYTE *key; /* This SHALL be a structure interpreted according to the algorithm Id in + the corresponding TPM_KEY_PARMS structure. */ +} TPM_STORE_PUBKEY; +#endif + +/* 10.7 TPM_STORE_PRIVKEY rev 87 + + This structure can be used in conjunction with a corresponding TPM_PUBKEY to construct a private + key which can be unambiguously used. +*/ + +#if 0 +typedef struct tdTPM_STORE_PRIVKEY { + uint32_t keyLength; /* This SHALL be the length of the key field. */ + BYTE* key; /* This SHALL be a structure interpreted according to the algorithm Id in + the corresponding TPM_KEY structure. */ +} TPM_STORE_PRIVKEY; +#endif + +/* NOTE: Hard coded for RSA keys. This will change if other algorithms are supported */ + +typedef struct tdTPM_STORE_PRIVKEY { + TPM_SIZED_BUFFER d_key; /* private key */ + TPM_SIZED_BUFFER p_key; /* private prime factor */ + TPM_SIZED_BUFFER q_key; /* private prime factor */ +} TPM_STORE_PRIVKEY; + +/* 10.6 TPM_STORE_ASYMKEY rev 87 + + The TPM_STORE_ASYMKEY structure provides the area to identify the confidential information + related to a key. This will include the private key factors for an asymmetric key. + + The structure is designed so that encryption of a TPM_STORE_ASYMKEY structure containing a 2048 + bit RSA key can be done in one operation if the encrypting key is 2048 bits. + + Using typical RSA notation the structure would include P, and when loading the key include the + unencrypted P*Q which would be used to recover the Q value. + + To accommodate the future use of multiple prime RSA keys the specification of additional prime + factors is an optional capability. + + This structure provides the basis of defining the protection of the private key. Changes in this + structure MUST be reflected in the TPM_MIGRATE_ASYMKEY structure (section 10.8). +*/ + +typedef struct tdTPM_STORE_ASYMKEY { + TPM_PAYLOAD_TYPE payload; /* This SHALL set to TPM_PT_ASYM to indicate an asymmetric + key. If used in TPM_CMK_ConvertMigration the value SHALL + be TPM_PT_MIGRATE_EXTERNAL. If used in TPM_CMK_CreateKey + the value SHALL be TPM_PT_MIGRATE_RESTRICTED */ + TPM_SECRET usageAuth; /* This SHALL be the authorization data necessary to + authorize the use of this value */ + TPM_SECRET migrationAuth; /* This SHALL be the migration authorization data for a + migratable key, or the TPM secret value tpmProof for a + non-migratable key created by the TPM. + + If the TPM sets this parameter to the value tpmProof, + then the TPM_KEY.keyFlags.migratable of the corresponding + TPM_KEY structure MUST be set to 0. + + If this parameter is set to the migration authorization + data for the key in parameter PrivKey, then the + TPM_KEY.keyFlags.migratable of the corresponding TPM_KEY + structure SHOULD be set to 1. */ + TPM_DIGEST pubDataDigest; /* This SHALL be the digest of the corresponding TPM_KEY + structure, excluding the fields TPM_KEY.encSize and + TPM_KEY.encData. + + When TPM_KEY -> pcrInfoSize is 0 then the digest + calculation has no input from the pcrInfo field. The + pcrInfoSize field MUST always be part of the digest + calculation. + */ + TPM_STORE_PRIVKEY privKey; /* This SHALL be the private key data. The privKey can be a + variable length which allows for differences in the key + format. The maximum size of the area would be 151 + bytes. */ +} TPM_STORE_ASYMKEY; + +/* 10.8 TPM_MIGRATE_ASYMKEY rev 87 + + The TPM_MIGRATE_ASYMKEY structure provides the area to identify the private key factors of a + asymmetric key while the key is migrating between TPM's. + + This structure provides the basis of defining the protection of the private key. + + k1k2 - 132 privkey.key (128 + 4) + k1 - 20, OAEP seed + k2 - 112, partPrivKey + TPM_STORE_PRIVKEY 4 partPrivKey.keyLength + 108 partPrivKey.key (128 - 20) +*/ + +typedef struct tdTPM_MIGRATE_ASYMKEY { + TPM_PAYLOAD_TYPE payload; /* This SHALL set to TPM_PT_MIGRATE or TPM_PT_CMK_MIGRATE to + indicate an migrating asymmetric key or TPM_PT_MAINT to indicate + a maintenance key. */ + TPM_SECRET usageAuth; /* This SHALL be a copy of the usageAuth from the TPM_STORE_ASYMKEY + structure. */ + TPM_DIGEST pubDataDigest; /* This SHALL be a copy of the pubDataDigest from the + TPM_STORE_ASYMKEY structure. */ +#if 0 + uint32_t partPrivKeyLen; /* This SHALL be the size of the partPrivKey field */ + BYTE *partPrivKey; /* This SHALL be the k2 area as described in TPM_CreateMigrationBlob + */ +#endif + TPM_SIZED_BUFFER partPrivKey; +} TPM_MIGRATE_ASYMKEY; + +/* 10.2 TPM_KEY rev 87 + + The TPM_KEY structure provides a mechanism to transport the entire asymmetric key pair. The + private portion of the key is always encrypted. + + The reason for using a size and pointer for the PCR info structure is save space when the key is + not bound to a PCR. The only time the information for the PCR is kept with the key is when the + key needs PCR info. + + The 1.2 version has a change in the PCRInfo area. For 1.2 the structure uses the + TPM_PCR_INFO_LONG structure to properly define the PCR registers in use. +*/ + +typedef struct tdTPM_KEY { + TPM_STRUCT_VER ver; /* This MUST be 1.1.0.0 */ + TPM_KEY_USAGE keyUsage; /* This SHALL be the TPM key usage that determines the operations + permitted with this key */ + TPM_KEY_FLAGS keyFlags; /* This SHALL be the indication of migration, redirection etc.*/ + TPM_AUTH_DATA_USAGE authDataUsage; /* This SHALL Indicate the conditions where it is required + that authorization be presented.*/ + TPM_KEY_PARMS algorithmParms; /* This SHALL be the information regarding the algorithm for + this key*/ +#if 0 + uint32_t PCRInfoSize; /* This SHALL be the length of the pcrInfo parameter. If the key is + not bound to a PCR this value SHOULD be 0.*/ + BYTE* PCRInfo; /* This SHALL be a structure of type TPM_PCR_INFO, or an empty array + if the key is not bound to PCRs.*/ + TPM_STORE_PUBKEY pubKey; /* This SHALL be the public portion of the key */ + uint32_t encDataSize; /* This SHALL be the size of the encData parameter. */ + BYTE* encData; /* This SHALL be an encrypted TPM_STORE_ASYMKEY structure or + TPM_MIGRATE_ASYMKEY structure */ +#endif + TPM_SIZED_BUFFER pcrInfo; + TPM_SIZED_BUFFER pubKey; + TPM_SIZED_BUFFER encData; + /* This SHALL be an encrypted TPM_STORE_ASYMKEY structure or TPM_MIGRATE_ASYMKEY structure */ + /* NOTE: kgold - Added these structures, a cache of PCRInfo when not NULL */ + TPM_PCR_INFO *tpm_pcr_info; /* for TPM_KEY */ + TPM_PCR_INFO_LONG *tpm_pcr_info_long; /* for TPM_KEY12 */ + /* NOTE: kgold - Added these structures. They act as a cache of the result of encData + decryption when non-NULL. In the case of internal keys (e.g. SRK) there is no encData, so + these structures are always non-NULL. */ + TPM_STORE_ASYMKEY *tpm_store_asymkey; + TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey; +} TPM_KEY; + +/* 10.3 TPM_KEY12 rev 87 + + This provides the same functionality as TPM_KEY but uses the new PCR_INFO_LONG structures and the + new structure tagging. In all other aspects this is the same structure. +*/ + +/* NOTE: The TPM_KEY12 structure is never instantiated. It is just needed for the cast of TPM_KEY + to get the TPM_KEY12->tag member. */ + +typedef struct tdTPM_KEY12 { + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_KEY12 */ + uint16_t fill; /* MUST be 0x0000 */ + TPM_KEY_USAGE keyUsage; /* This SHALL be the TPM key usage that determines the operations + permitted with this key */ + TPM_KEY_FLAGS keyFlags; /* This SHALL be the indication of migration, redirection etc. */ + TPM_AUTH_DATA_USAGE authDataUsage; /* This SHALL Indicate the conditions where it is required + that authorization be presented. */ + TPM_KEY_PARMS algorithmParms; /* This SHALL be the information regarding the algorithm for + this key */ +#if 0 + uint32_t PCRInfoSize; /* This SHALL be the length of the pcrInfo parameter. If the key is + not bound to a PCR this value SHOULD be 0. */ + BYTE* PCRInfo; /* This SHALL be a structure of type TPM_PCR_INFO_LONG, or an empty + array if the key is not bound to PCRs. */ + TPM_STORE_PUBKEY pubKey; /* This SHALL be the public portion of the key */ + uint32_t encDataSize; /* This SHALL be the size of the encData parameter. */ + BYTE* encData; /* This SHALL be an encrypted TPM_STORE_ASYMKEY structure + TPM_MIGRATE_ASYMKEY structure */ +#endif + TPM_SIZED_BUFFER pcrInfo; + TPM_SIZED_BUFFER pubKey; + TPM_SIZED_BUFFER encData; +} TPM_KEY12; + + +/* 10.5 TPM_PUBKEY rev 99 + + The TPM_PUBKEY structure contains the public portion of an asymmetric key pair. It contains all + the information necessary for its unambiguous usage. It is possible to construct this structure + from a TPM_KEY, using the algorithmParms and pubKey fields. + + The pubKey member of this structure shall contain the public key for a specific algorithm. +*/ + +typedef struct tdTPM_PUBKEY { + TPM_KEY_PARMS algorithmParms; /* This SHALL be the information regarding this key */ +#if 0 + TPM_STORE_PUBKEY pubKey; /* This SHALL be the public key information */ +#endif + TPM_SIZED_BUFFER pubKey; +} TPM_PUBKEY; + +/* 5.b. The TPM must support a minimum of 2 key slots. */ + +#ifdef TPM_KEY_HANDLES +#if (TPM_KEY_HANDLES < 2) +#error "TPM_KEY_HANDLES minimum is 2" +#endif +#endif + +/* Set the default to 3 so that there can be one owner evict key */ + +#ifndef TPM_KEY_HANDLES +#define TPM_KEY_HANDLES 3 /* entries in global TPM_KEY_HANDLE_ENTRY array */ +#endif + +/* TPM_GetCapability uses a uint_16 for the number of key slots */ + +#if (TPM_KEY_HANDLES > 0xffff) +#error "TPM_KEY_HANDLES must be less than 0x10000" +#endif + +/* The TPM does not have to support any minimum number of owner evict keys. Adjust this value to + match the amount of NV space available. An owner evict key consumes about 512 bytes. + + A value greater than (TPM_KEY_HANDLES - 2) is useless, as the TPM reserves 2 key slots for + non-owner evict keys to avoid blocking. +*/ + +#ifndef TPM_OWNER_EVICT_KEY_HANDLES +#define TPM_OWNER_EVICT_KEY_HANDLES 1 +#endif + +#if (TPM_OWNER_EVICT_KEY_HANDLES > (TPM_KEY_HANDLES - 2)) +#error "TPM_OWNER_EVICT_KEY_HANDLES too large for TPM_KEY_HANDLES" +#endif + +/* This is the version used by the TPM implementation. It is part of the global TPM state */ + +/* kgold: Added TPM_KEY member. There needs to be a mapping between a key handle + and the pointer to TPM_KEY objects, and this seems to be the right place for it. */ + +typedef struct tdTPM_KEY_HANDLE_ENTRY { + TPM_KEY_HANDLE handle; /* Handles for a key currently loaded in the TPM */ + TPM_KEY *key; /* Pointer to the key object */ + TPM_BOOL parentPCRStatus; /* TRUE if parent of this key uses PCR's */ + TPM_KEY_CONTROL keyControl; /* Attributes that can control various aspects of key usage and + manipulation. */ +} TPM_KEY_HANDLE_ENTRY; + +/* 5.12 TPM_MIGRATIONKEYAUTH rev 87 + + This structure provides the proof that the associated public key has TPM Owner authorization to + be a migration key. +*/ + +typedef struct tdTPM_MIGRATIONKEYAUTH { + TPM_PUBKEY migrationKey; /* This SHALL be the public key of the migration facility */ + TPM_MIGRATE_SCHEME migrationScheme; /* This shall be the type of migration operation.*/ + TPM_DIGEST digest; /* This SHALL be the digest value of the concatenation of + migration key, migration scheme and tpmProof */ +} TPM_MIGRATIONKEYAUTH; + +/* 5.13 TPM_COUNTER_VALUE rev 87 + + This structure returns the counter value. For interoperability, the value size should be 4 bytes. +*/ + +#define TPM_COUNTER_LABEL_SIZE 4 +#define TPM_COUNT_ID_NULL 0xffffffff /* unused value TPM_CAP_PROP_ACTIVE_COUNTER expects this + value if no counter is active */ +#define TPM_COUNT_ID_ILLEGAL 0xfffffffe /* after releasing an active counter */ + +typedef struct tdTPM_COUNTER_VALUE { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_COUNTER_VALUE */ +#endif + BYTE label[TPM_COUNTER_LABEL_SIZE]; /* The label for the counter */ + TPM_ACTUAL_COUNT counter; /* The 32-bit counter value. */ + /* NOTE: Added. TPMWG email says the specification structure is the public part, but these are + vendor specific private members. */ + TPM_SECRET authData; /* Authorization secret for counter */ + TPM_BOOL valid; + TPM_DIGEST digest; /* for OSAP comparison */ +} TPM_COUNTER_VALUE; + +/* 5.14 TPM_SIGN_INFO Structure rev 102 + + This is an addition in 1.2 and is the structure signed for certain commands (e.g., + TPM_ReleaseTransportSigned). Some commands have a structure specific to that command (e.g., + TPM_Quote uses TPM_QUOTE_INFO) and do not use TPM_SIGN_INFO. + + TPM_Sign uses this structure when the signature scheme is TPM_SS_RSASSAPKCS1v15_INFO. +*/ + +#define TPM_SIGN_INFO_FIXED_SIZE 4 + +typedef struct tdTPM_SIGN_INFO { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_SIGNINFO */ +#endif + BYTE fixed[TPM_SIGN_INFO_FIXED_SIZE]; /* The ASCII text that identifies what function was + performing the signing operation*/ + TPM_NONCE replay; /* Nonce provided by caller to prevent replay attacks */ +#if 0 + uint32_t dataLen; /* The length of the data area */ + BYTE* data; /* The data that is being signed */ +#endif + TPM_SIZED_BUFFER data; /* The data that is being signed */ +} TPM_SIGN_INFO; + +/* 5.15 TPM_MSA_COMPOSITE Structure rev 87 + + TPM_MSA_COMPOSITE contains an arbitrary number of digests of public keys belonging to Migration + Authorities. An instance of TPM_MSA_COMPOSITE is incorporated into the migrationAuth value of a + certified-migration-key (CMK), and any of the Migration Authorities specified in that instance is + able to approve the migration of that certified-migration-key. + + TPMs MUST support TPM_MSA_COMPOSITE structures with MSAlist of four (4) or less, and MAY support + larger values of MSAlist. +*/ + +typedef struct tdTPM_MSA_COMPOSITE { + uint32_t MSAlist; /* The number of migAuthDigests. MSAlist MUST be one (1) or + greater. */ + TPM_DIGEST *migAuthDigest; /* An arbitrary number of digests of public keys belonging + to Migration Authorities. */ +} TPM_MSA_COMPOSITE; + +/* 5.16 TPM_CMK_AUTH + + The signed digest of TPM_CMK_AUTH is a ticket to prove that the entity with public key + "migrationAuthority" has approved the public key "destination Key" as a migration destination for + the key with public key "sourceKey". + + Normally the digest of TPM_CMK_AUTH is signed by the private key corresponding to + "migrationAuthority". + + To reduce data size, TPM_CMK_AUTH contains just the digests of "migrationAuthority", + "destinationKey" and "sourceKey". +*/ + +typedef struct tdTPM_CMK_AUTH { + TPM_DIGEST migrationAuthorityDigest; /* The digest of the public key of a Migration + Authority */ + TPM_DIGEST destinationKeyDigest; /* The digest of a TPM_PUBKEY structure that is an + approved destination key for the private key + associated with "sourceKey"*/ + TPM_DIGEST sourceKeyDigest; /* The digest of a TPM_PUBKEY structure whose + corresponding private key is approved by the + Migration Authority to be migrated as a child to + the destinationKey. */ +} TPM_CMK_AUTH; + +/* 5.18 TPM_SELECT_SIZE rev 87 + + This structure provides the indication for the version and sizeOfSelect structure in GetCapability +*/ + +typedef struct tdTPM_SELECT_SIZE { + BYTE major; /* This SHALL indicate the major version of the TPM. This MUST be 0x01 */ + BYTE minor; /* This SHALL indicate the minor version of the TPM. This MAY be 0x01 or + 0x02 */ + uint16_t reqSize; /* This SHALL indicate the value for a sizeOfSelect field in the + TPM_SELECTION structure */ +} TPM_SELECT_SIZE; + +/* 5.19 TPM_CMK_MIGAUTH rev 89 + + Structure to keep track of the CMK migration authorization +*/ + +typedef struct tdTPM_CMK_MIGAUTH { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* Set to TPM_TAG_CMK_MIGAUTH */ +#endif + TPM_DIGEST msaDigest; /* The digest of a TPM_MSA_COMPOSITE structure containing the + migration authority public key and parameters. */ + TPM_DIGEST pubKeyDigest; /* The hash of the associated public key */ +} TPM_CMK_MIGAUTH; + +/* 5.20 TPM_CMK_SIGTICKET rev 87 + + Structure to keep track of the CMK migration authorization +*/ + +typedef struct tdTPM_CMK_SIGTICKET { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* Set to TPM_TAG_CMK_SIGTICKET */ +#endif + TPM_DIGEST verKeyDigest; /* The hash of a TPM_PUBKEY structure containing the public key and + parameters of the key that can verify the ticket */ + TPM_DIGEST signedData; /* The ticket data */ +} TPM_CMK_SIGTICKET; + +/* 5.21 TPM_CMK_MA_APPROVAL rev 87 + + Structure to keep track of the CMK migration authorization +*/ + +typedef struct tdTPM_CMK_MA_APPROVAL { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* Set to TPM_TAG_CMK_MA_APPROVAL */ +#endif + TPM_DIGEST migrationAuthorityDigest; /* The hash of a TPM_MSA_COMPOSITE structure + containing the hash of one or more migration + authority public keys and parameters. */ +} TPM_CMK_MA_APPROVAL; + +/* 20.2 Delegate Definitions rev 101 + + The delegations are in a 64-bit field. Each bit describes a capability that the TPM Owner can + delegate to a trusted process by setting that bit. Each delegation bit setting is independent of + any other delegation bit setting in a row. + + If a TPM command is not listed in the following table, then the TPM Owner cannot delegate that + capability to a trusted process. For the TPM commands that are listed in the following table, if + the bit associated with a TPM command is set to zero in the row of the table that identifies a + trusted process, then that process has not been delegated to use that TPM command. + + The minimum granularity for delegation is at the ordinal level. It is not possible to delegate an + option of an ordinal. This implies that if the options present a difficulty and there is a need + to separate the delegations then there needs to be a split into two separate ordinals. +*/ + +#define TPM_DEL_OWNER_BITS 0x00000001 +#define TPM_DEL_KEY_BITS 0x00000002 + +typedef struct tdTPM_DELEGATIONS { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_DELEGATIONS */ +#endif + uint32_t delegateType; /* Owner or key */ + uint32_t per1; /* The first block of permissions */ + uint32_t per2; /* The second block of permissions */ +} TPM_DELEGATIONS; + +/* 20.4 TPM_FAMILY_LABEL rev 85 + + Used in the family table to hold a one-byte numeric value (sequence number) that software can map + to a string of bytes that can be displayed or used by applications. + + This is not sensitive data. +*/ + +#if 0 +typedef struct tdTPM_FAMILY_LABEL { + BYTE label; /* A sequence number that software can map to a string of bytes that can be + displayed or used by the applications. This MUST not contain sensitive + information. */ +} TPM_FAMILY_LABEL; +#endif + +typedef BYTE TPM_FAMILY_LABEL; /* NOTE: No need for a structure here */ + +/* 20.5 TPM_FAMILY_TABLE_ENTRY rev 101 + + The family table entry is an individual row in the family table. There are no sensitive values in + a family table entry. + + Each family table entry contains values to facilitate table management: the familyID sequence + number value that associates a family table row with one or more delegate table rows, a + verification sequence number value that identifies when rows in the delegate table were last + verified, and BYTE family label value that software can map to an ASCII text description of the + entity using the family table entry +*/ + +typedef struct tdTPM_FAMILY_TABLE_ENTRY { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_FAMILY_TABLE_ENTRY */ +#endif + TPM_FAMILY_LABEL familyLabel; /* A sequence number that software can map to a string of + bytes that can be displayed of used by the applications. + This MUST not contain sensitive information. */ + TPM_FAMILY_ID familyID; /* The family ID in use to tie values together. This is not + a sensitive value. */ + TPM_FAMILY_VERIFICATION verificationCount; /* The value inserted into delegation rows to + indicate that they are the current generation of + rows. Used to identify when a row in the delegate + table was last verified. This is not a sensitive + value. */ + TPM_FAMILY_FLAGS flags; /* See section on TPM_FAMILY_FLAGS. */ + /* NOTE Added */ + TPM_BOOL valid; +} TPM_FAMILY_TABLE_ENTRY; + +/* 20.6 TPM_FAMILY_TABLE rev 87 + + The family table is stored in a TPM shielded location. There are no confidential values in the + family table. The family table contains a minimum of 8 rows. +*/ + +#ifdef TPM_NUM_FAMILY_TABLE_ENTRY_MIN +#if (TPM_NUM_FAMILY_TABLE_ENTRY_MIN < 8) +#error "TPM_NUM_FAMILY_TABLE_ENTRY_MIN minimum is 8" +#endif +#endif + +#ifndef TPM_NUM_FAMILY_TABLE_ENTRY_MIN +#define TPM_NUM_FAMILY_TABLE_ENTRY_MIN 8 +#endif + +typedef struct tdTPM_FAMILY_TABLE { + TPM_FAMILY_TABLE_ENTRY famTableRow[TPM_NUM_FAMILY_TABLE_ENTRY_MIN]; +} TPM_FAMILY_TABLE; + +/* 20.7 TPM_DELEGATE_LABEL rev 87 + + Used in both the delegate table and the family table to hold a string of bytes that can be + displayed or used by applications. This is not sensitive data. +*/ + +#if 0 +typedef struct tdTPM_DELEGATE_LABEL { + BYTE label; /* A byte that can be displayed or used by the applications. This MUST not + contain sensitive information. */ +} TPM_DELEGATE_LABEL; +#endif + +typedef BYTE TPM_DELEGATE_LABEL; /* NOTE: No need for structure */ + +/* 20.8 TPM_DELEGATE_PUBLIC rev 101 + + The information of a delegate row that is public and does not have any sensitive information. + + PCR_INFO_SHORT is appropriate here as the command to create this is done using owner + authorization, hence the owner authorized the command and the delegation. There is no need to + validate what configuration was controlling the platform during the blob creation. +*/ + +typedef struct tdTPM_DELEGATE_PUBLIC { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_DELEGATE_PUBLIC */ +#endif + TPM_DELEGATE_LABEL rowLabel; /* This SHALL be the label for the row. It + MUST not contain any sensitive information. */ + TPM_PCR_INFO_SHORT pcrInfo; /* This SHALL be the designation of the process that can use + the permission. This is a not sensitive + value. PCR_SELECTION may be NULL. + + If selected the pcrInfo MUST be checked on each use of + the delegation. Use of the delegation is where the + delegation is passed as an authorization handle. */ + TPM_DELEGATIONS permissions; /* This SHALL be the permissions that are allowed to the + indicated process. This is not a sensitive value. */ + TPM_FAMILY_ID familyID; /* This SHALL be the family ID that identifies which family + the row belongs to. This is not a sensitive value. */ + TPM_FAMILY_VERIFICATION verificationCount; /* A copy of verificationCount from the associated + family table. This is not a sensitive value. */ +} TPM_DELEGATE_PUBLIC; + + +/* 20.9 TPM_DELEGATE_TABLE_ROW rev 101 + + A row of the delegate table. +*/ + +typedef struct tdTPM_DELEGATE_TABLE_ROW { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_DELEGATE_TABLE_ROW */ +#endif + TPM_DELEGATE_PUBLIC pub; /* This SHALL be the public information for a table row. */ + TPM_SECRET authValue; /* This SHALL be the authorization value that can use the + permissions. This is a sensitive value. */ + /* NOTE Added */ + TPM_BOOL valid; +} TPM_DELEGATE_TABLE_ROW; + +/* 20.10 TPM_DELEGATE_TABLE rev 87 + + This is the delegate table. The table contains a minimum of 2 rows. + + This will be an entry in the TPM_PERMANENT_DATA structure. +*/ + +#ifdef TPM_NUM_DELEGATE_TABLE_ENTRY_MIN +#if (TPM_NUM_DELEGATE_TABLE_ENTRY_MIN < 2) +#error "TPM_NUM_DELEGATE_TABLE_ENTRY_MIN minimum is 2" +#endif +#endif + +#ifndef TPM_NUM_DELEGATE_TABLE_ENTRY_MIN +#define TPM_NUM_DELEGATE_TABLE_ENTRY_MIN 2 +#endif + + +typedef struct tdTPM_DELEGATE_TABLE { + TPM_DELEGATE_TABLE_ROW delRow[TPM_NUM_DELEGATE_TABLE_ENTRY_MIN]; /* The array of delegations */ +} TPM_DELEGATE_TABLE; + +/* 20.11 TPM_DELEGATE_SENSITIVE rev 115 + + The TPM_DELEGATE_SENSITIVE structure is the area of a delegate blob that contains sensitive + information. + + This structure is normative for loading unencrypted blobs before there is an owner. It is + informative for TPM_CreateOwnerDelegation and TPM_LoadOwnerDelegation after there is an owner and + encrypted blobs are used, since the structure is under complete control of the TPM. +*/ + +typedef struct tdTPM_DELEGATE_SENSITIVE { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This MUST be TPM_TAG_DELEGATE_SENSITIVE */ +#endif + TPM_SECRET authValue; /* AuthData value */ +} TPM_DELEGATE_SENSITIVE; + +/* 20.12 TPM_DELEGATE_OWNER_BLOB rev 87 + + This data structure contains all the information necessary to externally store a set of owner + delegation rights that can subsequently be loaded or used by this TPM. + + The encryption mechanism for the sensitive area is a TPM choice. The TPM may use asymmetric + encryption and the SRK for the key. The TPM may use symmetric encryption and a secret key known + only to the TPM. +*/ + +typedef struct tdTPM_DELEGATE_OWNER_BLOB { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This MUST be TPM_TAG_DELG_OWNER_BLOB */ +#endif + TPM_DELEGATE_PUBLIC pub; /* The public information for this blob */ + TPM_DIGEST integrityDigest; /* The HMAC to guarantee the integrity of the entire structure */ + TPM_SIZED_BUFFER additionalArea; /* An area that the TPM can add to the blob which MUST NOT + contain any sensitive information. This would include any + IV material for symmetric encryption */ + TPM_SIZED_BUFFER sensitiveArea; /* The area that contains the encrypted + TPM_DELEGATE_SENSITIVE */ +} TPM_DELEGATE_OWNER_BLOB; + +/* 20.13 TPM_DELEGATE_KEY_BLOB rev 87 + + A structure identical to TPM_DELEGATE_OWNER_BLOB but which stores delegation information for user + keys. As compared to TPM_DELEGATE_OWNER_BLOB, it adds a hash of the corresponding public key + value to the public information. +*/ + +typedef struct tdTPM_DELEGATE_KEY_BLOB { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This MUST be TPM_TAG_DELG_KEY_BLOB */ +#endif + TPM_DELEGATE_PUBLIC pub; /* The public information for this blob */ + TPM_DIGEST integrityDigest; /* The HMAC to guarantee the integrity of the entire + structure */ + TPM_DIGEST pubKeyDigest; /* The digest, that uniquely identifies the key for which + this usage delegation applies. */ + TPM_SIZED_BUFFER additionalArea; /* An area that the TPM can add to the blob which MUST NOT + contain any sensitive information. This would include any + IV material for symmetric encryption */ + TPM_SIZED_BUFFER sensitiveArea; /* The area that contains the encrypted + TPM_DELEGATE_SENSITIVE */ +} TPM_DELEGATE_KEY_BLOB; + +/* 15.1 TPM_CURRENT_TICKS rev 110 + + This structure holds the current number of time ticks in the TPM. The value is the number of time + ticks from the start of the current session. Session start is a variable function that is + platform dependent. Some platforms may have batteries or other power sources and keep the TPM + clock session across TPM initialization sessions. + + The element of the TPM_CURRENT_TICKS structure provides the number of microseconds per + tick. The platform manufacturer must satisfy input clock requirements set by the TPM vendor to + ensure the accuracy of the tickRate. + + No external entity may ever set the current number of time ticks held in TPM_CURRENT_TICKS. This + value is always reset to 0 when a new clock session starts and increments under control of the + TPM. + + Maintaining the relationship between the number of ticks counted by the TPM and some real world + clock is a task for external software. +*/ + +/* This is not a true UINT64, but a special structure to hold currentTicks */ + +typedef struct tdTPM_UINT64 { + uint32_t sec; + uint32_t usec; +} TPM_UINT64; + +typedef struct tdTPM_CURRENT_TICKS { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_CURRENT_TICKS */ +#endif + TPM_UINT64 currentTicks; /* The number of ticks since the start of this tick session */ + /* upper is seconds, lower is useconds */ + uint16_t tickRate; /* The number of microseconds per tick. The maximum resolution of + the TPM tick counter is thus 1 microsecond. The minimum + resolution SHOULD be 1 millisecond. */ + TPM_NONCE tickNonce; /* TPM_NONCE tickNonce The nonce created by the TPM when resetting + the currentTicks to 0. This indicates the beginning of a time + session. This value MUST be valid before the first use of + TPM_CURRENT_TICKS. The value can be set at TPM_Startup or just + prior to first use. */ + /* NOTE Added */ + TPM_UINT64 initialTime; /* Time from TPM_GetTimeOfDay() */ +} TPM_CURRENT_TICKS; + +/* + 13. Transport Structures +*/ + +/* 13.1 TPM _TRANSPORT_PUBLIC rev 87 + + The public information relative to a transport session +*/ + +typedef struct tdTPM_TRANSPORT_PUBLIC { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_PUBLIC */ +#endif + TPM_TRANSPORT_ATTRIBUTES transAttributes; /* The attributes of this session */ + TPM_ALGORITHM_ID algId; /* This SHALL be the algorithm identifier of the + symmetric key. */ + TPM_ENC_SCHEME encScheme; /* This SHALL fully identify the manner in which the + key will be used for encryption operations. */ +} TPM_TRANSPORT_PUBLIC; + +/* 13.2 TPM_TRANSPORT_INTERNAL rev 88 + + The internal information regarding transport session +*/ + +/* 7.6 TPM_STANY_DATA */ + +#ifdef TPM_MIN_TRANS_SESSIONS +#if (TPM_MIN_TRANS_SESSIONS < 3) +#error "TPM_MIN_TRANS_SESSIONS minimum is 3" +#endif +#endif + +#ifndef TPM_MIN_TRANS_SESSIONS +#define TPM_MIN_TRANS_SESSIONS 3 +#endif + +typedef struct tdTPM_TRANSPORT_INTERNAL { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_INTERNAL */ +#endif + TPM_AUTHDATA authData; /* The shared secret for this session */ + TPM_TRANSPORT_PUBLIC transPublic; /* The public information of this session */ + TPM_TRANSHANDLE transHandle; /* The handle for this session */ + TPM_NONCE transNonceEven; /* The even nonce for the rolling protocol */ + TPM_DIGEST transDigest; /* The log of transport events */ + /* added kgold */ + TPM_BOOL valid; /* entry is valid */ +} TPM_TRANSPORT_INTERNAL; + +/* 13.3 TPM_TRANSPORT_LOG_IN rev 87 + + The logging of transport commands occurs in two steps, before execution with the input + parameters and after execution with the output parameters. + + This structure is in use for input log calculations. +*/ + +typedef struct tdTPM_TRANSPORT_LOG_IN { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_LOG_IN */ +#endif + TPM_DIGEST parameters; /* The actual parameters contained in the digest are subject to the + rules of the command using this structure. To find the exact + calculation refer to the actions in the command using this + structure. */ + TPM_DIGEST pubKeyHash; /* The hash of any keys in the transport command */ +} TPM_TRANSPORT_LOG_IN; + +/* 13.4 TPM_TRANSPORT_LOG_OUT rev 88 + + The logging of transport commands occurs in two steps, before execution with the input parameters + and after execution with the output parameters. + + This structure is in use for output log calculations. + + This structure is in use for the INPUT logging during releaseTransport. +*/ + +typedef struct tdTPM_TRANSPORT_LOG_OUT { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_LOG_OUT */ +#endif + TPM_CURRENT_TICKS currentTicks; /* The current tick count. This SHALL be the value of the + current TPM tick counter. */ + TPM_DIGEST parameters; /* The actual parameters contained in the digest are subject + to the rules of the command using this structure. To find + the exact calculation refer to the actions in the command + using this structure. */ + TPM_MODIFIER_INDICATOR locality; /* The locality that called TPM_ExecuteTransport */ +} TPM_TRANSPORT_LOG_OUT; + +/* 13.5 TPM_TRANSPORT_AUTH structure rev 87 + + This structure provides the validation for the encrypted AuthData value. +*/ + +typedef struct tdTPM_TRANSPORT_AUTH { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_AUTH */ +#endif + TPM_AUTHDATA authData; /* The AuthData value */ +} TPM_TRANSPORT_AUTH; + +/* 22.3 TPM_DAA_ISSUER rev 91 + + This structure is the abstract representation of non-secret settings controlling a DAA + context. The structure is required when loading public DAA data into a TPM. TPM_DAA_ISSUER + parameters are normally held outside the TPM as plain text data, and loaded into a TPM when a DAA + session is required. A TPM_DAA_ISSUER structure contains no integrity check: the TPM_DAA_ISSUER + structure at time of JOIN is indirectly verified by the issuer during the JOIN process, and a + digest of the verified TPM_DAA_ISSUER structure is held inside the TPM_DAA_TPM structure created + by the JOIN process. Parameters DAA_digest_X are digests of public DAA_generic_X parameters, and + used to verify that the correct value of DAA_generic_X has been loaded. DAA_generic_q is stored + in its native form to reduce command complexity. +*/ + +typedef struct tdTPM_DAA_ISSUER { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_ISSUER */ +#endif + TPM_DIGEST DAA_digest_R0; /* A digest of the parameter "R0", which is not secret and may be + common to many TPMs. */ + TPM_DIGEST DAA_digest_R1; /* A digest of the parameter "R1", which is not secret and may be + common to many TPMs. */ + TPM_DIGEST DAA_digest_S0; /* A digest of the parameter "S0", which is not secret and may be + common to many TPMs. */ + TPM_DIGEST DAA_digest_S1; /* A digest of the parameter "S1", which is not secret and may be + common to many TPMs. */ + TPM_DIGEST DAA_digest_n; /* A digest of the parameter "n", which is not secret and may be + common to many TPMs. */ + TPM_DIGEST DAA_digest_gamma; /* A digest of the parameter "gamma", which is not secret + and may be common to many TPMs. */ + BYTE DAA_generic_q[26]; /* The parameter q, which is not secret and may be common to + many TPMs. Note that q is slightly larger than a digest, + but is stored in its native form to simplify the + TPM_DAA_join command. Otherwise, JOIN requires 3 input + parameters. */ +} TPM_DAA_ISSUER; + +/* 22.4 TPM_DAA_TPM rev 91 + + This structure is the abstract representation of TPM specific parameters used during a DAA + context. TPM-specific DAA parameters may be stored outside the TPM, and hence this + structure is needed to save private DAA data from a TPM, or load private DAA data into a + TPM. + + If a TPM_DAA_TPM structure is stored outside the TPM, it is stored in a confidential format that + can be interpreted only by the TPM created it. This is to ensure that secret parameters are + rendered confidential, and that both secret and non-secret data in TPM_DAA_TPM form a + self-consistent set. + + TPM_DAA_TPM includes a digest of the public DAA parameters that were used during creation of the + TPM_DAA_TPM structure. This is needed to verify that a TPM_DAA_TPM is being used with the public + DAA parameters used to create the TPM_DAA_TPM structure. Parameters DAA_digest_v0 and + DAA_digest_v1 are digests of public DAA_private_v0 and DAA_private_v1 parameters, and used to + verify that the correct private parameters have been loaded. + + Parameter DAA_count is stored in its native form, because it is smaller than a digest, and is + required to enforce consistency. +*/ + +typedef struct tdTPM_DAA_TPM { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_TPM */ +#endif + TPM_DIGEST DAA_digestIssuer; /* A digest of a TPM_DAA_ISSUER structure that contains the + parameters used to generate this TPM_DAA_TPM + structure. */ + TPM_DIGEST DAA_digest_v0; /* A digest of the parameter "v0", which is secret and specific to + this TPM. "v0" is generated during a JOIN phase. */ + TPM_DIGEST DAA_digest_v1; /* A digest of the parameter "v1", which is secret and specific to + this TPM. "v1" is generated during a JOIN phase. */ + TPM_DIGEST DAA_rekey; /* A digest related to the rekeying process, which is not secret but + is specific to this TPM, and must be consistent across JOIN/SIGN + sessions. "rekey" is generated during a JOIN phase. */ + uint32_t DAA_count; /* The parameter "count", which is not secret but must be consistent + across JOIN/SIGN sessions. "count" is an input to the TPM from + the host system. */ +} TPM_DAA_TPM; + +/* 22.5 TPM_DAA_CONTEXT rev 91 + + TPM_DAA_CONTEXT structure is created and used inside a TPM, and never leaves the TPM. This + entire section is informative as the TPM does not expose this structure. TPM_DAA_CONTEXT + includes a digest of the public and private DAA parameters that were used during creation of the + TPM_DAA_CONTEXT structure. This is needed to verify that a TPM_DAA_CONTEXT is being used with the + public and private DAA parameters used to create the TPM_DAA_CONTEXT structure. +*/ + +typedef struct tdTPM_DAA_CONTEXT { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_CONTEXT */ +#endif + TPM_DIGEST DAA_digestContext; /* A digest of parameters used to generate this + structure. The parameters vary, depending on whether the + session is a JOIN session or a SIGN session. */ + TPM_DIGEST DAA_digest; /* A running digest of certain parameters generated during DAA + computation; operationally the same as a PCR (which holds a + running digest of integrity metrics). */ + TPM_DAA_CONTEXT_SEED DAA_contextSeed; /* The seed used to generate other DAA + session parameters */ + BYTE DAA_scratch[256]; /* Memory used to hold different parameters at different + times of DAA computation, but only one parameter at a + time. The maximum size of this field is 256 bytes */ + BYTE DAA_stage; /* A counter, indicating the stage of DAA computation that was most + recently completed. The value of the counter is zero if the TPM + currently contains no DAA context. + + When set to zero (0) the TPM MUST clear all other fields in this + structure. + + The TPM MUST set DAA_stage to 0 on TPM_Startup(ANY) */ + TPM_BOOL DAA_scratch_null; +} TPM_DAA_CONTEXT; + +/* 22.6 TPM_DAA_JOINDATA rev 91 + + This structure is the abstract representation of data that exists only during a specific JOIN + session. +*/ + +typedef struct tdTPM_DAA_JOINDATA { + BYTE DAA_join_u0[128]; /* A TPM-specific secret "u0", used during the JOIN phase, + and discarded afterwards. */ + BYTE DAA_join_u1[138]; /* A TPM-specific secret "u1", used during the JOIN phase, + and discarded afterwards. */ + TPM_DIGEST DAA_digest_n0; /* A digest of the parameter "n0", which is an RSA public key with + exponent 2^16 +1 */ +} TPM_DAA_JOINDATA; + +/* DAA Session structure + +*/ + +#ifdef TPM_MIN_DAA_SESSIONS +#if (TPM_MIN_DAA_SESSIONS < 1) +#error "TPM_MIN_DAA_SESSIONS minimum is 1" +#endif +#endif + +#ifndef TPM_MIN_DAA_SESSIONS +#define TPM_MIN_DAA_SESSIONS 1 +#endif + +typedef struct tdTPM_DAA_SESSION_DATA { + TPM_DAA_ISSUER DAA_issuerSettings; /* A set of DAA issuer parameters controlling a DAA + session. (non-secret) */ + TPM_DAA_TPM DAA_tpmSpecific; /* A set of DAA parameters associated with a + specific TPM. (secret) */ + TPM_DAA_CONTEXT DAA_session; /* A set of DAA parameters associated with a DAA + session. (secret) */ + TPM_DAA_JOINDATA DAA_joinSession; /* A set of DAA parameters used only during the JOIN + phase of a DAA session, and generated by the + TPM. (secret) */ + /* added kgold */ + TPM_HANDLE daaHandle; /* DAA session handle */ + TPM_BOOL valid; /* array entry is valid */ + /* FIXME should have handle type Join or Sign */ +} TPM_DAA_SESSION_DATA; + +/* 22.8 TPM_DAA_BLOB rev 98 + + The structure passed during the join process +*/ + +typedef struct tdTPM_DAA_BLOB { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_BLOB */ +#endif + TPM_RESOURCE_TYPE resourceType; /* The resource type: enc(DAA_tpmSpecific) or enc(v0) or + enc(v1) */ + BYTE label[16]; /* Label for identification of the blob. Free format + area. */ + TPM_DIGEST blobIntegrity; /* The integrity of the entire blob including the sensitive + area. This is a HMAC calculation with the entire + structure (including sensitiveData) being the hash and + daaProof is the secret */ + TPM_SIZED_BUFFER additionalData; /* Additional information set by the TPM that helps define + and reload the context. The information held in this area + MUST NOT expose any information held in shielded + locations. This should include any IV for symmetric + encryption */ + TPM_SIZED_BUFFER sensitiveData; /* A TPM_DAA_SENSITIVE structure */ +#if 0 + uint32_t additionalSize; + [size_is(additionalSize)] BYTE* additionalData; + uint32_t sensitiveSize; + [size_is(sensitiveSize)] BYTE* sensitiveData; +#endif +} TPM_DAA_BLOB; + +/* 22.9 TPM_DAA_SENSITIVE rev 91 + + The encrypted area for the DAA parameters +*/ + +typedef struct tdTPM_DAA_SENSITIVE { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_SENSITIVE */ +#endif + TPM_SIZED_BUFFER internalData; /* DAA_tpmSpecific or DAA_private_v0 or DAA_private_v1 */ +#if 0 + uint32_t internalSize; + [size_is(internalSize)] BYTE* internalData; +#endif +} TPM_DAA_SENSITIVE; + +/* 7.1 TPM_PERMANENT_FLAGS rev 110 + + These flags maintain state information for the TPM. The values are not affected by any + TPM_Startup command. + + The flag history includes: + + Rev 62 specLevel 1 errataRev 0: 15 BOOLs + Rev 85 specLevel 2 errataRev 0: 19 BOOLs + Added: nvLocked, readSRKPub, tpmEstablished, maintenanceDone + Rev 94 specLevel 2 errataRev 1: 19 BOOLs + Rev 103 specLevel 2 errataRev 2: 20 BOOLs + Added: disableFullDALogicInfo +*/ + +typedef struct tdTPM_PERMANENT_FLAGS { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_PERMANENT_FLAGS */ +#endif + TPM_BOOL disable; /* disable The state of the disable flag. The default state is TRUE + */ + TPM_BOOL ownership; /* The ability to install an owner. The default state is TRUE. */ + TPM_BOOL deactivated; /* The state of the inactive flag. The default state is TRUE. */ + TPM_BOOL readPubek; /* The ability to read the PUBEK without owner authorization. The + default state is TRUE. + + set TRUE on owner clear + set FALSE on take owner, disablePubekRead + */ + TPM_BOOL disableOwnerClear; /* Whether the owner authorized clear commands are active. The + default state is FALSE. */ + TPM_BOOL allowMaintenance; /* Whether the TPM Owner may create a maintenance archive. The + default state is TRUE. */ + TPM_BOOL physicalPresenceLifetimeLock; /* This bit can only be set to TRUE; it cannot be set to + FALSE except during the manufacturing process. + + FALSE: The state of either physicalPresenceHWEnable or + physicalPresenceCMDEnable MAY be changed. (DEFAULT) + + TRUE: The state of either physicalPresenceHWEnable or + physicalPresenceCMDEnable MUST NOT be changed for the + life of the TPM. */ + TPM_BOOL physicalPresenceHWEnable; /* FALSE: Disable the hardware signal indicating physical + presence. (DEFAULT) + + TRUE: Enables the hardware signal indicating physical + presence. */ + TPM_BOOL physicalPresenceCMDEnable; /* FALSE: Disable the command indicating physical + presence. (DEFAULT) + + TRUE: Enables the command indicating physical + presence. */ + TPM_BOOL CEKPUsed; /* TRUE: The PRIVEK and PUBEK were created using + TPM_CreateEndorsementKeyPair. + + FALSE: The PRIVEK and PUBEK were created using a manufacturer's + process. NOTE: This flag has no default value as the key pair + MUST be created by one or the other mechanism. */ + TPM_BOOL TPMpost; /* TRUE: After TPM_Startup, if there is a call to + TPM_ContinueSelfTest the TPM MUST execute the actions of + TPM_SelfTestFull + + FALSE: After TPM_Startup, if there is a call to + TPM_ContinueSelfTest the TPM MUST execute TPM_ContinueSelfTest + + If the TPM supports the implicit invocation of + TPM_ContinueSelftTest upon the use of an untested resource, the + TPM MUST use the TPMPost flag to call either TPM_ContinueSelfTest + or TPM_SelfTestFull + + The TPM manufacturer sets this bit during TPM manufacturing and + the bit is unchangeable after shipping the TPM + + The default state is FALSE */ + TPM_BOOL TPMpostLock; /* With the clarification of TPMPost TPMpostLock is now + unnecessary. + This flag is now deprecated */ + TPM_BOOL FIPS; /* TRUE: This TPM operates in FIPS mode + FALSE: This TPM does NOT operate in FIPS mode */ + TPM_BOOL tpmOperator; /* TRUE: The operator authorization value is valid + FALSE: the operator authorization value is not set */ + TPM_BOOL enableRevokeEK; /* TRUE: The TPM_RevokeTrust command is active + FALSE: the TPM RevokeTrust command is disabled */ + TPM_BOOL nvLocked; /* TRUE: All NV area authorization checks are active + FALSE: No NV area checks are performed, except for maxNVWrites. + FALSE is the default value */ + TPM_BOOL readSRKPub; /* TRUE: GetPubKey will return the SRK pub key + FALSE: GetPubKey will not return the SRK pub key + Default SHOULD be FALSE */ + TPM_BOOL tpmEstablished; /* TRUE: TPM_HASH_START has been executed at some time + FALSE: TPM_HASH_START has not been executed at any time + Default is FALSE - resets using TPM_ResetEstablishmentBit */ + TPM_BOOL maintenanceDone; /* TRUE: A maintenance archive has been created for the current + SRK */ +#if (TPM_REVISION >= 103) /* added for rev 103 */ + TPM_BOOL disableFullDALogicInfo; /* TRUE: The full dictionary attack TPM_GetCapability info is + deactivated. The returned structure is TPM_DA_INFO_LIMITED. + FALSE: The full dictionary attack TPM_GetCapability info is + activated. The returned structure is TPM_DA_INFO. + Default is FALSE. + */ +#endif + /* NOTE: Cannot add vendor specific flags here, since TPM_GetCapability() returns the serialized + structure */ +} TPM_PERMANENT_FLAGS; + +/* 7.2 TPM_STCLEAR_FLAGS rev 109 + + These flags maintain state that is reset on each TPM_Startup(ST_Clear) command. The values are + not affected by TPM_Startup(ST_State) commands. +*/ + +typedef struct tdTPM_STCLEAR_FLAGS { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_STCLEAR_FLAGS */ +#endif + TPM_BOOL deactivated; /* Prevents the operation of most capabilities. There is no + default state. It is initialized by TPM_Startup to the + same value as TPM_PERMANENT_FLAGS -> + deactivated. TPM_SetTempDeactivated sets it to TRUE. */ + TPM_BOOL disableForceClear; /* Prevents the operation of TPM_ForceClear when TRUE. The + default state is FALSE. TPM_DisableForceClear sets it to + TRUE. */ + TPM_BOOL physicalPresence; /* Command assertion of physical presence. The default state + is FALSE. This flag is affected by the + TSC_PhysicalPresence command but not by the hardware + signal. */ + TPM_BOOL physicalPresenceLock; /* Indicates whether changes to the TPM_STCLEAR_FLAGS -> + physicalPresence flag are permitted. + TPM_Startup(ST_CLEAR) sets PhysicalPresenceLock to its + default state of FALSE (allow changes to the + physicalPresence flag). When TRUE, the physicalPresence + flag is FALSE. TSC_PhysicalPresence can change the state + of physicalPresenceLock. */ + TPM_BOOL bGlobalLock; /* Set to FALSE on each TPM_Startup(ST_CLEAR). Set to TRUE + when a write to NV_Index =0 is successful */ + /* NOTE: Cannot add vendor specific flags here, since TPM_GetCapability() returns the serialized + structure */ +} TPM_STCLEAR_FLAGS; + + +/* 7.3 TPM_STANY_FLAGS rev 87 + + These flags reset on any TPM_Startup command. +*/ + +typedef struct tdTPM_STANY_FLAGS { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_STANY_FLAGS */ +#endif + TPM_BOOL postInitialise; /* Prevents the operation of most capabilities. There is no default + state. It is initialized by TPM_Init to TRUE. TPM_Startup sets it + to FALSE. */ + TPM_MODIFIER_INDICATOR localityModifier; /*This SHALL indicate for each command the presence of + a locality modifier for the command. It MUST be set + to NULL after the TPM executes each command. */ +#if 0 + TPM_BOOL transportExclusive; /* Defaults to FALSE. TRUE when there is an exclusive transport + session active. Execution of ANY command other than + TPM_ExecuteTransport or TPM_ReleaseTransportSigned MUST + invalidate the exclusive transport session. */ +#endif + TPM_TRANSHANDLE transportExclusive; /* Defaults to 0x00000000, Set to the handle when an + exclusive transport session is active */ + TPM_BOOL TOSPresent; /* Defaults to FALSE + Set to TRUE on TPM_HASH_START + set to FALSE using setCapability */ + /* NOTE: Added kgold */ + TPM_BOOL stateSaved; /* Defaults to FALSE + Set to TRUE on TPM_SaveState + Set to FALSE on any other ordinal + + This is an optimization flag, so the file need not be deleted if + it does not exist. + */ +} TPM_STANY_FLAGS; + +/* 7.4 TPM_PERMANENT_DATA rev 105 + + This structure contains the data fields that are permanently held in the TPM and not affected by + TPM_Startup(any). + + Many of these fields contain highly confidential and privacy sensitive material. The TPM must + maintain the protections around these fields. +*/ + +#ifdef TPM_MIN_COUNTERS +#if (TPM_MIN_COUNTERS < 4) +#error "TPM_MIN_COUNTERS minimum is 4" +#endif +#endif + +#ifndef TPM_MIN_COUNTERS +#define TPM_MIN_COUNTERS 4 /* the minimum number of counters is 4 */ +#endif + +#define TPM_DELEGATE_KEY TPM_KEY +#define TPM_MAX_NV_WRITE_NOOWNER 64 + +/* Although the ordinal is 32 bits, only the lower 8 bits seem to be used. So for now, define an + array of 256/8 bytes for ordinalAuditStatus - kgold */ + +#define TPM_ORDINALS_MAX 256 /* assumes a multiple of CHAR_BIT */ +#define TPM_AUTHDIR_SIZE 1 /* Number of DIR registers */ + + + + +typedef struct tdTPM_PERMANENT_DATA { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_PERMANENT_DATA */ +#endif + BYTE revMajor; /* This is the TPM major revision indicator. This SHALL be set by + the TPME, only. The default value is manufacturer-specific. */ + BYTE revMinor; /* This is the TPM minor revision indicator. This SHALL be set by + the TPME, only. The default value is manufacturer-specific. */ + TPM_SECRET tpmProof; /* This is a random number that each TPM maintains to validate blobs + in the SEAL and other processes. The default value is + manufacturer-specific. */ + TPM_NONCE EKReset; /* Nonce held by TPM to validate TPM_RevokeTrust. This value is set + as the next 20 bytes from the TPM RNG when the EK is set + (was fipsReset - kgold) */ + TPM_SECRET ownerAuth; /* This is the TPM-Owner's authorization data. The default value is + manufacturer-specific. */ + TPM_SECRET operatorAuth; /* The value that allows the execution of the SetTempDeactivated + command */ + TPM_DIRVALUE authDIR; /* The array of TPM Owner authorized DIR. Points to the same + location as the NV index value. (kgold - was array of 1) */ +#ifndef TPM_NOMAINTENANCE + TPM_PUBKEY manuMaintPub; /* This is the manufacturer's public key to use in the maintenance + operations. The default value is manufacturer-specific. */ +#endif + TPM_KEY endorsementKey; /* This is the TPM's endorsement key pair. */ + TPM_KEY srk; /* This is the TPM's StorageRootKey. */ + TPM_SYMMETRIC_KEY_TOKEN contextKey; /* This is the key in use to perform context saves. The key + may be symmetric or asymmetric. The key size is + predicated by the algorithm in use. */ + TPM_SYMMETRIC_KEY_TOKEN delegateKey; /* This key encrypts delegate rows that are stored + outside the TPM. */ + TPM_COUNTER_VALUE auditMonotonicCounter; /* This SHALL be the audit monotonic counter for the + TPM. This value starts at 0 and increments + according to the rules of auditing */ + TPM_COUNTER_VALUE monotonicCounter[TPM_MIN_COUNTERS]; /* This SHALL be the monotonic + counters for the TPM. The + individual counters start and + increment according to the rules + of monotonic counters. */ + TPM_PCR_ATTRIBUTES pcrAttrib[TPM_NUM_PCR]; /* The attributes for all of the PCR registers + supported by the TPM. */ + BYTE ordinalAuditStatus[TPM_ORDINALS_MAX/CHAR_BIT]; /* Table indicating which ordinals are being + audited. */ +#if 0 + /* kgold - The xcrypto RNG is good enough that this is not needed */ + BYTE* rngState; /* State information describing the random number + generator. */ +#endif + TPM_FAMILY_TABLE familyTable; /* The family table in use for delegations */ + TPM_DELEGATE_TABLE delegateTable; /* The delegate table */ + uint32_t lastFamilyID; /* A value that sets the high water mark for family ID's. Set to 0 + during TPM manufacturing and never reset. */ + uint32_t noOwnerNVWrite; /* The count of NV writes that have occurred when there is no TPM + Owner. + + This value starts at 0 in manufacturing and after each + TPM_OwnerClear. If the value exceeds 64 the TPM returns + TPM_MAXNVWRITES to any command attempting to manipulate the NV + storage. */ + TPM_CMK_DELEGATE restrictDelegate; /* The settings that allow for the delegation and + use on CMK keys. Default value is false. */ + TPM_DAA_TPM_SEED tpmDAASeed; /* This SHALL be a random value generated after generation + of the EK. + + tpmDAASeed does not change during TPM Owner changes. If + the EK is removed (RevokeTrust) then the TPM MUST + invalidate the tpmDAASeed. The owner can force a change + in the value through TPM_SetCapability. + + (linked to daaProof) */ + TPM_NONCE daaProof; /* This is a random number that each TPM maintains to validate blobs + in the DAA processes. The default value is manufacturer-specific. + + The value is not changed when the owner is changed. It is + changed when the EK changes. The owner can force a change in the + value through TPM_SetCapability. */ + TPM_SYMMETRIC_KEY_TOKEN daaBlobKey; /* This is the key in use to perform DAA encryption and + decryption. The key may be symmetric or asymmetric. The + key size is predicated by the algorithm in use. + + This value MUST be changed when daaProof changes. + + This key MUST NOT be a copy of the EK or SRK. + + (linked to daaProof) */ + /* NOTE: added kgold */ + TPM_BOOL ownerInstalled; /* TRUE: The TPM has an owner installed. + FALSE: The TPM has no owner installed. (default) */ + BYTE tscOrdinalAuditStatus; /* extra byte to track TSC ordinals */ + TPM_BOOL allowLoadMaintPub; /* TRUE allows the TPM_LoadManuMaintPub command */ + +} TPM_PERMANENT_DATA; + +/* 7.6 TPM_STANY_DATA */ + +#ifdef TPM_MIN_AUTH_SESSIONS +#if (TPM_MIN_AUTH_SESSIONS < 3) +#error "TPM_MIN_AUTH_SESSIONS minimum is 3" +#endif +#endif + +#ifndef TPM_MIN_AUTH_SESSIONS +#define TPM_MIN_AUTH_SESSIONS 3 +#endif + +/* NOTE: Vendor specific */ + +typedef struct tdTPM_AUTH_SESSION_DATA { + /* vendor specific */ + TPM_AUTHHANDLE handle; /* Handle for a session */ + TPM_PROTOCOL_ID protocolID; /* TPM_PID_OIAP, TPM_PID_OSAP, TPM_PID_DSAP */ + TPM_ENT_TYPE entityTypeByte; /* The type of entity in use (TPM_ET_SRK, TPM_ET_OWNER, + TPM_ET_KEYHANDLE ... */ + TPM_ADIP_ENC_SCHEME adipEncScheme; /* ADIP encryption scheme */ + TPM_NONCE nonceEven; /* OIAP, OSAP, DSAP */ + TPM_SECRET sharedSecret; /* OSAP */ + TPM_DIGEST entityDigest; /* OSAP tracks which entity established the OSAP session */ + TPM_DELEGATE_PUBLIC pub; /* DSAP */ + TPM_BOOL valid; /* added kgold: array entry is valid */ +} TPM_AUTH_SESSION_DATA; + + +/* 3. contextList MUST support a minimum of 16 entries, it MAY support more. */ + +#ifdef TPM_MIN_SESSION_LIST +#if (TPM_MIN_SESSION_LIST < 16) +#error "TPM_MIN_SESSION_LIST minimum is 16" +#endif +#endif + +#ifndef TPM_MIN_SESSION_LIST +#define TPM_MIN_SESSION_LIST 16 +#endif + +/* 7.5 TPM_STCLEAR_DATA rev 101 + + This is an informative structure and not normative. It is purely for convenience of writing the + spec. + + Most of the data in this structure resets on TPM_Startup(ST_Clear). A TPM may implement rules + that provide longer-term persistence for the data. The TPM reflects how it handles the data in + various TPM_GetCapability fields including startup effects. +*/ + +typedef struct tdTPM_STCLEAR_DATA { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_STCLEAR_DATA */ +#endif + TPM_NONCE contextNonceKey; /* This is the nonce in use to properly identify saved key context + blobs This SHALL be set to all zeros on each TPM_Startup + (ST_Clear). + */ + TPM_COUNT_ID countID; /* This is the handle for the current monotonic counter. This SHALL + be set to zero on each TPM_Startup(ST_Clear). */ + uint32_t ownerReference; /* Points to where to obtain the owner secret in OIAP and OSAP + commands. This allows a TSS to manage 1.1 applications on a 1.2 + TPM where delegation is in operation. */ + TPM_BOOL disableResetLock; /* Disables TPM_ResetLockValue upon authorization failure. + The value remains TRUE for the timeout period. + + Default is FALSE. + + The value is in the STCLEAR_DATA structure as the + implementation of this flag is TPM vendor specific. */ + TPM_PCRVALUE PCRS[TPM_NUM_PCR]; /* Platform configuration registers */ +#if (TPM_REVISION >= 103) /* added for rev 103 */ + uint32_t deferredPhysicalPresence; /* The value can save the assertion of physicalPresence. + Individual bits indicate to its ordinal that + physicalPresence was previously asserted when the + software state is such that it can no longer be asserted. + Set to zero on each TPM_Startup(ST_Clear). */ +#endif + /* NOTE: Added for dictionary attack mitigation */ + uint32_t authFailCount; /* number of authorization failures without a TPM_ResetLockValue */ + uint32_t authFailTime; /* time of threshold failure in seconds */ + /* NOTE: Moved from TPM_STANY_DATA. Saving this state is optional. This implementation + does. */ + TPM_AUTH_SESSION_DATA authSessions[TPM_MIN_AUTH_SESSIONS]; /* List of current + sessions. Sessions can be OSAP, + OIAP, DSAP and Transport */ + /* NOTE: Added for transport */ + TPM_TRANSPORT_INTERNAL transSessions[TPM_MIN_TRANS_SESSIONS]; + /* 22.7 TPM_STANY_DATA Additions (for DAA) - moved to TPM_STCLEAR_DATA for startup state */ + TPM_DAA_SESSION_DATA daaSessions[TPM_MIN_DAA_SESSIONS]; + /* 1. The group of contextNonceSession, contextCount, contextList MUST reset at the same + time. */ + TPM_NONCE contextNonceSession; /* This is the nonce in use to properly identify saved + session context blobs. This MUST be set to all zeros on + each TPM_Startup (ST_Clear). The nonce MAY be set to + null on TPM_Startup( any). */ + uint32_t contextCount; /* This is the counter to avoid session context blob replay + attacks. This MUST be set to 0 on each TPM_Startup + (ST_Clear). The value MAY be set to 0 on TPM_Startup + (any). */ + uint32_t contextList[TPM_MIN_SESSION_LIST]; /* This is the list of outstanding session blobs. + All elements of this array MUST be set to 0 on + each TPM_Startup (ST_Clear). The values MAY be + set to 0 on TPM_Startup (any). */ + /* NOTE Added auditDigest effect, saved with ST_STATE */ + TPM_DIGEST auditDigest; /* This is the extended value that is the audit log. This + SHALL be set to all zeros at the start of each audit + session. */ + /* NOTE Storage for the ordinal response */ + TPM_STORE_BUFFER ordinalResponse; /* outgoing response buffer for this ordinal */ +} TPM_STCLEAR_DATA; + +/* 7.6 TPM_STANY_DATA rev 87 + + This is an informative structure and not normative. It is purely for convenience of writing the + spec. + + Most of the data in this structure resets on TPM_Startup(ST_State). A TPM may implement rules + that provide longer-term persistence for the data. The TPM reflects how it handles the data in + various getcapability fields including startup effects. +*/ + +typedef struct tdTPM_STANY_DATA { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_STANY_DATA */ +#endif + TPM_CURRENT_TICKS currentTicks; /* This is the current tick counter. This is reset to 0 + according to the rules when the TPM can tick. See the + section on the tick counter for details. */ +} TPM_STANY_DATA; + +/* 11. Signed Structures */ + +/* 11.1 TPM_CERTIFY_INFO rev 101 + + When the TPM certifies a key, it must provide a signature with a TPM identity key on information + that describes that key. This structure provides the mechanism to do so. + + Key usage and keyFlags must have their upper byte set to zero to avoid collisions with the other + signature headers. +*/ + +typedef struct tdTPM_CERTIFY_INFO { + TPM_STRUCT_VER version; /* This MUST be 1.1.0.0 */ + TPM_KEY_USAGE keyUsage; /* This SHALL be the same value that would be set in a + TPM_KEY representation of the key to be certified. The + upper byte MUST be zero */ + TPM_KEY_FLAGS keyFlags; /* This SHALL be set to the same value as the corresponding + parameter in the TPM_KEY structure that describes the + public key that is being certified. The upper byte MUST + be zero */ + TPM_AUTH_DATA_USAGE authDataUsage; /* This SHALL be the same value that would be set in a + TPM_KEY representation of the key to be certified */ + TPM_KEY_PARMS algorithmParms; /* This SHALL be the same value that would be set in a + TPM_KEY representation of the key to be certified */ + TPM_DIGEST pubkeyDigest; /* This SHALL be a digest of the value TPM_KEY -> pubKey -> + key in a TPM_KEY representation of the key to be + certified */ + TPM_NONCE data; /* This SHALL be externally provided data. */ + TPM_BOOL parentPCRStatus; /* This SHALL indicate if any parent key was wrapped to a + PCR */ + TPM_SIZED_BUFFER pcrInfo; /* */ +#if 0 + uint32_t PCRInfoSize; /* This SHALL be the size of the pcrInfo parameter. A value + of zero indicates that the key is not wrapped to a PCR */ + BYTE* PCRInfo; /* This SHALL be the TPM_PCR_INFO structure. */ +#endif + /* NOTE: kgold - Added this structure, a cache of PCRInfo when not NULL */ + TPM_PCR_INFO *tpm_pcr_info; +} TPM_CERTIFY_INFO; + +/* 11.2 TPM_CERTIFY_INFO2 rev 101 + + When the TPM certifies a key, it must provide a signature with a TPM identity key on information + that describes that key. This structure provides the mechanism to do so. + + Key usage and keyFlags must have their upper byte set to zero to avoid collisions with the other + signature headers. +*/ + +typedef struct tdTPM_CERTIFY_INFO2 { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_CERTIFY_INFO2 */ +#endif + BYTE fill; /* MUST be 0x00 */ + TPM_PAYLOAD_TYPE payloadType; /* This SHALL be the same value that would be set in a + TPM_KEY representation of the key to be certified */ + TPM_KEY_USAGE keyUsage; /* This SHALL be the same value that would be set in a + TPM_KEY representation of the key to be certified. The + upper byte MUST be zero */ + TPM_KEY_FLAGS keyFlags; /* This SHALL be set to the same value as the corresponding + parameter in the TPM_KEY structure that describes the + public key that is being certified. The upper byte MUST + be zero. */ + TPM_AUTH_DATA_USAGE authDataUsage; /* This SHALL be the same value that would be set in a + TPM_KEY representation of the key to be certified */ + TPM_KEY_PARMS algorithmParms; /* This SHALL be the same value that would be set in a + TPM_KEY representation of the key to be certified */ + TPM_DIGEST pubkeyDigest; /* This SHALL be a digest of the value TPM_KEY -> pubKey -> + key in a TPM_KEY representation of the key to be + certified */ + TPM_NONCE data; /* This SHALL be externally provided data. */ + TPM_BOOL parentPCRStatus; /* This SHALL indicate if any parent key was wrapped to a + PCR */ +#if 0 + uint32_t PCRInfoSize; /* This SHALL be the size of the pcrInfo parameter. A value + of zero indicates that the key is not wrapped to a PCR */ + BYTE* PCRInfo; /* This SHALL be the TPM_PCR_INFO_SHORT structure. */ +#endif + TPM_SIZED_BUFFER pcrInfo; +#if 0 + uint32_t migrationAuthoritySize; /* This SHALL be the size of migrationAuthority */ + BYTE *migrationAuthority; /* If the key to be certified has [payload == + TPM_PT_MIGRATE_RESTRICTED or payload + ==TPM_PT_MIGRATE_EXTERNAL], migrationAuthority is the + digest of the TPM_MSA_COMPOSITE and has TYPE == + TPM_DIGEST. Otherwise it is NULL. */ +#endif + TPM_SIZED_BUFFER migrationAuthority; + /* NOTE: kgold - Added this structure, a cache of PCRInfo when not NULL */ + TPM_PCR_INFO_SHORT *tpm_pcr_info_short; +} TPM_CERTIFY_INFO2; + +/* 11.3 TPM_QUOTE_INFO rev 87 + + This structure provides the mechanism for the TPM to quote the current values of a list of PCRs. +*/ + +typedef struct tdTPM_QUOTE_INFO { + TPM_STRUCT_VER version; /* This MUST be 1.1.0.0 */ + BYTE fixed[4]; /* This SHALL always be the string 'QUOT' */ + TPM_COMPOSITE_HASH digestValue; /* This SHALL be the result of the composite hash algorithm + using the current values of the requested PCR indices. */ + TPM_NONCE externalData; /* 160 bits of externally supplied data */ +} TPM_QUOTE_INFO; + +/* 11.4 TPM_QUOTE_INFO2 rev 87 + + This structure provides the mechanism for the TPM to quote the current values of a list of PCRs. +*/ + +typedef struct tdTPM_QUOTE_INFO2 { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_QUOTE_INFO2 */ +#endif + BYTE fixed[4]; /* This SHALL always be the string 'QUT2' */ + TPM_NONCE externalData; /* 160 bits of externally supplied data */ + TPM_PCR_INFO_SHORT infoShort; /* */ +} TPM_QUOTE_INFO2; + +/* 12.1 TPM_EK_BLOB rev 87 + + This structure provides a wrapper to each type of structure that will be in use when the + endorsement key is in use. +*/ + +typedef struct tdTPM_EK_BLOB { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_EK_BLOB */ +#endif + TPM_EK_TYPE ekType; /* This SHALL be set to reflect the type of blob in use */ + TPM_SIZED_BUFFER blob; /* The blob of information depending on the type */ +#if 0 + uint32_t blobSize; /* */ + [size_is(blobSize)] byte* blob; /* */ +#endif +} TPM_EK_BLOB; + +/* 12.2 TPM_EK_BLOB_ACTIVATE rev 87 + + This structure contains the symmetric key to encrypt the identity credential. This structure + always is contained in a TPM_EK_BLOB. +*/ + +typedef struct tdTPM_EK_BLOB_ACTIVATE { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_EK_BLOB_ACTIVATE */ +#endif + TPM_SYMMETRIC_KEY sessionKey; /* This SHALL be the session key used by the CA to encrypt + the TPM_IDENTITY_CREDENTIAL */ + TPM_DIGEST idDigest; /* This SHALL be the digest of the TPM identity public key + that is being certified by the CA */ + TPM_PCR_INFO_SHORT pcrInfo; /* This SHALL indicate the PCR's and localities */ +} TPM_EK_BLOB_ACTIVATE; + +/* 12.3 TPM_EK_BLOB_AUTH rev 87 + + This structure contains the symmetric key to encrypt the identity credential. This structure + always is contained in a TPM_EK_BLOB. +*/ + +typedef struct tdTPM_EK_BLOB_AUTH { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_EK_BLOB_AUTH */ +#endif + TPM_SECRET authValue; /* This SHALL be the authorization value */ +} TPM_EK_BLOB_AUTH; + +/* 12.5 TPM_IDENTITY_CONTENTS rev 87 + + TPM_MakeIdentity uses this structure and the signature of this structure goes to a privacy CA + during the certification process. +*/ + +typedef struct tdTPM_IDENTITY_CONTENTS { + TPM_STRUCT_VER ver; /* This MUST be 1.1.0.0 */ + uint32_t ordinal; /* This SHALL be the ordinal of the TPM_MakeIdentity + command. */ + TPM_CHOSENID_HASH labelPrivCADigest; /* This SHALL be the result of hashing the chosen + identityLabel and privacyCA for the new TPM + identity */ + TPM_PUBKEY identityPubKey; /* This SHALL be the public key structure of the identity + key */ +} TPM_IDENTITY_CONTENTS; + +/* 12.8 TPM_ASYM_CA_CONTENTS rev 87 + + This structure contains the symmetric key to encrypt the identity credential. +*/ + +typedef struct tdTPM_ASYM_CA_CONTENTS { + TPM_SYMMETRIC_KEY sessionKey; /* This SHALL be the session key used by the CA to encrypt + the TPM_IDENTITY_CREDENTIAL */ + TPM_DIGEST idDigest; /* This SHALL be the digest of the TPM_PUBKEY of the key + that is being certified by the CA */ +} TPM_ASYM_CA_CONTENTS; + +/* + 14. Audit Structures +*/ + +/* 14.1 TPM_AUDIT_EVENT_IN rev 87 + + This structure provides the auditing of the command upon receipt of the command. It provides the + information regarding the input parameters. +*/ + +typedef struct tdTPM_AUDIT_EVENT_IN { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_AUDIT_EVENT_IN */ +#endif + TPM_DIGEST inputParms; /* Digest value according to the HMAC digest rules of the + "above the line" parameters (i.e. the first HMAC digest + calculation). When there are no HMAC rules, the input + digest includes all parameters including and after the + ordinal. */ + TPM_COUNTER_VALUE auditCount; /* The current value of the audit monotonic counter */ +} TPM_AUDIT_EVENT_IN; + +/* 14.2 TPM_AUDIT_EVENT_OUT rev 87 + + This structure reports the results of the command execution. It includes the return code and the + output parameters. +*/ + +typedef struct tdTPM_AUDIT_EVENT_OUT { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_AUDIT_EVENT_OUT */ +#endif + TPM_DIGEST outputParms; /* Digest value according to the HMAC digest rules of the + "above the line" parameters (i.e. the first HMAC digest + calculation). When there are no HMAC rules, the output + digest includes the return code, the ordinal, and all + parameters after the return code. */ + TPM_COUNTER_VALUE auditCount; /* The current value of the audit monotonic counter */ +} TPM_AUDIT_EVENT_OUT; + +/* + 18. Context structures +*/ + +/* 18.1 TPM_CONTEXT_BLOB rev 102 + + This is the header for the wrapped context. The blob contains all information necessary to reload + the context back into the TPM. + + The additional data is used by the TPM manufacturer to save information that will assist in the + reloading of the context. This area must not contain any shielded data. For instance, the field + could contain some size information that allows the TPM more efficient loads of the context. The + additional area could not contain one of the primes for a RSA key. + + To ensure integrity of the blob when using symmetric encryption the TPM vendor could use some + valid cipher chaining mechanism. To ensure the integrity without depending on correct + implementation, the TPM_CONTEXT_BLOB structure uses a HMAC of the entire structure using tpmProof + as the secret value. + + Since both additionalData and sensitiveData are informative, any or all of additionalData + could be moved to sensitiveData. +*/ + +#define TPM_CONTEXT_LABEL_SIZE 16 + +typedef struct tdTPM_CONTEXT_BLOB { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_CONTEXTBLOB */ +#endif + TPM_RESOURCE_TYPE resourceType; /* The resource type */ + TPM_HANDLE handle; /* Previous handle of the resource */ + BYTE label[TPM_CONTEXT_LABEL_SIZE]; /* Label for identification of the blob. Free format + area. */ + uint32_t contextCount; /* MUST be TPM_STANY_DATA -> contextCount when creating the + structure. This value is ignored for context blobs that + reference a key. */ + TPM_DIGEST integrityDigest; /* The integrity of the entire blob including the sensitive + area. This is a HMAC calculation with the entire + structure (including sensitiveData) being the hash and + tpmProof is the secret */ +#if 0 + uint32_t additionalSize; + [size_is(additionalSize)] BYTE* additionalData; + uint32_t sensitiveSize; + [size_is(sensitiveSize)] BYTE* sensitiveData; +#endif + TPM_SIZED_BUFFER additionalData; /* Additional information set by the TPM that helps define + and reload the context. The information held in this area + MUST NOT expose any information held in shielded + locations. This should include any IV for symmetric + encryption */ + TPM_SIZED_BUFFER sensitiveData; /* The normal information for the resource that can be + exported */ +} TPM_CONTEXT_BLOB; + +/* 18.2 TPM_CONTEXT_SENSITIVE rev 87 + + The internal areas that the TPM needs to encrypt and store off the TPM. + + This is an informative structure and the TPM can implement in any manner they wish. +*/ + +typedef struct tdTPM_CONTEXT_SENSITIVE { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_CONTEXT_SENSITIVE */ +#endif + TPM_NONCE contextNonce; /* On context blobs other than keys this MUST be + TPM_STANY_DATA - > contextNonceSession For keys the value + is TPM_STCLEAR_DATA -> contextNonceKey */ +#if 0 + uint32_t internalSize; + [size_is(internalSize)] BYTE* internalData; +#endif + TPM_SIZED_BUFFER internalData; /* The internal data area */ +} TPM_CONTEXT_SENSITIVE; + +/* 19.2 TPM_NV_ATTRIBUTES rev 99 + + This structure allows the TPM to keep track of the data and permissions to manipulate the area. +*/ + +typedef struct tdTPM_NV_ATTRIBUTES { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* TPM_TAG_NV_ATTRIBUTES */ +#endif + uint32_t attributes; /* The attribute area */ +} TPM_NV_ATTRIBUTES; + +/* 19.3 TPM_NV_DATA_PUBLIC rev 110 + + This structure represents the public description and controls on the NV area. + + bReadSTClear and bWriteSTClear are volatile, in that they are set FALSE at TPM_Startup(ST_Clear). + bWriteDefine is persistent, in that it remains TRUE through startup. + + A pcrSelect of 0 indicates that the digestAsRelease is not checked. In this case, the TPM is not + required to consume NVRAM space to store the digest, although it may do so. When + TPM_GetCapability (TPM_CAP_NV_INDEX) returns the structure, a TPM that does not store the digest + can return zero. A TPM that does store the digest may return either the digest or zero. +*/ + +typedef struct tdTPM_NV_DATA_PUBLIC { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_NV_DATA_PUBLIC */ +#endif + TPM_NV_INDEX nvIndex; /* The index of the data area */ + TPM_PCR_INFO_SHORT pcrInfoRead; /* The PCR selection that allows reading of the area */ + TPM_PCR_INFO_SHORT pcrInfoWrite; /* The PCR selection that allows writing of the area */ + TPM_NV_ATTRIBUTES permission; /* The permissions for manipulating the area */ + TPM_BOOL bReadSTClear; /* Set to FALSE on each TPM_Startup(ST_Clear) and set to + TRUE after a ReadValuexxx with datasize of 0 */ + TPM_BOOL bWriteSTClear; /* Set to FALSE on each TPM_Startup(ST_CLEAR) and set to + TRUE after a WriteValuexxx with a datasize of 0. */ + TPM_BOOL bWriteDefine; /* Set to FALSE after TPM_NV_DefineSpace and set to TRUE + after a successful WriteValuexxx with a datasize of 0 */ + uint32_t dataSize; /* The size of the data area in bytes */ +} TPM_NV_DATA_PUBLIC; + +/* 19.4 TPM_NV_DATA_SENSITIVE rev 101 + + This is an internal structure that the TPM uses to keep the actual NV data and the controls + regarding the area. +*/ + +typedef struct tdTPM_NV_DATA_SENSITIVE { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_NV_DATA_SENSITIVE */ +#endif + TPM_NV_DATA_PUBLIC pubInfo; /* The public information regarding this area */ + TPM_AUTHDATA authValue; /* The authorization value to manipulate the value */ + BYTE *data; /* The data area. This MUST not contain any sensitive information as + the TPM does not provide any confidentiality on the data. */ + /* NOTE Added kg */ + TPM_DIGEST digest; /* for OSAP comparison */ +} TPM_NV_DATA_SENSITIVE; + +typedef struct tdTPM_NV_INDEX_ENTRIES { + uint32_t nvIndexCount; /* number of entries */ + TPM_NV_DATA_SENSITIVE *tpm_nvindex_entry; /* array of TPM_NV_DATA_SENSITIVE */ +} TPM_NV_INDEX_ENTRIES; + +/* TPM_NV_DATA_ST + + This is a cache of the the NV defined space volatile flags, used during error rollback +*/ + +typedef struct tdTPM_NV_DATA_ST { + TPM_NV_INDEX nvIndex; /* The index of the data area */ + TPM_BOOL bReadSTClear; + TPM_BOOL bWriteSTClear; +} TPM_NV_DATA_ST; + +/* + 21. Capability areas +*/ + +/* 21.6 TPM_CAP_VERSION_INFO rev 99 + + This structure is an output from a TPM_GetCapability -> TPM_CAP_VERSION_VAL request. TPM returns + the current version and revision of the TPM. + + The specLevel and errataRev are defined in the document "Specification and File Naming + Conventions" + + The tpmVendorID is a value unique to each vendor. It is defined in the document "TCG Vendor + Naming". + + The vendor specific area allows the TPM vendor to provide support for vendor options. The TPM + vendor may define the area to the TPM vendor's needs. +*/ + +typedef struct tdTPM_CAP_VERSION_INFO { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_CAP_VERSION_INFO */ +#endif + TPM_VERSION version; /* The version and revision */ + uint16_t specLevel; /* A number indicating the level of ordinals supported */ + BYTE errataRev; /* A number indicating the errata version of the specification */ + BYTE tpmVendorID[4]; /* The vendor ID unique to each TPM manufacturer. */ + uint16_t vendorSpecificSize; /* The size of the vendor specific area */ + BYTE* vendorSpecific; /* Vendor specific information */ + /* NOTE Cannot be TPM_SIZED_BUFFER, because of uint16_t */ +} TPM_CAP_VERSION_INFO; + +/* 21.10 TPM_DA_ACTION_TYPE rev 100 + + This structure indicates the action taken when the dictionary attack mitigation logic is active, + when TPM_DA_STATE is TPM_DA_STATE_ACTIVE. +*/ + +typedef struct tdTPM_DA_ACTION_TYPE { + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DA_ACTION_TYPE */ + uint32_t actions; /* The action taken when TPM_DA_STATE is TPM_DA_STATE_ACTIVE. */ +} TPM_DA_ACTION_TYPE; + +/* 21.7 TPM_DA_INFO rev 100 + + This structure is an output from a TPM_GetCapability -> TPM_CAP_DA_LOGIC request if + TPM_PERMANENT_FLAGS -> disableFullDALogicInfo is FALSE. + + It returns static information describing the TPM response to authorization failures that might + indicate a dictionary attack and dynamic information regarding the current state of the + dictionary attack mitigation logic. +*/ + +typedef struct tdTPM_DA_INFO { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DA_INFO */ +#endif + TPM_DA_STATE state; /* Dynamic. The actual state of the dictionary attack mitigation + logic. See 21.9. */ + uint16_t currentCount; /* Dynamic. The actual count of the authorization failure counter + for the selected entity type */ + uint16_t thresholdCount; /* Static. Dictionary attack mitigation threshold count for the + selected entity type */ + TPM_DA_ACTION_TYPE actionAtThreshold; /* Static Action of the TPM when currentCount passes + thresholdCount. See 21.10. */ + uint32_t actionDependValue; /* Dynamic. Action being taken when the dictionary attack + mitigation logic is active. E.g., when actionAtThreshold is + TPM_DA_ACTION_TIMEOUT, this is the lockout time remaining in + seconds. */ + TPM_SIZED_BUFFER vendorData; /* Vendor specific data field */ +} TPM_DA_INFO; + +/* 21.8 TPM_DA_INFO_LIMITED rev 100 + + This structure is an output from a TPM_GetCapability -> TPM_CAP_DA_LOGIC request if + TPM_PERMANENT_FLAGS -> disableFullDALogicInfo is TRUE. + + It returns static information describing the TPM response to authorization failures that might + indicate a dictionary attack and dynamic information regarding the current state of the + dictionary attack mitigation logic. This structure omits information that might aid an attacker. +*/ + +typedef struct tdTPM_DA_INFO_LIMITED { +#ifdef TPM_USE_TAG_IN_STRUCTURE + TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DA_INFO_LIMITED */ +#endif + TPM_DA_STATE state; /* Dynamic. The actual state of the dictionary attack mitigation + logic. See 21.9. */ + TPM_DA_ACTION_TYPE actionAtThreshold; /* Static Action of the TPM when currentCount passes + thresholdCount. See 21.10. */ + TPM_SIZED_BUFFER vendorData; /* Vendor specific data field */ +} TPM_DA_INFO_LIMITED; + +#endif + +/* Sanity check the size of the NV file vs. the maximum allocation size + + The multipliers are very conservative +*/ + +#if (TPM_ALLOC_MAX < \ + (4000 + \ + (TPM_OWNER_EVICT_KEY_HANDLES * 2000) + \ + TPM_MAX_NV_DEFINED_SPACE)) +#error "TPM_ALLOC_MAX too small for NV file size" +#endif + +/* Sanity check the size of the volatile file vs. the maximum allocation size + + The multipliers are very conservative +*/ + +#if (TPM_ALLOC_MAX < \ + (4000 + \ + TPM_KEY_HANDLES * 2000 + \ + TPM_MIN_TRANS_SESSIONS * 500 + \ + TPM_MIN_DAA_SESSIONS * 2000 + \ + TPM_MIN_AUTH_SESSIONS * 500)) +#error "TPM_ALLOC_MAX too small for volatile file size" +#endif diff --git a/src/tpm12/tpm_svnrevision.c b/src/tpm12/tpm_svnrevision.c new file mode 100644 index 0000000..e0bba60 --- /dev/null +++ b/src/tpm12/tpm_svnrevision.c @@ -0,0 +1 @@ +const unsigned short tpm_svn_revision = 4766; diff --git a/src/tpm12/tpm_svnrevision.h b/src/tpm12/tpm_svnrevision.h new file mode 100644 index 0000000..0ed4c4b --- /dev/null +++ b/src/tpm12/tpm_svnrevision.h @@ -0,0 +1,46 @@ +/********************************************************************************/ +/* */ +/* TPM svn revision */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_svnrevision.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_REVISION_H +#define TPM_REVISION_H + +extern const unsigned short tpm_svn_revision; + +#endif + diff --git a/src/tpm12/tpm_ticks.c b/src/tpm12/tpm_ticks.c new file mode 100644 index 0000000..c8dc58b --- /dev/null +++ b/src/tpm12/tpm_ticks.c @@ -0,0 +1,913 @@ +/********************************************************************************/ +/* */ +/* Tick Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_ticks.c 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_auth.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_key.h" +#include "tpm_structures.h" +#include "tpm_nonce.h" +#include "tpm_process.h" +#include "tpm_time.h" + +#include "tpm_ticks.h" + +static void TPM_Uint64_ConvertFrom(uint32_t *upper, + uint32_t *lower, + uint32_t sec, + uint32_t usec); +static void TPM_Uint64_ConvertTo(uint32_t *sec, + uint32_t *usec, + uint32_t upper, + uint32_t lower); + +/* + UINT64 for currentTicks + + Internally, the UINT64 is stored as sec || usec. This makes calculations easy since TPM_GetTimeOfDay + returns those structure elements. + + The TPM_Uint64_Store() function, the public interface, converts this to a true 64 bit integer. +*/ + +/* TPM_Uint64_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_Uint64_Init(TPM_UINT64 *tpm_uint64) +{ + printf(" TPM_Uint64_Init:\n"); + tpm_uint64->sec = 0; + tpm_uint64->usec = 0; + return; +} + +/* TPM_Uint64_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + This function does the conversion from a 64 bit usec to sec / usec. +*/ + +TPM_RESULT TPM_Uint64_Load(TPM_UINT64 *tpm_uint64, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + uint32_t upper; + uint32_t lower; + + printf(" TPM_Uint64_Load:\n"); + /* load upper */ + if (rc == 0) { + rc = TPM_Load32(&upper, stream, stream_size); + } + /* load lower */ + if (rc == 0) { + rc = TPM_Load32(&lower, stream, stream_size); + } + /* convert from 64 bit usec to sec, usec */ + if (rc == 0) { + TPM_Uint64_ConvertTo(&(tpm_uint64->sec), + &(tpm_uint64->usec), + upper, + lower); + } + return rc; +} + +/* TPM_Uint64_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes + + This function does the conversion from sec / usec to a 64 bit usec. +*/ + +TPM_RESULT TPM_Uint64_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_UINT64 *tpm_uint64) +{ + TPM_RESULT rc = 0; + uint32_t upper; + uint32_t lower; + + printf(" TPM_Uint64_Store:\n"); + /* store upper */ + if (rc == 0) { + /* convert to 64 bit number */ + TPM_Uint64_ConvertFrom(&upper, &lower, tpm_uint64->sec, tpm_uint64->usec); + rc = TPM_Sbuffer_Append32(sbuffer, upper); + } + /* store lower */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, lower); + } + return rc; +} + +void TPM_Uint64_Copy(TPM_UINT64 *dest, + const TPM_UINT64 *src) +{ + printf(" TPM_Uint64_Copy:\n"); + dest->sec = src->sec; + dest->usec = src->usec; + return; +} + +/* TPM_Uint64_ConvertFrom() does the calculation result = sec * 1000000 + usec and splits the result + into two uint32_t's. + + This may not be portable if the compiler does not support long long. +*/ + +/* TPM_Uint64_ConvertTo() does the calculation uint32_t || uint32_t to sec and usec. + + This may not be portable if the compiler does not support long long. +*/ + +#if defined(TPM_POSIX) || defined(TPM_SYSTEM_P) + +static void TPM_Uint64_ConvertFrom(uint32_t *upper, + uint32_t *lower, + uint32_t sec, + uint32_t usec) +{ + long long result; + + printf(" TPM_Uint64_ConvertFrom: sec %u, usec %u\n", sec, usec); + result = (sec * 1000000LL) + (long long)usec; + printf(" TPM_Uint64_ConvertFrom: Result usec %llu, %llx\n", result, result); + *upper = (result >> 32) & 0xffffffff; + *lower = result & 0xffffffff; + printf(" TPM_Uint64_ConvertFrom: Upper %u, %x\n", *upper, *upper); + printf(" TPM_Uint64_ConvertFrom: Lower %u, %x\n", *lower, *lower); + return; +} + +static void TPM_Uint64_ConvertTo(uint32_t *sec, + uint32_t *usec, + uint32_t upper, + uint32_t lower) +{ + long long result; + + printf(" TPM_Uint64_ConvertTo: Upper %u, %x\n", upper, upper); + printf(" TPM_Uint64_ConvertTo: Lower %u, %x\n", lower, lower); + result = ((long long)upper << 32) | (long long)lower; + printf(" TPM_Uint64_ConvertTo: Result usec %llu, %llx\n", result, result); + *sec = result / 1000000LL; + *usec = result % 1000000LL; + printf(" TPM_Uint64_ConvertTo: sec %u, usec %u\n", *sec, *usec); + return; +} + +#endif + + +TPM_RESULT TPM_Uint64_Test() +{ + TPM_RESULT rc = 0; + TPM_UINT64 uint64In; + TPM_UINT64 uint64Out; + TPM_STORE_BUFFER sbuffer; + unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_Uint64_Test\n"); + TPM_Sbuffer_Init(&sbuffer); + uint64In.sec = 12345678; + uint64In.usec = 781234; + + if (rc == 0) { + rc = TPM_Uint64_Store(&sbuffer, &uint64In); + } + if (rc == 0) { + TPM_Sbuffer_Get(&sbuffer, (const unsigned char **)&stream, &stream_size); + rc = TPM_Uint64_Load(&uint64Out, &stream, &stream_size); + } + if (rc == 0) { + if ((uint64In.sec != uint64Out.sec) || + (uint64In.usec != uint64Out.usec)) { + printf("TPM_Uint64_Test: Error (fatal)\n"); + rc = TPM_FAILEDSELFTEST; + } + } + TPM_Sbuffer_Delete(&sbuffer); + return rc; +} + +/* + TPM_CURRENT_TICKS +*/ + +/* TPM_CurrentTicks_Init() initializes the tick structure + +*/ + +void TPM_CurrentTicks_Init(TPM_CURRENT_TICKS *tpm_current_ticks) +{ + printf(" TPM_CurrentTicks_Init:\n"); + TPM_Uint64_Init(&(tpm_current_ticks->currentTicks)); + tpm_current_ticks->tickRate = TPM_TICK_RATE; + TPM_Nonce_Init(tpm_current_ticks->tickNonce); + TPM_Uint64_Init(&(tpm_current_ticks->initialTime)); + return; +} + +/* TPM_CurrentTicks_Start() sets the initialTime member to the + current time of day. + + It assumes TPM_CurrentTicks_Init() has been called +*/ + +TPM_RESULT TPM_CurrentTicks_Start(TPM_CURRENT_TICKS *tpm_current_ticks) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CurrentTicks_Start:\n"); + if (rc == 0) { + /* current is relative to the initial value, and is always 0 */ + TPM_Uint64_Init(&(tpm_current_ticks->currentTicks)); + /* save the current time */ + rc = TPM_GetTimeOfDay(&(tpm_current_ticks->initialTime.sec), + &(tpm_current_ticks->initialTime.usec)); + } + if (rc == 0) { + tpm_current_ticks->tickRate = TPM_TICK_RATE; + rc = TPM_Nonce_Generate(tpm_current_ticks->tickNonce); + } + return rc; +} + +/* TPM_CurrentTicks_LoadAll() loads the standard TCG structure plus the SW TPM members + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_CurrentTicks_Init() +*/ + +TPM_RESULT TPM_CurrentTicks_LoadAll(TPM_CURRENT_TICKS *tpm_current_ticks, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CurrentTicks_LoadAll:\n"); + /* load tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_CURRENT_TICKS, stream, stream_size); + } + /* load currentTicks */ + if (rc == 0) { + rc = TPM_Uint64_Load(&(tpm_current_ticks->currentTicks), stream, stream_size); + } + /* load tickRate */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_current_ticks->tickRate), stream, stream_size); + } + /* load tickNonce */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_current_ticks->tickNonce, stream, stream_size); + } + /* load initialTime */ + if (rc == 0) { + rc = TPM_Uint64_Load(&(tpm_current_ticks->initialTime), stream, stream_size); + } + return rc; +} + +/* TPM_CurrentTicks_Store() stores the standard TCG structure + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CurrentTicks_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CURRENT_TICKS *tpm_current_ticks) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CurrentTicks_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CURRENT_TICKS); + } + /* store currentTicks */ + if (rc == 0) { + rc = TPM_Uint64_Store(sbuffer, &(tpm_current_ticks->currentTicks)); + } + /* store tickRate */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_current_ticks->tickRate); + } + /* store tickNonce */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_current_ticks->tickNonce); + } + return rc; +} + +/* TPM_CurrentTicks_Store() stores the standard TCG structure plus the SW TPM members + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_CurrentTicks_StoreAll(TPM_STORE_BUFFER *sbuffer, + const TPM_CURRENT_TICKS *tpm_current_ticks) +{ + TPM_RESULT rc = 0; + + printf(" TPM_CurrentTicks_StoreAll:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_CurrentTicks_Store(sbuffer, tpm_current_ticks); + } + /* store initialTime */ + if (rc == 0) { + rc = TPM_Uint64_Store(sbuffer, &(tpm_current_ticks->initialTime)); + } + return rc; +} + +/* TPM_CurrentTicks_Update() updates the currentTicks member of TPM_CURRENT_TICKS + relative to the initial time + +*/ + +TPM_RESULT TPM_CurrentTicks_Update(TPM_CURRENT_TICKS *tpm_current_ticks) +{ + TPM_RESULT rc = 0; + uint32_t currentTimeSec; + uint32_t currentTimeUsec; + + printf(" TPM_CurrentTicks_Update: Initial %u sec %u usec\n", + tpm_current_ticks->initialTime.sec, tpm_current_ticks->initialTime.usec); + /* get the current time of day */ + if (rc == 0) { + rc = TPM_GetTimeOfDay(¤tTimeSec, ¤tTimeUsec); + } + /* Calculate: + currentTimeSec currentTimeUsec + - initialTimeSec initialTimeUsec + */ + if (rc == 0) { + /* case 1: no borrow */ + if (currentTimeUsec >= tpm_current_ticks->initialTime.usec) { + /* subtract usec */ + tpm_current_ticks->currentTicks.usec = currentTimeUsec - + tpm_current_ticks->initialTime.usec; + + /* check that time went forward */ + if (currentTimeSec >= tpm_current_ticks->initialTime.sec) { + /* subtract sec */ + tpm_current_ticks->currentTicks.sec = currentTimeSec - + tpm_current_ticks->initialTime.sec; + } + else { + printf(" TPM_CurrentTicks_Update: Error (fatal), illegal current time\n"); + rc = TPM_FAIL; + } + } + /* case 2: borrow */ + else { + /* subtract usec with borrow */ + tpm_current_ticks->currentTicks.usec = 1000000 + currentTimeUsec - + tpm_current_ticks->initialTime.usec; + /* check that time went forward, with borrow */ + if ((currentTimeSec - 1) >= tpm_current_ticks->initialTime.sec) { + /* subtract sec */ + tpm_current_ticks->currentTicks.sec = currentTimeSec - 1 - + tpm_current_ticks->initialTime.sec; + } + else { + printf(" TPM_CurrentTicks_Update: Error (fatal), illegal current time\n"); + rc = TPM_FAIL; + } + } + } + if (rc == 0) { + printf(" TPM_CurrentTicks_Update: Ticks %u sec %u usec\n", + tpm_current_ticks->currentTicks.sec, + tpm_current_ticks->currentTicks.usec); + } + return rc; +} + +/* TPM_CurrentTicks_Copy() copies the 'src' to 'dest' + +*/ + +void TPM_CurrentTicks_Copy(TPM_CURRENT_TICKS *dest, + TPM_CURRENT_TICKS *src) +{ + printf(" TPM_CurrentTicks_Copy:\n"); + TPM_Uint64_Copy(&(dest->currentTicks), &(src->currentTicks)); + dest->tickRate = src->tickRate; + TPM_Nonce_Copy(dest->tickNonce, src->tickNonce); + TPM_Uint64_Copy(&(dest->initialTime), &(src->initialTime)); + return; +} + +/* + Processing Functions +*/ + +/* 23. Timing Ticks rev 87 + + The TPM timing ticks are always available for use. The association of timing ticks to actual time + is a protocol that occurs outside of the TPM. See the design document for details. + + The setting of the clock type variable is a one time operation that allows the TPM to be + configured to the type of platform that is installed on. + + The ability for the TPM to continue to increment the timer ticks across power cycles of the + platform is a TPM and platform manufacturer decision. +*/ + +/* 23.1 TPM_GetTicks rev 87 + + This command returns the current tick count of the TPM. + + This command returns the current time held in the TPM. It is the responsibility of the external + system to maintain any relation between this time and a UTC value or local real time value. +*/ + +TPM_RESULT TPM_Process_GetTicks(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_CURRENT_TICKS *t1CurrentTicks = NULL; /* The current time held in the TPM */ + + printf("TPM_Process_GetTicks: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_GetTicks: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + /* 1. Set T1 to the internal TPM_CURRENT_TICKS structure */ + t1CurrentTicks = &(tpm_state->tpm_stany_data.currentTicks); + /* update the ticks based on the current time */ + returnCode = TPM_CurrentTicks_Update(t1CurrentTicks); + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_GetTicks: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 2. Return T1 as currentTime. */ + returnCode = TPM_CurrentTicks_Store(response, t1CurrentTicks); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* + cleanup + */ + return rcf; +} + +/* 23.2 TPM_TickStampBlob rev 101 + + This command applies a time stamp to the passed blob. The TPM makes no representation regarding + the blob merely that the blob was present at the TPM at the time indicated. + + The function performs a digital signature on the hash of digestToStamp and the current tick + count. + + It is the responsibility of the external system to maintain any relation between tick count and a + UTC value or local real time value. + +*/ + +TPM_RESULT TPM_Process_TickStampBlob(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform digital + signatures. */ + TPM_NONCE antiReplay; /* Anti replay value added to signature */ + TPM_DIGEST digestToStamp; /* The digest to perform the tick stamp on */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle authorization + */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the use of + keyHandle. HMAC key: key.usageAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_BOOL authHandleValid = FALSE; + TPM_KEY *sigKey; /* signing key */ + TPM_SECRET *keyUsageAuth; + TPM_SECRET *hmacKey; + TPM_BOOL parentPCRStatus; + TPM_SIGN_INFO h1SignInfo; + TPM_STORE_BUFFER h2Data; + TPM_STORE_BUFFER h1sbuffer; /* serialization of h1SignInfo */ + TPM_DIGEST h3Digest; /* digest to be signed */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_CURRENT_TICKS *currentTicks = NULL; /* The current time according to the TPM */ + TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ + + printf("TPM_Process_TickStampBlob: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&sig); /* freed @1 */ + TPM_SignInfo_Init(&h1SignInfo); /* freed @2 */ + TPM_Sbuffer_Init(&h2Data); /* freed @3 */ + TPM_Sbuffer_Init(&h1sbuffer); /* freed @4 */ + /* + get inputs + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TickStampBlob: keyHandle %08x\n", keyHandle); + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* get digestToStamp parameter */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_TickStampBlob: antiReplay", antiReplay); + returnCode = TPM_Digest_Load(digestToStamp, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_TickStampBlob: digestToStamp", digestToStamp); + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + privAuth, + &command, ¶mSize); + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + printf("TPM_Process_TickStampBlob: authHandle %08x\n", authHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_TickStampBlob: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not read-only */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { + if (sigKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_TickStampBlob: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + sigKey, + keyUsageAuth, /* OIAP */ + sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 1. The TPM validates the AuthData to use the key pointed to by keyHandle. */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + privAuth); /* Authorization digest for input */ + } + /* 2. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or + TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TickStampBlob: Checking key properties\n"); + if ((sigKey->keyUsage != TPM_KEY_SIGNING) && + (sigKey->keyUsage != TPM_KEY_IDENTITY) && + (sigKey->keyUsage != TPM_KEY_LEGACY)) { + printf("TPM_Process_TickStampBlob: Error, keyUsage %04hx is invalid\n", + sigKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 3. Validate that keyHandle -> sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1 or + TPM_SS_RSASSAPKCS1v15_INFO, if not return TPM_INAPPROPRIATE_SIG. */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { + printf("TPM_Process_TickStampBlob: Error, invalid sigKey sigScheme %04hx\n", + sigKey->algorithmParms.sigScheme); + returnCode = TPM_INAPPROPRIATE_SIG; + } + } + /* 4. If TPM_STCLEAR_DATA -> currentTicks is not properly initialized */ + /* a. Initialize the TPM_STCLEAR_DATA -> currentTicks */ + /* NOTE: Always initialized */ + /* 5. Create T1, a TPM_CURRENT_TICKS structure. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TickStampBlob: Creating TPM_CURRENT_TICKS structure\n"); + currentTicks = &(tpm_state->tpm_stany_data.currentTicks); + /* update the ticks based on the current time */ + returnCode = TPM_CurrentTicks_Update(currentTicks); + } + if (returnCode == TPM_SUCCESS) { + /* 6. Create H1 a TPM_SIGN_INFO structure and set the structure defaults */ + printf("TPM_Process_TickStampBlob: Creating TPM_SIGN_INFO structure\n"); + /* NOTE: Done by TPM_SignInfo_Init() */ + /* a. Set H1 -> fixed to 'TSTP' */ + memcpy(h1SignInfo.fixed, "TSTP", TPM_SIGN_INFO_FIXED_SIZE); + /* b. Set H1 -> replay to antiReplay */ + TPM_Nonce_Copy(h1SignInfo.replay, antiReplay ); + /* c. Create H2 the concatenation of digestToStamp || T1 */ + /* add digestToStamp */ + returnCode = TPM_Digest_Store(&h2Data, digestToStamp); + } + /* add T1 (currentTicks) */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CurrentTicks_Store(&h2Data, currentTicks); + } + /* d. Set H1 -> dataLen to the length of H2 */ + /* e. Set H1 -> data */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_SetFromStore(&(h1SignInfo.data), &h2Data); + } + /* 7. The TPM computes the signature, sig, using the key referenced by keyHandle, using SHA-1 of + H1 as the information to be signed */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TickStampBlob: Digesting TPM_SIGN_INFO structure\n"); + returnCode = TPM_SHA1_GenerateStructure(h3Digest, &h1SignInfo, + (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TickStampBlob: Signing TPM_SIGN_INFO digest\n"); + returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ + h3Digest, /* message */ + TPM_DIGEST_SIZE, /* message size */ + sigKey); /* input, signing key */ + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_TickStampBlob: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* 7. The TPM returns T1 as currentTicks parameter */ + returnCode = TPM_CurrentTicks_Store(response, currentTicks); + } + /* 6. Return the signature in sig */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Store(response, &sig); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&sig); /* @1 */ + TPM_SignInfo_Delete(&h1SignInfo); /* @2 */ + TPM_Sbuffer_Delete(&h2Data); /* @3 */ + TPM_Sbuffer_Delete(&h1sbuffer); /* @4 */ + return rcf; +} + diff --git a/src/tpm12/tpm_ticks.h b/src/tpm12/tpm_ticks.h new file mode 100644 index 0000000..bebfdc6 --- /dev/null +++ b/src/tpm12/tpm_ticks.h @@ -0,0 +1,97 @@ +/********************************************************************************/ +/* */ +/* Tick Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_ticks.h 4114 2010-09-30 22:24:32Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_TICKS_H +#define TPM_TICKS_H + +#include "tpm_types.h" +#include "tpm_global.h" +#include "tpm_structures.h" + +/* + UINT64 +*/ + +void TPM_Uint64_Init(TPM_UINT64 *tpm_uint64); +TPM_RESULT TPM_Uint64_Load(TPM_UINT64 *tpm_uint64, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_Uint64_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_UINT64 *tpm_uint64); +void TPM_Uint64_Copy(TPM_UINT64 *dest, + const TPM_UINT64 *src); +TPM_RESULT TPM_Uint64_Test(void); + +/* + TPM_CURRENT_TICKS +*/ + +void TPM_CurrentTicks_Init(TPM_CURRENT_TICKS *tpm_current_ticks); +TPM_RESULT TPM_CurrentTicks_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_CURRENT_TICKS *tpm_current_ticks); +TPM_RESULT TPM_CurrentTicks_LoadAll(TPM_CURRENT_TICKS *tpm_current_ticks, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_CurrentTicks_StoreAll(TPM_STORE_BUFFER *sbuffer, + const TPM_CURRENT_TICKS *tpm_current_ticks); +TPM_RESULT TPM_CurrentTicks_Start(TPM_CURRENT_TICKS *tpm_current_ticks); +TPM_RESULT TPM_CurrentTicks_Update(TPM_CURRENT_TICKS *tpm_current_ticks); +void TPM_CurrentTicks_Copy(TPM_CURRENT_TICKS *dest, + TPM_CURRENT_TICKS *src); + +/* + Processing Functions +*/ + +TPM_RESULT TPM_Process_GetTicks(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_TickStampBlob(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + +#endif diff --git a/src/tpm12/tpm_time.c b/src/tpm12/tpm_time.c new file mode 100644 index 0000000..3e747f6 --- /dev/null +++ b/src/tpm12/tpm_time.c @@ -0,0 +1,80 @@ +/********************************************************************************/ +/* */ +/* Time Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_time.c 4648 2011-10-25 19:22:18Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* TPM_GetTimeOfDay() calls platform specific code to get the time in seconds and microseconds + */ + +#include + +#include "tpm_debug.h" +#include "tpm_error.h" + +#include "tpm_time.h" + +/* TPM_GetTimeOfDay() gets the current time of day. + + Must return TPM_FAIL on error, so that the caller knows to shut down the TPM +*/ + +#ifdef TPM_POSIX + +#include + +TPM_RESULT TPM_GetTimeOfDay(uint32_t *tv_sec, uint32_t *tv_usec) +{ + TPM_RESULT rc = 0; + struct timeval tval; + int irc; + + irc = gettimeofday(&tval, NULL ); /* get the time */ + if (irc == 0) { + *tv_sec = tval.tv_sec; + *tv_usec = tval.tv_usec; + printf(" TPM_GetTimeOfDay: %d sec %d usec\n",*tv_sec, *tv_usec); + } + else { + printf("TPM_GetTimeOfDay: Error (fatal) getting time of day\n"); + rc = TPM_FAIL; + } + return rc; +} + +#endif + + diff --git a/src/tpm12/tpm_time.h b/src/tpm12/tpm_time.h new file mode 100644 index 0000000..d701551 --- /dev/null +++ b/src/tpm12/tpm_time.h @@ -0,0 +1,49 @@ +/********************************************************************************/ +/* */ +/* TPM Time Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_time.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_TIME_H +#define TPM_TIME_H + +#include "tpm_types.h" + +#define TPM_TICK_RATE 1 /* in usec for Linux */ +TPM_RESULT TPM_GetTimeOfDay(uint32_t *tv_sec, uint32_t *tv_usec); + + +#endif diff --git a/src/tpm12/tpm_transport.c b/src/tpm12/tpm_transport.c new file mode 100644 index 0000000..7b9c520 --- /dev/null +++ b/src/tpm12/tpm_transport.c @@ -0,0 +1,2935 @@ +/********************************************************************************/ +/* */ +/* Transport */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_transport.c 4719 2014-01-15 21:17:47Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_audit.h" +#include "tpm_auth.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_digest.h" +#include "tpm_error.h" +#include "tpm_init.h" +#include "tpm_key.h" +#include "tpm_memory.h" +#include "tpm_nonce.h" +#include "tpm_process.h" +#include "tpm_secret.h" +#include "tpm_ticks.h" + +#include "tpm_transport.h" + +/* TPM_Transport_CryptMgf1() takes a 'src', a preallocated 'dest', and an MGF1 'pad' of length + 'len'. + + 'size is the total length of 'src' and 'dest'. + 'index' is the start of the encrypt area + 'len' is the length of the encrypt area + + It copies 'src' to 'dest' up to 'index'. + It then copies 'src' XOR'ed with 'pad' for 'len' + It then copies the remainder of 'src' to 'dest' +*/ + +TPM_RESULT TPM_Transport_CryptMgf1(unsigned char *dest, + const unsigned char *src, + const unsigned char *pad, + uint32_t size, + uint32_t index, + uint32_t len) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Transport_CryptMgf1: size %u index %u len %u\n", size, index, len); + /* sanity check the length */ + if (rc == 0) { + if (index + len > size) { + printf("TPM_Transport_CryptMgf1: Error (fatal), bad size\n"); + rc = TPM_FAIL; /* internal error, should never occur */ + } + } + if (rc == 0) { + /* leading clear text area */ + memcpy(dest, src, index); + dest += index; + src += index; + /* encrypt area */ + TPM_XOR(dest, pad, src, len); + dest += len; + src += len; + /* trailing clear text area */ + memcpy(dest, src, size - index - len); + } + return rc; +} + +/* TPM_Transport_CryptSymmetric() takes a 'src', a preallocated 'dest', and a 'symmetric_key' + 'pad_in' (CTR or IV) of length 'len'. + + 'size is the total length of 'src' and 'dest'. + 'index' is the start of the encrypt area + 'len' is the length of the encrypt area + + It copies 'src' to 'dest' up to 'index'. + It then encrypts 'src' to 'dest' using 'symmetric_key and 'pad_in' for 'len' + It then copies the remainder of 'src' to 'dest' +*/ + +TPM_RESULT TPM_Transport_CryptSymmetric(unsigned char *dest, + const unsigned char *src, + TPM_ALGORITHM_ID algId, /* algorithm */ + TPM_ENC_SCHEME encScheme, /* mode */ + const unsigned char *symmetric_key, + uint32_t symmetric_key_size, + unsigned char *pad_in, + uint32_t pad_in_size, + uint32_t size, + uint32_t index, + uint32_t len) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Transport_CryptSymmetric: size %u index %u len %u\n", size, index, len); + /* sanity check the length */ + if (rc == 0) { + if (index + len > size) { + printf("TPM_Transport_CryptSymmetric: Error (fatal), bad size\n"); + rc = TPM_FAIL; /* internal error, should never occur */ + } + } + if (rc == 0) { + /* leading clear text area */ + memcpy(dest, src, index); + dest += index; + src += index; + /* encrypt area */ + rc = TPM_SymmetricKeyData_StreamCrypt(dest, /* output */ + src, /* input */ + len, /* input */ + algId, /* algorithm */ + encScheme, /* mode */ + symmetric_key, /* input */ + symmetric_key_size, /* input */ + pad_in, /* input */ + pad_in_size); /* input */ + } + if (rc == 0) { + dest += len; + src += len; + /* trailing clear text area */ + memcpy(dest, src, size - index - len); + } + return rc; +} + +/* + Transport Sessions (the entire array) +*/ + +void TPM_TransportSessions_Init(TPM_TRANSPORT_INTERNAL *transSessions) +{ + size_t i; + + printf(" TPM_TransportSessions_Init:\n"); + for (i = 0 ; i < TPM_MIN_TRANS_SESSIONS ; i++) { + TPM_TransportInternal_Init(&(transSessions[i])); + } + return; +} + +/* TPM_TransportSessions_Load() reads a count of the number of stored sessions and then loads those + sessions. + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_TransportSessions_Init() + After use, call TPM_TransportSessions_Delete() to free memory +*/ + +TPM_RESULT TPM_TransportSessions_Load(TPM_TRANSPORT_INTERNAL *transSessions, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + size_t i; + uint32_t activeCount; + + printf(" TPM_TransportSessions_Load:\n"); + /* load active count */ + if (rc == 0) { + rc = TPM_Load32(&activeCount, stream, stream_size); + } + if (rc == 0) { + if (activeCount > TPM_MIN_TRANS_SESSIONS) { + printf("TPM_TransportSessions_Load: Error (fatal) %u sessions, %u slots\n", + activeCount, TPM_MIN_TRANS_SESSIONS); + rc = TPM_FAIL; + } + } + if (rc == 0) { + printf(" TPM_TransportSessions_Load: Loading %u sessions\n", activeCount); + } + for (i = 0 ; (rc == 0) && (i < activeCount) ; i++) { + rc = TPM_TransportInternal_Load(&(transSessions[i]), stream, stream_size); + } + return rc; +} + +/* TPM_TransportSessions_Store() stores a count of the active sessions, followed by the sessions. + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_TransportSessions_Store(TPM_STORE_BUFFER *sbuffer, + TPM_TRANSPORT_INTERNAL *transSessions) +{ + TPM_RESULT rc = 0; + size_t i; + uint32_t space; /* free transport session slots */ + uint32_t activeCount; /* used transport session slots */ + + /* store active count */ + if (rc == 0) { + TPM_TransportSessions_GetSpace(&space, transSessions); + activeCount = TPM_MIN_TRANS_SESSIONS - space; + printf(" TPM_TransSessions_Store: Storing %u sessions\n", activeCount); + rc = TPM_Sbuffer_Append32(sbuffer, activeCount); + } + /* store transport sessions */ + for (i = 0 ; (rc == 0) && (i < TPM_MIN_TRANS_SESSIONS) ; i++) { + if ((transSessions[i]).valid) { /* if the session is active */ + rc = TPM_TransportInternal_Store(sbuffer, &(transSessions[i])); + } + } + return rc; +} + +/* TPM_TransportSessions_Delete() terminates all sessions + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_TransportSessions_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_TransportSessions_Delete(TPM_TRANSPORT_INTERNAL *transSessions) +{ + size_t i; + + printf(" TPM_TransportSessions_Delete:\n"); + for (i = 0 ; i < TPM_MIN_TRANS_SESSIONS ; i++) { + TPM_TransportInternal_Delete(&(transSessions[i])); + } + return; +} + +/* TPM_TransportSessions_IsSpace() returns 'isSpace' TRUE if an entry is available, FALSE if not. + + If TRUE, 'index' holds the first free position. +*/ + +void TPM_TransportSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, + TPM_TRANSPORT_INTERNAL *transSessions) +{ + printf(" TPM_TransportSessions_IsSpace:\n"); + for (*index = 0, *isSpace = FALSE ; *index < TPM_MIN_TRANS_SESSIONS ; (*index)++) { + if (!((transSessions[*index]).valid)) { + printf(" TPM_TransportSessions_IsSpace: Found space at %u\n", *index); + *isSpace = TRUE; + break; + } + } + return; +} + +/* TPM_TransportSessions_GetSpace() returns the number of unused transport sessions. + +*/ + +void TPM_TransportSessions_GetSpace(uint32_t *space, + TPM_TRANSPORT_INTERNAL *transSessions) +{ + uint32_t i; + + printf(" TPM_TransportSessions_GetSpace:\n"); + for (*space = 0 , i = 0 ; i < TPM_MIN_TRANS_SESSIONS ; i++) { + if (!((transSessions[i]).valid)) { + (*space)++; + } + } + return; +} + +/* TPM_TransportSessions_StoreHandles() stores + + - the number of loaded sessions + - a list of session handles +*/ + +TPM_RESULT TPM_TransportSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, + TPM_TRANSPORT_INTERNAL *transSessions) +{ + TPM_RESULT rc = 0; + uint16_t i; + uint32_t space; + + printf(" TPM_TransportSessions_StoreHandles:\n"); + /* get the number of loaded handles */ + if (rc == 0) { + TPM_TransportSessions_GetSpace(&space, transSessions); + /* store loaded handle count. Cast safe because of TPM_MIN_TRANS_SESSIONS value */ + printf(" TPM_TransportSessions_StoreHandles: %u handles\n", + TPM_MIN_TRANS_SESSIONS - space); + rc = TPM_Sbuffer_Append16(sbuffer, (uint16_t)(TPM_MIN_TRANS_SESSIONS - space)); + } + for (i = 0 ; (rc == 0) && (i < TPM_MIN_TRANS_SESSIONS) ; i++) { + if ((transSessions[i]).valid) { /* if the index is loaded */ + rc = TPM_Sbuffer_Append32(sbuffer, (transSessions[i]).transHandle); /* store it */ + } + } + return rc; +} + +/* TPM_TransportSessions_GetNewHandle() checks for space in the transport sessions table. + + If there is space, it returns a TPM_TRANSPORT_INTERNAL entry in 'tpm_transport_internal'. The + entry is marked 'valid'. + + Returns TPM_RESOURCES if there is no space in the transport sessions table. +*/ + +TPM_RESULT TPM_TransportSessions_GetNewHandle(TPM_TRANSPORT_INTERNAL **tpm_transport_internal, + TPM_TRANSPORT_INTERNAL *transportSessions) +{ + TPM_RESULT rc = 0; + uint32_t index; + TPM_BOOL isSpace; + TPM_TRANSHANDLE transportHandle = 0; /* no suggested value */ + + printf(" TPM_TransportSessions_GetNewHandle:\n"); + /* is there an empty entry, get the location index */ + if (rc == 0) { + TPM_TransportSessions_IsSpace(&isSpace, &index, transportSessions); + if (!isSpace) { + printf("TPM_TransportSessions_GetNewHandle: Error, " + "no space in TransportSessions table\n"); + rc = TPM_RESOURCES; + } + } + /* assign transport handle */ + if (rc == 0) { + rc = TPM_Handle_GenerateHandle(&transportHandle, /* I/O */ + transportSessions, /* handle array */ + FALSE, /* keepHandle */ + FALSE, /* isKeyHandle */ + (TPM_GETENTRY_FUNCTION_T)TPM_TransportSessions_GetEntry); + } + if (rc == 0) { + printf(" TPM_TransportSessions_GetNewHandle: Assigned handle %08x\n", transportHandle); + /* return the TPM_TRANSPORT_INTERNAL */ + *tpm_transport_internal = &(transportSessions[index]); + /* assign the handle */ + (*tpm_transport_internal)->transHandle = transportHandle; + (*tpm_transport_internal)->valid = TRUE; + } + return rc; +} + +/* TPM_TransportSessions_GetEntry() searches all 'transportSessions' entries for the entry matching + the handle, and returns the TPM_TRANSPORT_INTERNAL entry associated with the handle. + + Returns + 0 for success + TPM_INVALID_AUTHHANDLE if the handle is not found +*/ + +TPM_RESULT TPM_TransportSessions_GetEntry(TPM_TRANSPORT_INTERNAL **tpm_transport_internal, + TPM_TRANSPORT_INTERNAL *transportSessions, /* array */ + TPM_TRANSHANDLE transportHandle) /* input */ +{ + TPM_RESULT rc = 0; + size_t i; + TPM_BOOL found; + + printf(" TPM_TransportSessions_GetEntry: transportHandle %08x\n", transportHandle); + for (i = 0, found = FALSE ; (i < TPM_MIN_TRANS_SESSIONS) && !found ; i++) { + if ((transportSessions[i].valid) && + (transportSessions[i].transHandle == transportHandle)) { /* found */ + found = TRUE; + *tpm_transport_internal = &(transportSessions[i]); + } + } + if (!found) { + printf(" TPM_TransportSessions_GetEntry: transport session handle %08x not found\n", + transportHandle); + rc = TPM_INVALID_AUTHHANDLE; + } + return rc; +} + +/* TPM_TransportSessions_AddEntry() adds an TPM_TRANSPORT_INTERNAL object to the list. + + If *tpm_handle == 0, a value is assigned. If *tpm_handle != 0, that value is used if it it not + currently in use. + + The handle is returned in tpm_handle. +*/ + +TPM_RESULT TPM_TransportSessions_AddEntry(TPM_HANDLE *tpm_handle, /* i/o */ + TPM_BOOL keepHandle, /* input */ + TPM_TRANSPORT_INTERNAL *transSessions, /* input */ + TPM_TRANSPORT_INTERNAL *tpm_transport_internal) /* in */ +{ + TPM_RESULT rc = 0; + uint32_t index; + TPM_BOOL isSpace; + + printf(" TPM_TransportSessions_AddEntry: handle %08x, keepHandle %u\n", + *tpm_handle, keepHandle); + /* check for valid TPM_TRANSPORT_INTERNAL */ + if (rc == 0) { + if (tpm_transport_internal == NULL) { /* NOTE: should never occur */ + printf("TPM_TransportSessions_AddEntry: Error (fatal), NULL TPM_TRANSPORT_INTERNAL\n"); + rc = TPM_FAIL; + } + } + /* is there an empty entry, get the location index */ + if (rc == 0) { + TPM_TransportSessions_IsSpace(&isSpace, &index, transSessions); + if (!isSpace) { + printf("TPM_TransportSessions_AddEntry: Error, transport session entries full\n"); + rc = TPM_RESOURCES; + } + } + if (rc == 0) { + rc = TPM_Handle_GenerateHandle(tpm_handle, /* I/O */ + transSessions, /* handle array */ + keepHandle, /* keepHandle */ + FALSE, /* isKeyHandle */ + (TPM_GETENTRY_FUNCTION_T)TPM_TransportSessions_GetEntry); + } + if (rc == 0) { + tpm_transport_internal->transHandle = *tpm_handle; + tpm_transport_internal->valid = TRUE; + TPM_TransportInternal_Copy(&(transSessions[index]), tpm_transport_internal); + printf(" TPM_TransportSessions_AddEntry: Index %u handle %08x\n", + index, transSessions[index].transHandle); + } + return rc; +} + +/* TPM_TransportSessions_TerminateHandle() terminates the session associated with + 'transporthHandle'. + + If the session is exclusive (indicated by a match with TPM_STANY_FLAGS -> transportExclusive), + clear that flag. +*/ + +TPM_RESULT TPM_TransportSessions_TerminateHandle(TPM_TRANSPORT_INTERNAL *transportSessions, + TPM_TRANSHANDLE transportHandle, + TPM_TRANSHANDLE *transportExclusive) +{ + TPM_RESULT rc = 0; + TPM_TRANSPORT_INTERNAL *tpm_transport_internal; + + printf(" TPM_TransportSessions_TerminateHandle: Handle %08x\n", transportHandle); + /* get the TPM_TRANSPORT_INTERNAL associated with the TPM_TRANSHANDLE */ + if (rc == 0) { + rc = TPM_TransportSessions_GetEntry(&tpm_transport_internal, + transportSessions, + transportHandle); + } + /* if the session being terminated is exclusive, reset the flag */ + if (rc == 0) { + if (transportHandle == *transportExclusive) { + printf(" TPM_TransportSessions_TerminateHandle: Is exclusive transport session\n"); + if (!(tpm_transport_internal->transPublic.transAttributes & TPM_TRANSPORT_EXCLUSIVE)) { + printf("TPM_TransportSessions_TerminateHandle: Error (fatal), " + "attribute is not exclusive\n"); + rc = TPM_FAIL; /* internal error, should not occur */ + } + *transportExclusive = 0; + } + } + /* invalidate the valid handle */ + if (rc == 0) { + TPM_TransportInternal_Delete(tpm_transport_internal); + } + return rc; +} + +/* + TPM_TRANSPORT_PUBLIC +*/ + +/* TPM_TransportPublic_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_TransportPublic_Init(TPM_TRANSPORT_PUBLIC *tpm_transport_public) +{ + printf(" TPM_TransportPublic_Init:\n"); + tpm_transport_public->transAttributes = 0; + tpm_transport_public->algId = 0; + tpm_transport_public->encScheme = TPM_ES_NONE; + return; +} + +/* TPM_TransportPublic_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_TransportPublic_Init() + After use, call TPM_TransportPublic_Delete() to free memory +*/ + +TPM_RESULT TPM_TransportPublic_Load(TPM_TRANSPORT_PUBLIC *tpm_transport_public, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportPublic_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_TRANSPORT_PUBLIC, stream, stream_size); + } + /* load transAttributes */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_transport_public->transAttributes ), stream, stream_size); + } + /* load algId */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_transport_public->algId), stream, stream_size); + } + /* load encScheme */ + if (rc == 0) { + rc = TPM_Load16(&(tpm_transport_public->encScheme), stream, stream_size); + } + return rc; +} + +/* TPM_TransportPublic_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_TransportPublic_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_PUBLIC *tpm_transport_public) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportPublic_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_PUBLIC); + } + /* store transAttributes */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_transport_public->transAttributes); + } + /* store algId */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_transport_public->algId); + } + /* store encScheme */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, tpm_transport_public->encScheme); + } + return rc; +} + +/* TPM_TransportPublic_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_TransportPublic_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_TransportPublic_Delete(TPM_TRANSPORT_PUBLIC *tpm_transport_public) +{ + printf(" TPM_TransportPublic_Delete:\n"); + if (tpm_transport_public != NULL) { + TPM_TransportPublic_Init(tpm_transport_public); + } + return; +} + +/* TPM_TransportPublic_Copy() copies the 'src' to the 'dest' structure + +*/ + +TPM_RESULT TPM_TransportPublic_Copy(TPM_TRANSPORT_PUBLIC *dest, + const TPM_TRANSPORT_PUBLIC *src) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportPublic_Copy:\n"); + /* copy transAttributes */ + dest->transAttributes = src->transAttributes; + /* copy algId */ + dest->algId = src->algId; + /* copy encScheme */ + dest->encScheme = src->encScheme; + return rc; +} + +/* TPM_TransportPublic_CheckAlgId() returns 'supported' TRUE if the transport encryption algorithm + is supported by the TPM + +*/ + +void TPM_TransportPublic_CheckAlgId(TPM_BOOL *supported, + TPM_ALGORITHM_ID algId) +{ + printf(" TPM_TransportPublic_CheckAlgId: %08x\n", algId); + switch (algId) { + /* supported protocols */ + case TPM_ALG_MGF1: + case TPM_ALG_AES128: + *supported = TRUE; + break; + /* unsupported protocols */ + case TPM_ALG_RSA: + case TPM_ALG_SHA: + case TPM_ALG_HMAC: + case TPM_ALG_AES192: + case TPM_ALG_AES256: + default: + *supported = FALSE; + break; + } + return; +} + +/* TPM_TransportPublic_CheckEncScheme() returns success and the blockSize if the transport algId and + encScheme are supported by the TPM. +*/ + +TPM_RESULT TPM_TransportPublic_CheckEncScheme(uint32_t *blockSize, + TPM_ALGORITHM_ID algId, + TPM_ENC_SCHEME encScheme, + TPM_BOOL FIPS) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportPublic_CheckEncScheme: algId %08x encScheme %04hx\n", algId, encScheme); + switch (algId) { + /* supported protocols with no encScheme */ + case TPM_ALG_MGF1: + *blockSize = 0; /* MGF1 does not use blocks */ + if (FIPS) { + printf("TPM_TransportPublic_CheckEncScheme: Error, " + "TPM_ALG_MGF1 not supported in FIPS\n"); + rc = TPM_INAPPROPRIATE_ENC; + } + /* For TPM_ALG_MGF1, TPM_ENC_SCHEME is not used. The TPM MAY validate that TPM_ENC_SCHEME + is TPM_ES_NONE. */ + if (encScheme != TPM_ES_NONE) { + printf("TPM_TransportPublic_CheckEncScheme: Error, " + "TPM_ALG_MGF1 must use TPM_ES_NONE\n"); + rc = TPM_INAPPROPRIATE_ENC; + } + break; + /* protocols with encScheme */ + case TPM_ALG_AES128: + switch(encScheme) { + case TPM_ES_SYM_CTR: /* CTR mode */ + case TPM_ES_SYM_OFB: /* OFB mode */ + *blockSize = 128/8; + break; + default: + printf("TPM_TransportPublic_CheckEncScheme: Error, AES128 encScheme not supported\n"); + rc = TPM_INAPPROPRIATE_ENC; + break; + } + break; + /* unsupported protocols */ + case TPM_ALG_AES192: + case TPM_ALG_AES256: + case TPM_ALG_RSA: + case TPM_ALG_SHA: + case TPM_ALG_HMAC: + case TPM_ALG_XOR: + default: + printf("TPM_TransportPublic_CheckEncScheme: Error, algId not supported\n"); + rc = TPM_BAD_KEY_PROPERTY; + break; + } + return rc; +} + +/* + TPM_TRANSPORT_INTERNAL +*/ + +/* TPM_TransportInternal_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_TransportInternal_Init(TPM_TRANSPORT_INTERNAL *tpm_transport_internal) +{ + printf(" TPM_TransportInternal_Init:\n"); + TPM_Secret_Init(tpm_transport_internal->authData); + TPM_TransportPublic_Init(&(tpm_transport_internal->transPublic)); + tpm_transport_internal->transHandle = 0; + TPM_Nonce_Init(tpm_transport_internal->transNonceEven); + TPM_Digest_Init(tpm_transport_internal->transDigest); + tpm_transport_internal->valid = FALSE; + return; +} + +/* TPM_TransportInternal_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_TransportInternal_Init() + After use, call TPM_TransportInternal_Delete() to free memory +*/ + +TPM_RESULT TPM_TransportInternal_Load(TPM_TRANSPORT_INTERNAL *tpm_transport_internal, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportInternal_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_TRANSPORT_INTERNAL, stream, stream_size); + } + /* load authData */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_transport_internal->authData, stream, stream_size); + } + /* load transPublic */ + if (rc == 0) { + rc = TPM_TransportPublic_Load(&(tpm_transport_internal->transPublic), stream, stream_size); + } + /* load transHandle */ + if (rc == 0) { + rc = TPM_Load32(&(tpm_transport_internal->transHandle), stream, stream_size); + } + /* load transNonceEven */ + if (rc == 0) { + rc = TPM_Nonce_Load(tpm_transport_internal->transNonceEven, stream, stream_size); + } + /* load transDigest */ + if (rc == 0) { + rc = TPM_Digest_Load(tpm_transport_internal->transDigest, stream, stream_size); + } + /* load valid */ + if (rc == 0) { + tpm_transport_internal->valid = TRUE; + } + return rc; +} + +/* TPM_TransportInternal_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_TransportInternal_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_INTERNAL *tpm_transport_internal) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportInternal_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_INTERNAL); + } + /* store authData */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_transport_internal->authData); + } + /* store transPublic */ + if (rc == 0) { + rc = TPM_TransportPublic_Store(sbuffer, &(tpm_transport_internal->transPublic)); + } + /* store transHandle */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_transport_internal->transHandle); + } + /* store transNonceEven */ + if (rc == 0) { + rc = TPM_Nonce_Store(sbuffer, tpm_transport_internal->transNonceEven); + } + /* store transDigest */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_transport_internal->transDigest); + } + return rc; +} + +/* TPM_TransportInternal_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_TransportInternal_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_TransportInternal_Delete(TPM_TRANSPORT_INTERNAL *tpm_transport_internal) +{ + printf(" TPM_TransportInternal_Delete:\n"); + if (tpm_transport_internal != NULL) { + TPM_TransportPublic_Delete(&(tpm_transport_internal->transPublic)); + TPM_TransportInternal_Init(tpm_transport_internal); + } + return; +} + +/* TPM_TransportInternal_Copy() copies the source to the destination. + +*/ + +void TPM_TransportInternal_Copy(TPM_TRANSPORT_INTERNAL *dest_transport_internal, + TPM_TRANSPORT_INTERNAL *src_transport_internal) +{ + TPM_Secret_Copy(dest_transport_internal->authData, src_transport_internal->authData); + TPM_TransportPublic_Copy(&(dest_transport_internal->transPublic), + &(src_transport_internal->transPublic)); + dest_transport_internal->transHandle = src_transport_internal->transHandle; + TPM_Nonce_Copy(dest_transport_internal->transNonceEven, src_transport_internal->transNonceEven); + TPM_Digest_Copy(dest_transport_internal->transDigest, src_transport_internal->transDigest); + dest_transport_internal->valid = src_transport_internal->valid; +} + +/* TPM_TransportInternal_Check() checks the authorization of a command. + + There is no need to protect against dictionary attacks. The first failure terminates the + transport session. + + Returns TPM_AUTH2FAIL if the TPM_AUTHDATA does not match. +*/ + +TPM_RESULT TPM_TransportInternal_Check(TPM_DIGEST inParamDigest, /* digest of inputs + above line */ + TPM_TRANSPORT_INTERNAL *tpm_transport_internal, + TPM_NONCE transNonceOdd, /* Nonce generated + by system + associated with + transHandle */ + TPM_BOOL continueTransSession, + TPM_AUTHDATA transAuth) /* Authorization + digest for + input */ +{ + TPM_RESULT rc = 0; + TPM_BOOL valid; + + printf(" TPM_TransportInternal_Check:\n"); + if (rc == 0) { + TPM_PrintFour(" TPM_TransportInternal_Check: inParamDigest", inParamDigest); + TPM_PrintFour(" TPM_TransportInternal_Check: usageAuth (key)", + tpm_transport_internal->authData); + TPM_PrintFour(" TPM_TransportInternal_Check: nonceEven", + tpm_transport_internal->transNonceEven); + TPM_PrintFour(" TPM_TransportInternal_Check: nonceOdd", transNonceOdd); + printf (" TPM_TransportInternal_Check: continueSession %02x\n", continueTransSession); + /* HMAC the inParamDigest, transLastNonceEven, transNonceOdd, continueTransSession */ + /* transLastNonceEven is retrieved from internal transport session storage */ + rc = TPM_HMAC_Check(&valid, + transAuth, /* expected, from command */ + tpm_transport_internal->authData, /* key */ + sizeof(TPM_DIGEST), inParamDigest, /* command digest */ + sizeof(TPM_NONCE), tpm_transport_internal->transNonceEven, /* 2H */ + sizeof(TPM_NONCE), transNonceOdd, /* 3H */ + sizeof(TPM_BOOL), &continueTransSession, /* 4H */ + 0, NULL); + } + if (rc == 0) { + if (!valid) { + printf("TPM_TransportInternal_Check: Error, authorization failed\n"); + rc = TPM_AUTH2FAIL; + } + } + return rc; +} + +/* TPM_TransportInternal_Set() sets the transport response transAuth. + + It conditionally generates the next transNonceEven. + + It appends transNonceEven and continueTransSession to the response. + + It generates transAuth using outParamDigest and the standard 'below the line' HMAC rules and + appends it to the response. +*/ + +TPM_RESULT TPM_TransportInternal_Set(TPM_STORE_BUFFER *response, + TPM_TRANSPORT_INTERNAL *tpm_transport_internal, + TPM_DIGEST outParamDigest, + TPM_NONCE transNonceOdd, + TPM_BOOL continueTransSession, + TPM_BOOL generateNonceEven) +{ + TPM_RESULT rc = 0; + TPM_AUTHDATA transAuth; /* The authorization digest for the returned parameters */ + + printf(" TPM_TransportInternal_Set:\n"); + /* generate transNonceEven if not already done by caller */ + if ((rc == 0) && generateNonceEven) { + rc = TPM_Nonce_Generate(tpm_transport_internal->transNonceEven); + } + /* append transNonceEven */ + if (rc == 0) { + rc = TPM_Nonce_Store(response, tpm_transport_internal->transNonceEven); + } + /* append continueTransSession*/ + if (rc == 0) { + rc = TPM_Sbuffer_Append(response, &continueTransSession, sizeof(TPM_BOOL)); + } + /* Calculate transAuth using the transport session authData */ + if (rc == 0) { + rc = TPM_Authdata_Generate(transAuth, /* result */ + tpm_transport_internal->authData, /* HMAC key */ + outParamDigest, /* params */ + tpm_transport_internal->transNonceEven, + transNonceOdd, + continueTransSession); + } + /* append transAuth */ + if (rc == 0) { + rc = TPM_Authdata_Store(response, transAuth); + } + return rc; +} + +/* + TPM_TRANSPORT_LOG_IN +*/ + +/* TPM_TransportLogIn_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_TransportLogIn_Init(TPM_TRANSPORT_LOG_IN *tpm_transport_log_in) +{ + printf(" TPM_TransportLogIn_Init:\n"); + TPM_Digest_Init(tpm_transport_log_in->parameters); + TPM_Digest_Init(tpm_transport_log_in->pubKeyHash); + return; +} + +/* TPM_TransportLogIn_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_TransportLogIn_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_LOG_IN *tpm_transport_log_in) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportLogIn_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_LOG_IN); + } + /* store parameters */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_transport_log_in->parameters); + } + /* store pubKeyHash */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_transport_log_in->pubKeyHash); + } + return rc; +} + +/* TPM_TransportLogIn_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_TransportLogIn_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_TransportLogIn_Delete(TPM_TRANSPORT_LOG_IN *tpm_transport_log_in) +{ + printf(" TPM_TransportLogIn_Delete:\n"); + if (tpm_transport_log_in != NULL) { + TPM_TransportLogIn_Init(tpm_transport_log_in); + } + return; +} + +/* TPM_TransportLogIn_Extend() extends 'tpm_digest' + + tpm_digest = SHA-1 (tpm_digest || tpm_transport_log_in) +*/ + +TPM_RESULT TPM_TransportLogIn_Extend(TPM_DIGEST tpm_digest, + TPM_TRANSPORT_LOG_IN *tpm_transport_log_in) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; + const unsigned char *buffer; /* serialized buffer */ + uint32_t length; /* serialization length */ + + printf(" TPM_TransportLogIn_Extend:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize TPM_TRANSPORT_LOG_IN */ + if (rc == 0) { + rc = TPM_TransportLogIn_Store(&sbuffer, tpm_transport_log_in); + } + if (rc == 0) { + /* get the TPM_TRANSPORT_LOG_IN serialization results */ + TPM_Sbuffer_Get(&sbuffer, &buffer, &length); + TPM_PrintAll(" TPM_TransportLogIn_Extend: transDigest in", tpm_digest, TPM_DIGEST_SIZE); + TPM_PrintAll(" TPM_TransportLogIn_Extend", buffer, length); + rc = TPM_SHA1(tpm_digest, + TPM_DIGEST_SIZE, tpm_digest, + length, buffer, + 0, NULL); + TPM_PrintAll(" TPM_TransportLogIn_Extend: transDigest out", tpm_digest, TPM_DIGEST_SIZE); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* + TPM_TRANSPORT_LOG_OUT +*/ + +/* TPM_TransportLogOut_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_TransportLogOut_Init(TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out) +{ + printf(" TPM_TransportLogOut_Init:\n"); + TPM_CurrentTicks_Init(&(tpm_transport_log_out->currentTicks)); + TPM_Digest_Init(tpm_transport_log_out->parameters); + tpm_transport_log_out = 0; + return; +} + +/* TPM_TransportLogOut_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_TransportLogOut_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportLogOut_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_LOG_OUT); + } + /* store currentTicks */ + if (rc == 0) { + rc = TPM_CurrentTicks_Store(sbuffer, &(tpm_transport_log_out->currentTicks)); + } + /* store parameters */ + if (rc == 0) { + rc = TPM_Digest_Store(sbuffer, tpm_transport_log_out->parameters); + } + /* store locality */ + if (rc == 0) { + rc = TPM_Sbuffer_Append32(sbuffer, tpm_transport_log_out->locality); + } + return rc; +} + +/* TPM_TransportLogOut_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_TransportLogOut_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_TransportLogOut_Delete(TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out) +{ + printf(" TPM_TransportLogOut_Delete:\n"); + if (tpm_transport_log_out != NULL) { + TPM_TransportLogOut_Init(tpm_transport_log_out); + } + return; +} + +/* TPM_TransportLogOut_Extend() extends 'tpm_digest' + + tpm_digest = SHA-1 (tpm_digest || tpm_transport_log_out) +*/ + +TPM_RESULT TPM_TransportLogOut_Extend(TPM_DIGEST tpm_digest, + TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out) +{ + TPM_RESULT rc = 0; + TPM_STORE_BUFFER sbuffer; + const unsigned char *buffer; /* serialized buffer */ + uint32_t length; /* serialization length */ + + printf(" TPM_TransportLogOut_Extend:\n"); + TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ + /* serialize TPM_TRANSPORT_LOG_OUT */ + if (rc == 0) { + rc = TPM_TransportLogOut_Store(&sbuffer, tpm_transport_log_out); + } + if (rc == 0) { + /* get the TPM_TRANSPORT_LOG_OUT serialization results */ + TPM_Sbuffer_Get(&sbuffer, &buffer, &length); + TPM_PrintAll(" TPM_TransportLogOut_Extend: transDigest in", tpm_digest, TPM_DIGEST_SIZE); + TPM_PrintAll(" TPM_TransportLogOut_Extend:", buffer, length); + rc = TPM_SHA1(tpm_digest, + TPM_DIGEST_SIZE, tpm_digest, + length, buffer, + 0, NULL); + TPM_PrintAll(" TPM_TransportLogOut_Extend: transDigest out", tpm_digest, TPM_DIGEST_SIZE); + } + TPM_Sbuffer_Delete(&sbuffer); /* @1 */ + return rc; +} + +/* + TPM_TRANSPORT_AUTH +*/ + +/* TPM_TransportAuth_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_TransportAuth_Init(TPM_TRANSPORT_AUTH *tpm_transport_auth) +{ + printf(" TPM_TransportAuth_Init:\n"); + TPM_Secret_Init(tpm_transport_auth->authData); + return; +} + +/* TPM_TransportAuth_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_TransportAuth_Init() + After use, call TPM_TransportAuth_Delete() to free memory +*/ + +TPM_RESULT TPM_TransportAuth_Load(TPM_TRANSPORT_AUTH *tpm_transport_auth, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportAuth_Load:\n"); + /* check tag */ + if (rc == 0) { + rc = TPM_CheckTag(TPM_TAG_TRANSPORT_AUTH, stream, stream_size); + } + /* load authData */ + if (rc == 0) { + rc = TPM_Secret_Load(tpm_transport_auth->authData, stream, stream_size); + } + return rc; +} + +/* TPM_TransportAuth_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_TransportAuth_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_AUTH *tpm_transport_auth) +{ + TPM_RESULT rc = 0; + + printf(" TPM_TransportAuth_Store:\n"); + /* store tag */ + if (rc == 0) { + rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_AUTH); + } + /* store authData */ + if (rc == 0) { + rc = TPM_Secret_Store(sbuffer, tpm_transport_auth->authData); + } + return rc; +} + +/* TPM_TransportAuth_Delete() + + No-OP if the parameter is NULL, else: + frees memory allocated for the object + sets pointers to NULL + calls TPM_TransportAuth_Init to set members back to default values + The object itself is not freed +*/ + +void TPM_TransportAuth_Delete(TPM_TRANSPORT_AUTH *tpm_transport_auth) +{ + printf(" TPM_TransportAuth_Delete:\n"); + if (tpm_transport_auth != NULL) { + TPM_TransportAuth_Init(tpm_transport_auth); + } + return; +} + +/* TPM_TransportAuth_DecryptSecret() decrypts the secret using the private key. The + result is deserialized and stored in the TPM_TRANSPORT_AUTH structure. +*/ + +TPM_RESULT TPM_TransportAuth_DecryptSecret(TPM_TRANSPORT_AUTH *tpm_transport_auth, /* result */ + TPM_SIZED_BUFFER *secret, /* encrypted input */ + TPM_KEY *tpm_key) /* key for decrypting */ +{ + TPM_RESULT rc = 0; + unsigned char *decryptData = NULL; /* freed @1 */ + uint32_t decryptDataLength = 0; /* actual valid data */ + unsigned char *stream; + uint32_t stream_size; + + printf(" TPM_TransportAuth_DecryptSecret:\n"); + /* allocate space for the decrypted data */ + if (rc == 0) { + rc = TPM_RSAPrivateDecryptMalloc(&decryptData, /* decrypted data */ + &decryptDataLength, /* actual size of decrypted data */ + secret->buffer, /* encrypted data */ + secret->size, /* encrypted data size */ + tpm_key); + } + /* load the TPM_TRANSPORT_AUTH structure from the decrypted data stream */ + if (rc == 0) { + /* use temporary variables, because TPM_TransportAuth_Load() moves the stream */ + stream = decryptData; + stream_size = decryptDataLength; + rc = TPM_TransportAuth_Load(tpm_transport_auth, &stream, &stream_size); + } + free(decryptData); /* @1 */ + return rc; +} + +/* + Processing Functions +*/ + +/* 24.1 TPM_EstablishTransport rev 98 + + This establishes the transport session. Depending on the attributes specified for the session + this may establish shared secrets, encryption keys, and session logs. The session will be in use + for by the TPM_ExecuteTransport command. + + The only restriction on what can happen inside of a transport session is that there is no + "nesting" of sessions. It is permissible to perform operations that delete internal state and + make the TPM inoperable. +*/ + +TPM_RESULT TPM_Process_EstablishTransport(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE encHandle; /* The handle to the key that encrypted the blob */ + TPM_TRANSPORT_PUBLIC transPublic; /* The public information describing the transport + session */ + TPM_SIZED_BUFFER secret; /* The encrypted secret area */ + TPM_AUTHHANDLE authHandle; /* The authorization session handle used for + keyHandle authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with + authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the + authorization session handle */ + TPM_AUTHDATA keyAuth; /* Authorization. HMAC key: encKey.usageAuth */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */ + TPM_SECRET *hmacKey; + TPM_KEY *encKey = NULL; /* the key specified by encHandle */ + TPM_BOOL parentPCRStatus; + TPM_SECRET *encKeyUsageAuth; + TPM_AUTHDATA *a1AuthData = NULL; + TPM_TRANSPORT_INTERNAL *t1TpmTransportInternal; + TPM_TRANSPORT_AUTH k1TransportAuth; + uint32_t blockSize; /* symmetric key block size, not used */ + TPM_TRANSPORT_LOG_IN l1TransportLogIn; + TPM_TRANSPORT_LOG_OUT l2TransportLogOut; + TPM_STORE_BUFFER transPublicSbuffer; /* serialized transPublic */ + const unsigned char *transPublicBuffer; /* serialized buffer */ + uint32_t transPublicLength; /* serialization length */ + TPM_STORE_BUFFER currentTicksSbuffer; /* serialized currentTicks */ + const unsigned char *currentTicksBuffer; /* serialized buffer */ + uint32_t currentTicksLength; /* serialization length */ + TPM_COMMAND_CODE nOrdinal; /* ordinal in nbo */ + uint32_t nSecretSize; /* secretSize in nbo */ + TPM_RESULT nReturnCode; /* returnCode in nbo */ + TPM_MODIFIER_INDICATOR nLocality; /* locality in nbo */ + TPM_BOOL trans_session_added = FALSE; + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_CURRENT_TICKS currentTicks; /* The current tick count */ + TPM_NONCE transNonceEven; /* The even nonce in use for subsequent + execute transport */ + + printf("TPM_Process_EstablishTransport: Ordinal Entry\n"); + TPM_TransportPublic_Init(&transPublic); /* freed @1 */ + TPM_SizedBuffer_Init(&secret); /* freed @2 */ + TPM_CurrentTicks_Init(¤tTicks); /* no need to free */ + TPM_TransportAuth_Init(&k1TransportAuth); /* freed @4 */ + TPM_TransportLogIn_Init(&l1TransportLogIn); /* freed @5 */ + TPM_TransportLogOut_Init(&l2TransportLogOut); /* freed @6 */ + TPM_Sbuffer_Init(&transPublicSbuffer); /* freed @7 */ + TPM_Sbuffer_Init(¤tTicksSbuffer); /* freed @8 */ + /* + get inputs + */ + /* get encHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&encHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get transPublic */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_EstablishTransport: keyHandle %08x\n", encHandle); + returnCode = TPM_TransportPublic_Load(&transPublic, &command, ¶mSize); + } + /* get secret */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_EstablishTransport: transPublic->transAttributes %08x\n", + transPublic.transAttributes); + returnCode = TPM_SizedBuffer_Load(&secret, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag10(tag); + } + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + nonceOdd, + &continueAuthSession, + keyAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_EstablishTransport: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + authHandleValid = FALSE; + } + /* + Processing + */ + if (returnCode == TPM_SUCCESS) { + /* 1. If encHandle is TPM_KH_TRANSPORT then */ + if (encHandle == TPM_KH_TRANSPORT) { + printf("TPM_Process_EstablishTransport: TPM_KH_TRANSPORT clear text secret\n"); + /* a. If tag is NOT TPM_TAG_RQU_COMMAND return TPM_BADTAG */ + if (returnCode == TPM_SUCCESS) { + if (tag != TPM_TAG_RQU_COMMAND) { + printf("TPM_Process_EstablishTransport: Error, " + "TPM_KH_TRANSPORT but not auth-0\n"); + returnCode = TPM_BADTAG; + } + } + /* b. If transPublic -> transAttributes specifies TPM_TRANSPORT_ENCRYPT return + TPM_BAD_SCHEME */ + if (returnCode == TPM_SUCCESS) { + if (transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) { + printf("TPM_Process_EstablishTransport: Error, " + "TPM_KH_TRANSPORT but TPM_TRANSPORT_ENCRYPT\n"); + returnCode = TPM_BAD_SCHEME; + } + } + /* c. If secretSize is not 20 return TPM_BAD_PARAM_SIZE */ + if (returnCode == TPM_SUCCESS) { + if (secret.size != TPM_DIGEST_SIZE) { + printf("TPM_Process_EstablishTransport: Error, secretSize %u not %u\n", + secret.size, TPM_DIGEST_SIZE); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* d. Set A1 to secret */ + if (returnCode == TPM_SUCCESS) { + a1AuthData = (TPM_AUTHDATA *)(secret.buffer); + TPM_PrintFour("TPM_Process_EstablishTransport: transport clear text authData", *a1AuthData); + } + } + /* 2. Else */ + else { + printf("TPM_Process_EstablishTransport: Decrypt secret\n"); + /* get the key corresponding to the encHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&encKey, &parentPCRStatus, tpm_state, + encHandle, + FALSE, /* not r/o, using to encrypt */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* a. encHandle -> keyUsage MUST be TPM_KEY_STORAGE or TPM_KEY_LEGACY return + TPM_INVALID_KEYUSAGE on error */ + if (returnCode == TPM_SUCCESS) { + if ((encKey->keyUsage != TPM_KEY_STORAGE) && + (encKey->keyUsage != TPM_KEY_LEGACY)) { + printf("TPM_Process_EstablishTransport: Error, " + "key keyUsage %04hx must be TPM_KEY_STORAGE or TPM_KEY_LEGACY\n", + encKey->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* b. If encHandle -> authDataUsage does not equal TPM_AUTH_NEVER and tag is NOT + TPM_TAG_RQU_AUTH1_COMMAND return TPM_AUTHFAIL */ + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) { + if (encKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_EstablishTransport: Error, " + "encKey authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get encHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&encKeyUsageAuth, encKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + encKey, + encKeyUsageAuth, /* OIAP */ + encKey->tpm_store_asymkey-> + pubDataDigest); /*OSAP */ + } + /* c. Using encHandle -> usageAuth, validate the AuthData to use the key and the + parameters to the command */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + keyAuth); /* Authorization digest for input */ + } + /* d. Create K1 a TPM_TRANSPORT_AUTH structure by decrypting secret using the key + pointed to by encHandle */ + /* e. Validate K1 for tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_TransportAuth_DecryptSecret(&k1TransportAuth, + &secret, + encKey); + + } + /* f. Set A1 to K1 -> authData */ + if (returnCode == TPM_SUCCESS) { + a1AuthData = &(k1TransportAuth.authData); + TPM_PrintFour("TPM_Process_EstablishTransport: transport decrypted authData", + *a1AuthData); + } + } + } + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_EstablishTransport: transport authData", *a1AuthData); + } + /* 3. If transPublic -> transAttributes has TPM_TRANSPORT_ENCRYPT */ + if ((returnCode == TPM_SUCCESS) && (transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT)) { + printf("TPM_Process_EstablishTransport: Check encrypt attributes\n"); + /* a. If TPM_PERMANENT_FLAGS -> FIPS is true and transPublic -> algId is equal to + TPM_ALG_MGF1 return TPM_INAPPROPRIATE_ENC */ + /* b. Check if the transPublic -> algId is supported, if not return TPM_BAD_KEY_PROPERTY */ + /* c. If transPublic -> algid is TPM_ALG_AESXXX, check that transPublic -> encScheme is + supported, if not return TPM_INAPPROPRIATE_ENC */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_TransportPublic_CheckEncScheme(&blockSize, + transPublic.algId, + transPublic.encScheme, + tpm_state->tpm_permanent_flags.FIPS); + } + /* d. Perform any initializations necessary for the algorithm */ + } + /* 4. Generate transNonceEven from the TPM RNG */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Generate(transNonceEven); + } + /* 5. Create T1 a TPM_TRANSPORT_INTERNAL structure */ + /* NOTE Done by TPM_TransportInternal_Init() */ + /* a. Ensure that the TPM has sufficient internal space to allocate the transport session, + return TPM_RESOURCES on error */ + /* b. Assign a T1 -> transHandle value. This value is assigned by the TPM */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_EstablishTransport: Construct TPM_TRANSPORT_INTERNAL\n"); + returnCode = + TPM_TransportSessions_GetNewHandle(&t1TpmTransportInternal, + tpm_state->tpm_stclear_data.transSessions); + } + if (returnCode == TPM_SUCCESS) { + /* record that the entry is allocated, for invalidation on error */ + trans_session_added = TRUE; + /* c. Set T1 -> transDigest to NULL */ + TPM_Digest_Init(t1TpmTransportInternal->transDigest); + /* d. Set T1 -> transPublic to transPublic */ + TPM_TransportPublic_Copy(&(t1TpmTransportInternal->transPublic), &transPublic); + /* e. Set T1-> transNonceEven to transNonceEven */ + TPM_Nonce_Copy(t1TpmTransportInternal->transNonceEven , transNonceEven); + /* f. Set T1 -> authData to A1 */ + TPM_Secret_Copy(t1TpmTransportInternal->authData, *a1AuthData); + /* 6. If TPM_STANY_DATA -> currentTicks is not properly initialized */ + /* a. Initialize the TPM_STANY_DATA -> currentTicks */ + returnCode = TPM_CurrentTicks_Update(&(tpm_state->tpm_stany_data.currentTicks)); + } + /* 7. Set currentTicks to TPM_STANY_DATA -> currentTicks */ + if (returnCode == TPM_SUCCESS) { + TPM_CurrentTicks_Copy(¤tTicks, &(tpm_state->tpm_stany_data.currentTicks)); + } + /* 8. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_LOG set then */ + if ((returnCode == TPM_SUCCESS) && + (t1TpmTransportInternal->transPublic.transAttributes & TPM_TRANSPORT_LOG)) { + + printf("TPM_Process_EstablishTransport: Construct TPM_TRANSPORT_LOG_IN\n"); + /* a. Create L1 a TPM_TRANSPORT_LOG_IN structure */ + /* NOTE Done by TPM_TransportLogIn_Init() */ + /* i. Set L1 -> parameters to SHA-1 (ordinal || transPublic || secretSize || secret) */ + /* serialize transPublic */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_TransportPublic_Store(&transPublicSbuffer, &transPublic); + } + if (returnCode == TPM_SUCCESS) { + /* get the transPublic serialization results */ + TPM_Sbuffer_Get(&transPublicSbuffer, &transPublicBuffer, &transPublicLength); + /* digest the fields */ + nOrdinal = htonl(ordinal); + nSecretSize = htonl(secret.size); + returnCode = TPM_SHA1(l1TransportLogIn.parameters, + sizeof(TPM_COMMAND_CODE), &nOrdinal, + transPublicLength, transPublicBuffer, + sizeof(uint32_t), &nSecretSize, + secret.size, secret.buffer, + 0, NULL); + } + if (returnCode == TPM_SUCCESS) { + /* ii. Set L1 -> pubKeyHash to NULL */ + /* NOTE Done by TPM_TransportLogIn_Init() */ + /* iii. Set T1 -> transDigest to SHA-1 (T1 -> transDigest || L1) */ + printf("TPM_Process_EstablishTransport: Extend transDigest with input\n"); + returnCode = TPM_TransportLogIn_Extend(t1TpmTransportInternal->transDigest, + &l1TransportLogIn); + } + /* b. Create L2 a TPM_TRANSPORT_LOG_OUT structure */ + /* NOTE Done by TPM_TransportLogOut_Init() */ + /* i. Set L2 -> parameters to SHA-1 (returnCode || ordinal || locality || currentTicks || + transNonceEven) */ + /* serialize currentTicks */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_EstablishTransport: Construct TPM_TRANSPORT_LOG_OUT\n"); + returnCode = TPM_CurrentTicks_Store(¤tTicksSbuffer, ¤tTicks); + } + if (returnCode == TPM_SUCCESS) { + /* get the currentTicks serialization results */ + TPM_Sbuffer_Get(¤tTicksSbuffer, ¤tTicksBuffer, ¤tTicksLength); + nReturnCode = htonl(returnCode); + nLocality = htonl(tpm_state->tpm_stany_flags.localityModifier); + returnCode = TPM_SHA1(l2TransportLogOut.parameters, + sizeof(TPM_RESULT), &nReturnCode, + sizeof(TPM_COMMAND_CODE), &nOrdinal, + sizeof(TPM_MODIFIER_INDICATOR), &nLocality, + currentTicksLength, currentTicksBuffer, + TPM_NONCE_SIZE, transNonceEven, + 0, NULL); + } + if (returnCode == TPM_SUCCESS) { + /* ii. Set L2 -> locality to the locality of this command */ + l2TransportLogOut.locality = tpm_state->tpm_stany_flags.localityModifier; + /* iii. Set L2 -> currentTicks to currentTicks, this MUST be the same value that is + returned in the currentTicks parameter */ + TPM_CurrentTicks_Copy(&(l2TransportLogOut.currentTicks), ¤tTicks); + /* iv. Set T1 -> transDigest to SHA-1 (T1 -> transDigest || L2) */ + printf("TPM_Process_EstablishTransport: Extend transDigest with output\n"); + returnCode = TPM_TransportLogOut_Extend(t1TpmTransportInternal->transDigest, + &l2TransportLogOut); + } + } + /* 9. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_EXCLUSIVE then + set TPM_STANY_FLAGS -> transportExclusive to TRUE */ + if (returnCode == TPM_SUCCESS) { + if (t1TpmTransportInternal->transPublic.transAttributes & TPM_TRANSPORT_EXCLUSIVE) { + printf("TPM_Process_EstablishTransport: Session is exclusive\n"); + tpm_state->tpm_stany_flags.transportExclusive = t1TpmTransportInternal->transHandle; + } + } + /* a. Execution of any command other than TPM_ExecuteTransport or TPM_ReleaseTransportSigned + targeting this transport session will cause the abnormal invalidation of this transport + session transHandle */ + /* b. The TPM gives no indication, other than invalidation of transHandle, that the session is + terminated */ + /* NOTE Done by TPM_Process_Preprocess() */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_EstablishTransport: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + /* 10. Return T1 -> transHandle as transHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append32(response, t1TpmTransportInternal->transHandle); + } + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return locality */ + returnCode = TPM_Sbuffer_Append32(response, + tpm_state->tpm_stany_flags.localityModifier); + } + /* return currentTicks */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CurrentTicks_Store(response, ¤tTicks); + } + if (returnCode == TPM_SUCCESS) { + /* return transNonceEven */ + returnCode = TPM_Nonce_Store(response, transNonceEven); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + nonceOdd, + continueAuthSession); + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING))) && + trans_session_added) { + TPM_TransportSessions_TerminateHandle(tpm_state->tpm_stclear_data.transSessions, + t1TpmTransportInternal->transHandle, + &(tpm_state->tpm_stany_flags.transportExclusive)); + } + /* + cleanup + */ + TPM_TransportPublic_Delete(&transPublic); /* @1 */ + TPM_SizedBuffer_Delete(&secret); /* @2 */ + TPM_TransportAuth_Delete(&k1TransportAuth); /* @4 */ + TPM_TransportLogIn_Delete(&l1TransportLogIn); /* @5 */ + TPM_TransportLogOut_Delete(&l2TransportLogOut); /* @6 */ + TPM_Sbuffer_Delete(&transPublicSbuffer); /* @7 */ + TPM_Sbuffer_Delete(¤tTicksSbuffer); /* @8 */ + return rcf; +} + +/* 24.2 TPM_ExecuteTransport rev 117 + + Delivers a wrapped TPM command to the TPM where the TPM unwraps the command and then executes the + command. + + TPM_ExecuteTransport uses the same rolling nonce paradigm as other authorized TPM commands. The + even nonces start in EstablishTransport and change on each invocation of TPM_ExecuteTransport. + + The only restriction on what can happen inside of a transport session is that there is no + "nesting" of sessions. It is permissible to perform operations that delete internal state and + make the TPM inoperable. + + Because, in general, key handles are not logged, a digest of the corresponding public key is + logged. In cases where the key handle is logged (e.g. TPM_OwnerReadInternalPub), the + public key is also logged. + + The wrapped command is audited twice - once according to the actions of TPM_ExecuteTransport and + once within the wrapped command itself according to the special rules for auditing a command + wrapped in an encrypted transport session. +*/ + +TPM_RESULT TPM_Process_ExecuteTransport(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_SIZED_BUFFER wrappedCmd; /* The wrapped command */ + TPM_TRANSHANDLE transHandle; /* The transport session handle */ + TPM_NONCE transNonceOdd; /* Nonce generated by caller */ + TPM_BOOL continueTransSession; /* The continue use flag for the authorization + session handle */ + TPM_AUTHDATA transAuth; /* HMAC for transHandle key: transHandle -> + authData */ + + /* processing parameters */ + /* unsigned char * inParamStart; /\* starting point of inParam's *\/ */ + /* unsigned char * inParamEnd; /\* ending point of inParam's *\/ */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transHandleValid = FALSE; + TPM_TRANSPORT_INTERNAL *t1TpmTransportInternal; + TPM_TRANSPORT_INTERNAL t1TransportCopy; /* because original might be invalidated */ + TPM_BOOL transportWrappable; /* inner command can be wrapped in + transport */ + uint32_t keyHandles; /* number of key handles in ordw */ + uint32_t keyHandle1Index; /* index of key handles in wrapped command */ + uint32_t keyHandle2Index; + TPM_KEY_HANDLE keyHandle1; /* key handles in wrapped command */ + TPM_KEY_HANDLE keyHandle2; + uint32_t blockSize; /* symmetric key block size, if needed */ + TPM_RESOURCE_TYPE wrappedResourceType; /* for key handle special cases */ + TPM_COMMAND_CODE ordw; /* wrapped ORDW */ + uint32_t e1Dataw; /* index into wrapped E1 */ + uint32_t len1; /* wrapped LEN1 */ + unsigned char *g1Mgf1; /* input MGF1 XOR string */ + unsigned char *g2Mgf1; /* output MGF1 XOR string */ + unsigned char *decryptCmd; /* decrypted wrapped command */ + unsigned char *cmdStream; /* temporary for constructing decryptCmd */ + uint32_t cmdStreamSize; + TPM_COMMAND_CODE nOrdw; /* ordinal in nbo */ + TPM_COMMAND_CODE nOrdet; /* ordinal in nbo */ + uint32_t nWrappedCmdSize; /* wrappedCmdSize in nbo */ + TPM_DIGEST h1InWrappedDigest; + TPM_DIGEST h2OutWrappedDigest; + TPM_TRANSPORT_LOG_IN l2TransportLogIn; + TPM_TRANSPORT_LOG_OUT l3TransportLogOut; + TPM_DIGEST k2PubkeyDigest; + TPM_DIGEST k3PubkeyDigest; + TPM_KEY *k2Key; /* wrapped command keys */ + TPM_KEY *k3Key; + TPM_BOOL parentPCRStatus; + TPM_STORE_BUFFER wrappedRspSbuffer; + const unsigned char *wrappedRspStream; + uint32_t wrappedRspStreamSize; + uint32_t s2Dataw; /* index into S2 */ + uint32_t len2; /* length of S2 */ + TPM_RESULT rcw; /* wrapped return code */ + TPM_RESULT nRcw; /* return code in nbo */ + TPM_STORE_BUFFER currentTicksSbuffer; + const unsigned char *currentTicksBuffer; /* serialized buffer */ + uint32_t currentTicksLength; /* serialization length */ + TPM_RESULT nRCet; /* return code in nbo */ + TPM_MODIFIER_INDICATOR nLocality; /* locality in nbo */ + uint32_t nWrappedRspStreamSize; /* wrappedRspStreamSize in nbo */ + unsigned char *encryptRsp; /* encrypted response */ + + /* output parameters */ + TPM_DIGEST outParamDigest; + TPM_UINT64 currentTicks; /* The current ticks when the command was + executed */ + TPM_SIZED_BUFFER wrappedRsp; /* The wrapped response */ + + printf("TPM_Process_ExecuteTransport: Ordinal Entry\n"); + transportInternal = transportInternal; /* TPM_ExecuteTransport cannot be wrapped */ + TPM_SizedBuffer_Init(&wrappedCmd); /* freed @1 */ + TPM_SizedBuffer_Init(&wrappedRsp); /* freed @2 */ + g1Mgf1 = NULL; /* freed @3 */ + decryptCmd = NULL; /* freed @4 */ + TPM_TransportLogIn_Init(&l2TransportLogIn); /* freed @5 */ + TPM_TransportLogOut_Init(&l3TransportLogOut); /* freed @6 */ + TPM_Sbuffer_Init(&wrappedRspSbuffer); /* freed @7 */ + TPM_Sbuffer_Init(¤tTicksSbuffer); /* freed @8 */ + g2Mgf1 = NULL; /* freed @9 */ + TPM_TransportInternal_Init(&t1TransportCopy); /* freed @10 */ + encryptRsp = NULL; /* freed @11 */ + /* + get inputs + */ + if (returnCode == TPM_SUCCESS) { + /* save the starting point of inParam's for authorization and auditing */ + /* inParamStart = command; */ + /* get wrappedCmd */ + returnCode = TPM_SizedBuffer_Load(&wrappedCmd, &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: wrapped command size %u\n", wrappedCmd.size); + /* save the ending point of inParam's for authorization and auditing */ + /* inParamEnd = command; */ + /* NOTE: The common TPM_GetInParamDigest() is not called here, since inParamDigest cannot be + calculated until the wrapped command is decrypted */ + returnCode = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, + ordinal, + &(tpm_state->tpm_permanent_data)); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag1(tag); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&transHandle, + &transHandleValid, + transNonceOdd, + &continueTransSession, + transAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: transHandle %08x\n", transHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ExecuteTransport: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + transHandleValid = FALSE; + } + /* + Processing + */ + /* if there is an active exclusive transport session and it's not this session, terminate it */ + if (returnCode == TPM_SUCCESS) { + if ((tpm_state->tpm_stany_flags.transportExclusive != 0) && + (tpm_state->tpm_stany_flags.transportExclusive != transHandle)) { + returnCode = TPM_TransportSessions_TerminateHandle + (tpm_state->tpm_stclear_data.transSessions, + tpm_state->tpm_stany_flags.transportExclusive, + &(tpm_state->tpm_stany_flags.transportExclusive)); + } + } + /* 1. Using transHandle locate the TPM_TRANSPORT_INTERNAL structure T1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_TransportSessions_GetEntry(&t1TpmTransportInternal, + tpm_state->tpm_stclear_data.transSessions, + transHandle); + } + /* For the corner case where the wrapped command invalidates the transport session, make a copy + for the response. */ + if (returnCode == TPM_SUCCESS) { + TPM_TransportInternal_Copy(&t1TransportCopy, + t1TpmTransportInternal); + } + /* 2. Parse wrappedCmd */ + /* a. Set TAGw, LENw, and ORDw to the parameters from wrappedCmd */ + /* b. Set E1 to DATAw */ + /* i. This pointer is ordinal dependent and requires the execute transport command to parse + wrappedCmd */ + /* c. Set LEN1 to the length of DATAw */ + /* i. DATAw always ends at the start of AUTH1w if AUTH1w is present */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_OrdinalTable_ParseWrappedCmd(&e1Dataw, /* index into wrappedCmd */ + &len1, + &keyHandles, + &keyHandle1Index, /* index into key handles */ + &keyHandle2Index, + &ordw, + &transportWrappable, + &wrappedCmd); + if (returnCode != TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Error parsing wrapped command\n"); + } + } + /* 3. If LEN1 is less than 0, or if ORDw is unknown, unimplemented, or cannot be determined + a. Return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (wrappedCmd.size < e1Dataw + len1) { + printf("TPM_Process_ExecuteTransport: Error (fatal), wrappedCmdSize %u e1 %u len1 %u\n", + wrappedCmd.size, e1Dataw, len1); + returnCode = TPM_FAIL; /* internal error, should never occur */ + } + } + /* allocate memory for the decrypted command, which is always the same length as the encrypted + command */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc(&decryptCmd, wrappedCmd.size); + } + /* 4. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_ENCRYPT set then */ + if ((returnCode == TPM_SUCCESS) && + (t1TransportCopy.transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) && + (len1 != 0)) { /* some commands have no DATAw area to encrypt */ + /* a. If T1 -> transPublic -> algId is TPM_ALG_MGF1 */ + if (t1TransportCopy.transPublic.algId == TPM_ALG_MGF1) { + printf("TPM_Process_ExecuteTransport: Wrapped command MGF1 encrypted\n"); + /* i. Using the MGF1 function, create string G1 of length LEN1. The inputs to the MGF1 + are transLastNonceEven, transNonceOdd, "in", and T1 -> authData. These four values + concatenated together form the Z value that is the seed for the MGF1. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_MGF1_GenerateArray(&g1Mgf1, /* G1 MGF1 array */ + len1, /* G1 length */ + + TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("in") - 1 + + TPM_AUTHDATA_SIZE, /* seed length */ + + TPM_NONCE_SIZE, t1TransportCopy.transNonceEven, + TPM_NONCE_SIZE, transNonceOdd, + sizeof("in") - 1, "in", + TPM_AUTHDATA_SIZE, t1TransportCopy.authData, + 0, NULL); + } + /* ii. Create C1 by performing an XOR of G1 and wrappedCmd starting at E1. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Transport_CryptMgf1(decryptCmd, /* output */ + wrappedCmd.buffer, /* input */ + g1Mgf1, /* XOR pad */ + wrappedCmd.size, /* total size of buffers */ + e1Dataw, /* start of encrypted part */ + len1); /* length of encrypted part */ + } + } + /* b. If the encryption algorithm requires an IV or CTR calculate the IV or CTR value */ + else { + printf("TPM_Process_ExecuteTransport: " + "Wrapped command algId %08x encScheme %04hx encrypted\n", + t1TransportCopy.transPublic.algId, t1TransportCopy.transPublic.encScheme); + /* This function call should not fail, as the parameters were checked at + TPM_EstablishTransport. The call is used here to get the block size. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_TransportPublic_CheckEncScheme(&blockSize, + t1TransportCopy.transPublic.algId, + t1TransportCopy.transPublic.encScheme, + tpm_state->tpm_permanent_flags.FIPS); + } + /* i. Using the MGF1 function, create string IV1 or CTR1 with a length set by the block + size of the encryption algorithm. The inputs to the MGF1 are transLastNonceEven, + transNonceOdd, and "in". These three values concatenated together form the Z value + that is the seed for the MGF1. Note that any terminating characters within the string + "in" are ignored, so a total of 42 bytes are hashed. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_MGF1_GenerateArray(&g1Mgf1, /* G1 MGF1 array */ + blockSize, /* G1 length */ + + TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("in") - 1, + /* seed length */ + + TPM_NONCE_SIZE, t1TransportCopy.transNonceEven, + TPM_NONCE_SIZE, transNonceOdd, + sizeof("in") - 1, "in", + 0, NULL); + } + /* ii. The symmetric key is taken from the first bytes of T1 -> authData. */ + /* iii. Decrypt DATAw and replace the DATAw area of E1 creating C1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_Transport_CryptSymmetric(decryptCmd, /* output */ + wrappedCmd.buffer, /* input */ + t1TransportCopy.transPublic.algId, + t1TransportCopy.transPublic.encScheme, + t1TransportCopy.authData, /* key */ + TPM_AUTHDATA_SIZE, /* key size */ + g1Mgf1, /* pad, IV or CTR */ + blockSize, + wrappedCmd.size, /* total size of buffers */ + e1Dataw, /* start of encrypted part */ + len1); /* length of encrypted part */ + } + } + /* 4.c. TPM_OSAP, TPM_OIAP have no parameters encrypted */ + /* NOTE Handled by len1 = 0 */ + /* 4.d. TPM_DSAP has special rules for parameter encryption */ + /* NOTE Handled by setting inputHandleSize to all but entityValue */ + } + /* 5. Else (no encryption) */ + else if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Wrapped command not encrypted\n"); + /* a. Set C1 to the DATAw area E1 of wrappedCmd */ + memcpy(decryptCmd, wrappedCmd.buffer, wrappedCmd.size); + } + + /* Now that the wrapped command is decrypted, handle the special cases (e.g., TPM_FlushSpecific + and TPM_SaveContext) where the handle may or may not be a key handle, dependent on the value + of resourceType */ + if ((returnCode == TPM_SUCCESS) && (keyHandles == 0xffffffff)) { + printf("TPM_Process_ExecuteTransport: key handles special case\n"); + + /* point to the resourceType in the decrypted stream, directly after the key handle */ + cmdStream = decryptCmd + keyHandle1Index + sizeof(TPM_KEY_HANDLE); + cmdStreamSize = wrappedCmd.size - keyHandle1Index - sizeof(TPM_KEY_HANDLE); + returnCode = TPM_Load32(&wrappedResourceType, &cmdStream , &cmdStreamSize ); + } + /* ii. If the resourceType is TPM_RT_KEY, then the public key MUST be logged */ + if ((returnCode == TPM_SUCCESS) && (keyHandles == 0xffffffff)) { + printf("TPM_Process_ExecuteTransport: special case resource type %08x\n", + wrappedResourceType); + if (wrappedResourceType == TPM_RT_KEY) { + printf("TPM_Process_ExecuteTransport: Special case, 1 key handle\n"); + keyHandles = 1; + } + else { + keyHandles = 0; + } + } + + /* 6. Create H1 the SHA-1 of (ORDw || C1). */ + /* a. C1 MUST point at the decrypted DATAw area of E1 */ + /* b. The TPM MAY use this calculation for both execute transport authorization, authorization + of the wrapped command and transport log creation */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_ExecuteTransport: DATAw decrypted", decryptCmd); + printf("TPM_Process_ExecuteTransport: Create H1\n"); + nOrdw = htonl(ordw); + returnCode = TPM_SHA1(h1InWrappedDigest, + sizeof(TPM_COMMAND_CODE), &nOrdw, + len1, decryptCmd + e1Dataw, + 0, NULL); + } + /* 7. Validate the incoming transport session authorization */ + /* a. Set inParamDigest to SHA-1 (ORDet || wrappedCmdSize || H1) */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Validate AUTHet\n"); + nOrdet = htonl(ordinal); + nWrappedCmdSize = htonl(wrappedCmd.size); + returnCode = TPM_SHA1(inParamDigest, + sizeof(TPM_COMMAND_CODE), &nOrdet, + sizeof(uint32_t), &nWrappedCmdSize, + TPM_DIGEST_SIZE, h1InWrappedDigest, + 0, NULL); + } + /* b. Calculate the HMAC of (inParamDigest || transLastNonceEven || transNonceOdd || + continueTransSession) using T1 -> authData as the HMAC key */ + /* c. Validate transAuth, on errors return TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_TransportInternal_Check(inParamDigest, + &t1TransportCopy, /* transport session */ + transNonceOdd, /* Nonce generated by system + associated with authHandle */ + continueTransSession, + transAuth); /* Authorization digest for input */ + } + /* 8. If TPM_ExecuteTransport requires auditing */ + /* a. Create TPM_AUDIT_EVENT_IN using H1 */ + /* NOTE: Done during response */ + /* 9. If ORDw is from the list of following commands return TPM_NO_WRAP_TRANSPORT */ + /* a. TPM_EstablishTransport */ + /* b. TPM_ExecuteTransport */ + /* c. TPM_ReleaseTransportSigned */ + if (returnCode == TPM_SUCCESS) { + if (!transportWrappable) { + printf("TPM_Process_ExecuteTransport: Error, ordinal %08x cannot be wrapped\n", + ordw); + returnCode = TPM_NO_WRAP_TRANSPORT; + } + } + /* 10. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_LOG set then */ + if ((returnCode == TPM_SUCCESS) && + (t1TransportCopy.transPublic.transAttributes & TPM_TRANSPORT_LOG)) { + printf("TPM_Process_ExecuteTransport: Create transport log\n"); + /* a. Create L2 a TPM_TRANSPORT_LOG_IN structure */ + /* NOTE Done by TPM_TransportLogIn_Init() */ + /* b. Set L2 -> parameters to H1 */ + TPM_Digest_Copy(l2TransportLogIn.parameters, h1InWrappedDigest); + /* c. If ORDw is a command with no key handles */ + /* i. Set L2 -> pubKeyHash to NULL */ + /* NOTE Done by TPM_TransportLogIn_Init() */ + if ((returnCode == TPM_SUCCESS) && ((keyHandles == 1) || (keyHandles == 2))) { + if (returnCode == TPM_SUCCESS) { + /* point to the first key handle in the decrypted stream */ + cmdStream = decryptCmd + keyHandle1Index; + cmdStreamSize = wrappedCmd.size - keyHandle1Index; + /* get the key handle */ + returnCode = TPM_Load32(&keyHandle1, &cmdStream, &cmdStreamSize); + } + /* get the first key */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Create pubKeyHash for key 1 handle %08x\n", + keyHandle1); + returnCode = TPM_KeyHandleEntries_GetKey(&k2Key, + &parentPCRStatus, + tpm_state, + keyHandle1, + TRUE, /* read-only */ + FALSE, /* do not ignore PCRs */ + TRUE); /* can use EK */ + } + /* 10.d. If ORDw is a command with one key handle */ + /* 10.i. Create K2 the hash of the TPM_STORE_PUBKEY structure of the key pointed to by + the key handle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_SHA1_GenerateStructure(k2PubkeyDigest, + &(k2Key->pubKey), + (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store); + } + } + if ((returnCode == TPM_SUCCESS) && (keyHandles == 1)) { + printf("TPM_Process_ExecuteTransport: Digesting one public key\n"); + /* 10.ii. Set L2 -> pubKeyHash to SHA-1 (K2) */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1(l2TransportLogIn.pubKeyHash, + TPM_DIGEST_SIZE, k2PubkeyDigest, + 0, NULL); + } + } + /* 10.e. If ORDw is a command with two key handles */ + if ((returnCode == TPM_SUCCESS) && (keyHandles == 2)) { + printf("TPM_Process_ExecuteTransport: Digesting two public keys\n"); + /* i. Create K2 the hash of the TPM_STORE_PUBKEY structure of the key pointed to by the + first key handle. */ + /* NOTE Done above for 1 or 2 key case */ + if (returnCode == TPM_SUCCESS) { + /* point to the second key handle in the decrypted stream */ + cmdStream = decryptCmd + keyHandle2Index; + cmdStreamSize = wrappedCmd.size - keyHandle2Index; + /* get the key handle */ + returnCode = TPM_Load32(&keyHandle2, &cmdStream, &cmdStreamSize); + } + /* get the second key */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Create pubKeyHash for key 2 handle %08x\n", + keyHandle2); + returnCode = TPM_KeyHandleEntries_GetKey(&k3Key, + &parentPCRStatus, + tpm_state, + keyHandle2, + TRUE, /* read-only */ + FALSE, /* do not ignore PCRs */ + TRUE); /* can use EK */ + } + /* ii. Create K3 the hash of the TPM_STORE_PUBKEY structure of the key pointed to by the + second key handle. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_SHA1_GenerateStructure(k3PubkeyDigest, + &(k3Key->pubKey), + (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store); + } + /* 10.iii. Set L2 -> pubKeyHash to SHA-1 (K2 || K3) */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1(l2TransportLogIn.pubKeyHash, + TPM_DIGEST_SIZE, k2PubkeyDigest, + TPM_DIGEST_SIZE, k3PubkeyDigest, + 0, NULL); + } + } + /* 10.f. Set T1 -> transDigest to the SHA-1 (T1 -> transDigest || L2) */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Extend transDigest with input\n"); + returnCode = TPM_TransportLogIn_Extend(t1TransportCopy.transDigest, + &l2TransportLogIn); + } + /* 10.g. If ORDw is a command with key handles, and the key is not loaded, return + TPM_INVALID_KEYHANDLE. */ + /* NOTE Done by TPM_KeyHandleEntries_GetKey() */ + } + /* 11. Send the wrapped command to the normal TPM command parser, the output is C2 and the + return code is RCw */ + /* a. If ORDw is a command that is audited then the TPM MUST perform the input and output audit + of the command as part of this action */ + /* b. The TPM MAY use H1 as the data value in the authorization and audit calculations during + the execution of C1 */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Call wrapped command\n"); + returnCode = TPM_Process_Wrapped(&wrappedRspSbuffer, /* response buffer */ + decryptCmd, /* complete command array */ + wrappedCmd.size, /* actual bytes in command */ + tpm_state, + &t1TransportCopy); /* TPM_ExecuteTransport */ + printf("TPM_Process_ExecuteTransport: Completed wrapped command\n"); + } + /* 12. Set CT1 to TPM_STANY_DATA -> currentTicks -> currentTicks and return CT1 in the + currentTicks output parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CurrentTicks_Update(&(tpm_state->tpm_stany_data.currentTicks)); + } + if (returnCode == TPM_SUCCESS) { + TPM_Uint64_Copy(¤tTicks, &(tpm_state->tpm_stany_data.currentTicks.currentTicks)); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Uint64_Store(¤tTicksSbuffer, + &(tpm_state->tpm_stany_data.currentTicks.currentTicks)); + } + /* 13. Calculate S2 the pointer to the DATAw area of C2 */ + /* a. Calculate LEN2 the length of S2 according to the same rules that calculated LEN1 */ + if (returnCode == TPM_SUCCESS) { + /* get the response buffer and length */ + TPM_Sbuffer_Get(&wrappedRspSbuffer, &wrappedRspStream, &wrappedRspStreamSize); + /* parse the three standard input parameters, check paramSize against wrappedRsp->size */ + returnCode = TPM_OrdinalTable_ParseWrappedRsp(&s2Dataw, + &len2, + &rcw, + ordw, + wrappedRspStream, + wrappedRspStreamSize); + } + /* 14. Create H2 the SHA-1 of (RCw || ORDw || S2) */ + /* a. The TPM MAY use this calculation for execute transport authorization and transport log out + creation */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Create H2\n"); + nRcw = htonl(rcw); + /* The TPM_ExecuteTransport input ordinal and output ordinal, currentTicks and locality are + not audited. This was simply an error, and not a deliberate attempt to make + TPM_ExecuteTransport different from other ordinals. */ + returnCode = TPM_SHA1(h2OutWrappedDigest, + sizeof(TPM_RESULT), &nRcw, + sizeof(TPM_COMMAND_CODE), &nOrdw, + len2, wrappedRspStream + s2Dataw, + 0, NULL); + } + /* 15. Calculate the outgoing transport session authorization */ + /* a. Create the new transNonceEven for the output of the command */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Nonce_Generate(t1TransportCopy.transNonceEven); + } + /* b. Set outParamDigest to SHA-1 (RCet || ORDet || TPM_STANY_DATA -> currentTicks -> + currentTicks || locality || wrappedRspSize || H2) */ + if (returnCode == TPM_SUCCESS) { + nRCet = htonl(returnCode); + TPM_Sbuffer_Get(¤tTicksSbuffer, ¤tTicksBuffer, ¤tTicksLength); + nLocality = htonl(tpm_state->tpm_stany_flags.localityModifier); + nWrappedRspStreamSize = htonl(wrappedRspStreamSize); + returnCode = TPM_SHA1(outParamDigest, + sizeof(TPM_RESULT), &nRCet, + sizeof(TPM_COMMAND_CODE), &nOrdet, + currentTicksLength, currentTicksBuffer, + sizeof(TPM_MODIFIER_INDICATOR), &nLocality, + sizeof(uint32_t), &nWrappedRspStreamSize, + TPM_DIGEST_SIZE, h2OutWrappedDigest, + 0, NULL); + } + /* c. Calculate transAuth, the HMAC of (outParamDigest || transNonceEven || transNonceOdd || + continueTransSession) using T1 -> authData as the HMAC key */ + /* NOTE: Done as part of response */ + /* 16. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_LOG set then */ + if ((returnCode == TPM_SUCCESS) && + (t1TransportCopy.transPublic.transAttributes & TPM_TRANSPORT_LOG)) { + /* a. Create L3 a TPM_TRANSPORT_LOG_OUT structure */ + /* NOTE Done by TPM_TransportLogOut_Init() */ + /* b. Set L3 -> parameters to H2 */ + TPM_Digest_Copy(l3TransportLogOut.parameters, h2OutWrappedDigest); + /* c. Set L3 -> currentTicks to TPM_STANY_DATA -> currentTicks */ + TPM_CurrentTicks_Copy(&(l3TransportLogOut.currentTicks), + &(tpm_state->tpm_stany_data.currentTicks)); + /* d. Set L3 -> locality to TPM_STANY_DATA -> localityModifier */ + l3TransportLogOut.locality = tpm_state->tpm_stany_flags.localityModifier; + /* e. Set T1 -> transDigest to the SHA-1 (T1 -> transDigest || L3) */ + printf("TPM_Process_ExecuteTransport: Extend transDigest with output\n"); + returnCode = TPM_TransportLogOut_Extend(t1TransportCopy.transDigest, + &l3TransportLogOut); + } + /* allocate memory for the encrypted response, which is always the same length as the decrypted + response */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Malloc(&encryptRsp, wrappedRspStreamSize); + } + /* 17. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_ENCRYPT set then */ + if ((returnCode == TPM_SUCCESS) && + (t1TransportCopy.transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) && + (len2 != 0)) { /* some commands have no DATAw area to encrypt */ + /* NOTE No TPM_OSAP encryption handled by len2 = 0 */ + /* a. If T1 -> transPublic -> algId is TPM_ALG_MGF1 */ + if (t1TransportCopy.transPublic.algId == TPM_ALG_MGF1) { + printf("TPM_Process_ExecuteTransport: Wrapped response MGF1 encrypted\n"); + /* i. Using the MGF1 function, create string G2 of length LEN2. The inputs to the MGF1 + are transNonceEven, transNonceOdd, "out", and T1 -> authData. These four values + concatenated together form the Z value that is the seed for the MGF1. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_MGF1_GenerateArray(&g2Mgf1, /* G2 MGF1 array */ + len2, /* G2 length */ + + TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("out") - 1 + + TPM_AUTHDATA_SIZE, /* seed length */ + + TPM_NONCE_SIZE, t1TransportCopy.transNonceEven, + TPM_NONCE_SIZE, transNonceOdd, + sizeof("out") - 1, "out", + TPM_AUTHDATA_SIZE, t1TransportCopy.authData, + 0, NULL); + } + /* ii. Create E2 by performing an XOR of G2 and C2 starting at S2. */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Transport_CryptMgf1(encryptRsp, + wrappedRspStream, + g2Mgf1, + wrappedRspStreamSize, + s2Dataw, + len2); + } + } + /* b. Else */ + else { + printf("TPM_Process_ExecuteTransport: " + "Wrapped response algId %08x encScheme %04hx encrypted\n", + t1TransportCopy.transPublic.algId, t1TransportCopy.transPublic.encScheme); + /* This function call should not fail, as the parameters were checked at + TPM_EstablishTransport. The call is used here to get the block size. + + This is a duplicate of the call for the command. However, there are cases where + there is no encrypted command (len1 == 0) so the call was not made. Rather than + keep track of whether blockSize is valid, it's clearer to just call the function + twice in some cases. + */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_TransportPublic_CheckEncScheme(&blockSize, + t1TransportCopy.transPublic.algId, + t1TransportCopy.transPublic.encScheme, + tpm_state->tpm_permanent_flags.FIPS); + } + /* i. Create IV2 or CTR2 using the same algorithm as IV1 or CTR1 with the input values + transNonceEven, transNonceOdd, and "out". Note that any terminating characters within + the string "out" are ignored, so a total of 43 bytes are hashed. */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_MGF1_GenerateArray(&g2Mgf1, /* G2 MGF1 array */ + blockSize, /* G2 length */ + + TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("out") - 1, + /* seed length */ + + TPM_NONCE_SIZE, t1TransportCopy.transNonceEven, + TPM_NONCE_SIZE, transNonceOdd, + sizeof("out") - 1, "out", + 0, NULL); + } + /* ii. The symmetric key is taken from the first bytes of T1 -> authData */ + /* iii. Create E2 by encrypting C2 starting at S2 */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_Transport_CryptSymmetric(encryptRsp, /* output */ + wrappedRspStream, /* input */ + t1TransportCopy.transPublic.algId, + t1TransportCopy.transPublic.encScheme, + t1TransportCopy.authData, /* key */ + TPM_AUTHDATA_SIZE, /* key size */ + g2Mgf1, /* pad, IV or CTR */ + blockSize, + wrappedRspStreamSize, /* total size of buffers */ + s2Dataw, /* start of encrypted part */ + len2); /* length of encrypted part */ + } + } + } + /* 18. Else (no encryption) */ + else if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ExecuteTransport: Wrapped response not encrypted\n"); + /* a. Set E2 to the DATAw area S2 of wrappedRsp */ + memcpy(encryptRsp, wrappedRspStream ,wrappedRspStreamSize); + } + /* 19. If continueTransSession is FALSE */ + /* a. Invalidate all session data related to transHandle */ + /* NOTE: Done after response */ + /* 20. If TPM_ExecuteTranport requires auditing */ + /* a. Create TPM_AUDIT_EVENT_OUT using H2 */ + /* NOTE: Done during response */ + /* 21. Return C2 but with S2 replaced by E2 in the wrappedRsp parameter */ + if (returnCode == TPM_SUCCESS) { + /* if the wrapped command invalidated the transport session, set continueTransSession to + FALSE */ + if (!(t1TpmTransportInternal->valid)) { + continueTransSession = FALSE; + } + /* if the session is still valid, copy the copy back to the original so the log gets + updated */ + else { + TPM_TransportInternal_Copy(t1TpmTransportInternal, &t1TransportCopy); + } + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ExecuteTransport: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + /* return currentTicks */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append(response, currentTicksBuffer, currentTicksLength); + } + /* return locality */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append32(response, + tpm_state->tpm_stany_flags.localityModifier); + } + /* return wrappedRspSize */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append32(response, wrappedRspStreamSize); + } + /* return wrappedRsp */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Sbuffer_Append(response, encryptRsp, wrappedRspStreamSize); + } + /* non-standard - digest the above the line output parameters, H1 used */ + /* non-standard - calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_TransportInternal_Set(response, + &t1TransportCopy, + outParamDigest, + transNonceOdd, + continueTransSession, + FALSE); /* transNonceEven already generated */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + FALSE, /* transportEncrypt */ + h1InWrappedDigest, + h2OutWrappedDigest, /* exception to normal digest */ + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueTransSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueTransSession) && + transHandleValid) { + TPM_TransportSessions_TerminateHandle(tpm_state->tpm_stclear_data.transSessions, + transHandle, + &(tpm_state->tpm_stany_flags.transportExclusive)); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&wrappedCmd); /* @1 */ + TPM_SizedBuffer_Delete(&wrappedRsp); /* @2 */ + free(g1Mgf1); /* @3 */ + free (decryptCmd); /* @4 */ + TPM_TransportLogIn_Delete(&l2TransportLogIn); /* @5 */ + TPM_TransportLogOut_Delete(&l3TransportLogOut); /* @6 */ + TPM_Sbuffer_Delete(&wrappedRspSbuffer); /* @7 */ + TPM_Sbuffer_Delete(¤tTicksSbuffer); /* @8 */ + free(g2Mgf1); /* @9 */ + TPM_TransportInternal_Delete(&t1TransportCopy); /* @10 */ + free(encryptRsp); /* @11 */ + return rcf; +} + +/* 24.3 TPM_ReleaseTransportSigned rev 101 + + This command completes the transport session. If logging for this session is turned on, then this + command returns a hash of all operations performed during the session along with a digital + signature of the hash. + + This command serves no purpose if logging is turned off, and results in an error if attempted. + + This command uses two authorization sessions, the key that will sign the log and the + authorization from the session. Having the session authorization proves that the requester that + is signing the log is the owner of the session. If this restriction is not put in then an + attacker can close the log and sign using their own key. + + The hash of the session log includes the information associated with the input phase of execution + of the TPM_ReleaseTransportSigned command. It cannot include the output phase information. +*/ + +TPM_RESULT TPM_Process_ReleaseTransportSigned(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal) +{ + TPM_RESULT rcf = 0; /* fatal error precluding response */ + TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ + + /* input parameters */ + TPM_KEY_HANDLE keyHandle; /* Handle of a loaded key that will perform the signing */ + TPM_NONCE antiReplay; /* Value provided by caller for anti-replay protection */ + TPM_AUTHHANDLE authHandle; /* The authorization session to use key */ + TPM_NONCE authNonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session + handle */ + TPM_AUTHDATA keyAuth; /* The authorization session digest that authorizes the use + of key. HMAC key: key -> usageAuth */ + TPM_TRANSHANDLE transHandle; /* The transport session handle */ + TPM_NONCE transNonceOdd; /* Nonce supplied by caller for transport session */ + TPM_BOOL continueTransSession = TRUE; /* The continue use flag for the + authorization session handle */ + TPM_AUTHDATA transAuth; /* HMAC for transport session key: tranHandle -> authData */ + + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus; /* audit the ordinal */ + TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ + TPM_BOOL authHandleValid = FALSE; + TPM_BOOL transHandleValid = FALSE; + TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ + TPM_TRANSPORT_INTERNAL *t1TpmTransportInternal = NULL; + TPM_SECRET *hmacKey; + TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ + TPM_BOOL parentPCRStatus; + TPM_SECRET *keyUsageAuth; + TPM_TRANSPORT_LOG_OUT a1TransportLogOut; + TPM_SIGN_INFO h1SignInfo; + TPM_DIGEST h1Digest; /* digest of h1SignInfo */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_CURRENT_TICKS *currentTicks = NULL; /* The current time according to the TPM */ + TPM_SIZED_BUFFER signature; /* The signature of the digest */ + + printf("TPM_Process_ReleaseTransportSigned: Ordinal Entry\n"); + TPM_SizedBuffer_Init(&signature); /* freed @1 */ + TPM_TransportLogOut_Init(&a1TransportLogOut); /* freed @2 */ + TPM_SignInfo_Init(&h1SignInfo); /* freed @3 */ + /* + get inputs + + */ + /* get keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); + } + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get antiReplay */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ReleaseTransportSigned: keyHandle %08x\n", keyHandle ); + returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); + } + /* save the ending point of inParam's for authorization and auditing */ + inParamEnd = command; + /* digest the input parameters */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_ReleaseTransportSigned: antiReplay", antiReplay); + returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ + &auditStatus, /* output */ + &transportEncrypt, /* output */ + tpm_state, + tag, + ordinal, + inParamStart, + inParamEnd, + transportInternal); + } + /* check state */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag21(tag); + } + + /* get the optional 'below the line' authorization parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Get(&authHandle, + &authHandleValid, + authNonceOdd, + &continueAuthSession, + keyAuth, + &command, ¶mSize); + printf("TPM_Process_ReleaseTransportSigned: authHandle %08x\n", authHandle); + } + /* get the 'below the line' authorization parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthParams_Get(&transHandle, + &transHandleValid, + transNonceOdd, + &continueTransSession, + transAuth, + &command, ¶mSize); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_ReleaseTransportSigned: transHandle %08x\n", transHandle); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ReleaseTransportSigned: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* do not terminate sessions if the command did not parse correctly */ + if (returnCode != TPM_SUCCESS) { + transHandleValid = FALSE; + } + /* + Processing + */ + /* if there is an active exclusive transport session and it's not this session, terminate it */ + if (returnCode == TPM_SUCCESS) { + if ((tpm_state->tpm_stany_flags.transportExclusive != 0) && + (tpm_state->tpm_stany_flags.transportExclusive != transHandle)) { + returnCode = + TPM_TransportSessions_TerminateHandle(tpm_state->tpm_stclear_data.transSessions, + tpm_state->tpm_stany_flags.transportExclusive, + &(tpm_state->tpm_stany_flags.transportExclusive)); + } + } + /* 1. Using transHandle locate the TPM_TRANSPORT_INTERNAL structure T1 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_TransportSessions_GetEntry(&t1TpmTransportInternal, + tpm_state->tpm_stclear_data.transSessions, + transHandle); + } + /* get the key corresponding to the keyHandle parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, + FALSE, /* not r/o, used to sign */ + FALSE, /* do not ignore PCRs */ + FALSE); /* cannot use EK */ + } + /* 2. Validate that keyHandle -> sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1 or + TPM_SS_RSASSAPKCS1v15_INFO, if not return TPM_INAPPROPRIATE_SIG. */ + if (returnCode == TPM_SUCCESS) { + if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && + (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { + printf("TPM_Process_ReleaseTransportSigned: Error, invalid sigKey sigScheme %04hx\n", + sigKey->algorithmParms.sigScheme); + returnCode = TPM_INAPPROPRIATE_SIG; + } + } + if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { + if (sigKey->authDataUsage != TPM_AUTH_NEVER) { + printf("TPM_Process_ReleaseTransportSigned: Error, authorization required\n"); + returnCode = TPM_AUTHFAIL; + } + } + /* get keyHandle -> usageAuth */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); + } + /* get the session data */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_NONE, + TPM_ET_KEYHANDLE, + ordinal, + sigKey, + keyUsageAuth, /* OIAP */ + sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ + } + /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, if not return + TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (sigKey ->keyUsage != TPM_KEY_SIGNING) { + printf("TPM_Process_ReleaseTransportSigned: Error, keyUsage %04hx is invalid\n", + sigKey ->keyUsage); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* 4. Using key -> authData validate the command and parameters, on error return TPM_AUTHFAIL */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_Authdata_Check(tpm_state, + *hmacKey, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + authNonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + keyAuth); /* Authorization digest for input */ + } + /* 5. Using transHandle -> authData validate the command and parameters, on error return + TPM_AUTH2FAIL */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_TransportInternal_Check(inParamDigest, + t1TpmTransportInternal, /* transport session */ + transNonceOdd, /* Nonce generated by system + associated with authHandle */ + continueTransSession, + transAuth); /* Authorization digest for input */ + } + /* 7. Else */ + if (returnCode == TPM_SUCCESS) { + if (!(t1TpmTransportInternal->transPublic.transAttributes & TPM_TRANSPORT_LOG)) { + /* a. Return TPM_BAD_MODE */ + printf("TPM_Process_ReleaseTransportSigned: Error, TPM_TRANSPORT_LOG not set\n"); + returnCode = TPM_BAD_MODE; + } + } + /* 6. If T1 -> transAttributes has TPM_TRANSPORT_LOG set then update the current ticks + structure */ + if (returnCode == TPM_SUCCESS) { + currentTicks = &(tpm_state->tpm_stany_data.currentTicks); + /* update the ticks based on the current time */ + returnCode = TPM_CurrentTicks_Update(currentTicks); + } + if (returnCode == TPM_SUCCESS) { + /* a. Create A1 a TPM_TRANSPORT_LOG_OUT structure */ + /* NOTE Done by TPM_TransportLogOut_Init() */ + /* b. Set A1 -> parameters to the SHA-1 (ordinal || antiReplay) */ + TPM_Digest_Copy(a1TransportLogOut.parameters, inParamDigest); + /* c. Set A1 -> currentTicks to TPM_STANY_DATA -> currentTicks */ + TPM_CurrentTicks_Copy(&(a1TransportLogOut.currentTicks), currentTicks); + /* d. Set A1 -> locality to the locality modifier for this command */ + a1TransportLogOut.locality = tpm_state->tpm_stany_flags.localityModifier; + /* e. Set T1 -> transDigest to SHA-1 (T1 -> transDigest || A1) */ + printf("TPM_Process_ReleaseTransportSigned: Extend transDigest with output\n"); + returnCode = TPM_TransportLogOut_Extend(t1TpmTransportInternal->transDigest, + &a1TransportLogOut); + } + if (returnCode == TPM_SUCCESS) { + /* 8. Create H1 a TPM_SIGN_INFO structure and set the structure defaults */ + /* NOTE: Done by TPM_SignInfo_Init() */ + /* a. Set H1 -> fixed to "TRAN" */ + memcpy(h1SignInfo.fixed, "TRAN", TPM_SIGN_INFO_FIXED_SIZE); + /* b. Set H1 -> replay to antiReplay */ + TPM_Nonce_Copy(h1SignInfo.replay, antiReplay); + /* c. Set H1 -> data to T1 -> transDigest */ + returnCode = TPM_SizedBuffer_Set(&(h1SignInfo.data), + TPM_DIGEST_SIZE, + t1TpmTransportInternal->transDigest); + } + /* d. Sign SHA-1 hash of H1 using the key pointed to by keyHandle */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SHA1_GenerateStructure(h1Digest, &h1SignInfo, + (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); + TPM_PrintAll("TPM_Process_ReleaseTransportSigned: h1Digest", h1Digest, TPM_DIGEST_SIZE); + } + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSASignToSizedBuffer(&signature, /* signature */ + h1Digest, /* message */ + TPM_DIGEST_SIZE, /* message size */ + sigKey); /* input, signing key */ + } + /* 9. Invalidate all session data related to T1 */ + /* NOTE Done after response */ + /* 10. Set continueTransSession to FALSE */ + if (returnCode == TPM_SUCCESS) { + continueTransSession = FALSE; + } + /* 11. Return TPM_SUCCESS */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ReleaseTransportSigned: Ordinal returnCode %08x %u\n", + returnCode, returnCode); + rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); + } + /* success response, append the rest of the parameters. */ + if (rcf == 0) { + if (returnCode == TPM_SUCCESS) { + /* checkpoint the beginning of the outParam's */ + outParamStart = response->buffer_current - response->buffer; + /* return locality */ + returnCode = TPM_Sbuffer_Append32(response, + tpm_state->tpm_stany_flags.localityModifier); + } + /* return currentTicks */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CurrentTicks_Store(response, currentTicks); + } + if (returnCode == TPM_SUCCESS) { + /* return signature */ + returnCode = TPM_SizedBuffer_Store(response, &signature); + /* checkpoint the end of the outParam's */ + outParamEnd = response->buffer_current - response->buffer; + } + /* digest the above the line output parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ + auditStatus, /* input audit status */ + transportEncrypt, + tag, + returnCode, + ordinal, /* command ordinal */ + response->buffer + outParamStart, /* start */ + outParamEnd - outParamStart); /* length */ + } + /* calculate and set the optional below the line parameters */ + if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { + returnCode = TPM_AuthParams_Set(response, + *hmacKey, /* owner HMAC key */ + auth_session_data, + outParamDigest, + authNonceOdd, + continueAuthSession); + } + /* calculate and set the below the line parameters */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_TransportInternal_Set(response, + t1TpmTransportInternal, + outParamDigest, + transNonceOdd, + continueTransSession, + TRUE); /* generate transNonceEven */ + } + /* audit if required */ + if ((returnCode == TPM_SUCCESS) && auditStatus) { + returnCode = TPM_ProcessAudit(tpm_state, + transportEncrypt, + inParamDigest, + outParamDigest, + ordinal); + } + /* adjust the initial response */ + rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); + } + /* if there was an error, or continueTransSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueTransSession) && + transHandleValid) { + TPM_TransportSessions_TerminateHandle(tpm_state->tpm_stclear_data.transSessions, + transHandle, + &(tpm_state->tpm_stany_flags.transportExclusive)); + } + /* if there was an error, or continueAuthSession is FALSE, terminate the session */ + if (((rcf != 0) || + ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || + !continueAuthSession) && + authHandleValid) { + TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); + } + /* + cleanup + */ + TPM_SizedBuffer_Delete(&signature); /* @1 */ + TPM_TransportLogOut_Delete(&a1TransportLogOut); /* @2 */ + TPM_SignInfo_Delete(&h1SignInfo); /* @3 */ + return rcf; +} diff --git a/src/tpm12/tpm_transport.h b/src/tpm12/tpm_transport.h new file mode 100644 index 0000000..1bb70f7 --- /dev/null +++ b/src/tpm12/tpm_transport.h @@ -0,0 +1,211 @@ +/********************************************************************************/ +/* */ +/* Transport */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_transport.h 4526 2011-03-24 21:14:42Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_TRANSPORT_H +#define TPM_TRANSPORT_H + +#include "tpm_global.h" + +/* + Transport Encryption for wrapped commands and responses +*/ + +TPM_RESULT TPM_Transport_CryptMgf1(unsigned char *dest, + const unsigned char *src, + const unsigned char *pad, + uint32_t size, + uint32_t index, + uint32_t len); + +TPM_RESULT TPM_Transport_CryptSymmetric(unsigned char *dest, + const unsigned char *src, + TPM_ALGORITHM_ID algId, + TPM_ENC_SCHEME encScheme, + const unsigned char *symmetric_key, + uint32_t symmetric_key_size, + unsigned char *pad_in, + uint32_t pad_in_size, + uint32_t size, + uint32_t index, + uint32_t len); + +/* + Transport Sessions (the entire array) +*/ + +void TPM_TransportSessions_Init(TPM_TRANSPORT_INTERNAL *transSessions); +TPM_RESULT TPM_TransportSessions_Load(TPM_TRANSPORT_INTERNAL *transSessions, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_TransportSessions_Store(TPM_STORE_BUFFER *sbuffer, + TPM_TRANSPORT_INTERNAL *transSessions); +void TPM_TransportSessions_Delete(TPM_TRANSPORT_INTERNAL *transSessions); + +void TPM_TransportSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, + TPM_TRANSPORT_INTERNAL *transSessions); +void TPM_TransportSessions_GetSpace(uint32_t *space, + TPM_TRANSPORT_INTERNAL *transSessions); +TPM_RESULT TPM_TransportSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, + TPM_TRANSPORT_INTERNAL *transSessions); +TPM_RESULT TPM_TransportSessions_GetNewHandle(TPM_TRANSPORT_INTERNAL **tpm_transport_internal, + TPM_TRANSPORT_INTERNAL *transportSessions); +TPM_RESULT TPM_TransportSessions_GetEntry(TPM_TRANSPORT_INTERNAL **tpm_transport_internal , + TPM_TRANSPORT_INTERNAL *transportSessions, + TPM_TRANSHANDLE transportHandle); +TPM_RESULT TPM_TransportSessions_AddEntry(TPM_HANDLE *tpm_handle, + TPM_BOOL keepHandle, + TPM_TRANSPORT_INTERNAL *transSessions, + TPM_TRANSPORT_INTERNAL *tpm_transport_internal); +TPM_RESULT TPM_TransportSessions_TerminateHandle(TPM_TRANSPORT_INTERNAL *tpm_transport_internal, + TPM_TRANSHANDLE transportHandle, + TPM_TRANSHANDLE *transportExclusive); + +/* + TPM_TRANSPORT_PUBLIC +*/ + +void TPM_TransportPublic_Init(TPM_TRANSPORT_PUBLIC *tpm_transport_public); +TPM_RESULT TPM_TransportPublic_Load(TPM_TRANSPORT_PUBLIC *tpm_transport_public, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_TransportPublic_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_PUBLIC *tpm_transport_public); +void TPM_TransportPublic_Delete(TPM_TRANSPORT_PUBLIC *tpm_transport_public); + +TPM_RESULT TPM_TransportPublic_Copy(TPM_TRANSPORT_PUBLIC *dest, + const TPM_TRANSPORT_PUBLIC *src); +void TPM_TransportPublic_CheckAlgId(TPM_BOOL *supported, + TPM_ALGORITHM_ID algId); +TPM_RESULT TPM_TransportPublic_CheckEncScheme(uint32_t *blockSize, + TPM_ALGORITHM_ID algId, + TPM_ENC_SCHEME encScheme, + TPM_BOOL FIPS); + +/* + TPM_TRANSPORT_INTERNAL +*/ + +void TPM_TransportInternal_Init(TPM_TRANSPORT_INTERNAL *tpm_transport_internal); +TPM_RESULT TPM_TransportInternal_Load(TPM_TRANSPORT_INTERNAL *tpm_transport_internal, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_TransportInternal_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_INTERNAL *tpm_transport_internal); +void TPM_TransportInternal_Delete(TPM_TRANSPORT_INTERNAL *tpm_transport_internal); + +void TPM_TransportInternal_Copy(TPM_TRANSPORT_INTERNAL *dest_transport_internal, + TPM_TRANSPORT_INTERNAL *src_transport_internal); +TPM_RESULT TPM_TransportInternal_Check(TPM_DIGEST inParamDigest, + TPM_TRANSPORT_INTERNAL *tpm_transport_internal, + TPM_NONCE transNonceOdd, + TPM_BOOL continueTransSession, + TPM_AUTHDATA transAuth); +TPM_RESULT TPM_TransportInternal_Set(TPM_STORE_BUFFER *response, + TPM_TRANSPORT_INTERNAL *tpm_transport_internal, + TPM_DIGEST outParamDigest, + TPM_NONCE transNonceOdd, + TPM_BOOL continueTransSession, + TPM_BOOL generateNonceEven); + +/* + TPM_TRANSPORT_LOG_IN +*/ + +void TPM_TransportLogIn_Init(TPM_TRANSPORT_LOG_IN *tpm_transport_log_in); +TPM_RESULT TPM_TransportLogIn_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_LOG_IN *tpm_transport_log_in); +void TPM_TransportLogIn_Delete(TPM_TRANSPORT_LOG_IN *tpm_transport_log_in); + +TPM_RESULT TPM_TransportLogIn_Extend(TPM_DIGEST tpm_digest, + TPM_TRANSPORT_LOG_IN *tpm_transport_log_in); + +/* + TPM_TRANSPORT_LOG_OUT +*/ + +void TPM_TransportLogOut_Init(TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out); +TPM_RESULT TPM_TransportLogOut_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out); +void TPM_TransportLogOut_Delete(TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out); + +TPM_RESULT TPM_TransportLogOut_Extend(TPM_DIGEST tpm_digest, + TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out); + +/* + TPM_TRANSPORT_AUTH +*/ + +void TPM_TransportAuth_Init(TPM_TRANSPORT_AUTH *tpm_transport_auth); +TPM_RESULT TPM_TransportAuth_Load(TPM_TRANSPORT_AUTH *tpm_transport_auth, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_TransportAuth_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_TRANSPORT_AUTH *tpm_transport_auth); +void TPM_TransportAuth_Delete(TPM_TRANSPORT_AUTH *tpm_transport_auth); + +TPM_RESULT TPM_TransportAuth_DecryptSecret(TPM_TRANSPORT_AUTH *tpm_transport_auth, + TPM_SIZED_BUFFER *secret, + TPM_KEY *tpm_key); + +/* Command Processing Functions */ + +TPM_RESULT TPM_Process_EstablishTransport(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ExecuteTransport(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); +TPM_RESULT TPM_Process_ReleaseTransportSigned(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, + TPM_COMMAND_CODE ordinal, + unsigned char *command, + TPM_TRANSPORT_INTERNAL *transportInternal); + + +#endif diff --git a/src/tpm12/tpm_ver.c b/src/tpm12/tpm_ver.c new file mode 100644 index 0000000..a88154e --- /dev/null +++ b/src/tpm12/tpm_ver.c @@ -0,0 +1,273 @@ +/********************************************************************************/ +/* */ +/* Ver Structure Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_ver.c 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_structures.h" + +#include "tpm_ver.h" + +/* + TPM_STRUCT_VER + + This indicates the version of the structure. + + Version 1.2 deprecates the use of this structure in all other structures. The structure is not + deprecated as many of the structures that contain this structure are not deprecated. + + The rationale behind keeping this structure and adding the new version structure is that in + version 1.1 this structure was in use for two purposes. The first was to indicate the structure + version, and in that mode the revMajor and revMinor were supposed to be set to 0. The second use + was in TPM_GetCapability and the structure would then return the correct revMajor and + revMinor. This use model caused problems in keeping track of when the revs were or were not set + and how software used the information. Version 1.2 went to structure tags. Some structures did not + change and the TPM_STRUCT_VER is still in use. To avoid the problems from 1.1 this structure now + is a fixed value and only remains for backwards compatibility. Structure versioning comes from the + tag on the structure and the TPM_GetCapability response for TPM versioning uses TPM_VERSION. +*/ + +/* TPM_StructVer_Init() + + sets members to default values + sets all pointers to NULL and sizes to 0 + always succeeds - no return code +*/ + +void TPM_StructVer_Init(TPM_STRUCT_VER *tpm_struct_ver) +{ + printf(" TPM_StructVer_Init:\n"); + tpm_struct_ver->major = 0x01; + tpm_struct_ver->minor = 0x01; + tpm_struct_ver->revMajor = 0x00; + tpm_struct_ver->revMinor = 0x00; + return; +} + +/* TPM_StructVer_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes +*/ + +TPM_RESULT TPM_StructVer_Load(TPM_STRUCT_VER *tpm_struct_ver, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StructVer_Load:\n"); + if (rc == 0) { + rc = TPM_Load8(&(tpm_struct_ver->major), stream, stream_size); + } + if (rc == 0) { + rc = TPM_Load8(&(tpm_struct_ver->minor), stream, stream_size); + } + if (rc == 0) { + rc = TPM_Load8(&(tpm_struct_ver->revMajor), stream, stream_size); + } + if (rc == 0) { + rc = TPM_Load8(&(tpm_struct_ver->revMinor), stream, stream_size); + } + return rc; +} + + +/* TPM_StructVer_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_StructVer_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_STRUCT_VER *tpm_struct_ver) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StructVer_Store:\n"); + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_struct_ver->major), sizeof(BYTE)); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_struct_ver->minor), sizeof(BYTE)); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_struct_ver->revMajor), sizeof(BYTE)); + } + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_struct_ver->revMinor), sizeof(BYTE)); + } + return rc; +} + +/* TPM_StructVer_Copy() copies the src to the destination. */ + +void TPM_StructVer_Copy(TPM_STRUCT_VER *tpm_struct_ver_dest, + TPM_STRUCT_VER *tpm_struct_ver_src) +{ + printf(" TPM_StructVer_Copy:\n"); + tpm_struct_ver_dest->major = tpm_struct_ver_src->major; + tpm_struct_ver_dest->minor = tpm_struct_ver_src->minor; + tpm_struct_ver_dest->revMajor = tpm_struct_ver_src->revMajor; + tpm_struct_ver_dest->revMinor = tpm_struct_ver_src->revMinor; + return; +} + +/* TPM_StructVer_CheckVer() checks that the major and minor version are 0x01, 0x01 */ + +TPM_RESULT TPM_StructVer_CheckVer(TPM_STRUCT_VER *tpm_struct_ver) +{ + TPM_RESULT rc = 0; + + printf(" TPM_StructVer_CheckVer: version %u.%u.%u.%u\n", + tpm_struct_ver->major, + tpm_struct_ver->minor, + tpm_struct_ver->revMajor, + tpm_struct_ver->revMinor); + if ((tpm_struct_ver->major != 0x01) || + (tpm_struct_ver->minor != 0x01)) { + printf("TPM_StructVer_CheckVer: Error checking version\n"); + rc = TPM_BAD_VERSION; + } + return rc; +} + +/* + TPM_VERSION + + This structure provides information relative the version of the TPM. This structure should only be + in use by TPM_GetCapability to provide the information relative to the TPM. +*/ + +void TPM_Version_Init(TPM_VERSION *tpm_version) +{ + printf(" TPM_Version_Init:\n"); + tpm_version->major = 0; + tpm_version->minor = 0; + tpm_version->revMajor = 0; + tpm_version->revMinor = 0; + return; +} + +void TPM_Version_Set(TPM_VERSION *tpm_version, + TPM_PERMANENT_DATA *tpm_permanent_data) +{ + printf(" TPM_Version_Set:\n"); + /* This SHALL indicate the major version of the TPM, mostSigVer MUST be 0x01, leastSigVer MUST + be 0x00 */ + tpm_version->major = TPM_MAJOR; + /* This SHALL indicate the minor version of the TPM, mostSigVer MUST be 0x01 or 0x02, + leastSigVer MUST be 0x00 */ + tpm_version->minor = TPM_MINOR; + /* This SHALL be the value of the TPM_PERMANENT_DATA -> revMajor */ + tpm_version->revMajor = tpm_permanent_data->revMajor; + /* This SHALL be the value of the TPM_PERMANENT_DATA -> revMinor */ + tpm_version->revMinor = tpm_permanent_data->revMinor; + return; +} + +#if 0 +/* TPM_Version_Load() + + deserialize the structure from a 'stream' + 'stream_size' is checked for sufficient data + returns 0 or error codes + + Before use, call TPM_Version_Init() +*/ + +TPM_RESULT TPM_Version_Load(TPM_VERSION *tpm_version, + unsigned char **stream, + uint32_t *stream_size) +{ + TPM_RESULT rc = 0; + + printf(" TPM_Version_Load:\n"); + /* load major */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_version->major), stream, stream_size); + } + /* load minor */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_version->minor), stream, stream_size); + } + /* load revMajor */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_version->revMajor), stream, stream_size); + } + /* load revMinor */ + if (rc == 0) { + rc = TPM_Load8(&(tpm_version->revMinor), stream, stream_size); + } + return rc; +} +#endif +/* TPM_Version_Store() + + serialize the structure to a stream contained in 'sbuffer' + returns 0 or error codes +*/ + +TPM_RESULT TPM_Version_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_VERSION *tpm_version) + +{ + TPM_RESULT rc = 0; + + printf(" TPM_Version_Store:\n"); + /* store major */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_version->major), sizeof(BYTE)); + } + /* store minor */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_version->minor), sizeof(BYTE)); + } + /* store revMajor */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_version->revMajor), sizeof(BYTE)); + } + /* store revMinor */ + if (rc == 0) { + rc = TPM_Sbuffer_Append(sbuffer, &(tpm_version->revMinor), sizeof(BYTE)); + } + return rc; +} diff --git a/src/tpm12/tpm_ver.h b/src/tpm12/tpm_ver.h new file mode 100644 index 0000000..5417bfe --- /dev/null +++ b/src/tpm12/tpm_ver.h @@ -0,0 +1,76 @@ +/********************************************************************************/ +/* */ +/* Ver Structure Handler */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_ver.h 4071 2010-04-29 19:26:45Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_VER_H +#define TPM_VER_H + +#include "tpm_types.h" +#include "tpm_store.h" +#include "tpm_structures.h" + +/* TPM_STRUCT_VER */ + +void TPM_StructVer_Init(TPM_STRUCT_VER *tpm_struct_ver); +TPM_RESULT TPM_StructVer_Load(TPM_STRUCT_VER *tpm_struct_ver, + unsigned char **stream, + uint32_t *stream_size); +TPM_RESULT TPM_StructVer_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_STRUCT_VER *tpm_struct_ver); +void TPM_StructVer_Copy(TPM_STRUCT_VER *tpm_struct_ver_dest, + TPM_STRUCT_VER *tpm_struct_ver_src); +TPM_RESULT TPM_StructVer_CheckVer(TPM_STRUCT_VER *tpm_struct_ver); + +/* TPM_VERSION */ + +void TPM_Version_Init(TPM_VERSION *tpm_version); +void TPM_Version_Set(TPM_VERSION *tpm_version, + TPM_PERMANENT_DATA *tpm_permanent_data); +#if 0 +TPM_RESULT TPM_Version_Load(TPM_VERSION *tpm_version, + unsigned char **stream, + uint32_t *stream_size); +#endif +TPM_RESULT TPM_Version_Store(TPM_STORE_BUFFER *sbuffer, + const TPM_VERSION *tpm_version); +void TPM_Version_Delete(TPM_VERSION *tpm_version); + + + + +#endif diff --git a/src/tpm2/ACT.h b/src/tpm2/ACT.h new file mode 100644 index 0000000..ec609af --- /dev/null +++ b/src/tpm2/ACT.h @@ -0,0 +1,257 @@ +/********************************************************************************/ +/* */ +/* Authenticated Countdown Timer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id$ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +// 5.24 ACT.h + +#ifndef _ACT_H_ +#define _ACT_H_ +#include "TpmProfile.h" +#if !(defined RH_ACT_0) || (RH_ACT_0 != YES) +# undef RH_ACT_0 +# define RH_ACT_0 NO +# define IF_ACT_0_IMPLEMENTED(op) +#else +# define IF_ACT_0_IMPLEMENTED(op) op(0) +#endif +#if !(defined RH_ACT_1) || (RH_ACT_1 != YES) +# undef RH_ACT_1 +# define RH_ACT_1 NO +# define IF_ACT_1_IMPLEMENTED(op) +#else +# define IF_ACT_1_IMPLEMENTED(op) op(1) +#endif +#if !(defined RH_ACT_2) || (RH_ACT_2 != YES) +# undef RH_ACT_2 +# define RH_ACT_2 NO +# define IF_ACT_2_IMPLEMENTED(op) +#else +# define IF_ACT_2_IMPLEMENTED(op) op(2) +#endif +#if !(defined RH_ACT_3) || (RH_ACT_3 != YES) +# undef RH_ACT_3 +# define RH_ACT_3 NO +# define IF_ACT_3_IMPLEMENTED(op) +#else +# define IF_ACT_3_IMPLEMENTED(op) op(3) +#endif +#if !(defined RH_ACT_4) || (RH_ACT_4 != YES) +# undef RH_ACT_4 +# define RH_ACT_4 NO +# define IF_ACT_4_IMPLEMENTED(op) +#else +# define IF_ACT_4_IMPLEMENTED(op) op(4) +#endif +#if !(defined RH_ACT_5) || (RH_ACT_5 != YES) +# undef RH_ACT_5 +# define RH_ACT_5 NO +# define IF_ACT_5_IMPLEMENTED(op) +#else +# define IF_ACT_5_IMPLEMENTED(op) op(5) +#endif +#if !(defined RH_ACT_6) || (RH_ACT_6 != YES) +# undef RH_ACT_6 +# define RH_ACT_6 NO +# define IF_ACT_6_IMPLEMENTED(op) +#else +# define IF_ACT_6_IMPLEMENTED(op) op(6) +#endif +#if !(defined RH_ACT_7) || (RH_ACT_7 != YES) +# undef RH_ACT_7 +# define RH_ACT_7 NO +# define IF_ACT_7_IMPLEMENTED(op) +#else +# define IF_ACT_7_IMPLEMENTED(op) op(7) +#endif +#if !(defined RH_ACT_8) || (RH_ACT_8 != YES) +# undef RH_ACT_8 +# define RH_ACT_8 NO +# define IF_ACT_8_IMPLEMENTED(op) +#else +# define IF_ACT_8_IMPLEMENTED(op) op(8) +#endif +#if !(defined RH_ACT_9) || (RH_ACT_9 != YES) +# undef RH_ACT_9 +# define RH_ACT_9 NO +# define IF_ACT_9_IMPLEMENTED(op) +#else +# define IF_ACT_9_IMPLEMENTED(op) op(9) +#endif +#if !(defined RH_ACT_A) || (RH_ACT_A != YES) +# undef RH_ACT_A +# define RH_ACT_A NO +# define IF_ACT_A_IMPLEMENTED(op) +#else +# define IF_ACT_A_IMPLEMENTED(op) op(A) +#endif +#if !(defined RH_ACT_B) || (RH_ACT_B != YES) +# undef RH_ACT_B +# define RH_ACT_B NO +# define IF_ACT_B_IMPLEMENTED(op) +#else +# define IF_ACT_B_IMPLEMENTED(op) op(B) +#endif +#if !(defined RH_ACT_C) || (RH_ACT_C != YES) +# undef RH_ACT_C +# define RH_ACT_C NO +# define IF_ACT_C_IMPLEMENTED(op) +#else +# define IF_ACT_C_IMPLEMENTED(op) op(C) +#endif +#if !(defined RH_ACT_D) || (RH_ACT_D != YES) +# undef RH_ACT_D +# define RH_ACT_D NO +# define IF_ACT_D_IMPLEMENTED(op) +#else +# define IF_ACT_D_IMPLEMENTED(op) op(D) +#endif +#if !(defined RH_ACT_E) || (RH_ACT_E != YES) +# undef RH_ACT_E +# define RH_ACT_E NO +# define IF_ACT_E_IMPLEMENTED(op) +#else +# define IF_ACT_E_IMPLEMENTED(op) op(E) +#endif +#if !(defined RH_ACT_F) || (RH_ACT_F != YES) +# undef RH_ACT_F +# define RH_ACT_F NO +# define IF_ACT_F_IMPLEMENTED(op) +#else +# define IF_ACT_F_IMPLEMENTED(op) op(F) +#endif +#ifndef TPM_RH_ACT_0 +#error Need numeric definition for TPM_RH_ACT_0 +#endif +#ifndef TPM_RH_ACT_1 +# define TPM_RH_ACT_1 (TPM_RH_ACT_0 + 1) +#endif +#ifndef TPM_RH_ACT_2 +# define TPM_RH_ACT_2 (TPM_RH_ACT_0 + 2) +#endif +#ifndef TPM_RH_ACT_3 +# define TPM_RH_ACT_3 (TPM_RH_ACT_0 + 3) +#endif +#ifndef TPM_RH_ACT_4 +# define TPM_RH_ACT_4 (TPM_RH_ACT_0 + 4) +#endif +#ifndef TPM_RH_ACT_5 +# define TPM_RH_ACT_5 (TPM_RH_ACT_0 + 5) +#endif +#ifndef TPM_RH_ACT_6 +# define TPM_RH_ACT_6 (TPM_RH_ACT_0 + 6) +#endif +#ifndef TPM_RH_ACT_7 +# define TPM_RH_ACT_7 (TPM_RH_ACT_0 + 7) +#endif +#ifndef TPM_RH_ACT_8 +# define TPM_RH_ACT_8 (TPM_RH_ACT_0 + 8) +#endif +#ifndef TPM_RH_ACT_9 +# define TPM_RH_ACT_9 (TPM_RH_ACT_0 + 9) +#endif +#ifndef TPM_RH_ACT_A +# define TPM_RH_ACT_A (TPM_RH_ACT_0 + 0xA) +#endif +#ifndef TPM_RH_ACT_B +# define TPM_RH_ACT_B (TPM_RH_ACT_0 + 0xB) +#endif +#ifndef TPM_RH_ACT_C +# define TPM_RH_ACT_C (TPM_RH_ACT_0 + 0xC) +#endif +#ifndef TPM_RH_ACT_D +# define TPM_RH_ACT_D (TPM_RH_ACT_0 + 0xD) +#endif +#ifndef TPM_RH_ACT_E +# define TPM_RH_ACT_E (TPM_RH_ACT_0 + 0xE) +#endif +#ifndef TPM_RH_ACT_F +# define TPM_RH_ACT_F (TPM_RH_ACT_0 + 0xF) +#endif +#define FOR_EACH_ACT(op) \ + IF_ACT_0_IMPLEMENTED(op) \ + IF_ACT_1_IMPLEMENTED(op) \ + IF_ACT_2_IMPLEMENTED(op) \ + IF_ACT_3_IMPLEMENTED(op) \ + IF_ACT_4_IMPLEMENTED(op) \ + IF_ACT_5_IMPLEMENTED(op) \ + IF_ACT_6_IMPLEMENTED(op) \ + IF_ACT_7_IMPLEMENTED(op) \ + IF_ACT_8_IMPLEMENTED(op) \ + IF_ACT_9_IMPLEMENTED(op) \ + IF_ACT_A_IMPLEMENTED(op) \ + IF_ACT_B_IMPLEMENTED(op) \ + IF_ACT_C_IMPLEMENTED(op) \ + IF_ACT_D_IMPLEMENTED(op) \ + IF_ACT_E_IMPLEMENTED(op) \ + IF_ACT_F_IMPLEMENTED(op) + +// This is the mask for ACT that are implemented + +//#define ACT_MASK(N) | (1 << 0x##N) +//#define ACT_IMPLEMENTED_MASK (0 FOR_EACH_ACT(ACT_MASK)) +#define CASE_ACT_HANDLE(N) case TPM_RH_ACT_##N: +#define CASE_ACT_NUMBER(N) case 0x##N: +typedef struct ACT_STATE +{ + UINT32 remaining; + TPM_ALG_ID hashAlg; + TPM2B_DIGEST authPolicy; +} ACT_STATE, *P_ACT_STATE; +#endif // _ACT_H_ diff --git a/src/tpm2/ACTCommands.c b/src/tpm2/ACTCommands.c new file mode 100644 index 0000000..7a66db7 --- /dev/null +++ b/src/tpm2/ACTCommands.c @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* Authenticated COuntdown Timer Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id$ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "ACT_SetTimeout_fp.h" +#if CC_ACT_SetTimeout // Conditional expansion of this file + +/* Error Returns Meaning */ +/* TPM_RC_RETRY returned when an update for the selected ACT is already pending */ +/* TPM_RC_VALUE attempt to disable signaling from an ACT that has not expired */ +TPM_RC +TPM2_ACT_SetTimeout( + ACT_SetTimeout_In *in // IN: input parameter list + ) +{ + // If 'startTimeout' is UINT32_MAX, then this is an attempt to disable the ACT + // and turn off the signaling for the ACT. This is only valid if the ACT + // is signaling. + if((in->startTimeout == UINT32_MAX) && !ActGetSignaled(in->actHandle)) + return TPM_RC_VALUE + RC_ACT_SetTimeout_startTimeout; + return ActCounterUpdate(in->actHandle, in->startTimeout); +} +#endif // CC_ACT_SetTimeout diff --git a/src/tpm2/ACT_SetTimeout_fp.h b/src/tpm2/ACT_SetTimeout_fp.h new file mode 100644 index 0000000..8137538 --- /dev/null +++ b/src/tpm2/ACT_SetTimeout_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* TPM2_ACT_SetTimeout Header */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id$ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#ifndef ACT_SETTIMEOUT_FP_H +#define ACT_SETTIMEOUT_FP_H + +typedef struct { + TPMI_RH_ACT actHandle; + UINT32 startTimeout; +} ACT_SetTimeout_In; + +#define RC_ACT_SetTimeout_actHandle (TPM_RC_H + TPM_RC_1) +#define RC_ACT_SetTimeout_startTimeout (TPM_RC_H + TPM_RC_2) + +TPM_RC +TPM2_ACT_SetTimeout( + ACT_SetTimeout_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/ACT_spt.c b/src/tpm2/ACT_spt.c new file mode 100644 index 0000000..5b19c85 --- /dev/null +++ b/src/tpm2/ACT_spt.c @@ -0,0 +1,317 @@ +/********************************************************************************/ +/* */ +/* ACT Command Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Object_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 7.8 ACT Support (ACT_spt.c) */ +/* 7.8.1 Introduction */ +/* This code implements the ACT update code. It does not use a mutex. This code uses a platform + service (_plat__ACT_UpdateCounter()) that returns false if the update is not accepted. If this + occurs, then TPM_RC_RETRY should be sent to the caller so that they can retry the operation + later. The implementation of this is platform dependent but the reference uses a simple flag to + indicate that an update is pending and the only process that can clear that flag is the process + that does the actual update. */ + +/* 7.8.2 Includes */ + +#include "Tpm.h" +#include "ACT_spt_fp.h" +#include "Platform_fp.h" +#include "PlatformACT_fp.h" /* added kgold */ + +/* 7.8.3 Functions */ +/* 7.8.3.1 _ActResume() */ +/* This function does the resume processing for an ACT. It updates the saved count and turns + signaling back on if necessary. */ +#ifndef __ACT_DISABLED // libtpms added +static void +_ActResume( + UINT32 act, //IN: the act number + ACT_STATE *actData //IN: pointer to the saved ACT data + ) +{ + // If the act was non-zero, then restore the counter value. + if(actData->remaining > 0) + _plat__ACT_UpdateCounter(act, actData->remaining); + // if the counter was zero and the ACT signaling, enable the signaling. + else if(go.signaledACT & (1 << act)) + _plat__ACT_SetSignaled(act, TRUE); +} +#endif // libtpms added +/* 7.8.3.2 ActStartup() */ +/* This function is called by TPM2_Startup() to initialize the ACT counter values. */ +BOOL +ActStartup( + STARTUP_TYPE type + ) +{ + // Reset all the ACT hardware + _plat__ACT_Initialize(); + + // If this not a cold start, copy all the current 'signaled' settings to + // 'preservedSignaled'. +#ifndef __ACT_DISABLED // libtpms added + if (g_powerWasLost) + go.preservedSignaled = 0; + else + go.preservedSignaled |= go.signaledACT; +#endif // libtpms added + + // For TPM_RESET or TPM_RESTART, the ACTs will all be disabled and the output + // de-asserted. + if(type != SU_RESUME) + { +#ifndef __ACT_DISABLED // libtpms added + go.signaledACT = 0; +#endif // libtpms added +#define CLEAR_ACT_POLICY(N) \ + go.ACT_##N.hashAlg = TPM_ALG_NULL; \ + go.ACT_##N.authPolicy.b.size = 0; + + FOR_EACH_ACT(CLEAR_ACT_POLICY) + + } + else + { + // Resume each of the implemented ACT +#define RESUME_ACT(N) _ActResume(0x##N, &go.ACT_##N); + + FOR_EACH_ACT(RESUME_ACT) + } + // set no ACT updated since last startup. This is to enable the halving of the + // timeout value + s_ActUpdated = 0; + _plat__ACT_EnableTicks(TRUE); + return TRUE; +} +/* 7.8.3.3 _ActSaveState() */ +/* Get the counter state and the signaled state for an ACT. If the ACT has not been updated since + the last time it was saved, then divide the count by 2. */ +#ifndef __ACT_DISABLED // libtpms added +static void +_ActSaveState( + UINT32 act, + P_ACT_STATE actData + ) +{ + actData->remaining = _plat__ACT_GetRemaining(act); + // If the ACT hasn't been updated since the last startup, then it should be + // be halved. + if((s_ActUpdated & (1 << act)) == 0) + { + // Don't halve if the count is set to max or if halving would make it zero + if((actData->remaining != UINT32_MAX) && (actData->remaining > 1)) + actData->remaining /= 2; + } + if(_plat__ACT_GetSignaled(act)) + go.signaledACT |= (1 << act); +} +/* 7.8.3.4 ActGetSignaled() */ +/* This function returns the state of the signaled flag associated with an ACT. */ +BOOL +ActGetSignaled( + TPM_RH actHandle + ) +{ + UINT32 act = actHandle - TPM_RH_ACT_0; + // + return _plat__ACT_GetSignaled(act); +} +#endif // libtpms added +/* 7.8.3.5 ActShutdown() */ +/* This function saves the current state of the counters */ +BOOL +ActShutdown( + TPM_SU state //IN: the type of the shutdown. + ) +{ + // if this is not shutdown state, then the only type of startup is TPM_RESTART + // so the timer values will be cleared. If this is shutdown state, get the current + // countdown and signaled values. Plus, if the counter has not been updated + // since the last restart, divide the time by 2 so that there is no attack on the + // countdown by saving the countdown state early and then not using the TPM. + if(state == TPM_SU_STATE) + { + // This will be populated as each of the ACT is queried +#ifndef __ACT_DISABLED // libtpms added + go.signaledACT = 0; +#endif // libtpms added + // Get the current count and the signaled state +#define SAVE_ACT_STATE(N) _ActSaveState(0x##N, &go.ACT_##N); + + FOR_EACH_ACT(SAVE_ACT_STATE); + } + return TRUE; +} +/* 7.8.3.6 ActIsImplemented() */ +/* This function determines if an ACT is implemented in both the TPM and the platform code. */ +BOOL +ActIsImplemented( + UINT32 act + ) +{ +#define CASE_ACT_ + // This switch accounts for the TPM implemented values. + switch(act) + { +#ifndef __ACT_DISABLED // libtpms added + FOR_EACH_ACT(CASE_ACT_NUMBER) + // This ensures that the platorm implemented the values implemented by + // the TPM + return _plat__ACT_GetImplemented(act); +#endif // libtpms added + default: + break; + } + return FALSE; +} +/* 7.8.3.7 ActCounterUpdate() */ +/* This function updates the ACT counter. If the counter already has a pending update, it returns + TPM_RC_RETRY so that the update can be tried again later. */ +#if CC_ACT_SetTimeout // libtpms added +TPM_RC +ActCounterUpdate( + TPM_RH handle, //IN: the handle of the act + UINT32 newValue //IN: the value to set in the ACT + ) +{ + UINT32 act; + TPM_RC result; + // + act = handle - TPM_RH_ACT_0; + // This should never fail, but... + if(!_plat__ACT_GetImplemented(act)) + result = TPM_RC_VALUE; + else + { + // Will need to clear orderly so fail if we are orderly and NV is not available + if(NV_IS_ORDERLY) + RETURN_IF_NV_IS_NOT_AVAILABLE; + // if the attempt to update the counter fails, it means that there is an + // update pending so wait until it has occurred and then do an update. + if(!_plat__ACT_UpdateCounter(act, newValue)) + result = TPM_RC_RETRY; + else + { + // Indicate that the ACT has been updated since last TPM2_Startup(). + s_ActUpdated |= (UINT16)(1 << act); + + // Clear the preservedSignaled attribute. + go.preservedSignaled &= ~((UINT16)(1 << act)); + + // Need to clear the orderly flag + g_clearOrderly = TRUE; + + result = TPM_RC_SUCCESS; + } + } + return result; +} +#endif // libtpms added +/* 7.8.3.8 ActGetCapabilityData() */ +/* This function returns the list of ACT data */ +/* Return Value Meaning */ +/* YES if more ACT data is available */ +/* NO if no more ACT data to */ +TPMI_YES_NO +ActGetCapabilityData( + TPM_HANDLE actHandle, // IN: the handle for the starting ACT + UINT32 maxCount, // IN: maximum allowed return values + TPML_ACT_DATA *actList // OUT: ACT data list + ) +{ + // Initialize output property list + actList->count = 0; + + // Make sure that the starting handle value is in range (again) + if((actHandle < TPM_RH_ACT_0) || (actHandle > TPM_RH_ACT_F)) + return FALSE; + // The maximum count of curves we may return is MAX_ECC_CURVES + if(maxCount > MAX_ACT_DATA) + maxCount = MAX_ACT_DATA; + // Scan the ACT data from the starting ACT + for(; actHandle <= TPM_RH_ACT_F; actHandle++) + { + UINT32 act = actHandle - TPM_RH_ACT_0; + if(actList->count < maxCount) + { + if(ActIsImplemented(act)) + { + TPMS_ACT_DATA *actData = &actList->actData[actList->count]; + // + memset(&actData->attributes, 0, sizeof(actData->attributes)); + actData->handle = actHandle; + actData->timeout = _plat__ACT_GetRemaining(act); + if (_plat__ACT_GetSignaled(act)) + SET_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled); + else + CLEAR_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled); + actList->count++; + } + } + else + { + if(_plat__ACT_GetImplemented(act)) + return YES; + } + } + // If we get here, either all of the ACT values were put in the list, or the list + // was filled and there are no more ACT values to return + return NO; +} diff --git a/src/tpm2/ACT_spt_fp.h b/src/tpm2/ACT_spt_fp.h new file mode 100644 index 0000000..380e9fb --- /dev/null +++ b/src/tpm2/ACT_spt_fp.h @@ -0,0 +1,95 @@ +/********************************************************************************/ +/* */ +/* ACT Command Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id$ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#ifndef ACT_SPT_FP_H +#define ACT_SPT_FP_H + +BOOL +ActStartup( + STARTUP_TYPE type + ); +BOOL +ActGetSignaled( + TPM_RH actHandle + ); +BOOL +ActShutdown( + TPM_SU state //IN: the type of the shutdown. + ); +BOOL +ActIsImplemented( + UINT32 act + ); +TPM_RC +ActCounterUpdate( + TPM_RH handle, //IN: the handle of the act + UINT32 newValue //IN: the value to set in the ACT + ); +TPMI_YES_NO +ActGetCapabilityData( + TPM_HANDLE actHandle, // IN: the handle for the starting ACT + UINT32 maxCount, // IN: maximum allowed return values + TPML_ACT_DATA *actList // OUT: ACT data list + ); + + + +#endif diff --git a/src/tpm2/ActivateCredential_fp.h b/src/tpm2/ActivateCredential_fp.h new file mode 100644 index 0000000..841d117 --- /dev/null +++ b/src/tpm2/ActivateCredential_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ActivateCredential_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef ACTIVATECREDENTIAL_FP_H +#define ACTIVATECREDENTIAL_FP_H + +typedef struct { + TPMI_DH_OBJECT activateHandle; + TPMI_DH_OBJECT keyHandle; + TPM2B_ID_OBJECT credentialBlob; + TPM2B_ENCRYPTED_SECRET secret; +} ActivateCredential_In; + +#define RC_ActivateCredential_activateHandle (TPM_RC_H + TPM_RC_1) +#define RC_ActivateCredential_keyHandle (TPM_RC_H + TPM_RC_2) +#define RC_ActivateCredential_credentialBlob (TPM_RC_P + TPM_RC_1) +#define RC_ActivateCredential_secret (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM2B_DIGEST certInfo; +} ActivateCredential_Out; + +TPM_RC +TPM2_ActivateCredential( + ActivateCredential_In *in, // IN: input parameter list + ActivateCredential_Out *out // OUT: output parameter list + ); +#endif diff --git a/src/tpm2/AlgorithmCap.c b/src/tpm2/AlgorithmCap.c new file mode 100644 index 0000000..a186280 --- /dev/null +++ b/src/tpm2/AlgorithmCap.c @@ -0,0 +1,244 @@ +/********************************************************************************/ +/* */ +/* Algorithm Property Definitions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: AlgorithmCap.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 9.1 AlgorithmCap.c */ +/* 9.1.1 Description */ +/* This file contains the algorithm property definitions for the algorithms and the code for the + TPM2_GetCapability() to return the algorithm properties. */ +/* 9.1.2 Includes and Defines */ +#include "Tpm.h" +typedef struct +{ + TPM_ALG_ID algID; + TPMA_ALGORITHM attributes; +} ALGORITHM; +static const ALGORITHM s_algorithms[] = + { + // The entries in this table need to be in ascending order but the table doesn't + // need to be full (gaps are allowed). One day, a tool might exist to fill in the + // table from the TPM_ALG description +#if ALG_RSA + {TPM_ALG_RSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)}, +#endif +#if ALG_TDES + {TPM_ALG_TDES, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SHA1 + {TPM_ALG_SHA1, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif + {TPM_ALG_HMAC, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 1, 0, 0, 0)}, +#if ALG_AES + {TPM_ALG_AES, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_MGF1 + {TPM_ALG_MGF1, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, +#endif + {TPM_ALG_KEYEDHASH, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 1, 0, 1, 1, 0, 0)}, +#if ALG_XOR + {TPM_ALG_XOR, TPMA_ALGORITHM_INITIALIZER(0, 1, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SHA256 + {TPM_ALG_SHA256, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SHA384 + {TPM_ALG_SHA384, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SHA512 + {TPM_ALG_SHA512, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SM3_256 + {TPM_ALG_SM3_256, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SM4 + {TPM_ALG_SM4, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_RSASSA + {TPM_ALG_RSASSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_RSAES + {TPM_ALG_RSAES, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_RSAPSS + {TPM_ALG_RSAPSS, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_OAEP + {TPM_ALG_OAEP, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_ECDSA + {TPM_ALG_ECDSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_ECDH + {TPM_ALG_ECDH, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_ECDAA + {TPM_ALG_ECDAA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_SM2 + {TPM_ALG_SM2, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 1, 0)}, +#endif +#if ALG_ECSCHNORR + {TPM_ALG_ECSCHNORR, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_ECMQV + {TPM_ALG_ECMQV, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_KDF1_SP800_56A + {TPM_ALG_KDF1_SP800_56A, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_KDF2 + {TPM_ALG_KDF2, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_KDF1_SP800_108 + {TPM_ALG_KDF1_SP800_108, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_ECC + {TPM_ALG_ECC, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)}, +#endif + {TPM_ALG_SYMCIPHER, TPMA_ALGORITHM_INITIALIZER(0, 0, 0, 1, 0, 0, 0, 0, 0)}, +#if ALG_CAMELLIA + {TPM_ALG_CAMELLIA, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_CMAC + {TPM_ALG_CMAC, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_CTR + {TPM_ALG_CTR, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_OFB + {TPM_ALG_OFB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_CBC + {TPM_ALG_CBC, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_CFB + {TPM_ALG_CFB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_ECB + {TPM_ALG_ECB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif + }; +/* 9.1.3 AlgorithmCapGetImplemented() */ +/* This function is used by TPM2_GetCapability() to return a list of the implemented algorithms. */ +/* Return Values Meaning */ +/* YES more algorithms to report */ +/* NO no more algorithms to report */ +TPMI_YES_NO +AlgorithmCapGetImplemented( + TPM_ALG_ID algID, // IN: the starting algorithm ID + UINT32 count, // IN: count of returned algorithms + TPML_ALG_PROPERTY *algList // OUT: algorithm list + ) +{ + TPMI_YES_NO more = NO; + UINT32 i; + UINT32 algNum; + // initialize output algorithm list + algList->count = 0; + // The maximum count of algorithms we may return is MAX_CAP_ALGS. + if(count > MAX_CAP_ALGS) + count = MAX_CAP_ALGS; + // Compute how many algorithms are defined in s_algorithms array. + algNum = sizeof(s_algorithms) / sizeof(s_algorithms[0]); + // Scan the implemented algorithm list to see if there is a match to 'algID'. + for(i = 0; i < algNum; i++) + { + // If algID is less than the starting algorithm ID, skip it + if(s_algorithms[i].algID < algID) + continue; + if(algList->count < count) + { + // If we have not filled up the return list, add more algorithms + // to it + algList->algProperties[algList->count].alg = s_algorithms[i].algID; + algList->algProperties[algList->count].algProperties = + s_algorithms[i].attributes; + algList->count++; + } + else + { + // If the return list is full but we still have algorithms + // available, report this and stop scanning. + more = YES; + break; + } + } + return more; +} +/* 9.1.4 AlgorithmGetImplementedVector() + + This function returns the bit vector of the implemented algorithms. +*/ +LIB_EXPORT +void +AlgorithmGetImplementedVector( + ALGORITHM_VECTOR *implemented // OUT: the implemented bits are SET + ) +{ + int index; + // Nothing implemented until we say it is + MemorySet(implemented, 0, sizeof(ALGORITHM_VECTOR)); + // Go through the list of implemented algorithms and SET the corresponding bit in + // in the implemented vector + for(index = (sizeof(s_algorithms) / sizeof(s_algorithms[0])) - 1; + index >= 0; index--) + SET_BIT(s_algorithms[index].algID, *implemented); + return; +} diff --git a/src/tpm2/AlgorithmCap_fp.h b/src/tpm2/AlgorithmCap_fp.h new file mode 100644 index 0000000..31e505c --- /dev/null +++ b/src/tpm2/AlgorithmCap_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: AlgorithmCap_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef ALGORITHMCAP_FP_H +#define ALGORITHMCAP_FP_H + +TPMI_YES_NO +AlgorithmCapGetImplemented( + TPM_ALG_ID algID, // IN: the starting algorithm ID + UINT32 count, // IN: count of returned algorithms + TPML_ALG_PROPERTY *algList // OUT: algorithm list + ); +LIB_EXPORT +void +AlgorithmGetImplementedVector( + ALGORITHM_VECTOR *implemented // OUT: the implemented bits are SET + ); + + +#endif diff --git a/src/tpm2/AlgorithmTests.c b/src/tpm2/AlgorithmTests.c new file mode 100644 index 0000000..08ee6b0 --- /dev/null +++ b/src/tpm2/AlgorithmTests.c @@ -0,0 +1,964 @@ +/********************************************************************************/ +/* */ +/* Code to perform the various self-test functions. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: AlgorithmTests.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.1 AlgorithmTests.c */ +/* 10.2.1.1 Introduction */ +/* This file contains the code to perform the various self-test functions. */ +/* 10.2.1.2 Includes and Defines */ +#include "Tpm.h" +#define SELF_TEST_DATA +#if SELF_TEST +/* These includes pull in the data structures. They contain data definitions for the various + tests. */ +#include "SelfTest.h" +#include "SymmetricTest.h" +#include "RsaTestData.h" +#include "EccTestData.h" +#include "HashTestData.h" +#include "KdfTestData.h" +#define TEST_DEFAULT_TEST_HASH(vector) \ + if(TEST_BIT(DEFAULT_TEST_HASH, g_toTest)) \ + TestHash(DEFAULT_TEST_HASH, vector); +/* Make sure that the algorithm has been tested */ +#define CLEAR_BOTH(alg) { CLEAR_BIT(alg, *toTest); \ + if(toTest != &g_toTest) \ + CLEAR_BIT(alg, g_toTest); } +#define SET_BOTH(alg) { SET_BIT(alg, *toTest); \ + if(toTest != &g_toTest) \ + SET_BIT(alg, g_toTest); } +#define TEST_BOTH(alg) ((toTest != &g_toTest) \ + ? TEST_BIT(alg, *toTest) || TEST_BIT(alg, g_toTest) \ + : TEST_BIT(alg, *toTest)) +/* Can only cancel if doing a list. */ +#define CHECK_CANCELED \ + if(_plat__IsCanceled() && toTest != &g_toTest) \ + return TPM_RC_CANCELED; +/* 10.2.1.3 Hash Tests */ +/* 10.2.1.3.1 Description */ +/* The hash test does a known-value HMAC using the specified hash algorithm. */ +/* 10.2.1.3.2 TestHash() */ +/* The hash test function. */ +static TPM_RC +TestHash( + TPM_ALG_ID hashAlg, + ALGORITHM_VECTOR *toTest + ) +{ + TPM2B_DIGEST computed; // value computed + HMAC_STATE state; + UINT16 digestSize; + const TPM2B *testDigest = NULL; + // TPM2B_TYPE(HMAC_BLOCK, DEFAULT_TEST_HASH_BLOCK_SIZE); + pAssert(hashAlg != TPM_ALG_NULL); +#define HASH_CASE_FOR_TEST(HASH, hash) case ALG_##HASH##_VALUE: \ + testDigest = &c_##HASH##_digest.b; \ + break; + switch(hashAlg) + { + FOR_EACH_HASH(HASH_CASE_FOR_TEST) + + default: + FAIL(FATAL_ERROR_INTERNAL); + } + // Clear the to-test bits + CLEAR_BOTH(hashAlg); + + // If there is an algorithm without test vectors, then assume that things are OK. + if(testDigest == NULL || testDigest->size == 0) + return TPM_RC_SUCCESS; + + // Set the HMAC key to twice the digest size + digestSize = CryptHashGetDigestSize(hashAlg); + CryptHmacStart(&state, hashAlg, digestSize * 2, + (BYTE *)c_hashTestKey.t.buffer); + CryptDigestUpdate(&state.hashState, 2 * CryptHashGetBlockSize(hashAlg), + (BYTE *)c_hashTestData.t.buffer); + computed.t.size = digestSize; + CryptHmacEnd(&state, digestSize, computed.t.buffer); + if((testDigest->size != computed.t.size) + || (memcmp(testDigest->buffer, computed.t.buffer, computed.b.size) != 0)) { + SELF_TEST_FAILURE; + } + return TPM_RC_SUCCESS; +} +// libtpms added begin +#if SMAC_IMPLEMENTED && ALG_CMAC +static TPM_RC +TestSMAC( + ALGORITHM_VECTOR *toTest + ) +{ + HMAC_STATE state; + UINT16 copied; + BYTE out[MAX_SYM_BLOCK_SIZE]; + UINT32 outSize = sizeof(out); + UINT16 blocksize; + int i; + TPMU_PUBLIC_PARMS cmac_keyParms; + + // initializing this statically seems impossible with gcc... + cmac_keyParms.symDetail.sym.algorithm = TPM_ALG_AES; + cmac_keyParms.symDetail.sym.keyBits.sym = 128; + + for (i = 0; CMACTests[i].key; i++ ) + { + blocksize = CryptMacStart(&state, &cmac_keyParms, + TPM_ALG_CMAC, CMACTests[i].key); + pAssert(blocksize <= outSize); + CryptDigestUpdate(&state.hashState, CMACTests[i].datalen, + CMACTests[i].data); + copied = CryptMacEnd(&state, outSize, out); + if((CMACTests[i].outlen != copied) + || (memcmp(out, CMACTests[i].out, CMACTests[i].outlen) != 0)) { + SELF_TEST_FAILURE; + } + } + return TPM_RC_SUCCESS; +} +#endif +// libtpms added end +/* 10.2.1.4 Symmetric Test Functions */ +/* 10.2.1.4.1 MakeIv() */ +/* Internal function to make the appropriate IV depending on the mode. */ +static UINT32 +MakeIv( + TPM_ALG_ID mode, // IN: symmetric mode + UINT32 size, // IN: block size of the algorithm + BYTE *iv // OUT: IV to fill in + ) +{ + BYTE i; + if(mode == TPM_ALG_ECB) + return 0; + if(mode == TPM_ALG_CTR) + { + // The test uses an IV that has 0xff in the last byte + for(i = 1; i <= size; i++) + *iv++ = 0xff - (BYTE)(size - i); + } + else + { + for(i = 0; i < size; i++) + *iv++ = i; + } + return size; +} +/* 10.2.1.4.2 TestSymmetricAlgorithm() */ +/* Function to test a specific algorithm, key size, and mode. */ +static void +TestSymmetricAlgorithm( + const SYMMETRIC_TEST_VECTOR *test, // + TPM_ALG_ID mode // + ) +{ + BYTE encrypted[MAX_SYM_BLOCK_SIZE * 2]; + BYTE decrypted[MAX_SYM_BLOCK_SIZE * 2]; + TPM2B_IV iv; + + // libtpms added beging + if (test->dataOut[mode - TPM_ALG_CTR] == NULL) + return; + // libtpms added end + + // + // Get the appropriate IV + iv.t.size = (UINT16)MakeIv(mode, test->ivSize, iv.t.buffer); + // Encrypt known data + CryptSymmetricEncrypt(encrypted, test->alg, test->keyBits, test->key, &iv, + mode, test->dataInOutSize, test->dataIn); + // Check that it matches the expected value + if(!MemoryEqual(encrypted, test->dataOut[mode - TPM_ALG_CTR], + test->dataInOutSize)) { + SELF_TEST_FAILURE; + } + // Reinitialize the iv for decryption + MakeIv(mode, test->ivSize, iv.t.buffer); + CryptSymmetricDecrypt(decrypted, test->alg, test->keyBits, test->key, &iv, + mode, test->dataInOutSize, + test->dataOut[mode - TPM_ALG_CTR]); + // Make sure that it matches what we started with + if(!MemoryEqual(decrypted, test->dataIn, test->dataInOutSize)) { + SELF_TEST_FAILURE; + } +} +/* 10.2.1.4.3 AllSymsAreDone() */ +/* Checks if both symmetric algorithms have been tested. This is put here so that addition of a + symmetric algorithm will be relatively easy to handle */ +/* Return Value Meaning */ +/* TRUE(1) all symmetric algorithms tested */ +/* FALSE(0) not all symmetric algorithms tested */ +static BOOL +AllSymsAreDone( + ALGORITHM_VECTOR *toTest + ) +{ + return (!TEST_BOTH(TPM_ALG_AES) && !TEST_BOTH(TPM_ALG_SM4)); +} +/* 10.2.1.4.4 AllModesAreDone() */ +/* Checks if all the modes have been tested */ +/* Return Value Meaning */ +/* TRUE(1) all modes tested */ +/* FALSE(0) all modes not tested */ +static BOOL +AllModesAreDone( + ALGORITHM_VECTOR *toTest + ) +{ + TPM_ALG_ID alg; + for(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++) + if(TEST_BOTH(alg)) + return FALSE; + return TRUE; +} +/* 10.2.1.4.5 TestSymmetric() */ +/* If alg is a symmetric block cipher, then all of the modes that are selected are tested. If alg is + a mode, then all algorithms of that mode are tested. */ +static TPM_RC +TestSymmetric( + TPM_ALG_ID alg, + ALGORITHM_VECTOR *toTest + ) +{ + SYM_INDEX index; + TPM_ALG_ID mode; + // + if(!TEST_BIT(alg, *toTest)) + return TPM_RC_SUCCESS; + if(alg == TPM_ALG_AES || alg == TPM_ALG_SM4 || alg == TPM_ALG_CAMELLIA || alg == TPM_ALG_TDES) + { + // Will test the algorithm for all modes and key sizes + CLEAR_BOTH(alg); + // A test this algorithm for all modes + for(index = 0; index < NUM_SYMS; index++) + { + if(c_symTestValues[index].alg == alg) + { + for(mode = SYM_MODE_FIRST; + mode <= SYM_MODE_LAST; + mode++) + { + if(TEST_BIT(mode, g_implementedAlgorithms)) // libtpms always test implemented modes + TestSymmetricAlgorithm(&c_symTestValues[index], mode); + } + } + } + // if all the symmetric tests are done + if(AllSymsAreDone(toTest)) + { + // all symmetric algorithms tested so no modes should be set + for(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++) + CLEAR_BOTH(alg); + } + } + else if(SYM_MODE_FIRST <= alg && alg <= SYM_MODE_LAST) + { + // Test this mode for all key sizes and algorithms + for(index = 0; index < NUM_SYMS; index++) + { + // The mode testing only comes into play when doing self tests + // by command. When doing self tests by command, the block ciphers are + // tested first. That means that all of their modes would have been + // tested for all key sizes. If there is no block cipher left to + // test, then clear this mode bit. + if(!TEST_BIT(TPM_ALG_AES, *toTest) + && !TEST_BIT(TPM_ALG_SM4, *toTest)) + { + CLEAR_BOTH(alg); + } + else + { + for(index = 0; index < NUM_SYMS; index++) + { + if(TEST_BIT(c_symTestValues[index].alg, *toTest)) + TestSymmetricAlgorithm(&c_symTestValues[index], alg); + } + // have tested this mode for all algorithms + CLEAR_BOTH(alg); + } + } + if(AllModesAreDone(toTest)) + { + CLEAR_BOTH(TPM_ALG_AES); + CLEAR_BOTH(TPM_ALG_SM4); + } + } + else + pAssert(alg == 0 && alg != 0); + return TPM_RC_SUCCESS; +} +/* 10.2.1.5 RSA Tests */ +#if ALG_RSA +/* 10.2.1.5.1 Introduction */ +/* The tests are for public key only operations and for private key operations. Signature + verification and encryption are public key operations. They are tested by using a KVT. For + signature verification, this means that a known good signature is checked by + CryptRsaValidateSignature(). If it fails, then the TPM enters failure mode. For encryption, the + TPM encrypts known values using the selected scheme and checks that the returned value matches + the expected value. */ +/* For private key operations, a full scheme check is used. For a signing key, a known key is used + to sign a known message. Then that signature is verified. since the signature may involve use of + random values, the signature will be different each time and we can't always check that the + signature matches a known value. The same technique is used for decryption (RSADP/RSAEP). */ +/* When an operation uses the public key and the verification has not been tested, the TPM will do a + KVT. */ +/* The test for the signing algorithm is built into the call for the algorithm */ +/* 10.2.1.5.2 RsaKeyInitialize() */ +/* The test key is defined by a public modulus and a private prime. The TPM's RSA code computes the + second prime and the private exponent. */ +static void +RsaKeyInitialize( + OBJECT *testObject + ) +{ + MemoryCopy2B(&testObject->publicArea.unique.rsa.b, (P2B)&c_rsaPublicModulus, + sizeof(c_rsaPublicModulus)); + MemoryCopy2B(&testObject->sensitive.sensitive.rsa.b, (P2B)&c_rsaPrivatePrime, + sizeof(testObject->sensitive.sensitive.rsa.t.buffer)); + testObject->publicArea.parameters.rsaDetail.keyBits = RSA_TEST_KEY_SIZE * 8; + // Use the default exponent + testObject->publicArea.parameters.rsaDetail.exponent = 0; + testObject->attributes.privateExp = 0; +} +/* 10.2.1.5.3 TestRsaEncryptDecrypt() */ +/* These tests are for a public key encryption that uses a random value. */ +static TPM_RC +TestRsaEncryptDecrypt( + TPM_ALG_ID scheme, // IN: the scheme + ALGORITHM_VECTOR *toTest // + ) +{ + TPM2B_PUBLIC_KEY_RSA testInput; + TPM2B_PUBLIC_KEY_RSA testOutput; + OBJECT testObject; + const TPM2B_RSA_TEST_KEY *kvtValue = NULL; + TPM_RC result = TPM_RC_SUCCESS; + const TPM2B *testLabel = NULL; + TPMT_RSA_DECRYPT rsaScheme; + // + // Don't need to initialize much of the test object but do need to initialize + // the flag indicating that the private exponent has been computed. + testObject.attributes.privateExp = CLEAR; + RsaKeyInitialize(&testObject); + rsaScheme.scheme = scheme; + rsaScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH; + CLEAR_BOTH(scheme); + CLEAR_BOTH(TPM_ALG_NULL); + if(scheme == TPM_ALG_NULL) + { + // This is an encryption scheme using the private key without any encoding. + memcpy(testInput.t.buffer, c_RsaTestValue, sizeof(c_RsaTestValue)); + testInput.t.size = sizeof(c_RsaTestValue); + if(TPM_RC_SUCCESS != CryptRsaEncrypt(&testOutput, &testInput.b, + &testObject, &rsaScheme, NULL, NULL)) { + SELF_TEST_FAILURE; + } + if(!MemoryEqual(testOutput.t.buffer, c_RsaepKvt.buffer, c_RsaepKvt.size)) { + SELF_TEST_FAILURE; + } + MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer)); + if(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b, + &testObject, &rsaScheme, NULL)) { + SELF_TEST_FAILURE; + } + if(!MemoryEqual(testOutput.t.buffer, c_RsaTestValue, + sizeof(c_RsaTestValue))) { + SELF_TEST_FAILURE; + } + } + else + { + // TPM_ALG_RSAES: + // This is an decryption scheme using padding according to + // PKCS#1v2.1, 7.2. This padding uses random bits. To test a public + // key encryption that uses random data, encrypt a value and then + // decrypt the value and see that we get the encrypted data back. + // The hash is not used by this encryption so it can be TMP_ALG_NULL + // TPM_ALG_OAEP_: + // This is also an decryption scheme and it also uses a + // pseudo-random + // value. However, this also uses a hash algorithm. So, we may need + // to test that algorithm before use. + if(scheme == TPM_ALG_OAEP) + { + TEST_DEFAULT_TEST_HASH(toTest); + kvtValue = &c_OaepKvt; + testLabel = OAEP_TEST_STRING; + } + else if(scheme == TPM_ALG_RSAES) + { + kvtValue = &c_RsaesKvt; + testLabel = NULL; + } + else { + SELF_TEST_FAILURE; + } + // Only use a digest-size portion of the test value + memcpy(testInput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE); + testInput.t.size = DEFAULT_TEST_DIGEST_SIZE; + // See if the encryption works + if(TPM_RC_SUCCESS != CryptRsaEncrypt(&testOutput, &testInput.b, + &testObject, &rsaScheme, testLabel, + NULL)) { + SELF_TEST_FAILURE; + } + MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer)); + // see if we can decrypt this value and get the original data back + if(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b, + &testObject, &rsaScheme, testLabel)) { + SELF_TEST_FAILURE; + } + // See if the results compare + if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE + || !MemoryEqual(testOutput.t.buffer, c_RsaTestValue, + DEFAULT_TEST_DIGEST_SIZE)) { + SELF_TEST_FAILURE; + } + // Now check that the decryption works on a known value + MemoryCopy2B(&testInput.b, (P2B)kvtValue, + sizeof(testInput.t.buffer)); + if(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b, + &testObject, &rsaScheme, testLabel)) { + SELF_TEST_FAILURE; + } + if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE + || !MemoryEqual(testOutput.t.buffer, c_RsaTestValue, + DEFAULT_TEST_DIGEST_SIZE)) { + SELF_TEST_FAILURE; + } + } + return result; +} +/* 10.2.1.5.4 TestRsaSignAndVerify() */ +/* This function does the testing of the RSA sign and verification functions. This test does a + KVT. */ +static TPM_RC +TestRsaSignAndVerify( + TPM_ALG_ID scheme, + ALGORITHM_VECTOR *toTest + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT testObject; + TPM2B_DIGEST testDigest; + TPMT_SIGNATURE testSig; + // Do a sign and signature verification. + // RSASSA: + // This is a signing scheme according to PKCS#1-v2.1 8.2. It does not + // use random data so there is a KVT for the signing operation. On + // first use of the scheme for signing, use the TPM's RSA key to + // sign a portion of c_RsaTestData and compare the results to c_RsassaKvt. Then + // decrypt the data to see that it matches the starting value. This verifies + // the signature with a KVT + // Clear the bits indicating that the function has not been checked. This is to + // prevent looping + CLEAR_BOTH(scheme); + CLEAR_BOTH(TPM_ALG_NULL); + CLEAR_BOTH(TPM_ALG_RSA); + RsaKeyInitialize(&testObject); + memcpy(testDigest.t.buffer, (BYTE *)c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE); + testDigest.t.size = DEFAULT_TEST_DIGEST_SIZE; + testSig.sigAlg = scheme; + testSig.signature.rsapss.hash = DEFAULT_TEST_HASH; + // RSAPSS: + // This is a signing scheme a according to PKCS#1-v2.2 8.1 it uses + // random data in the signature so there is no KVT for the signing + // operation. To test signing, the TPM will use the TPM's RSA key + // to sign a portion of c_RsaTestValue and then it will verify the + // signature. For verification, c_RsapssKvt is verified before the + // user signature blob is verified. The worst case for testing of this + // algorithm is two private and one public key operation. + // The process is to sign known data. If RSASSA is being done, verify that the + // signature matches the precomputed value. For both, use the signed value and + // see that the verification says that it is a good signature. Then + // if testing RSAPSS, do a verify of a known good signature. This ensures that + // the validation function works. + if(TPM_RC_SUCCESS != CryptRsaSign(&testSig, &testObject, &testDigest, NULL)) { + SELF_TEST_FAILURE; + } + // For RSASSA, make sure the results is what we are looking for + if(testSig.sigAlg == TPM_ALG_RSASSA) + { + if(testSig.signature.rsassa.sig.t.size != RSA_TEST_KEY_SIZE + || !MemoryEqual(c_RsassaKvt.buffer, + testSig.signature.rsassa.sig.t.buffer, + RSA_TEST_KEY_SIZE)) { + SELF_TEST_FAILURE; + } + } + // See if the TPM will validate its own signatures + if(TPM_RC_SUCCESS != CryptRsaValidateSignature(&testSig, &testObject, + &testDigest)) { + SELF_TEST_FAILURE; + } + // If this is RSAPSS, check the verification with known signature + // Have to copy because CrytpRsaValidateSignature() eats the signature + if(TPM_ALG_RSAPSS == scheme) + { + MemoryCopy2B(&testSig.signature.rsapss.sig.b, (P2B)&c_RsapssKvt, + sizeof(testSig.signature.rsapss.sig.t.buffer)); + if(TPM_RC_SUCCESS != CryptRsaValidateSignature(&testSig, &testObject, + &testDigest)) { + SELF_TEST_FAILURE; + } + } + return result; +} +/* 10.2.1.5.5 TestRSA() */ +/* Function uses the provided vector to indicate which tests to run. It will clear the vector after + each test is run and also clear g_toTest */ +static TPM_RC +TestRsa( + TPM_ALG_ID alg, + ALGORITHM_VECTOR *toTest + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + // + switch(alg) + { + case TPM_ALG_NULL: + // This is the RSAEP/RSADP function. If we are processing a list, don't + // need to test these now because any other test will validate + // RSAEP/RSADP. Can tell this is list of test by checking to see if + // 'toTest' is pointing at g_toTest. If so, this is an isolated test + // an need to go ahead and do the test; + if((toTest == &g_toTest) + || (!TEST_BIT(TPM_ALG_RSASSA, *toTest) + && !TEST_BIT(TPM_ALG_RSAES, *toTest) + && !TEST_BIT(TPM_ALG_RSAPSS, *toTest) + && !TEST_BIT(TPM_ALG_OAEP, *toTest))) + // Not running a list of tests or no other tests on the list + // so run the test now + result = TestRsaEncryptDecrypt(alg, toTest); + // if not running the test now, leave the bit on, just in case things + // get interrupted + break; + case TPM_ALG_OAEP: + case TPM_ALG_RSAES: + result = TestRsaEncryptDecrypt(alg, toTest); + break; + case TPM_ALG_RSAPSS: + case TPM_ALG_RSASSA: + result = TestRsaSignAndVerify(alg, toTest); + break; + default: + SELF_TEST_FAILURE; + } + return result; +} +#endif // TPM_ALG_RSA +/* 10.2.1.6 ECC Tests */ +#if ALG_ECC +/* 10.2.1.6.1 LoadEccParameter() */ +/* This function is mostly for readability and type checking */ +static void +LoadEccParameter( + TPM2B_ECC_PARAMETER *to, // target + const TPM2B_EC_TEST *from // source + ) +{ + MemoryCopy2B(&to->b, &from->b, sizeof(to->t.buffer)); +} +/* 10.2.1.6.2 LoadEccPoint() */ +static void +LoadEccPoint( + TPMS_ECC_POINT *point, // target + const TPM2B_EC_TEST *x, // source + const TPM2B_EC_TEST *y + ) +{ + MemoryCopy2B(&point->x.b, (TPM2B *)x, sizeof(point->x.t.buffer)); + MemoryCopy2B(&point->y.b, (TPM2B *)y, sizeof(point->y.t.buffer)); +} +/* 10.2.1.6.3 TestECDH() */ +/* This test does a KVT on a point multiply. */ +static TPM_RC +TestECDH( + TPM_ALG_ID scheme, // IN: for consistency + ALGORITHM_VECTOR *toTest // IN/OUT: modified after test is run + ) +{ + TPMS_ECC_POINT Z; + TPMS_ECC_POINT Qe; + TPM2B_ECC_PARAMETER ds; + TPM_RC result = TPM_RC_SUCCESS; + // + NOT_REFERENCED(scheme); + CLEAR_BOTH(TPM_ALG_ECDH); + LoadEccParameter(&ds, &c_ecTestKey_ds); + LoadEccPoint(&Qe, &c_ecTestKey_QeX, &c_ecTestKey_QeY); + if(TPM_RC_SUCCESS != CryptEccPointMultiply(&Z, c_testCurve, &Qe, &ds, + NULL, NULL)) { + SELF_TEST_FAILURE; + } + if(!MemoryEqual2B(&c_ecTestEcdh_X.b, &Z.x.b) + || !MemoryEqual2B(&c_ecTestEcdh_Y.b, &Z.y.b)) { + SELF_TEST_FAILURE; + } + return result; +} +/* 10.2.1.6.4 TestEccSignAndVerify() */ +static TPM_RC +TestEccSignAndVerify( + TPM_ALG_ID scheme, + ALGORITHM_VECTOR *toTest + ) +{ + OBJECT testObject; + TPMT_SIGNATURE testSig; + TPMT_ECC_SCHEME eccScheme; + testSig.sigAlg = scheme; + testSig.signature.ecdsa.hash = DEFAULT_TEST_HASH; + eccScheme.scheme = scheme; + eccScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH; + CLEAR_BOTH(scheme); + CLEAR_BOTH(TPM_ALG_ECDH); + // ECC signature verification testing uses a KVT. + switch(scheme) + { + case TPM_ALG_ECDSA: + LoadEccParameter(&testSig.signature.ecdsa.signatureR, &c_TestEcDsa_r); + LoadEccParameter(&testSig.signature.ecdsa.signatureS, &c_TestEcDsa_s); + break; + case TPM_ALG_ECSCHNORR: + LoadEccParameter(&testSig.signature.ecschnorr.signatureR, + &c_TestEcSchnorr_r); + LoadEccParameter(&testSig.signature.ecschnorr.signatureS, + &c_TestEcSchnorr_s); + break; + case TPM_ALG_SM2: + // don't have a test for SM2 + return TPM_RC_SUCCESS; + default: + SELF_TEST_FAILURE; + break; + } + TEST_DEFAULT_TEST_HASH(toTest); + // Have to copy the key. This is because the size used in the test vectors + // is the size of the ECC parameter for the test key while the size of a point + // is TPM dependent + MemoryCopy2B(&testObject.sensitive.sensitive.ecc.b, &c_ecTestKey_ds.b, + sizeof(testObject.sensitive.sensitive.ecc.t.buffer)); + LoadEccPoint(&testObject.publicArea.unique.ecc, &c_ecTestKey_QsX, + &c_ecTestKey_QsY); + testObject.publicArea.parameters.eccDetail.curveID = c_testCurve; + if(TPM_RC_SUCCESS != CryptEccValidateSignature(&testSig, &testObject, + (TPM2B_DIGEST *)&c_ecTestValue.b)) + { + SELF_TEST_FAILURE; + } + CHECK_CANCELED; + // Now sign and verify some data + if(TPM_RC_SUCCESS != CryptEccSign(&testSig, &testObject, + (TPM2B_DIGEST *)&c_ecTestValue, + &eccScheme, NULL)) { + SELF_TEST_FAILURE; + } + CHECK_CANCELED; + if(TPM_RC_SUCCESS != CryptEccValidateSignature(&testSig, &testObject, + (TPM2B_DIGEST *)&c_ecTestValue)) { + SELF_TEST_FAILURE; + } + CHECK_CANCELED; + return TPM_RC_SUCCESS; +} +/* 10.2.1.6.5 TestKDFa() */ + +static TPM_RC +TestKDFa( + ALGORITHM_VECTOR *toTest + ) +{ + static TPM2B_KDF_TEST_KEY keyOut; + UINT32 counter = 0; + // + CLEAR_BOTH(TPM_ALG_KDF1_SP800_108); + keyOut.t.size = CryptKDFa(KDF_TEST_ALG, &c_kdfTestKeyIn.b, &c_kdfTestLabel.b, + &c_kdfTestContextU.b, &c_kdfTestContextV.b, + TEST_KDF_KEY_SIZE * 8, keyOut.t.buffer, + &counter, FALSE); + if ( keyOut.t.size != TEST_KDF_KEY_SIZE + || !MemoryEqual(keyOut.t.buffer, c_kdfTestKeyOut.t.buffer, + TEST_KDF_KEY_SIZE)) + SELF_TEST_FAILURE; + return TPM_RC_SUCCESS; +} +/* 10.2.1.6.6 TestEcc() */ +static TPM_RC +TestEcc( + TPM_ALG_ID alg, + ALGORITHM_VECTOR *toTest + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + NOT_REFERENCED(toTest); + switch(alg) + { + case TPM_ALG_ECC: + case TPM_ALG_ECDH: + // If this is in a loop then see if another test is going to deal with + // this. + // If toTest is not a self-test list + if((toTest == &g_toTest) + // or this is the only ECC test in the list + || !(TEST_BIT(TPM_ALG_ECDSA, *toTest) + || TEST_BIT(TPM_ALG_ECSCHNORR, *toTest) + || TEST_BIT(TPM_ALG_SM2, *toTest))) + { + result = TestECDH(alg, toTest); + } + break; + case TPM_ALG_ECDSA: + case TPM_ALG_ECSCHNORR: + case TPM_ALG_SM2: + result = TestEccSignAndVerify(alg, toTest); + break; + default: + SELF_TEST_FAILURE; + break; + } + return result; +} +#endif // TPM_ALG_ECC +/* 10.2.1.6.4 TestAlgorithm() */ +/* Dispatches to the correct test function for the algorithm or gets a list of testable + algorithms. */ +/* If toTest is not NULL, then the test decisions are based on the algorithm selections in + toTest. Otherwise, g_toTest is used. When bits are clear in g_toTest they will also be cleared + toTest. */ +/* If there doesn't happen to be a test for the algorithm, its associated bit is quietly cleared. */ +/* If alg is zero (TPM_ALG_ERROR), then the toTest vector is cleared of any bits for which there is + no test (i.e. no tests are actually run but the vector is cleared). */ +/* NOTE: toTest will only ever have bits set for implemented algorithms but alg can be anything. */ +/* Error Returns Meaning */ +/* TPM_RC_CANCELED test was canceled */ +LIB_EXPORT +TPM_RC +TestAlgorithm( + TPM_ALG_ID alg, + ALGORITHM_VECTOR *toTest + ) +{ + TPM_ALG_ID first = (alg == TPM_ALG_ERROR) ? TPM_ALG_FIRST : alg; + TPM_ALG_ID last = (alg == TPM_ALG_ERROR) ? TPM_ALG_LAST : alg; + BOOL doTest = (alg != TPM_ALG_ERROR); + TPM_RC result = TPM_RC_SUCCESS; + if(toTest == NULL) + toTest = &g_toTest; + // This is kind of strange. This function will either run a test of the selected + // algorithm or just clear a bit if there is no test for the algorithm. So, + // either this loop will be executed once for the selected algorithm or once for + // each of the possible algorithms. If it is executed more than once ('alg' == + // TPM_ALG_ERROR), then no test will be run but bits will be cleared for + // unimplemented algorithms. This was done this way so that there is only one + // case statement with all of the algorithms. It was easier to have one case + // statement than to have multiple ones to manage whenever an algorithm ID is + // added. + for(alg = first; (alg <= last); alg++) + { + // if 'alg' was TPM_ALG_ERROR, then we will be cycling through + // values, some of which may not be implemented. If the bit in toTest + // happens to be set, then we could either generated an assert, or just + // silently CLEAR it. Decided to just clear. + if(!TEST_BIT(alg, g_implementedAlgorithms)) + { + CLEAR_BIT(alg, *toTest); + continue; + } + // Process whatever is left. + // NOTE: since this switch will only be called if the algorithm is + // implemented, it is not necessary to modify this list except to comment + // out the algorithms for which there is no test + switch(alg) + { + // Symmetric block ciphers +#if ALG_AES + case TPM_ALG_AES: +// libtpms added begin +#if SMAC_IMPLEMENTED && ALG_CMAC + if (doTest) { + result = TestSMAC(toTest); + if (result != TPM_RC_SUCCESS) + break; + } +#endif +// libtpms added end +#endif +#if ALG_SM4 + // if SM4 is implemented, its test is like other block ciphers but there + // aren't any test vectors for it yet + // case TPM_ALG_SM4: +#endif +#if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: // libtpms activated +#endif +#if ALG_TDES + case TPM_ALG_TDES: // libtpms added +#endif + // Symmetric modes +#if !ALG_CFB +# error CFB is required in all TPM implementations +#endif // !TPM_ALG_CFB + case TPM_ALG_CFB: + if(doTest) + result = TestSymmetric(alg, toTest); + break; +#if ALG_CTR + case TPM_ALG_CTR: +#endif // TPM_ALG_CRT +#if ALG_OFB + case TPM_ALG_OFB: +#endif // TPM_ALG_OFB +#if ALG_CBC + case TPM_ALG_CBC: +#endif // TPM_ALG_CBC +#if ALG_ECB + case TPM_ALG_ECB: +#endif + if(doTest) + result = TestSymmetric(alg, toTest); + else + // If doing the initialization of g_toTest vector, only need + // to test one of the modes for the symmetric algorithms. If + // initializing for a SelfTest(FULL_TEST), allow all the modes. + if(toTest == &g_toTest) + CLEAR_BIT(alg, *toTest); + break; +#if !ALG_HMAC +# error HMAC is required in all TPM implementations +#endif + case TPM_ALG_HMAC: + // Clear the bit that indicates that HMAC is required because + // HMAC is used as the basic test for all hash algorithms. + CLEAR_BOTH(alg); + // Testing HMAC means test the default hash + if(doTest) + TestHash(DEFAULT_TEST_HASH, toTest); + else + // If not testing, then indicate that the hash needs to be + // tested because this uses HMAC + SET_BOTH(DEFAULT_TEST_HASH); + break; + // Have to use two arguments for the macro even though only the first is used in the + // expansion. +#define HASH_CASE_TEST(HASH, hash) \ + case ALG_##HASH##_VALUE: + FOR_EACH_HASH(HASH_CASE_TEST) +#undef HASH_CASE_TEST + if(doTest) + result = TestHash(alg, toTest); + break; + // RSA-dependent +#if ALG_RSA + case TPM_ALG_RSA: + CLEAR_BOTH(alg); + if(doTest) + result = TestRsa(TPM_ALG_NULL, toTest); + else + SET_BOTH(TPM_ALG_NULL); + break; + case TPM_ALG_RSASSA: + case TPM_ALG_RSAES: + case TPM_ALG_RSAPSS: + case TPM_ALG_OAEP: + case TPM_ALG_NULL: // used or RSADP + if(doTest) + result = TestRsa(alg, toTest); + break; +#endif // ALG_RSA +#if ALG_KDF1_SP800_108 + case TPM_ALG_KDF1_SP800_108: + if(doTest) + result = TestKDFa(toTest); + break; +#endif // ALG_KDF1_SP800_108 +#if ALG_ECC + // ECC dependent but no tests + // case TPM_ALG_ECDAA: + // case TPM_ALG_ECMQV: + // case TPM_ALG_KDF1_SP800_56a: + // case TPM_ALG_KDF2: + // case TPM_ALG_MGF1: + case TPM_ALG_ECC: + CLEAR_BOTH(alg); + if(doTest) + result = TestEcc(TPM_ALG_ECDH, toTest); + else + SET_BOTH(TPM_ALG_ECDH); + break; + case TPM_ALG_ECDSA: + case TPM_ALG_ECDH: + case TPM_ALG_ECSCHNORR: + // case TPM_ALG_SM2: + if(doTest) + result = TestEcc(alg, toTest); + break; +#endif // ALG_ECC + default: + CLEAR_BIT(alg, *toTest); + break; + } + if(result != TPM_RC_SUCCESS) + break; + } + return result; +} +#endif // SELF_TESTS diff --git a/src/tpm2/AlgorithmTests_fp.h b/src/tpm2/AlgorithmTests_fp.h new file mode 100644 index 0000000..c180b7b --- /dev/null +++ b/src/tpm2/AlgorithmTests_fp.h @@ -0,0 +1,73 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: AlgorithmTests_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef ALGORITHMTESTS_FP_H +#define ALGORITHMTESTS_FP_H + +LIB_EXPORT +TPM_RC +TestAlgorithm( + TPM_ALG_ID alg, + ALGORITHM_VECTOR *toTest + ); + + +#endif diff --git a/src/tpm2/AsymmetricCommands.c b/src/tpm2/AsymmetricCommands.c new file mode 100644 index 0000000..885087b --- /dev/null +++ b/src/tpm2/AsymmetricCommands.c @@ -0,0 +1,299 @@ +/********************************************************************************/ +/* */ +/* Asymmetric Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: AsymmetricCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "RSA_Encrypt_fp.h" +#if CC_RSA_Encrypt // Conditional expansion of this file +TPM_RC +TPM2_RSA_Encrypt( + RSA_Encrypt_In *in, // IN: input parameter list + RSA_Encrypt_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *rsaKey; + TPMT_RSA_DECRYPT *scheme; + // Input Validation + rsaKey = HandleToObject(in->keyHandle); + // selected key must be an RSA key + if(rsaKey->publicArea.type != TPM_ALG_RSA) + return TPM_RCS_KEY + RC_RSA_Encrypt_keyHandle; + // selected key must have the decryption attribute + if(!IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_RSA_Encrypt_keyHandle; + // Is there a label? + if(!IsLabelProperlyFormatted(&in->label.b)) + return TPM_RCS_VALUE + RC_RSA_Encrypt_label; + // Command Output + // Select a scheme for encryption + scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); + if(scheme == NULL) + return TPM_RCS_SCHEME + RC_RSA_Encrypt_inScheme; + // Encryption. TPM_RC_VALUE, or TPM_RC_SCHEME errors my be returned buy + // CryptEncyptRSA. + out->outData.t.size = sizeof(out->outData.t.buffer); + result = CryptRsaEncrypt(&out->outData, &in->message.b, rsaKey, scheme, + &in->label.b, NULL); + return result; +} +#endif // CC_RSA_Encrypt +#include "Tpm.h" +#include "RSA_Decrypt_fp.h" +#if CC_RSA_Decrypt // Conditional expansion of this file +TPM_RC +TPM2_RSA_Decrypt( + RSA_Decrypt_In *in, // IN: input parameter list + RSA_Decrypt_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *rsaKey; + TPMT_RSA_DECRYPT *scheme; + // Input Validation + rsaKey = HandleToObject(in->keyHandle); + // The selected key must be an RSA key + if(rsaKey->publicArea.type != TPM_ALG_RSA) + return TPM_RCS_KEY + RC_RSA_Decrypt_keyHandle; + // The selected key must be an unrestricted decryption key + if(IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_RSA_Decrypt_keyHandle; + // NOTE: Proper operation of this command requires that the sensitive area + // of the key is loaded. This is assured because authorization is required + // to use the sensitive area of the key. In order to check the authorization, + // the sensitive area has to be loaded, even if authorization is with policy. + // If label is present, make sure that it is a NULL-terminated string + if(!IsLabelProperlyFormatted(&in->label.b)) + return TPM_RCS_VALUE + RC_RSA_Decrypt_label; + // Command Output + // Select a scheme for decrypt. + scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); + if(scheme == NULL) + return TPM_RCS_SCHEME + RC_RSA_Decrypt_inScheme; + // Decryption. TPM_RC_VALUE, TPM_RC_SIZE, and TPM_RC_KEY error may be + // returned by CryptRsaDecrypt. + // NOTE: CryptRsaDecrypt can also return TPM_RC_ATTRIBUTES or TPM_RC_BINDING + // when the key is not a decryption key but that was checked above. + out->message.t.size = sizeof(out->message.t.buffer); + result = CryptRsaDecrypt(&out->message.b, &in->cipherText.b, rsaKey, + scheme, &in->label.b); + return result; +} +#endif // CC_RSA_Decrypt +#include "Tpm.h" +#include "ECDH_KeyGen_fp.h" +#if CC_ECDH_KeyGen // Conditional expansion of this file +TPM_RC +TPM2_ECDH_KeyGen( + ECDH_KeyGen_In *in, // IN: input parameter list + ECDH_KeyGen_Out *out // OUT: output parameter list + ) +{ + OBJECT *eccKey; + TPM2B_ECC_PARAMETER sensitive; + TPM_RC result; + // Input Validation + eccKey = HandleToObject(in->keyHandle); + // Referenced key must be an ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; + // Command Output + do + { + TPMT_PUBLIC *keyPublic = &eccKey->publicArea; + // Create ephemeral ECC key + result = CryptEccNewKeyPair(&out->pubPoint.point, &sensitive, + keyPublic->parameters.eccDetail.curveID); + if(result == TPM_RC_SUCCESS) + { + // Compute Z + result = CryptEccPointMultiply(&out->zPoint.point, + keyPublic->parameters.eccDetail.curveID, + &keyPublic->unique.ecc, + &sensitive, + NULL, NULL); + // The point in the key is not on the curve. Indicate + // that the key is bad. + if(result == TPM_RC_ECC_POINT) + return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; + // The other possible error from CryptEccPointMultiply is + // TPM_RC_NO_RESULT indicating that the multiplication resulted in + // the point at infinity, so get a new random key and start over + // BTW, this never happens. + } + } while(result == TPM_RC_NO_RESULT); + return result; +} +#endif // CC_ECDH_KeyGen +#include "Tpm.h" +#include "ECDH_ZGen_fp.h" +#if CC_ECDH_ZGen // Conditional expansion of this file +TPM_RC +TPM2_ECDH_ZGen( + ECDH_ZGen_In *in, // IN: input parameter list + ECDH_ZGen_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *eccKey; + // Input Validation + eccKey = HandleToObject(in->keyHandle); + // Selected key must be a non-restricted, decrypt ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ECDH_ZGen_keyHandle; + // Selected key needs to be unrestricted with the 'decrypt' attribute + if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_ECDH_ZGen_keyHandle; + // Make sure the scheme allows this use + if(eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_ECDH + && eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME + RC_ECDH_ZGen_keyHandle; + // Command Output + // Compute Z. TPM_RC_ECC_POINT or TPM_RC_NO_RESULT may be returned here. + result = CryptEccPointMultiply(&out->outPoint.point, + eccKey->publicArea.parameters.eccDetail.curveID, + &in->inPoint.point, + &eccKey->sensitive.sensitive.ecc, + NULL, NULL); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_ECDH_ZGen_inPoint); + return result; +} +#endif // CC_ECDH_ZGen +#include "Tpm.h" +#include "ECC_Parameters_fp.h" +#if CC_ECC_Parameters // Conditional expansion of this file +TPM_RC +TPM2_ECC_Parameters( + ECC_Parameters_In *in, // IN: input parameter list + ECC_Parameters_Out *out // OUT: output parameter list + ) +{ + // Command Output + // Get ECC curve parameters + if(CryptEccGetParameters(in->curveID, &out->parameters)) + return TPM_RC_SUCCESS; + else + return TPM_RCS_VALUE + RC_ECC_Parameters_curveID; +} +#endif // CC_ECC_Parameters +#include "Tpm.h" +#include "ZGen_2Phase_fp.h" +#if CC_ZGen_2Phase // Conditional expansion of this file +TPM_RC +TPM2_ZGen_2Phase( + ZGen_2Phase_In *in, // IN: input parameter list + ZGen_2Phase_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *eccKey; + TPM2B_ECC_PARAMETER r; + TPM_ALG_ID scheme; + // Input Validation + eccKey = HandleToObject(in->keyA); + // keyA must be an ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ZGen_2Phase_keyA; + // keyA must not be restricted and must be a decrypt key + if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_ZGen_2Phase_keyA; + // if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise + // the input scheme must be the same as the scheme of keyA + scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme; + if(scheme != TPM_ALG_NULL) + { + if(scheme != in->inScheme) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + } + else + scheme = in->inScheme; + if(scheme == TPM_ALG_NULL) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + // Input points must be on the curve of keyA + if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, + &in->inQsB.point)) + return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQsB; + if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, + &in->inQeB.point)) + return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQeB; + if(!CryptGenerateR(&r, &in->counter, + eccKey->publicArea.parameters.eccDetail.curveID, + NULL)) + return TPM_RCS_VALUE + RC_ZGen_2Phase_counter; + // Command Output + result = CryptEcc2PhaseKeyExchange(&out->outZ1.point, + &out->outZ2.point, + eccKey->publicArea.parameters.eccDetail.curveID, + scheme, + &eccKey->sensitive.sensitive.ecc, + &r, + &in->inQsB.point, + &in->inQeB.point); + if(result == TPM_RC_SCHEME) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + if(result == TPM_RC_SUCCESS) + CryptEndCommit(in->counter); + return result; +} +#endif // CC_ZGen_2Phase diff --git a/src/tpm2/Attest_spt.c b/src/tpm2/Attest_spt.c new file mode 100644 index 0000000..0b8d29c --- /dev/null +++ b/src/tpm2/Attest_spt.c @@ -0,0 +1,209 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Attest_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "Attest_spt_fp.h" +/* 7.2.2 Functions */ +/* 7.2.2.1 FillInAttestInfo() */ +/* Fill in common fields of TPMS_ATTEST structure. */ +void +FillInAttestInfo( + TPMI_DH_OBJECT signHandle, // IN: handle of signing object + TPMT_SIG_SCHEME *scheme, // IN/OUT: scheme to be used for signing + TPM2B_DATA *data, // IN: qualifying data + TPMS_ATTEST *attest // OUT: attest structure + ) +{ + OBJECT *signObject = HandleToObject(signHandle); + // Magic number + attest->magic = TPM_GENERATED_VALUE; + if(signObject == NULL) + { + // The name for a null handle is TPM_RH_NULL + // This is defined because UINT32_TO_BYTE_ARRAY does a cast. If the + // size of the cast is smaller than a constant, the compiler warns + // about the truncation of a constant value. + TPM_HANDLE nullHandle = TPM_RH_NULL; + attest->qualifiedSigner.t.size = sizeof(TPM_HANDLE); + UINT32_TO_BYTE_ARRAY(nullHandle, attest->qualifiedSigner.t.name); + } + else + { + // Certifying object qualified name + // if the scheme is anonymous, this is an empty buffer + if(CryptIsSchemeAnonymous(scheme->scheme)) + attest->qualifiedSigner.t.size = 0; + else + attest->qualifiedSigner = signObject->qualifiedName; + } + // current clock in plain text + TimeFillInfo(&attest->clockInfo); + // Firmware version in plain text + attest->firmwareVersion = ((UINT64)gp.firmwareV1 << (sizeof(UINT32) * 8)); + attest->firmwareVersion += gp.firmwareV2; + // Check the hierarchy of sign object. For NULL sign handle, the hierarchy + // will be TPM_RH_NULL + if((signObject == NULL) + || (!signObject->attributes.epsHierarchy + && !signObject->attributes.ppsHierarchy)) + { + // For signing key that is not in platform or endorsement hierarchy, + // obfuscate the reset, restart and firmware version information + UINT64 obfuscation[2]; + CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gp.shProof.b, OBFUSCATE_STRING, + &attest->qualifiedSigner.b, NULL, 128, + (BYTE *)&obfuscation[0], NULL, FALSE); + // Obfuscate data + attest->firmwareVersion += obfuscation[0]; + attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32); + attest->clockInfo.restartCount += (UINT32)obfuscation[1]; + } + // External data + if(CryptIsSchemeAnonymous(scheme->scheme)) + attest->extraData.t.size = 0; + else + { + // If we move the data to the attestation structure, then it is not + // used in the signing operation except as part of the signed data + attest->extraData = *data; + data->t.size = 0; + } +} +/* 7.2.2.2 SignAttestInfo() */ +/* Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature is returned. */ +/* Error Returns Meaning */ +/* TPM_RC_ATTRIBUTES signHandle references not a signing key */ +/* TPM_RC_SCHEME scheme is not compatible with signHandle type */ +/* TPM_RC_VALUE digest generated for the given scheme is greater than the modulus of signHandle (for + an RSA key); invalid commit status or failed to generate r value (for an ECC key) */ +TPM_RC +SignAttestInfo( + OBJECT *signKey, // IN: sign object + TPMT_SIG_SCHEME *scheme, // IN: sign scheme + TPMS_ATTEST *certifyInfo, // IN: the data to be signed + TPM2B_DATA *qualifyingData, // IN: extra data for the signing + // process + TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be + // signed + TPMT_SIGNATURE *signature // OUT: signature + ) +{ + BYTE *buffer; + HASH_STATE hashState; + TPM2B_DIGEST digest; + TPM_RC result; + // Marshal TPMS_ATTEST structure for hash + buffer = attest->t.attestationData; + attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL); + if(signKey == NULL) + { + signature->sigAlg = TPM_ALG_NULL; + result = TPM_RC_SUCCESS; + } + else + { + TPMI_ALG_HASH hashAlg; + // Compute hash + hashAlg = scheme->details.any.hashAlg; + // need to set the receive buffer to get something put in it + digest.t.size = sizeof(digest.t.buffer); + digest.t.size = CryptHashBlock(hashAlg, attest->t.size, + attest->t.attestationData, + digest.t.size, digest.t.buffer); + // If there is qualifying data, need to rehash the data + // hash(qualifyingData || hash(attestationData)) + if(qualifyingData->t.size != 0) + { + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate2B(&hashState, &qualifyingData->b); + CryptDigestUpdate2B(&hashState, &digest.b); + CryptHashEnd2B(&hashState, &digest.b); + } + // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or + // TPM_RC_ATTRIBUTES error may be returned at this point + result = CryptSign(signKey, scheme, &digest, signature); + // Since the clock is used in an attestation, the state in NV is no longer + // "orderly" with respect to the data in RAM if the signature is valid + if(result == TPM_RC_SUCCESS) + { + // Command uses the clock so need to clear the orderly state if it is + // set. + result = NvClearOrderly(); + } + } + return result; +} +/* 7.2.2.3 IsSigningObject() */ +/* Checks to see if the object is OK for signing. This is here rather than in Object_spt.c because + all the attestation commands use this file but not Object_spt.c. */ +/* Return Values Meaning */ +/* TRUE object may sign */ +/* FALSE object may not sign */ +BOOL +IsSigningObject( + OBJECT *object // IN: + ) +{ + return ((object == NULL) + || ((IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign) + && object->publicArea.type != TPM_ALG_SYMCIPHER))); +} + diff --git a/src/tpm2/Attest_spt_fp.h b/src/tpm2/Attest_spt_fp.h new file mode 100644 index 0000000..25add17 --- /dev/null +++ b/src/tpm2/Attest_spt_fp.h @@ -0,0 +1,92 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Attest_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef ATTEST_SPT_FP_H +#define ATTEST_SPT_FP_H + +void +FillInAttestInfo( + TPMI_DH_OBJECT signHandle, // IN: handle of signing object + TPMT_SIG_SCHEME *scheme, // IN/OUT: scheme to be used for signing + TPM2B_DATA *data, // IN: qualifying data + TPMS_ATTEST *attest // OUT: attest structure + ); +TPM_RC +SignAttestInfo( + OBJECT *signKey, // IN: sign object + TPMT_SIG_SCHEME *scheme, // IN: sign scheme + TPMS_ATTEST *certifyInfo, // IN: the data to be signed + TPM2B_DATA *qualifyingData, // IN: extra data for the signing + // process + TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be + // signed + TPMT_SIGNATURE *signature // OUT: signature + ); +BOOL +IsSigningObject( + OBJECT *object // IN: + ); + + + + + +#endif diff --git a/src/tpm2/AttestationCommands.c b/src/tpm2/AttestationCommands.c new file mode 100644 index 0000000..9df4315 --- /dev/null +++ b/src/tpm2/AttestationCommands.c @@ -0,0 +1,544 @@ +/********************************************************************************/ +/* */ +/* Attestation Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: AttestationCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "Certify_fp.h" +#if CC_Certify // Conditional expansion of this file +TPM_RC +TPM2_Certify( + Certify_In *in, // IN: input parameter list + Certify_Out *out // OUT: output parameter list + ) +{ + TPMS_ATTEST certifyInfo; + OBJECT *signObject = HandleToObject(in->signHandle); + OBJECT *certifiedObject = HandleToObject(in->objectHandle); + // Input validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_Certify_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_Certify_inScheme; + // Command Output + // Filling in attest information + // Common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, + &certifyInfo); + // Certify specific fields + certifyInfo.type = TPM_ST_ATTEST_CERTIFY; + // NOTE: the certified object is not allowed to be TPM_ALG_NULL so + // 'certifiedObject' will never be NULL + certifyInfo.attested.certify.name = certifiedObject->name; + + // When using an anonymous signing scheme, need to set the qualified Name to the + // empty buffer to avoid correlation between keys + if(CryptIsSchemeAnonymous(in->inScheme.scheme)) + certifyInfo.attested.certify.qualifiedName.t.size = 0; + else + certifyInfo.attested.certify.qualifiedName = certifiedObject->qualifiedName; + + // Sign attestation structure. A NULL signature will be returned if + // signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, + // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned + // by SignAttestInfo() + return SignAttestInfo(signObject, &in->inScheme, &certifyInfo, + &in->qualifyingData, &out->certifyInfo, &out->signature); +} +#endif // CC_Certify +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "CertifyCreation_fp.h" +#if CC_CertifyCreation // Conditional expansion of this file +TPM_RC +TPM2_CertifyCreation( + CertifyCreation_In *in, // IN: input parameter list + CertifyCreation_Out *out // OUT: output parameter list + ) +{ + TPMT_TK_CREATION ticket; + TPMS_ATTEST certifyInfo; + OBJECT *certified = HandleToObject(in->objectHandle); + OBJECT *signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_CertifyCreation_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_CertifyCreation_inScheme; + // CertifyCreation specific input validation + // Re-compute ticket + TicketComputeCreation(in->creationTicket.hierarchy, &certified->name, + &in->creationHash, &ticket); + // Compare ticket + if(!MemoryEqual2B(&ticket.digest.b, &in->creationTicket.digest.b)) + return TPM_RCS_TICKET + RC_CertifyCreation_creationTicket; + // Command Output + // Common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, + &certifyInfo); + // CertifyCreation specific fields + // Attestation type + certifyInfo.type = TPM_ST_ATTEST_CREATION; + certifyInfo.attested.creation.objectName = certified->name; + // Copy the creationHash + certifyInfo.attested.creation.creationHash = in->creationHash; + // Sign attestation structure. A NULL signature will be returned if + // signObject is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, + // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at + // this point + return SignAttestInfo(signObject, &in->inScheme, &certifyInfo, + &in->qualifyingData, &out->certifyInfo, + &out->signature); +} +#endif // CC_CertifyCreation +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "Quote_fp.h" +#if CC_Quote // Conditional expansion of this file +TPM_RC +TPM2_Quote( + Quote_In *in, // IN: input parameter list + Quote_Out *out // OUT: output parameter list + ) +{ + TPMI_ALG_HASH hashAlg; + TPMS_ATTEST quoted; + OBJECT *signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_Quote_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_Quote_inScheme; + // Command Output + // Filling in attest information + // Common fields + // FillInAttestInfo may return TPM_RC_SCHEME or TPM_RC_KEY + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, "ed); + // Quote specific fields + // Attestation type + quoted.type = TPM_ST_ATTEST_QUOTE; + // Get hash algorithm in sign scheme. This hash algorithm is used to + // compute PCR digest. If there is no algorithm, then the PCR cannot + // be digested and this command returns TPM_RC_SCHEME + hashAlg = in->inScheme.details.any.hashAlg; + if(hashAlg == TPM_ALG_NULL) + return TPM_RCS_SCHEME + RC_Quote_inScheme; + // Compute PCR digest + PCRComputeCurrentDigest(hashAlg, &in->PCRselect, + "ed.attested.quote.pcrDigest); + // Copy PCR select. "PCRselect" is modified in PCRComputeCurrentDigest + // function + quoted.attested.quote.pcrSelect = in->PCRselect; + // Sign attestation structure. A NULL signature will be returned if + // signObject is NULL. + return SignAttestInfo(signObject, &in->inScheme, "ed, &in->qualifyingData, + &out->quoted, &out->signature); +} +#endif // CC_Quote +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "GetSessionAuditDigest_fp.h" +#if CC_GetSessionAuditDigest // Conditional expansion of this file +TPM_RC +TPM2_GetSessionAuditDigest( + GetSessionAuditDigest_In *in, // IN: input parameter list + GetSessionAuditDigest_Out *out // OUT: output parameter list + ) +{ + SESSION *session = SessionGet(in->sessionHandle); + TPMS_ATTEST auditInfo; + OBJECT *signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_GetSessionAuditDigest_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_GetSessionAuditDigest_inScheme; + // session must be an audit session + if(session->attributes.isAudit == CLEAR) + return TPM_RCS_TYPE + RC_GetSessionAuditDigest_sessionHandle; + // Command Output + // Fill in attest information common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, + &auditInfo); + // SessionAuditDigest specific fields + auditInfo.type = TPM_ST_ATTEST_SESSION_AUDIT; + auditInfo.attested.sessionAudit.sessionDigest = session->u2.auditDigest; + // Exclusive audit session + auditInfo.attested.sessionAudit.exclusiveSession + = (g_exclusiveAuditSession == in->sessionHandle); + // Sign attestation structure. A NULL signature will be returned if + // signObject is NULL. + return SignAttestInfo(signObject, &in->inScheme, &auditInfo, + &in->qualifyingData, &out->auditInfo, + &out->signature); +} +#endif // CC_GetSessionAuditDigest +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "GetCommandAuditDigest_fp.h" +#if CC_GetCommandAuditDigest // Conditional expansion of this file +TPM_RC +TPM2_GetCommandAuditDigest( + GetCommandAuditDigest_In *in, // IN: input parameter list + GetCommandAuditDigest_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + TPMS_ATTEST auditInfo; + OBJECT *signObject = HandleToObject(in->signHandle); + // Input validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_GetCommandAuditDigest_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_GetCommandAuditDigest_inScheme; + // Command Output + // Fill in attest information common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, + &auditInfo); + // CommandAuditDigest specific fields + auditInfo.type = TPM_ST_ATTEST_COMMAND_AUDIT; + auditInfo.attested.commandAudit.digestAlg = gp.auditHashAlg; + auditInfo.attested.commandAudit.auditCounter = gp.auditCounter; + // Copy command audit log + auditInfo.attested.commandAudit.auditDigest = gr.commandAuditDigest; + CommandAuditGetDigest(&auditInfo.attested.commandAudit.commandDigest); + // Sign attestation structure. A NULL signature will be returned if + // signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, + // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at + // this point + result = SignAttestInfo(signObject, &in->inScheme, &auditInfo, + &in->qualifyingData, &out->auditInfo, + &out->signature); + // Internal Data Update + if(result == TPM_RC_SUCCESS && in->signHandle != TPM_RH_NULL) + // Reset log + gr.commandAuditDigest.t.size = 0; + return result; +} +#endif // CC_GetCommandAuditDigest +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "GetTime_fp.h" +#if CC_GetTime // Conditional expansion of this file +TPM_RC +TPM2_GetTime( + GetTime_In *in, // IN: input parameter list + GetTime_Out *out // OUT: output parameter list + ) +{ + TPMS_ATTEST timeInfo; + OBJECT *signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_GetTime_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_GetTime_inScheme; + // Command Output + // Fill in attest common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &timeInfo); + // GetClock specific fields + timeInfo.type = TPM_ST_ATTEST_TIME; + timeInfo.attested.time.time.time = g_time; + TimeFillInfo(&timeInfo.attested.time.time.clockInfo); + // Firmware version in plain text + timeInfo.attested.time.firmwareVersion + = (((UINT64)gp.firmwareV1) << 32) + gp.firmwareV2; + // Sign attestation structure. A NULL signature will be returned if + // signObject is NULL. + return SignAttestInfo(signObject, &in->inScheme, &timeInfo, &in->qualifyingData, + &out->timeInfo, &out->signature); +} +#endif // CC_GetTime +#include "Tpm.h" +#include "CertifyX509_fp.h" +#include "X509.h" +#include "TpmAsn1_fp.h" +#include "X509_spt_fp.h" +#include "Attest_spt_fp.h" +#include "Platform_fp.h" +#if CC_CertifyX509 // Conditional expansion of this file +#if CERTIFYX509_DEBUG +#include "DebugHelpers_fp.h" +#endif + +/* Error Returns Meaning*/ +/* TPM_RC_ATTRIBUTES the attributes of objectHandle are not compatible with the KeyUsage() or TPMA_OBJECT values in the extensions fields */ +/* TPM_RC_BINDING the public and private portions of the key are not properly bound. */ +/* TPM_RC_HASH the hash algorithm in the scheme is not supported */ +/* TPM_RC_KEY signHandle does not reference a signing key; */ +/* TPM_RC_SCHEME the scheme is not compatible with sign key type, or input scheme is not compatible with default scheme, or the chosen scheme is not a valid sign scheme */ + /* TPM_RC_VALUE most likely a problem with the format of partialCertificate */ +TPM_RC +TPM2_CertifyX509( + CertifyX509_In *in, // IN: input parameter list + CertifyX509_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *signKey = HandleToObject(in->signHandle); + OBJECT *object = HandleToObject(in->objectHandle); + HASH_STATE hash; + INT16 length; // length for a tagged element + ASN1UnmarshalContext ctx; + ASN1MarshalContext ctxOut; + // certTBS holds an array of pointers and lengths. Each entry references the + // corresponding value in a TBSCertificate structure. For example, the 1th + // element references the version number + stringRef certTBS[REF_COUNT] = {{0}}; +#define ALLOWED_SEQUENCES (SUBJECT_PUBLIC_KEY_REF - SIGNATURE_REF) + stringRef partial[ALLOWED_SEQUENCES] = {{0}}; + INT16 countOfSequences = 0; + INT16 i; + // +#if CERTIFYX509_DEBUG + DebugFileInit(); + DebugDumpBuffer(in->partialCertificate.t.size, in->partialCertificate.t.buffer, + "partialCertificate"); +#endif + + // Input Validation + if(in->reserved.b.size != 0) + return TPM_RC_SIZE + RC_CertifyX509_reserved; + // signing key must be able to sign + if(!IsSigningObject(signKey)) + return TPM_RCS_KEY + RC_CertifyX509_signHandle; + // Pick a scheme for sign. If the input sign scheme is not compatible with + // the default scheme, return an error. + if(!CryptSelectSignScheme(signKey, &in->inScheme)) + return TPM_RCS_SCHEME + RC_CertifyX509_inScheme; + // Make sure that the public Key encoding is known + if(X509AddPublicKey(NULL, object) == 0) + return TPM_RCS_ASYMMETRIC + RC_CertifyX509_objectHandle; + // Unbundle 'partialCertificate'. + // Initialize the unmarshaling context + if(!ASN1UnmarshalContextInitialize(&ctx, in->partialCertificate.t.size, + in->partialCertificate.t.buffer)) + return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; + // Make sure that this is a constructed SEQUENCE + length = ASN1NextTag(&ctx); + // Must be a constructed SEQUENCE that uses all of the input parameter + if((ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE)) + || ((ctx.offset + length) != in->partialCertificate.t.size)) + return TPM_RCS_SIZE + RC_CertifyX509_partialCertificate; + + // This scans through the contents of the outermost SEQUENCE. This would be the + // 'issuer', 'validity', 'subject', 'issuerUniqueID' (optional), + // 'subjectUniqueID' (optional), and 'extensions.' + while(ctx.offset < ctx.size) + { + INT16 startOfElement = ctx.offset; + // + // Read the next tag and length field. + length = ASN1NextTag(&ctx); + if(length < 0) + break; + if(ctx.tag == ASN1_CONSTRUCTED_SEQUENCE) + { + partial[countOfSequences].buf = &ctx.buffer[startOfElement]; + ctx.offset += length; + partial[countOfSequences].len = (INT16)ctx.offset - startOfElement; + if(++countOfSequences > ALLOWED_SEQUENCES) + break; + } + else if(ctx.tag == X509_EXTENSIONS) + { + if(certTBS[EXTENSIONS_REF].len != 0) + return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; + certTBS[EXTENSIONS_REF].buf = &ctx.buffer[startOfElement]; + ctx.offset += length; + certTBS[EXTENSIONS_REF].len = + (INT16)ctx.offset - startOfElement; + } + else + return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; + } + // Make sure that we used all of the data and found at least the required + // number of elements. + if((ctx.offset != ctx.size) || (countOfSequences < 3) + || (countOfSequences > 4) + || (certTBS[EXTENSIONS_REF].buf == NULL)) + return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; + // Now that we know how many sequences there were, we can put them where they + // belong + for(i = 0; i < countOfSequences; i++) + certTBS[SUBJECT_KEY_REF - i] = partial[countOfSequences - 1 - i]; + + // If only three SEQUENCES, then the TPM needs to produce the signature algorithm. + // See if it can + if((countOfSequences == 3) && + (X509AddSigningAlgorithm(NULL, signKey, &in->inScheme) == 0)) + return TPM_RCS_SCHEME + RC_CertifyX509_signHandle; + + // Process the extensions + result = X509ProcessExtensions(object, &certTBS[EXTENSIONS_REF]); + if(result != TPM_RC_SUCCESS) + // If the extension has the TPMA_OBJECT extension and the attributes don't + // match, then the error code will be TPM_RCS_ATTRIBUTES. Otherwise, the error + // indicates a malformed partialCertificate. + return result + ((result == TPM_RCS_ATTRIBUTES) + ? RC_CertifyX509_objectHandle + : RC_CertifyX509_partialCertificate); + // Command Output + // Create the addedToCertificate values + + // Build the addedToCertificate from the bottom up. + // Initialize the context structure + ASN1InitialializeMarshalContext(&ctxOut, sizeof(out->addedToCertificate.t.buffer), + out->addedToCertificate.t.buffer); + // Place a marker for the overall context + ASN1StartMarshalContext(&ctxOut); // SEQUENCE for addedToCertificate + + // Add the subject public key descriptor + certTBS[SUBJECT_PUBLIC_KEY_REF].len = X509AddPublicKey(&ctxOut, object); + certTBS[SUBJECT_PUBLIC_KEY_REF].buf = ctxOut.buffer + ctxOut.offset; + // If the caller didn't provide the algorithm identifier, create it + if(certTBS[SIGNATURE_REF].len == 0) + { + certTBS[SIGNATURE_REF].len = X509AddSigningAlgorithm(&ctxOut, signKey, + &in->inScheme); + certTBS[SIGNATURE_REF].buf = ctxOut.buffer + ctxOut.offset; + } + // Create the serial number value. Use the out->tbsDigest as scratch. + { + TPM2B *digest = &out->tbsDigest.b; + // + digest->size = (INT16)CryptHashStart(&hash, signKey->publicArea.nameAlg); + pAssert(digest->size != 0); + + // The serial number size is the smaller of the digest and the vendor-defined + // value + digest->size = MIN(digest->size, SIZE_OF_X509_SERIAL_NUMBER); + // Add all the parts of the certificate other than the serial number + // and version number + for(i = SIGNATURE_REF; i < REF_COUNT; i++) + CryptDigestUpdate(&hash, certTBS[i].len, certTBS[i].buf); + // throw in the Name of the signing key... + CryptDigestUpdate2B(&hash, &signKey->name.b); + // ...and the Name of the signed key. + CryptDigestUpdate2B(&hash, &object->name.b); + // Done + CryptHashEnd2B(&hash, digest); + } + + // Add the serial number + certTBS[SERIAL_NUMBER_REF].len = + ASN1PushInteger(&ctxOut, out->tbsDigest.t.size, out->tbsDigest.t.buffer); + certTBS[SERIAL_NUMBER_REF].buf = ctxOut.buffer + ctxOut.offset; + + // Add the static version number + ASN1StartMarshalContext(&ctxOut); + ASN1PushUINT(&ctxOut, 2); + certTBS[VERSION_REF].len = + ASN1EndEncapsulation(&ctxOut, ASN1_APPLICAIION_SPECIFIC); + certTBS[VERSION_REF].buf = ctxOut.buffer + ctxOut.offset; + + // Create a fake tag and length for the TBS in the space used for + // 'addedToCertificate' + { + for(length = 0, i = 0; i < REF_COUNT; i++) + length += certTBS[i].len; + // Put a fake tag and length into the buffer for use in the tbsDigest + certTBS[ENCODED_SIZE_REF].len = + ASN1PushTagAndLength(&ctxOut, ASN1_CONSTRUCTED_SEQUENCE, length); + certTBS[ENCODED_SIZE_REF].buf = ctxOut.buffer + ctxOut.offset; + // Restore the buffer pointer to add back the number of octets used for the + // tag and length + ctxOut.offset += certTBS[ENCODED_SIZE_REF].len; + } + // sanity check + if(ctxOut.offset < 0) + return TPM_RC_FAILURE; + // Create the tbsDigest to sign + out->tbsDigest.t.size = CryptHashStart(&hash, in->inScheme.details.any.hashAlg); + for(i = 0; i < REF_COUNT; i++) + CryptDigestUpdate(&hash, certTBS[i].len, certTBS[i].buf); + CryptHashEnd2B(&hash, &out->tbsDigest.b); + +#if CERTIFYX509_DEBUG + { + BYTE fullTBS[4096]; + BYTE *fill = fullTBS; + int j; + for (j = 0; j < REF_COUNT; j++) + { + MemoryCopy(fill, certTBS[j].buf, certTBS[j].len); + fill += certTBS[j].len; + } + DebugDumpBuffer((int)(fill - &fullTBS[0]), fullTBS, "\nfull TBS"); + } +#endif + + // Finish up the processing of addedToCertificate + // Create the actual tag and length for the addedToCertificate structure + out->addedToCertificate.t.size = + ASN1EndEncapsulation(&ctxOut, ASN1_CONSTRUCTED_SEQUENCE); + // Now move all the addedToContext to the start of the buffer + MemoryCopy(out->addedToCertificate.t.buffer, ctxOut.buffer + ctxOut.offset, + out->addedToCertificate.t.size); +#if CERTIFYX509_DEBUG + DebugDumpBuffer(out->addedToCertificate.t.size, out->addedToCertificate.t.buffer, + "\naddedToCertificate"); +#endif + // only thing missing is the signature + result = CryptSign(signKey, &in->inScheme, &out->tbsDigest, &out->signature); + + return result; +} +#endif // CC_CertifyX509 diff --git a/src/tpm2/AuditCommands.c b/src/tpm2/AuditCommands.c new file mode 100644 index 0000000..60960bb --- /dev/null +++ b/src/tpm2/AuditCommands.c @@ -0,0 +1,112 @@ +/********************************************************************************/ +/* */ +/* Command Audit */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: AuditCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "SetCommandCodeAuditStatus_fp.h" +#if CC_SetCommandCodeAuditStatus // Conditional expansion of this file +TPM_RC +TPM2_SetCommandCodeAuditStatus( + SetCommandCodeAuditStatus_In *in // IN: input parameter list + ) +{ + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Internal Data Update + // Update hash algorithm + if(in->auditAlg != TPM_ALG_NULL && in->auditAlg != gp.auditHashAlg) + { + // Can't change the algorithm and command list at the same time + if(in->setList.count != 0 || in->clearList.count != 0) + return TPM_RCS_VALUE + RC_SetCommandCodeAuditStatus_auditAlg; + // Change the hash algorithm for audit + gp.auditHashAlg = in->auditAlg; + // Set the digest size to a unique value that indicates that the digest + // algorithm has been changed. The size will be cleared to zero in the + // command audit processing on exit. + gr.commandAuditDigest.t.size = 1; + // Save the change of command audit data (this sets g_updateNV so that NV + // will be updated on exit.) + NV_SYNC_PERSISTENT(auditHashAlg); + } + else + { + UINT32 i; + BOOL changed = FALSE; + // Process set list + for(i = 0; i < in->setList.count; i++) + // If change is made in CommandAuditSet, set changed flag + if(CommandAuditSet(in->setList.commandCodes[i])) + changed = TRUE; + // Process clear list + for(i = 0; i < in->clearList.count; i++) + // If change is made in CommandAuditClear, set changed flag + if(CommandAuditClear(in->clearList.commandCodes[i])) + changed = TRUE; + // if change was made to command list, update NV + if(changed) + // this sets g_updateNV so that NV will be updated on exit. + NV_SYNC_PERSISTENT(auditCommands); + } + return TPM_RC_SUCCESS; +} +#endif // CC_SetCommandCodeAuditStatus diff --git a/src/tpm2/BackwardsCompatibility.h b/src/tpm2/BackwardsCompatibility.h new file mode 100644 index 0000000..6d33b60 --- /dev/null +++ b/src/tpm2/BackwardsCompatibility.h @@ -0,0 +1,49 @@ +/********************************************************************************/ +/* */ +/* Backwards compatibility related stuff */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef BACKWARDS_COMPATIBILITY_H +#define BACKWARDS_COMPATIBILITY_H + +typedef UINT8 SEED_COMPAT_LEVEL; +enum { + SEED_COMPAT_LEVEL_ORIGINAL = 0, /* original TPM 2 code up to rev155 */ + SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX = 1, /* RsaAdjustPrimeCandidate was fixed */ + SEED_COMPAT_LEVEL_LAST = SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX +}; + +#endif /* BACKWARDS_COMPATIBILITY_H */ diff --git a/src/tpm2/BackwardsCompatibilityObject.c b/src/tpm2/BackwardsCompatibilityObject.c new file mode 100644 index 0000000..93e5710 --- /dev/null +++ b/src/tpm2/BackwardsCompatibilityObject.c @@ -0,0 +1,238 @@ +/********************************************************************************/ +/* */ +/* Backwards compatibility stuff related to OBJECT */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#include "BackwardsCompatibilityObject.h" + +#ifndef static_assert +#define static_assert(test, msg) +#endif + +/* The following are data structure from libtpms 0.7.x with RSA 2048 support + * that help to resume key and hash contexts (TPM2_ContextSave/Load) from this + * earlier version. All structures that have different sizes in 0.8 are found + * here. + */ +typedef union { + struct { + UINT16 size; + BYTE buffer[2048/8]; + } t; + TPM2B b; +} OLD_TPM2B_PUBLIC_KEY_RSA; + +typedef union { + TPM2B_DIGEST keyedHash; + TPM2B_DIGEST sym; + OLD_TPM2B_PUBLIC_KEY_RSA rsa; + TPMS_ECC_POINT ecc; +// TPMS_DERIVE derive; +} OLD_TPMU_PUBLIC_ID; + +typedef struct { + TPMI_ALG_PUBLIC type; + TPMI_ALG_HASH nameAlg; + TPMA_OBJECT objectAttributes; + TPM2B_DIGEST authPolicy; + TPMU_PUBLIC_PARMS parameters; + OLD_TPMU_PUBLIC_ID unique; +} OLD_TPMT_PUBLIC; + +static_assert(sizeof(OLD_TPMT_PUBLIC) == 356, + "OLD_TPMT_PUBLIC has wrong size"); + +typedef union { + struct { + UINT16 size; + BYTE buffer[((2048/8)/2)*5]; + } t; + TPM2B b; +} OLD_TPM2B_PRIVATE_KEY_RSA; + +static_assert(sizeof(OLD_TPM2B_PRIVATE_KEY_RSA) == 642, + "OLD_TPM2B_PRIVATE_KEY_RSA has wrong size"); + +typedef union { + struct { + UINT16 size; + BYTE buffer[((2048/8)/2)*5]; + } t; + TPM2B b; +} OLD_TPM2B_PRIVATE_VENDOR_SPECIFIC; + +typedef union { + OLD_TPM2B_PRIVATE_KEY_RSA rsa; + TPM2B_ECC_PARAMETER ecc; + TPM2B_SENSITIVE_DATA bits; + TPM2B_SYM_KEY sym; + OLD_TPM2B_PRIVATE_VENDOR_SPECIFIC any; +} OLD_TPMU_SENSITIVE_COMPOSITE; + +typedef struct { + TPMI_ALG_PUBLIC sensitiveType; + TPM2B_AUTH authValue; + TPM2B_DIGEST seedValue; + OLD_TPMU_SENSITIVE_COMPOSITE sensitive; +} OLD_TPMT_SENSITIVE; + +static_assert(sizeof(OLD_TPMT_SENSITIVE) == 776, + "OLD_TPMT_SENSITIVE has wrong size"); + +BN_TYPE(old_prime, (2048 / 2)); + +typedef struct OLD_privateExponent +{ + bn_old_prime_t Q; + bn_old_prime_t dP; + bn_old_prime_t dQ; + bn_old_prime_t qInv; +} OLD_privateExponent_t; + +static inline void CopyFromOldPrimeT(bn_prime_t *dst, + const bn_old_prime_t *src) +{ + dst->allocated = src->allocated; + dst->size = src->size; + memcpy(dst->d, src->d, sizeof(src->d)); +} + +static_assert(sizeof(OLD_privateExponent_t) == 608, + "OLD_privateExponent_t has wrong size"); + +typedef struct OLD_OBJECT +{ + // The attributes field is required to be first followed by the publicArea. + // This allows the overlay of the object structure and a sequence structure + OBJECT_ATTRIBUTES attributes; // object attributes + OLD_TPMT_PUBLIC publicArea; // public area of an object + OLD_TPMT_SENSITIVE sensitive; // sensitive area of an object + OLD_privateExponent_t privateExponent; // Additional field for the private + TPM2B_NAME qualifiedName; // object qualified name + TPMI_DH_OBJECT evictHandle; // if the object is an evict object, + // the original handle is kept here. + // The 'working' handle will be the + // handle of an object slot. + TPM2B_NAME name; // Name of the object name. Kept here + // to avoid repeatedly computing it. + + // libtpms added: OBJECT lies in NVRAM; to avoid that it needs different number + // of bytes on 32 bit and 64 bit architectures, we need to make sure it's the + // same size; simple padding at the end works here + UINT32 _pad; +} OLD_OBJECT; + +static_assert(sizeof(OLD_OBJECT) == 1896, + "OLD_OBJECT has wrong size"); + +// Convert an OLD_OBJECT that was copied into buffer using MemoryCopy +TPM_RC +OLD_OBJECTToOBJECT(OBJECT *newObject, BYTE *buffer, INT32 size) +{ + OLD_OBJECT oldObject; + TPM_RC rc = 0; + + // get the attributes + MemoryCopy(newObject, buffer, sizeof(newObject->attributes)); + if (ObjectIsSequence(newObject)) + { + /* resuming old hash contexts is not supported */ + rc = TPM_RC_DISABLED; + } + else + { + if (size != sizeof(OLD_OBJECT)) + return TPM_RC_SIZE; + MemoryCopy(&oldObject, buffer, sizeof(OLD_OBJECT)); + + /* fill the newObject with the contents of the oldObject */ + newObject->attributes = oldObject.attributes; + + newObject->publicArea.type = oldObject.publicArea.type; + newObject->publicArea.nameAlg = oldObject.publicArea.nameAlg; + newObject->publicArea.objectAttributes = oldObject.publicArea.objectAttributes; + newObject->publicArea.authPolicy = oldObject.publicArea.authPolicy; + newObject->publicArea.parameters = oldObject.publicArea.parameters; + /* the unique part can be one or two TPM2B's */ + switch (newObject->publicArea.type) { + case TPM_ALG_KEYEDHASH: + MemoryCopy2B(&newObject->publicArea.unique.keyedHash.b, + &oldObject.publicArea.unique.keyedHash.b, + sizeof(oldObject.publicArea.unique.keyedHash.t.buffer)); + break; + case TPM_ALG_SYMCIPHER: + MemoryCopy2B(&newObject->publicArea.unique.sym.b, + &oldObject.publicArea.unique.sym.b, + sizeof(oldObject.publicArea.unique.sym.t.buffer)); + break; + case TPM_ALG_RSA: + MemoryCopy2B(&newObject->publicArea.unique.rsa.b, + &oldObject.publicArea.unique.rsa.b, + sizeof(oldObject.publicArea.unique.rsa.t.buffer)); + break; + case TPM_ALG_ECC: + MemoryCopy2B(&newObject->publicArea.unique.ecc.x.b, + &oldObject.publicArea.unique.ecc.x.b, + sizeof(oldObject.publicArea.unique.ecc.x.t.buffer)); + MemoryCopy2B(&newObject->publicArea.unique.ecc.y.b, + &oldObject.publicArea.unique.ecc.y.b, + sizeof(oldObject.publicArea.unique.ecc.y.t.buffer)); + break; + } + + newObject->sensitive.sensitiveType = oldObject.sensitive.sensitiveType; + newObject->sensitive.authValue = oldObject.sensitive.authValue; + newObject->sensitive.seedValue = oldObject.sensitive.seedValue; + /* The OLD_TPMU_SENSITIVE_COMPOSITE is always a TPM2B */ + MemoryCopy2B(&newObject->sensitive.sensitive.any.b, + &oldObject.sensitive.sensitive.any.b, + sizeof(oldObject.sensitive.sensitive.any.t.buffer)); + + CopyFromOldPrimeT(&newObject->privateExponent.Q, &oldObject.privateExponent.Q); + CopyFromOldPrimeT(&newObject->privateExponent.dP, &oldObject.privateExponent.dP); + CopyFromOldPrimeT(&newObject->privateExponent.dQ, &oldObject.privateExponent.dQ); + CopyFromOldPrimeT(&newObject->privateExponent.qInv, &oldObject.privateExponent.qInv); + + newObject->qualifiedName = oldObject.qualifiedName; + newObject->evictHandle = oldObject.evictHandle; + newObject->name = oldObject.name; + } + + return rc; +} + diff --git a/src/tpm2/BackwardsCompatibilityObject.h b/src/tpm2/BackwardsCompatibilityObject.h new file mode 100644 index 0000000..7a2b1ab --- /dev/null +++ b/src/tpm2/BackwardsCompatibilityObject.h @@ -0,0 +1,47 @@ +/********************************************************************************/ +/* */ +/* Backwards compatibility stuff related to OBJECT */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef BACKWARDS_COMPATIBILITY_OBJECT_H +#define BACKWARDS_COMPATIBILITY_OBJECT_H + +#include "Tpm.h" + +TPM_RC OLD_OBJECTToOBJECT(OBJECT *object, BYTE *buffer, INT32 size); + +#endif /* BACKWARDS_COMPATIBILITY_OBJECT_H */ + diff --git a/src/tpm2/BaseTypes.h b/src/tpm2/BaseTypes.h new file mode 100644 index 0000000..b134b22 --- /dev/null +++ b/src/tpm2/BaseTypes.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* Basic Typedefs */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: BaseTypes.h 1531 2019-11-21 23:54:38Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 5.2 BaseTypes.h */ + +#ifndef BASETYPES_H +#define BASETYPES_H + +#include + +/* NULL definition */ + +#ifndef NULL +#define NULL (0) +#endif +typedef uint8_t UINT8; +typedef uint8_t BYTE; +typedef int8_t INT8; +typedef int BOOL; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint64_t UINT64; +typedef int64_t INT64; + +#endif diff --git a/src/tpm2/Bits.c b/src/tpm2/Bits.c new file mode 100644 index 0000000..5fb4785 --- /dev/null +++ b/src/tpm2/Bits.c @@ -0,0 +1,114 @@ +/********************************************************************************/ +/* */ +/* Bit Manipulation Routines */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Bits.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +/* 9.2 Bits.c */ +/* 9.2.1 Introduction */ +/* This file contains bit manipulation routines. They operate on bit arrays. */ +/* The 0th bit in the array is the right-most bit in the 0th octet in the array. */ +/* NOTE: If pAssert() is defined, the functions will assert if the indicated bit number is outside + of the range of bArray. How the assert is handled is implementation dependent. */ +/* 9.2.2 Includes */ +#include "Tpm.h" +/* 9.2.3 Functions */ +/* 9.2.3.1 TestBit() */ +/* This function is used to check the setting of a bit in an array of bits. */ +/* Return Values Meaning */ +/* TRUE bit is set */ +/* FALSE bit is not set */ + +BOOL +TestBit( + unsigned int bitNum, // IN: number of the bit in 'bArray' + BYTE *bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' + ) +{ + pAssert(bytesInArray > (bitNum >> 3)); + return((bArray[bitNum >> 3] & (1 << (bitNum & 7))) != 0); +} + +/* 9.2.3.2 SetBit() */ +/* This function will set the indicated bit in bArray. */ + +void +SetBit( + unsigned int bitNum, // IN: number of the bit in 'bArray' + BYTE *bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' + ) +{ + pAssert(bytesInArray > (bitNum >> 3)); + bArray[bitNum >> 3] |= (1 << (bitNum & 7)); +} + +/* 9.2.3.3 ClearBit() */ +/* This function will clear the indicated bit in bArray. */ + +void +ClearBit( + unsigned int bitNum, // IN: number of the bit in 'bArray'. + BYTE *bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' + ) +{ + pAssert(bytesInArray > (bitNum >> 3)); + bArray[bitNum >> 3] &= ~(1 << (bitNum & 7)); +} diff --git a/src/tpm2/Bits_fp.h b/src/tpm2/Bits_fp.h new file mode 100644 index 0000000..c4775cd --- /dev/null +++ b/src/tpm2/Bits_fp.h @@ -0,0 +1,98 @@ +/********************************************************************************/ +/* */ +/* Bit Handling */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Bits_fp.h 803 2016-11-15 20:19:26Z kgoldman */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#ifndef BITS_FP_H +#define BITS_FP_H + +/* 5.3.1 TestBit() */ +/* This function is used to check the setting of a bit in an array of bits. */ +/* Return Value Meaning */ +/* TRUE bit is set */ +/* FALSE bit is not set */ + +BOOL +TestBit( + unsigned int bitNum, // IN: number of the bit in 'bArray' + BYTE *bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' + ); + +/* 5.3.2 SetBit() */ +/* This function will set the indicated bit in bArray. */ + +void +SetBit( + unsigned int bitNum, // IN: number of the bit in 'bArray' + BYTE *bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' + ); + +/* 5.3.3 ClearBit() */ +/* This function will clear the indicated bit in bArray. */ + +void +ClearBit( + unsigned int bitNum, // IN: number of the bit in 'bArray'. + BYTE *bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' + ); + +#endif diff --git a/src/tpm2/BnConvert.c b/src/tpm2/BnConvert.c new file mode 100644 index 0000000..49cd6d5 --- /dev/null +++ b/src/tpm2/BnConvert.c @@ -0,0 +1,299 @@ +/********************************************************************************/ +/* */ +/* conversion functions that will convert TPM2B to/from internal format */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: BnConvert.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 10.2.2 BnConvert.c */ +/* 10.2.2.1 Introduction */ +/* This file contains the basic conversion functions that will convert TPM2B to/from the internal + format. The internal format is a bigNum, */ +/* 10.2.2.2 Includes */ +#include "Tpm.h" +/* 10.2.2.3 Functions */ +/* 10.2.2.3.1 BnFromBytes() */ +/* This function will convert a big-endian byte array to the internal number format. If bn is NULL, + then the output is NULL. If bytes is null or the required size is 0, then the output is set to + zero */ +LIB_EXPORT bigNum +BnFromBytes( + bigNum bn, + const BYTE *bytes, + NUMBYTES nBytes + ) +{ + const BYTE *pFrom; // 'p' points to the least significant bytes of source + BYTE *pTo; // points to least significant bytes of destination + crypt_uword_t size; + // + size = (bytes != NULL) ? BYTES_TO_CRYPT_WORDS(nBytes) : 0; + // If nothing in, nothing out + if(bn == NULL) + return NULL; + // make sure things fit + pAssert(BnGetAllocated(bn) >= size); + if(size > 0) + { + // Clear the topmost word in case it is not filled with data + bn->d[size - 1] = 0; + // Moving the input bytes from the end of the list (LSB) end + pFrom = bytes + nBytes - 1; + // To the LS0 of the LSW of the bigNum. + pTo = (BYTE *)bn->d; + for(; nBytes != 0; nBytes--) + *pTo++ = *pFrom--; + // For a little-endian machine, the conversion is a straight byte + // reversal. For a big-endian machine, we have to put the words in + // big-endian byte order +#if BIG_ENDIAN_TPM + { + crypt_word_t t; + for(t = (crypt_word_t)size - 1; t >= 0; t--) + bn->d[t] = SWAP_CRYPT_WORD(bn->d[t]); + } +#endif + } + BnSetTop(bn, size); + return bn; +} +/* 10.2.2.3.2 BnFrom2B() */ +/* Convert an TPM2B to a BIG_NUM. If the input value does not exist, or the output does not exist, + or the input will not fit into the output the function returns NULL */ +LIB_EXPORT bigNum +BnFrom2B( + bigNum bn, // OUT: + const TPM2B *a2B // IN: number to convert + ) +{ + if(a2B != NULL) + return BnFromBytes(bn, a2B->buffer, a2B->size); + // Make sure that the number has an initialized value rather than whatever + // was there before + BnSetTop(bn, 0); // Function accepts NULL + return NULL; +} +/* 10.2.2.3.3 BnFromHex() */ +/* Convert a hex string into a bigNum. This is primarily used in debugging. */ +#ifdef _SM2_SIGN_DEBUG // libtpms added +LIB_EXPORT bigNum +BnFromHex( + bigNum bn, // OUT: + const char *hex // IN: + ) +{ +#define FromHex(a) ((a) - (((a) > 'a') ? ('a' + 10) \ + : ((a) > 'A') ? ('A' - 10) : '0')) + unsigned i; + unsigned wordCount; + const char *p; + BYTE *d = (BYTE *)&(bn->d[0]); + // + pAssert(bn && hex); + i = (unsigned)strlen(hex); + wordCount = BYTES_TO_CRYPT_WORDS((i + 1) / 2); + if((i == 0) || (wordCount >= BnGetAllocated(bn))) + BnSetWord(bn, 0); + else + { + bn->d[wordCount - 1] = 0; + p = hex + i - 1; + for(;i > 1; i -= 2) + { + BYTE a; + a = FromHex(*p); + p--; + *d++ = a + (FromHex(*p) << 4); + p--; + } + if(i == 1) + *d = FromHex(*p); + } +#if !BIG_ENDIAN_TPM + for(i = 0; i < wordCount; i++) + bn->d[i] = SWAP_CRYPT_WORD(bn->d[i]); +#endif // BIG_ENDIAN_TPM + BnSetTop(bn, wordCount); + return bn; +} +#endif // libtpms added +/* 10.2.2.3.4 BnToBytes() */ +/* This function converts a BIG_NUM to a byte array. It converts the bigNum to a big-endian byte + string and sets size to the normalized value. If size is an input 0, then the receiving buffer is + guaranteed to be large enough for the result and the size will be set to the size required for + bigNum (leading zeros suppressed). */ +/* The conversion for a little-endian machine simply requires that all significant bytes of the + bigNum be reversed. For a big-endian machine, rather than unpack each word individually, + the bigNum is converted to little-endian words, copied, and then converted back to big-endian. */ +LIB_EXPORT BOOL +BnToBytes( + bigConst bn, + BYTE *buffer, + NUMBYTES *size // This the number of bytes that are + // available in the buffer. The result + // should be this big. + ) +{ + crypt_uword_t requiredSize; + BYTE *pFrom; + BYTE *pTo; + crypt_uword_t count; + // + // validate inputs + pAssert(bn && buffer && size); + requiredSize = (BnSizeInBits(bn) + 7) / 8; + if(requiredSize == 0) + { + // If the input value is 0, return a byte of zero + *size = 1; + *buffer = 0; + } + else + { +#if BIG_ENDIAN_TPM + // Copy the constant input value into a modifiable value + BN_VAR(bnL, LARGEST_NUMBER_BITS * 2); + BnCopy(bnL, bn); + // byte swap the words in the local value to make them little-endian + for(count = 0; count < bnL->size; count++) + bnL->d[count] = SWAP_CRYPT_WORD(bnL->d[count]); + bn = (bigConst)bnL; +#endif + if(*size == 0) + *size = (NUMBYTES)requiredSize; + pAssert(requiredSize <= *size); + // Byte swap the number (not words but the whole value) + count = *size; + // Start from the least significant word and offset to the most significant + // byte which is in some high word + pFrom = (BYTE *)(&bn->d[0]) + requiredSize - 1; + pTo = buffer; + // If the number of output bytes is larger than the number bytes required + // for the input number, pad with zeros + for(count = *size; count > requiredSize; count--) + *pTo++ = 0; + // Move the most significant byte at the end of the BigNum to the next most + // significant byte position of the 2B and repeat for all significant bytes. + for(; requiredSize > 0; requiredSize--) + *pTo++ = *pFrom--; + } + return TRUE; +} +/* 10.2.2.3.5 BnTo2B() */ +/* Function to convert a BIG_NUM to TPM2B. The TPM2B size is set to the requested size which may + require padding. If size is non-zero and less than required by the value in bn then an error is + returned. If size is zero, then the TPM2B is assumed to be large enough for the data and + a2b->size will be adjusted accordingly. */ +LIB_EXPORT BOOL +BnTo2B( + bigConst bn, // IN: + TPM2B *a2B, // OUT: + NUMBYTES size // IN: the desired size + ) +{ + // Set the output size + if(bn && a2B) + { + a2B->size = size; + return BnToBytes(bn, a2B->buffer, &a2B->size); + } + return FALSE; +} +#if ALG_ECC +/* 10.2.2.3.6 BnPointFrom2B() */ +/* Function to create a BIG_POINT structure from a 2B point. A point is going to be two ECC values + in the same buffer. The values are going to be the size of the modulus. They are in modular + form. */ +LIB_EXPORT bn_point_t * +BnPointFrom2B( + bigPoint ecP, // OUT: the preallocated point structure + TPMS_ECC_POINT *p // IN: the number to convert + ) +{ + if(p == NULL) + return NULL; + if(NULL != ecP) + { + BnFrom2B(ecP->x, &p->x.b); + BnFrom2B(ecP->y, &p->y.b); + BnSetWord(ecP->z, 1); + } + return ecP; +} +/* 10.2.2.3.7 BnPointTo2B() */ +/* This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT contains two + TPM2B_ECC_PARAMETER values. The maximum size of the parameters is dependent on the maximum EC key + size used in an implementation. The presumption is that the TPMS_ECC_POINT is large enough to + hold 2 TPM2B values, each as large as a MAX_ECC_PARAMETER_BYTES */ +LIB_EXPORT BOOL +BnPointTo2B( + TPMS_ECC_POINT *p, // OUT: the converted 2B structure + bigPoint ecP, // IN: the values to be converted + bigCurve E // IN: curve descriptor for the point + ) +{ + UINT16 size; + // + pAssert(p && ecP && E); + pAssert(BnEqualWord(ecP->z, 1)); + // BnMsb is the bit number of the MSB. This is one less than the number of bits + size = (UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(AccessCurveData(E)))); + BnTo2B(ecP->x, &p->x.b, size); + BnTo2B(ecP->y, &p->y.b, size); + return TRUE; +} +#endif // TPM_ALG_ECC diff --git a/src/tpm2/BnMath.c b/src/tpm2/BnMath.c new file mode 100644 index 0000000..0154fb5 --- /dev/null +++ b/src/tpm2/BnMath.c @@ -0,0 +1,651 @@ +/********************************************************************************/ +/* */ +/* Simple Operations on Big Numbers */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: BnMath.c 1529 2019-11-21 23:29:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 10.2.3 BnMath.c */ + +/* 10.2.3.1 Introduction */ +/* The simulator code uses the canonical form whenever possible in order to make the code in Part 3 + more accessible. The canonical data formats are simple and not well suited for complex big number + computations. When operating on big numbers, the data format is changed for easier + manipulation. The format is native words in little-endian format. As the magnitude of the number + decreases, the length of the array containing the number decreases but the starting address + doesn't change. */ +/* The functions in this file perform simple operations on these big numbers. Only the more complex + operations are passed to the underlying support library. Although the support library would have + most of these functions, the interface code to convert the format for the values is greater than + the size of the code to implement the functions here. So, rather than incur the overhead of + conversion, they are done here. */ +/* If an implementer would prefer, the underlying library can be used simply by making code + substitutions here. */ +/* NOTE: There is an intention to continue to augment these functions so that there would be no need + to use an external big number library. */ +/* Many of these functions have no error returns and will always return TRUE. This is to allow them + to be used in guarded sequences. That is: OK = OK || BnSomething(s); where the BnSomething() + function should not be called if OK isn't true. */ + +/* 10.2.3.2 Includes */ +#include "Tpm.h" +/* A constant value of zero as a stand in for NULL bigNum values */ +const bignum_t BnConstZero = {1, 0, {0}}; +/* 10.2.3.3 Functions */ +/* 10.2.3.3.1 AddSame() */ +/* Adds two values that are the same size. This function allows result to be the same as either of + the addends. This is a nice function to put into assembly because handling the carry for + multi-precision stuff is not as easy in C (unless there is a REALLY smart compiler). It would be + nice if there were idioms in a language that a compiler could recognize what is going on and + optimize loops like this. */ +/* Return Values Meaning */ +/* 0 no carry out */ +/* 1 carry out */ +static BOOL +AddSame( + crypt_uword_t *result, + const crypt_uword_t *op1, + const crypt_uword_t *op2, + int count + ) +{ + int carry = 0; + int i; + for(i = 0; i < count; i++) + { + crypt_uword_t a = op1[i]; + crypt_uword_t sum = a + op2[i]; + result[i] = sum + carry; + // generate a carry if the sum is less than either of the inputs + // propagate a carry if there was a carry and the sum + carry is zero + // do this using bit operations rather than logical operations so that + // the time is about the same. + // propagate term | generate term + carry = ((result[i] == 0) & carry) | (sum < a); + } + return carry; +} +/* 10.2.3.3.2 CarryProp() */ +/* Propagate a carry */ +static int +CarryProp( + crypt_uword_t *result, + const crypt_uword_t *op, + int count, + int carry + ) +{ + for(; count; count--) + carry = ((*result++ = *op++ + carry) == 0) & carry; + return carry; +} +static void +CarryResolve( + bigNum result, + int stop, + int carry + ) +{ + if(carry) + { + pAssert((unsigned)stop < result->allocated); + result->d[stop++] = 1; + } + BnSetTop(result, stop); +} +/* 10.2.3.3.3 BnAdd() */ +/* This function adds two bigNum values. Always returns TRUE */ +LIB_EXPORT BOOL +BnAdd( + bigNum result, + bigConst op1, + bigConst op2 + ) +{ + crypt_uword_t stop; + int carry; + const bignum_t *n1 = op1; + const bignum_t *n2 = op2; + // + if(n2->size > n1->size) + { + n1 = op2; + n2 = op1; + } + pAssert(result->allocated >= n1->size); + stop = MIN(n1->size, n2->allocated); + carry = (int)AddSame(result->d, n1->d, n2->d, (int)stop); + if(n1->size > stop) + carry = CarryProp(&result->d[stop], &n1->d[stop], (int)(n1->size - stop), carry); + CarryResolve(result, (int)n1->size, carry); + return TRUE; +} +/* 10.2.3.3.4 BnAddWord() */ +/* Adds a word value to a bigNum. */ +LIB_EXPORT BOOL +BnAddWord( + bigNum result, + bigConst op, + crypt_uword_t word + ) +{ + int carry; + // + carry = (result->d[0] = op->d[0] + word) < word; + carry = CarryProp(&result->d[1], &op->d[1], (int)(op->size - 1), carry); + CarryResolve(result, (int)op->size, carry); + return TRUE; +} +/* 10.2.3.3.5 SubSame() */ +/* Subtract two values that have the same size. */ +static int +SubSame( + crypt_uword_t *result, + const crypt_uword_t *op1, + const crypt_uword_t *op2, + int count + ) +{ + int borrow = 0; + int i; + for(i = 0; i < count; i++) + { + crypt_uword_t a = op1[i]; + crypt_uword_t diff = a - op2[i]; + result[i] = diff - borrow; + // generate | propagate + borrow = (diff > a) | ((diff == 0) & borrow); + } + return borrow; +} +/* 10.2.3.3.6 BorrowProp() */ +/* This propagates a borrow. If borrow is true when the end of the array is reached, then it means + that op2 was larger than op1 and we don't handle that case so an assert is generated. This design + choice was made because our only bigNum computations are on large positive numbers (primes) or on + fields. Propagate a borrow. */ +static int +BorrowProp( + crypt_uword_t *result, + const crypt_uword_t *op, + int size, + int borrow + ) +{ + for(; size > 0; size--) + borrow = ((*result++ = *op++ - borrow) == MAX_CRYPT_UWORD) && borrow; + return borrow; +} +/* 10.2.3.3.7 BnSub() */ +/* This function does subtraction of two bigNum values and returns result = op1 - op2 when op1 is + greater than op2. If op2 is greater than op1, then a fault is generated. This function always + returns TRUE. */ + +LIB_EXPORT BOOL +BnSub( + bigNum result, + bigConst op1, + bigConst op2 + ) +{ + int borrow; + int stop = (int)MIN(op1->size, op2->allocated); + // + // Make sure that op2 is not obviously larger than op1 + pAssert(op1->size >= op2->size); + borrow = SubSame(result->d, op1->d, op2->d, stop); + if(op1->size > (crypt_uword_t)stop) + borrow = BorrowProp(&result->d[stop], &op1->d[stop], (int)(op1->size - stop), + borrow); + pAssert(!borrow); + BnSetTop(result, op1->size); + return TRUE; +} +/* 10.2.3.3.8 BnSubWord() */ +/* This function subtracts a word value from a bigNum. This function always returns TRUE. */ +LIB_EXPORT BOOL +BnSubWord( + bigNum result, + bigConst op, + crypt_uword_t word + ) +{ + int borrow; + // + pAssert(op->size > 1 || word <= op->d[0]); + borrow = word > op->d[0]; + result->d[0] = op->d[0] - word; + borrow = BorrowProp(&result->d[1], &op->d[1], (int)(op->size - 1), borrow); + pAssert(!borrow); + BnSetTop(result, op->size); + return TRUE; +} +/* 10.2.3.3.9 BnUnsignedCmp() */ +/* This function performs a comparison of op1 to op2. The compare is approximately constant time if + the size of the values used in the compare is consistent across calls (from the same line in the + calling code). */ +/* Return Values Meaning */ +/* < 0 op1 is less than op2 */ +/* 0 op1 is equal to op2 */ +/* > 0 op1 is greater than op2 */ +LIB_EXPORT int +BnUnsignedCmp( + bigConst op1, + bigConst op2 + ) +{ + int retVal; + int diff; + int i; + // + pAssert((op1 != NULL) && (op2 != NULL)); + retVal = (int)(op1->size - op2->size); + if(retVal == 0) + { + for(i = (int)(op1->size - 1); i >= 0; i--) + { + diff = (op1->d[i] < op2->d[i]) ? -1 : (op1->d[i] != op2->d[i]); + retVal = retVal == 0 ? diff : retVal; + } + } + else + retVal = (retVal < 0) ? -1 : 1; + return retVal; +} +/* 10.2.3.3.10 BnUnsignedCmpWord() */ +/* Compare a bigNum to a crypt_uword_t. */ +/* Return Value Meaning */ +/* -1 op1 is less that word */ +/* 0 op1 is equal to word */ +/* 1 op1 is greater than word */ +LIB_EXPORT int +BnUnsignedCmpWord( + bigConst op1, + crypt_uword_t word + ) +{ + if(op1->size > 1) + return 1; + else if(op1->size == 1) + return (op1->d[0] < word) ? -1 : (op1->d[0] > word); + else // op1 is zero + // equal if word is zero + return (word == 0) ? 0 : -1; +} +/* 10.2.3.3.11 BnModWord() */ +/* This function does modular division of a big number when the modulus is a word value. */ +LIB_EXPORT crypt_word_t +BnModWord( + bigConst numerator, + crypt_word_t modulus + ) +{ + BN_MAX(remainder); + BN_VAR(mod, RADIX_BITS); + // + mod->d[0] = modulus; + mod->size = (modulus != 0); + BnDiv(NULL, remainder, numerator, mod); + return remainder->d[0]; +} +/* 10.2.3.3.12 Msb() */ +/* Returns the bit number of the most significant bit of a crypt_uword_t. The number for the least + significant bit of any bigNum value is 0. The maximum return value is RADIX_BITS - 1, */ +/* Return Values Meaning */ +/* -1 the word was zero */ +/* n the bit number of the most significant bit in the word */ +LIB_EXPORT int +Msb( + crypt_uword_t word + ) +{ + int retVal = -1; + // +#if RADIX_BITS == 64 + if(word & 0xffffffff00000000) { retVal += 32; word >>= 32; } +#endif + if(word & 0xffff0000) { retVal += 16; word >>= 16; } + if(word & 0x0000ff00) { retVal += 8; word >>= 8; } + if(word & 0x000000f0) { retVal += 4; word >>= 4; } + if(word & 0x0000000c) { retVal += 2; word >>= 2; } + if(word & 0x00000002) { retVal += 1; word >>= 1; } + return retVal + (int)word; +} +/* 10.2.3.3.13 BnMsb() */ +/* This function returns the number of the MSb() of a bigNum value. */ +/* Return Value Meaning */ +/* -1 the word was zero or bn was NULL */ +/* n the bit number of the most significant bit in the word */ + +LIB_EXPORT int +BnMsb( + bigConst bn + ) +{ + // If the value is NULL, or the size is zero then treat as zero and return -1 + if(bn != NULL && bn->size > 0) + { + int retVal = Msb(bn->d[bn->size - 1]); + retVal += (int)(bn->size - 1) * RADIX_BITS; + return retVal; + } + else + return -1; +} +/* 10.2.3.3.14 BnSizeInBits() */ +/* Returns the number of bits required to hold a number. It is one greater than the Msb. */ +LIB_EXPORT unsigned +BnSizeInBits( + bigConst n + ) +{ + int bits = BnMsb(n) + 1; + // + return bits < 0 ? 0 : (unsigned)bits; +} +/* 10.2.3.3.15 BnSetWord() */ +/* Change the value of a bignum_t to a word value. */ +LIB_EXPORT bigNum +BnSetWord( + bigNum n, + crypt_uword_t w + ) +{ + if(n != NULL) + { + pAssert(n->allocated > 1); + n->d[0] = w; + BnSetTop(n, (w != 0) ? 1 : 0); + } + return n; +} +/* 10.2.3.3.16 BnSetBit() */ +/* SET a bit in a bigNum. Bit 0 is the least-significant bit in the 0th digit_t. The function always + return TRUE */ +LIB_EXPORT BOOL +BnSetBit( + bigNum bn, // IN/OUT: big number to modify + unsigned int bitNum // IN: Bit number to SET + ) +{ + crypt_uword_t offset = bitNum / RADIX_BITS; + pAssert(bn->allocated * RADIX_BITS >= bitNum); + // Grow the number if necessary to set the bit. + while(bn->size <= offset) + bn->d[bn->size++] = 0; + bn->d[offset] |= (crypt_uword_t)(1 << RADIX_MOD(bitNum)); + return TRUE; +} +/* 10.2.3.3.17 BnTestBit() */ +/* Check to see if a bit is SET in a bignum_t. The 0th bit is the LSb() of d[0]. */ +/* Return Values Meaning */ +/* TRUE the bit is set */ +/* FALSE the bit is not set or the number is out of range */ +LIB_EXPORT BOOL +BnTestBit( + bigNum bn, // IN: number to check + unsigned int bitNum // IN: bit to test + ) +{ + crypt_uword_t offset = RADIX_DIV(bitNum); + // + if(bn->size > offset) + return ((bn->d[offset] & (((crypt_uword_t)1) << RADIX_MOD(bitNum))) != 0); + else + return FALSE; +} +/* 10.2.3.3.18 BnMaskBits() */ +/* Function to mask off high order bits of a big number. The returned value will have no more than + maskBit bits set. */ +/* NOTE: There is a requirement that unused words of a bignum_t are set to zero. */ +/* Return Values Meaning */ +/* TRUE result masked */ +/* FALSE the input was not as large as the mask */ +LIB_EXPORT BOOL +BnMaskBits( + bigNum bn, // IN/OUT: number to mask + crypt_uword_t maskBit // IN: the bit number for the mask. + ) +{ + crypt_uword_t finalSize; + BOOL retVal; + finalSize = BITS_TO_CRYPT_WORDS(maskBit); + retVal = (finalSize <= bn->allocated); + if(retVal && (finalSize > 0)) + { + crypt_uword_t mask; + mask = ~((crypt_uword_t)0) >> RADIX_MOD(maskBit); + bn->d[finalSize - 1] &= mask; + } + BnSetTop(bn, finalSize); + return retVal; +} +/* 10.2.3.3.19 BnShiftRight() */ +/* Function will shift a bigNum to the right by the shiftAmount. This function always returns + TRUE. */ +LIB_EXPORT BOOL +BnShiftRight( + bigNum result, + bigConst toShift, + uint32_t shiftAmount + ) +{ + uint32_t offset = (shiftAmount >> RADIX_LOG2); + uint32_t i; + uint32_t shiftIn; + crypt_uword_t finalSize; + // + shiftAmount = shiftAmount & RADIX_MASK; + shiftIn = RADIX_BITS - shiftAmount; + // The end size is toShift->size - offset less one additional + // word if the shiftAmount would make the upper word == 0 + if(toShift->size > offset) + { + finalSize = toShift->size - offset; + finalSize -= (toShift->d[toShift->size - 1] >> shiftAmount) == 0 ? 1 : 0; + } + else + finalSize = 0; + pAssert(finalSize <= result->allocated); + if(finalSize != 0) + { + for(i = 0; i < finalSize; i++) + { + result->d[i] = (toShift->d[i + offset] >> shiftAmount) + | (toShift->d[i + offset + 1] << shiftIn); + } + if(offset == 0) + result->d[i] = toShift->d[i] >> shiftAmount; + } + BnSetTop(result, finalSize); + return TRUE; +} +/* 10.2.3.3.20 BnGetRandomBits() */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure */ +LIB_EXPORT BOOL +BnGetRandomBits( + bigNum n, + size_t bits, + RAND_STATE *rand + ) +{ + // Since this could be used for ECC key generation using the extra bits method, + // make sure that the value is large enough + TPM2B_TYPE(LARGEST, LARGEST_NUMBER + 8); + TPM2B_LARGEST large; + // + large.b.size = (UINT16)BITS_TO_BYTES(bits); + if(DRBG_Generate(rand, large.t.buffer, large.t.size) == large.t.size) + { + if(BnFrom2B(n, &large.b) != NULL) + { + if(BnMaskBits(n, (crypt_uword_t)bits)) + return TRUE; + } + } + return FALSE; +} +/* 10.2.3.3.21 BnGenerateRandomInRange() */ +/* Function to generate a random number r in the range 1 <= r < limit. The function gets a random + number of bits that is the size of limit. There is some some probability that the returned number + is going to be greater than or equal to the limit. If it is, try again. There is no more than 50% + chance that the next number is also greater, so try again. We keep trying until we get a value + that meets the criteria. Since limit is very often a number with a LOT of high order ones, this + rarely would need a second try. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure */ +LIB_EXPORT BOOL +BnGenerateRandomInRange( + bigNum dest, + bigConst limit, + RAND_STATE *rand + ) +{ + size_t bits = BnSizeInBits(limit); + // + if(bits < 2) + { + BnSetWord(dest, 0); + return FALSE; + } + else + { + while(BnGetRandomBits(dest, bits, rand) + && (BnEqualZero(dest) || (BnUnsignedCmp(dest, limit) >= 0))); + } + return !g_inFailureMode; +} + +// libtpms added begin + +// This version of BnSizeInBits skips any leading zero bytes in bigConst +// and thus calculates the bits that OpenSSL will work with after truncating +// the leading zeros +static LIB_EXPORT unsigned +BnSizeInBitsSkipLeadingZeros( + bigConst n + ) +{ + int firstByte; + unsigned bitSize = BnSizeInBits(n); + crypt_uword_t i; + + if (bitSize <= 8) + return bitSize; + + // search for the first limb that is non-zero + for (i = 0; i < n->size; i++) { + if (n->d[i] != 0) + break; + } + if (i >= n->size) + return 0; // should never happen + + // get the first byte in this limb that is non-zero + firstByte = (RADIX_BITS - 1 - Msb(n->d[i])) >> 3; + + return bitSize - i * sizeof(n->d[0]) - (firstByte << 3); +} + + +/* This is a version of BnGenerateRandomInRange that ensures that the upper most + byte is non-zero, so that the number will not be shortened and subsequent operations + will not have a timing-sidechannel + */ +LIB_EXPORT BOOL +BnGenerateRandomInRangeAllBytes( + bigNum dest, + bigConst limit, + RAND_STATE *rand + ) +{ + BOOL OK; + int repeats = 0; + int maxRepeats; + unsigned requestedBits; + unsigned requestedBytes; + unsigned numBytes; + + if (rand) + return BnGenerateRandomInRange(dest, limit, rand); + + // a 'limit' like 'BN_P638_n' has leading zeros and we only need 73 bytes not 80 + requestedBits = BnSizeInBitsSkipLeadingZeros(limit); + requestedBytes = BITS_TO_BYTES(requestedBits); + maxRepeats = 8; + if (requestedBits & 7) + maxRepeats += (9 - (requestedBits & 7)); + + while (true) { + OK = BnGenerateRandomInRange(dest, limit, rand); + if (!OK) + break; + if (repeats < maxRepeats) { + numBytes = BITS_TO_BYTES(BnSizeInBitsSkipLeadingZeros(dest)); + if (numBytes < requestedBytes) { + repeats++; + continue; + } + } + break; + } + + return OK; +} +// libtpms added end diff --git a/src/tpm2/BnMemory.c b/src/tpm2/BnMemory.c new file mode 100644 index 0000000..620ca99 --- /dev/null +++ b/src/tpm2/BnMemory.c @@ -0,0 +1,205 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: BnMemory.c 1262 2018-07-11 21:03:43Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +/* 10.2.5 BnMemory.c */ +/* 10.2.5.1 Introduction */ +/* This file contains the memory setup functions used by the bigNum functions in CryptoEngine() */ +/* 10.2.5.2 Includes */ +#include "Tpm.h" +/* 10.2.5.3 Functions */ +/* 10.2.5.3.1 BnSetTop() */ +/* This function is used when the size of a bignum_t is changed. It makes sure that the unused words + are set to zero and that any significant words of zeros are eliminated from the used size + indicator. */ +LIB_EXPORT bigNum +BnSetTop( + bigNum bn, // IN/OUT: number to clean + crypt_uword_t top // IN: the new top + ) +{ + if(bn != NULL) + { + pAssert(top <= bn->allocated); + // If forcing the size to be decreased, make sure that the words being + // discarded are being set to 0 + while(bn->size > top) + bn->d[--bn->size] = 0; + bn->size = top; + // Now make sure that the words that are left are 'normalized' (no high-order + // words of zero. + while((bn->size > 0) && (bn->d[bn->size - 1] == 0)) + bn->size -= 1; + } + return bn; +} +#if 0 /* libtpms added */ +/* 10.2.5.3.2 BnClearTop() */ +/* This function will make sure that all unused words are zero. */ +LIB_EXPORT bigNum +BnClearTop( + bigNum bn + ) +{ + crypt_uword_t i; + // + if(bn != NULL) + { + for(i = bn->size; i < bn->allocated; i++) + bn->d[i] = 0; + while((bn->size > 0) && (bn->d[bn->size] == 0)) + bn->size -= 1; + } + return bn; +} +#endif /* libtpms added */ +/* 10.2.5.3.3 BnInitializeWord() */ +/* This function is used to initialize an allocated bigNum with a word value. The bigNum does not + have to be allocated with a single word. */ +LIB_EXPORT bigNum +BnInitializeWord( + bigNum bn, // IN: + crypt_uword_t allocated, // IN: + crypt_uword_t word // IN: + ) +{ + bn->allocated = allocated; + bn->size = (word != 0); + bn->d[0] = word; + while(allocated > 1) + bn->d[--allocated] = 0; + return bn; +} +/* 10.2.5.3.4 BnInit() */ +/* This function initializes a stack allocated bignum_t. It initializes allocated and size and zeros + the words of d. */ +LIB_EXPORT bigNum +BnInit( + bigNum bn, + crypt_uword_t allocated + ) +{ + if(bn != NULL) + { + bn->allocated = allocated; + bn->size = 0; + while(allocated != 0) + bn->d[--allocated] = 0; + } + return bn; +} +/* 10.2.5.3.5 BnCopy() */ +/* Function to copy a bignum_t. If the output is NULL, then nothing happens. If the input is NULL, + the output is set to zero. */ +LIB_EXPORT BOOL +BnCopy( + bigNum out, + bigConst in + ) +{ + if(in == out) + BnSetTop(out, BnGetSize(out)); + else if(out != NULL) + { + if(in != NULL) + { + unsigned int i; + pAssert(BnGetAllocated(out) >= BnGetSize(in)); + for(i = 0; i < BnGetSize(in); i++) + out->d[i] = in->d[i]; + BnSetTop(out, BnGetSize(in)); + } + else + BnSetTop(out, 0); + } + return TRUE; +} +#if ALG_ECC +#if 0 /* libtpms added */ +/* 10.2.5.3.6 BnPointCopy() */ +/* Function to copy a bn point. */ +LIB_EXPORT BOOL +BnPointCopy( + bigPoint pOut, + pointConst pIn + ) +{ + return BnCopy(pOut->x, pIn->x) + && BnCopy(pOut->y, pIn->y) + && BnCopy(pOut->z, pIn->z); +} +#endif /* libtpms added */ +/* 10.2.5.3.7 BnInitializePoint() */ +/* This function is used to initialize a point structure with the addresses of the coordinates. */ +LIB_EXPORT bn_point_t * +BnInitializePoint( + bigPoint p, // OUT: structure to receive pointers + bigNum x, // IN: x coordinate + bigNum y, // IN: y coordinate + bigNum z // IN: x coordinate + ) +{ + p->x = x; + p->y = y; + p->z = z; + BnSetWord(z, 1); + return p; +} +#endif // TPM_ALG_ECC diff --git a/src/tpm2/Cancel.c b/src/tpm2/Cancel.c new file mode 100644 index 0000000..2026ec0 --- /dev/null +++ b/src/tpm2/Cancel.c @@ -0,0 +1,100 @@ +/********************************************************************************/ +/* */ +/* Simulates the cancel pins on the TPM. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Cancel.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* C.2 Cancel.c */ +/* C.2.1. Description */ +/* This module simulates the cancel pins on the TPM. */ +/* C.2.2. Includes, Typedefs, Structures, and Defines */ +#include "Platform.h" +/* C.2.3. Functions */ +/* C.2.3.1. _plat__IsCanceled() */ +/* Check if the cancel flag is set */ +/* Return Values Meaning */ +/* TRUE(1) if cancel flag is set */ +/* FALSE(0) if cancel flag is not set */ +LIB_EXPORT int +_plat__IsCanceled( + void + ) +{ + // return cancel flag + return s_isCanceled; +} +/* C.2.3.2. _plat__SetCancel() */ +/* Set cancel flag. */ +LIB_EXPORT void +_plat__SetCancel( + void + ) +{ + s_isCanceled = TRUE; + return; +} +/* C.2.3.3. _plat__ClearCancel() */ +/* Clear cancel flag */ +LIB_EXPORT void +_plat__ClearCancel( + void + ) +{ + s_isCanceled = FALSE; + return; +} diff --git a/src/tpm2/Capabilities.h b/src/tpm2/Capabilities.h new file mode 100644 index 0000000..832187f --- /dev/null +++ b/src/tpm2/Capabilities.h @@ -0,0 +1,76 @@ +/********************************************************************************/ +/* */ +/* Number of capability values that will fit into the largest data buffer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Capabilities.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef _CAPABILITIES_H +#define _CAPABILITIES_H + +#define MAX_CAP_DATA (MAX_CAP_BUFFER - sizeof(TPM_CAP)-sizeof(UINT32)) +#define MAX_CAP_ALGS (MAX_CAP_DATA / sizeof(TPMS_ALG_PROPERTY)) +#define MAX_CAP_HANDLES (MAX_CAP_DATA / sizeof(TPM_HANDLE)) +#define MAX_CAP_CC (MAX_CAP_DATA / sizeof(TPM_CC)) +#define MAX_TPM_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PROPERTY)) +#define MAX_PCR_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PCR_SELECT)) +#define MAX_ECC_CURVES (MAX_CAP_DATA / sizeof(TPM_ECC_CURVE)) +#define MAX_TAGGED_POLICIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_POLICY)) +#define MAX_ACT_DATA (MAX_CAP_DATA / sizeof(TPMS_ACT_DATA)) +#define MAX_AC_CAPABILITIES (MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT)) + +#endif diff --git a/src/tpm2/CapabilityCommands.c b/src/tpm2/CapabilityCommands.c new file mode 100644 index 0000000..e7d675b --- /dev/null +++ b/src/tpm2/CapabilityCommands.c @@ -0,0 +1,215 @@ +/********************************************************************************/ +/* */ +/* Capability Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CapabilityCommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "GetCapability_fp.h" +#if CC_GetCapability // Conditional expansion of this file +TPM_RC +TPM2_GetCapability( + GetCapability_In *in, // IN: input parameter list + GetCapability_Out *out // OUT: output parameter list + ) +{ + TPMU_CAPABILITIES *data = &out->capabilityData.data; + // Command Output + // Set output capability type the same as input type + out->capabilityData.capability = in->capability; + switch(in->capability) + { + case TPM_CAP_ALGS: + out->moreData = AlgorithmCapGetImplemented((TPM_ALG_ID)in->property, + in->propertyCount, + &data->algorithms); + break; + case TPM_CAP_HANDLES: + switch(HandleGetType((TPM_HANDLE)in->property)) + { + case TPM_HT_TRANSIENT: + // Get list of handles of loaded transient objects + out->moreData = ObjectCapGetLoaded((TPM_HANDLE)in->property, + in->propertyCount, + &data->handles); + break; + case TPM_HT_PERSISTENT: + // Get list of handles of persistent objects + out->moreData = NvCapGetPersistent((TPM_HANDLE)in->property, + in->propertyCount, + &data->handles); + break; + case TPM_HT_NV_INDEX: + // Get list of defined NV index + out->moreData = NvCapGetIndex((TPM_HANDLE)in->property, + in->propertyCount, + &data->handles); + break; + case TPM_HT_LOADED_SESSION: + // Get list of handles of loaded sessions + out->moreData = SessionCapGetLoaded((TPM_HANDLE)in->property, + in->propertyCount, + &data->handles); + break; +#ifdef TPM_HT_SAVED_SESSION + case TPM_HT_SAVED_SESSION: +#else + case TPM_HT_ACTIVE_SESSION: +#endif + // Get list of handles of + out->moreData = SessionCapGetSaved((TPM_HANDLE)in->property, + in->propertyCount, + &data->handles); + break; + case TPM_HT_PCR: + // Get list of handles of PCR + out->moreData = PCRCapGetHandles((TPM_HANDLE)in->property, + in->propertyCount, + &data->handles); + break; + case TPM_HT_PERMANENT: + // Get list of permanent handles + out->moreData = PermanentCapGetHandles((TPM_HANDLE)in->property, + in->propertyCount, + &data->handles); + break; + default: + // Unsupported input handle type + return TPM_RCS_HANDLE + RC_GetCapability_property; + break; + } + break; + case TPM_CAP_COMMANDS: + out->moreData = CommandCapGetCCList((TPM_CC)in->property, + in->propertyCount, + &data->command); + break; + case TPM_CAP_PP_COMMANDS: + out->moreData = PhysicalPresenceCapGetCCList((TPM_CC)in->property, + in->propertyCount, + &data->ppCommands); + break; + case TPM_CAP_AUDIT_COMMANDS: + out->moreData = CommandAuditCapGetCCList((TPM_CC)in->property, + in->propertyCount, + &data->auditCommands); + break; + case TPM_CAP_PCRS: + // Input property must be 0 + if(in->property != 0) + return TPM_RCS_VALUE + RC_GetCapability_property; + out->moreData = PCRCapGetAllocation(in->propertyCount, + &data->assignedPCR); + break; + case TPM_CAP_PCR_PROPERTIES: + out->moreData = PCRCapGetProperties((TPM_PT_PCR)in->property, + in->propertyCount, + &data->pcrProperties); + break; + case TPM_CAP_TPM_PROPERTIES: + out->moreData = TPMCapGetProperties((TPM_PT)in->property, + in->propertyCount, + &data->tpmProperties); + break; +#if ALG_ECC + case TPM_CAP_ECC_CURVES: + out->moreData = CryptCapGetECCCurve((TPM_ECC_CURVE)in->property, + in->propertyCount, + &data->eccCurves); + break; +#endif // TPM_ALG_ECC + case TPM_CAP_AUTH_POLICIES: + if(HandleGetType((TPM_HANDLE)in->property) != TPM_HT_PERMANENT) + return TPM_RCS_VALUE + RC_GetCapability_property; + out->moreData = PermanentHandleGetPolicy((TPM_HANDLE)in->property, + in->propertyCount, + &data->authPolicies); + break; + case TPM_CAP_ACT: + if(((TPM_RH)in->property < TPM_RH_ACT_0) + || ((TPM_RH)in->property > TPM_RH_ACT_F)) + return TPM_RCS_VALUE + RC_GetCapability_property; + out->moreData = ActGetCapabilityData((TPM_HANDLE)in->property, + in->propertyCount, + &data->actData); + break; + case TPM_CAP_VENDOR_PROPERTY: + // vendor property is not implemented + default: + // Unsupported TPM_CAP value + return TPM_RCS_VALUE + RC_GetCapability_capability; + break; + } + return TPM_RC_SUCCESS; +} +#endif // CC_GetCapability +#include "Tpm.h" +#include "TestParms_fp.h" +#if CC_TestParms // Conditional expansion of this file +TPM_RC +TPM2_TestParms( + TestParms_In *in // IN: input parameter list + ) +{ + // Input parameter is not reference in command action + NOT_REFERENCED(in); + // The parameters are tested at unmarshal process. We do nothing in command + // action + return TPM_RC_SUCCESS; +} +#endif // CC_TestParms diff --git a/src/tpm2/CertifyCreation_fp.h b/src/tpm2/CertifyCreation_fp.h new file mode 100644 index 0000000..98be3b9 --- /dev/null +++ b/src/tpm2/CertifyCreation_fp.h @@ -0,0 +1,95 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CertifyCreation_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CERTIFYCREATION_FP_H +#define CERTIFYCREATION_FP_H + +typedef struct { + TPMI_DH_OBJECT signHandle; + TPMI_DH_OBJECT objectHandle; + TPM2B_DATA qualifyingData; + TPM2B_DIGEST creationHash; + TPMT_SIG_SCHEME inScheme; + TPMT_TK_CREATION creationTicket; +} CertifyCreation_In; + +#define RC_CertifyCreation_signHandle (TPM_RC_H + TPM_RC_1) +#define RC_CertifyCreation_objectHandle (TPM_RC_H + TPM_RC_2) +#define RC_CertifyCreation_qualifyingData (TPM_RC_P + TPM_RC_1) +#define RC_CertifyCreation_creationHash (TPM_RC_P + TPM_RC_2) +#define RC_CertifyCreation_inScheme (TPM_RC_P + TPM_RC_3) +#define RC_CertifyCreation_creationTicket (TPM_RC_P + TPM_RC_4) + +typedef struct { + TPM2B_ATTEST certifyInfo; + TPMT_SIGNATURE signature; +} CertifyCreation_Out; + +TPM_RC +TPM2_CertifyCreation( + CertifyCreation_In *in, // IN: input parameter list + CertifyCreation_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/CertifyX509_fp.h b/src/tpm2/CertifyX509_fp.h new file mode 100644 index 0000000..b7a002a --- /dev/null +++ b/src/tpm2/CertifyX509_fp.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* TPM2_CertifyX509 Command Header */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CertifyX509_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +/* rev 155 */ + +#ifndef CERTIFYX509_FP_H +#define CERTIFYX509_FP_H + +typedef struct { + TPMI_DH_OBJECT objectHandle; + TPMI_DH_OBJECT signHandle; + TPM2B_DATA reserved; + TPMT_SIG_SCHEME inScheme; + TPM2B_MAX_BUFFER partialCertificate; +} CertifyX509_In; + +#define RC_CertifyX509_signHandle (TPM_RC_H + TPM_RC_1) +#define RC_CertifyX509_objectHandle (TPM_RC_H + TPM_RC_2) +#define RC_CertifyX509_reserved (TPM_RC_P + TPM_RC_1) +#define RC_CertifyX509_inScheme (TPM_RC_P + TPM_RC_2) +#define RC_CertifyX509_partialCertificate (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPM2B_MAX_BUFFER addedToCertificate; + TPM2B_DIGEST tbsDigest; + TPMT_SIGNATURE signature; +} CertifyX509_Out; + +TPM_RC +TPM2_CertifyX509( + CertifyX509_In *in, // IN: input parameter list + CertifyX509_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/Certify_fp.h b/src/tpm2/Certify_fp.h new file mode 100644 index 0000000..2e2ff6d --- /dev/null +++ b/src/tpm2/Certify_fp.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Certify_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CERTIFY_FP_H +#define CERTIFY_FP_H + +typedef struct { + TPMI_DH_OBJECT objectHandle; + TPMI_DH_OBJECT signHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; +} Certify_In; + +#define RC_Certify_objectHandle (TPM_RC_H + TPM_RC_1) +#define RC_Certify_signHandle (TPM_RC_H + TPM_RC_2) +#define RC_Certify_qualifyingData (TPM_RC_P + TPM_RC_1) +#define RC_Certify_inScheme (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM2B_ATTEST certifyInfo; + TPMT_SIGNATURE signature; +} Certify_Out; + + + +TPM_RC +TPM2_Certify( + Certify_In *in, // IN: input parameter list + Certify_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/ChangeEPS_fp.h b/src/tpm2/ChangeEPS_fp.h new file mode 100644 index 0000000..33001e9 --- /dev/null +++ b/src/tpm2/ChangeEPS_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ChangeEPS_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CHANGEEPS_FP_H +#define CHANGEEPS_FP_H + +typedef struct { + TPMI_RH_PLATFORM authHandle; +} ChangeEPS_In; + +#define RC_ChangeEPS_authHandle (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_ChangeEPS( + ChangeEPS_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/ChangePPS_fp.h b/src/tpm2/ChangePPS_fp.h new file mode 100644 index 0000000..ec1ba45 --- /dev/null +++ b/src/tpm2/ChangePPS_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ChangePPS_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CHANGEPPS_FP_H +#define CHANGEPPS_FP_H + +typedef struct { + TPMI_RH_PLATFORM authHandle; +} ChangePPS_In; + +#define RC_ChangePPS_authHandle (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_ChangePPS( + ChangePPS_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/ClearControl_fp.h b/src/tpm2/ClearControl_fp.h new file mode 100644 index 0000000..7c6920e --- /dev/null +++ b/src/tpm2/ClearControl_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ClearControl_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CLEARCONTROL_FP_H +#define CLEARCONTROL_FP_H + +typedef struct { + TPMI_RH_CLEAR auth; + TPMI_YES_NO disable; +} ClearControl_In; + +#define RC_ClearControl_auth (TPM_RC_H + TPM_RC_1) +#define RC_ClearControl_disable (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_ClearControl( + ClearControl_In *in // IN: input parameter list + ); +#endif diff --git a/src/tpm2/Clear_fp.h b/src/tpm2/Clear_fp.h new file mode 100644 index 0000000..4440777 --- /dev/null +++ b/src/tpm2/Clear_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Clear_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CLEAR_FP_H +#define CLEAR_FP_H + +typedef struct { + TPMI_RH_CLEAR authHandle; +} Clear_In; + +#define RC_Clear_authHandle (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_Clear( + Clear_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/Clock.c b/src/tpm2/Clock.c new file mode 100644 index 0000000..cbbcc41 --- /dev/null +++ b/src/tpm2/Clock.c @@ -0,0 +1,346 @@ +/********************************************************************************/ +/* */ +/* Used by the simulator to mimic a hardware clock */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Clock.c 1529 2019-11-21 23:29:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* added for portability because Linux clock is 32 bits */ + +#include +#include +#include + +/* C.3 Clock.c */ +/* C.3.1. Description */ +/* This file contains the routines that are used by the simulator to mimic a hardware clock on a + TPM. In this implementation, all the time values are measured in millisecond. However, the + precision of the clock functions may be implementation dependent. */ +/* C.3.2. Includes and Data Definitions */ +#include +#include "Platform.h" +#include "TpmFail_fp.h" + +/* libtpms added begin */ +/* ClockGetTime -- get time given a specified clock type */ +uint64_t +ClockGetTime( + clockid_t clk_id + ) +{ + uint64_t time; +#ifdef TPM_WINDOWS +#error Not supported for TPM_WINDOWS +#else + struct timespec systime; + + clock_gettime(clk_id, &systime); + time = (uint64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000); +#endif + + return time; +} + +/* ClockAdjustPostResume -- adjust time parameters post resume */ +#include "Tpm.h" +void +ClockAdjustPostResume(UINT64 backthen, BOOL timesAreRealtime) +{ + UINT64 now = ClockGetTime(CLOCK_REALTIME); + INT64 timediff = now - backthen; + + if (timesAreRealtime) { + /* g_time, s_realTimePrevious, s_tpmTime are all in real time */ + s_suspendedElapsedTime = now; + s_hostMonotonicAdjustTime = -ClockGetTime(CLOCK_MONOTONIC); + + /* s_lastSystemTime & s_lastReportTime need to be set as well */ + s_lastSystemTime = now; + s_lastReportedTime = now; + } else if (timediff >= 0) { + s_suspendedElapsedTime += timediff; + } +} +/* libtpms added end */ + +/* C.3.3. Simulator Functions */ +/* C.3.3.1. Introduction */ +/* This set of functions is intended to be called by the simulator environment in order to simulate + hardware events. */ +/* C.3.3.2. _plat__TimerReset() */ +/* This function sets current system clock time as t0 for counting TPM time. This function is called + at a power on event to reset the clock. When the clock is reset, the indication that the clock + was stopped is also set. */ +LIB_EXPORT void +_plat__TimerReset( + void + ) +{ + s_lastSystemTime = 0; + s_tpmTime = 0; + s_adjustRate = CLOCK_NOMINAL; + s_timerReset = TRUE; + s_timerStopped = TRUE; + s_hostMonotonicAdjustTime = 0; /* libtpms added */ + s_suspendedElapsedTime = 0; /* libtpms added */ + return; +} +/* C.3.3.3. _plat__TimerRestart() */ +/* This function should be called in order to simulate the restart of the timer should it be stopped + while power is still applied. */ +LIB_EXPORT void +_plat__TimerRestart( + void + ) +{ + s_timerStopped = TRUE; + return; +} + +/* C.3.4. Functions Used by TPM */ +/* C.3.4.1. Introduction */ +/* These functions are called by the TPM code. They should be replaced by appropriated hardware + functions. */ + +clock_t debugTime; +/* C.3.4.2. _plat__Time() */ +/* This is another, probably futile, attempt to define a portable function that will return a 64-bit + clock value that has mSec resolution. */ +LIB_EXPORT uint64_t +_plat__RealTime( + void + ) +{ + clock64_t time; + //#ifdef _MSC_VER kgold +#ifdef TPM_WINDOWS + #include + struct _timeb sysTime; + // + _ftime(&sysTime); /* kgold, mingw doesn't have _ftime_s */ + time = (clock64_t)(sysTime.time) * 1000 + sysTime.millitm; + // set the time back by one hour if daylight savings + if(sysTime.dstflag) + time -= 1000 * 60 * 60; // mSec/sec * sec/min * min/hour = ms/hour +#else + // hopefully, this will work with most UNIX systems + struct timespec systime; + // + clock_gettime(CLOCK_MONOTONIC, &systime); + time = (clock64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000); +#endif + /* libtpms added begin */ + /* We have to make sure that this function returns monotonically increasing time + also when a vTPM has been suspended and the host has been rebooted. + Example: + - The vTPM is suspended at systime '5' + - The vTPM is resumed at systime '1' after a host reboot + -> we now need to add '4' to the time + Besides this we want to account for the time a vTPM was suspended. + If it was suspended for 10 time units, we need to add '10' here. + */ + time += s_hostMonotonicAdjustTime + s_suspendedElapsedTime; + /* libtpms added end */ + return time; +} + + + +/* C.3.4.3. _plat__TimerRead() */ +/* This function provides access to the tick timer of the platform. The TPM code uses this value to + drive the TPM Clock. */ +/* The tick timer is supposed to run when power is applied to the device. This timer should not be + reset by time events including _TPM_Init(). It should only be reset when TPM power is + re-applied. */ +/* If the TPM is run in a protected environment, that environment may provide the tick time to the + TPM as long as the time provided by the environment is not allowed to go backwards. If the time + provided by the system can go backwards during a power discontinuity, then the + _plat__Signal_PowerOn() should call _plat__TimerReset(). */ +LIB_EXPORT uint64_t +_plat__TimerRead( + void + ) +{ +#ifdef HARDWARE_CLOCK +#error "need a definition for reading the hardware clock" + return HARDWARE_CLOCK +#else + clock64_t timeDiff; + clock64_t adjustedTimeDiff; + clock64_t timeNow; + clock64_t readjustedTimeDiff; + // This produces a timeNow that is basically locked to the system clock. + timeNow = _plat__RealTime(); + // if this hasn't been initialized, initialize it + if(s_lastSystemTime == 0) + { + s_lastSystemTime = timeNow; + debugTime = clock(); + s_lastReportedTime = 0; + s_realTimePrevious = 0; + } + // The system time can bounce around and that's OK as long as we don't allow + // time to go backwards. When the time does appear to go backwards, set + // lastSystemTime to be the new value and then update the reported time. + if(timeNow < s_lastReportedTime) + s_lastSystemTime = timeNow; + s_lastReportedTime = s_lastReportedTime + timeNow - s_lastSystemTime; + s_lastSystemTime = timeNow; + timeNow = s_lastReportedTime; + // The code above produces a timeNow that is similar to the value returned + // by Clock(). The difference is that timeNow does not max out, and it is + // at a ms. rate rather than at a CLOCKS_PER_SEC rate. The code below + // uses that value and does the rate adjustment on the time value. + // If there is no difference in time, then skip all the computations + if(s_realTimePrevious >= timeNow) + return s_tpmTime; + // Compute the amount of time since the last update of the system clock + timeDiff = timeNow - s_realTimePrevious; + // Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec + adjustedTimeDiff = (timeDiff * CLOCK_NOMINAL) / ((uint64_t)s_adjustRate); + // update the TPM time with the adjusted timeDiff + s_tpmTime += (clock64_t)adjustedTimeDiff; + // Might have some rounding error that would loose CLOCKS. See what is not + // being used. As mentioned above, this could result in putting back more than + // is taken out. Here, we are trying to recreate timeDiff. + readjustedTimeDiff = (adjustedTimeDiff * (uint64_t)s_adjustRate ) + / CLOCK_NOMINAL; + // adjusted is now converted back to being the amount we should advance the + // previous sampled time. It should always be less than or equal to timeDiff. + // That is, we could not have use more time than we started with. + s_realTimePrevious = s_realTimePrevious + readjustedTimeDiff; +#ifdef DEBUGGING_TIME + // Put this in so that TPM time will pass much faster than real time when + // doing debug. + // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second + // A good value might be 100 + return (s_tpmTime * DEBUG_TIME_MULTIPLIER); +#endif + return s_tpmTime; +#endif +} + + +/* C.3.4.3. _plat__TimerWasReset() */ +/* This function is used to interrogate the flag indicating if the tick timer has been reset. */ +/* If the resetFlag parameter is SET, then the flag will be CLEAR before the function returns. */ +LIB_EXPORT int +_plat__TimerWasReset( + void + ) +{ + int retVal = s_timerReset; + s_timerReset = FALSE; + return retVal; +} +/* C.3.4.4. _plat__TimerWasStopped() */ +/* This function is used to interrogate the flag indicating if the tick timer has been stopped. If + so, this is typically a reason to roll the nonce. */ +/* This function will CLEAR the s_timerStopped flag before returning. This provides functionality + that is similar to status register that is cleared when read. This is the model used here because + it is the one that has the most impact on the TPM code as the flag can only be accessed by one + entity in the TPM. Any other implementation of the hardware can be made to look like a read-once + register. */ +LIB_EXPORT int +_plat__TimerWasStopped( + void + ) +{ + BOOL retVal = s_timerStopped; + s_timerStopped = FALSE; + return retVal; +} +/* C.3.4.5. _plat__ClockAdjustRate() */ +/* Adjust the clock rate */ +LIB_EXPORT void +_plat__ClockAdjustRate( + int adjust // IN: the adjust number. It could be positive + // or negative + ) +{ + // We expect the caller should only use a fixed set of constant values to + // adjust the rate + switch(adjust) + { + case CLOCK_ADJUST_COARSE: + s_adjustRate += CLOCK_ADJUST_COARSE; + break; + case -CLOCK_ADJUST_COARSE: + s_adjustRate -= CLOCK_ADJUST_COARSE; + break; + case CLOCK_ADJUST_MEDIUM: + s_adjustRate += CLOCK_ADJUST_MEDIUM; + break; + case -CLOCK_ADJUST_MEDIUM: + s_adjustRate -= CLOCK_ADJUST_MEDIUM; + break; + case CLOCK_ADJUST_FINE: + s_adjustRate += CLOCK_ADJUST_FINE; + break; + case -CLOCK_ADJUST_FINE: + s_adjustRate -= CLOCK_ADJUST_FINE; + break; + default: + // ignore any other values; + break; + } + if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT)) + s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT; + if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT)) + s_adjustRate = CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT; + return; +} diff --git a/src/tpm2/ClockCommands.c b/src/tpm2/ClockCommands.c new file mode 100644 index 0000000..fa0837c --- /dev/null +++ b/src/tpm2/ClockCommands.c @@ -0,0 +1,109 @@ +/********************************************************************************/ +/* */ +/* Clocks and Timers */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ClockCommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "ReadClock_fp.h" +#if CC_ReadClock // Conditional expansion of this file +TPM_RC +TPM2_ReadClock( + ReadClock_Out *out // OUT: output parameter list + ) +{ + // Command Output + out->currentTime.time = g_time; + TimeFillInfo(&out->currentTime.clockInfo); + return TPM_RC_SUCCESS; +} +#endif // CC_ReadClock +#include "Tpm.h" +#include "ClockSet_fp.h" +#if CC_ClockSet // Conditional expansion of this file +TPM_RC +TPM2_ClockSet( + ClockSet_In *in // IN: input parameter list + ) +{ + // Input Validation + // new time can not be bigger than 0xFFFF000000000000 or smaller than + // current clock + if(in->newTime > 0xFFFF000000000000ULL + || in->newTime < go.clock) + return TPM_RCS_VALUE + RC_ClockSet_newTime; + // Internal Data Update + // Can't modify the clock if NV is not available. + RETURN_IF_NV_IS_NOT_AVAILABLE; + TimeClockUpdate(in->newTime); + return TPM_RC_SUCCESS; +} +#endif // CC_ClockSet +#include "Tpm.h" +#include "ClockRateAdjust_fp.h" +#if CC_ClockRateAdjust // Conditional expansion of this file +TPM_RC +TPM2_ClockRateAdjust( + ClockRateAdjust_In *in // IN: input parameter list + ) +{ + // Internal Data Update + TimeSetAdjustRate(in->rateAdjust); + return TPM_RC_SUCCESS; +} +#endif // CC_ClockRateAdjust diff --git a/src/tpm2/ClockRateAdjust_fp.h b/src/tpm2/ClockRateAdjust_fp.h new file mode 100644 index 0000000..0c02067 --- /dev/null +++ b/src/tpm2/ClockRateAdjust_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ClockRateAdjust_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CLOCKRATEADJUST_FP_H +#define CLOCKRATEADJUST_FP_H + +typedef struct { + TPMI_RH_PROVISION auth; + TPM_CLOCK_ADJUST rateAdjust; +} ClockRateAdjust_In; + +#define RC_ClockRateAdjust_auth (TPM_RC_H + TPM_RC_1) +#define RC_ClockRateAdjust_rateAdjust (TPM_RC_P + TPM_RC_1) + + +TPM_RC +TPM2_ClockRateAdjust( + ClockRateAdjust_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/ClockSet_fp.h b/src/tpm2/ClockSet_fp.h new file mode 100644 index 0000000..8f76b73 --- /dev/null +++ b/src/tpm2/ClockSet_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ClockSet_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CLOCKSET_FP_H +#define CLOCKSET_FP_H + +typedef struct { + TPMI_RH_PROVISION auth; + UINT64 newTime; +} ClockSet_In; + +#define RC_ClockSet_auth (TPM_RC_H + TPM_RC_1) +#define RC_ClockSet_newTime (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_ClockSet( + ClockSet_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/CommandAttributeData.h b/src/tpm2/CommandAttributeData.h new file mode 100644 index 0000000..6facd32 --- /dev/null +++ b/src/tpm2/CommandAttributeData.h @@ -0,0 +1,958 @@ +/********************************************************************************/ +/* */ +/* Command code attribute array for GetCapability */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandAttributeData.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 5.6 CommandAttributeData.h */ +/* This file should only be included by CommandCodeAttibutes.c */ + +#ifdef _COMMAND_CODE_ATTRIBUTES_ +#include "CommandAttributes.h" +#if COMPRESSED_LISTS +# define PAD_LIST 0 +#else +# define PAD_LIST 1 +#endif + +/* This is the command code attribute array for GetCapability(). Both this array and + s_commandAttributes provides command code attributes, but tuned for different purpose */ + +const TPMA_CC s_ccAttr [] = { +#if (PAD_LIST || CC_NV_UndefineSpaceSpecial) + TPMA_CC_INITIALIZER(0x011f, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_EvictControl) + TPMA_CC_INITIALIZER(0x0120, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_HierarchyControl) + TPMA_CC_INITIALIZER(0x0121, 0, 1, 1, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_UndefineSpace) + TPMA_CC_INITIALIZER(0x0122, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST ) + TPMA_CC_INITIALIZER(0x0123, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ChangeEPS) + TPMA_CC_INITIALIZER(0x0124, 0, 1, 1, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ChangePPS) + TPMA_CC_INITIALIZER(0x0125, 0, 1, 1, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Clear) + TPMA_CC_INITIALIZER(0x0126, 0, 1, 1, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ClearControl) + TPMA_CC_INITIALIZER(0x0127, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ClockSet) + TPMA_CC_INITIALIZER(0x0128, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_HierarchyChangeAuth) + TPMA_CC_INITIALIZER(0x0129, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_DefineSpace) + TPMA_CC_INITIALIZER(0x012a, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PCR_Allocate) + TPMA_CC_INITIALIZER(0x012b, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PCR_SetAuthPolicy) + TPMA_CC_INITIALIZER(0x012c, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PP_Commands) + TPMA_CC_INITIALIZER(0x012d, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_SetPrimaryPolicy) + TPMA_CC_INITIALIZER(0x012e, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_FieldUpgradeStart) + TPMA_CC_INITIALIZER(0x012f, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ClockRateAdjust) + TPMA_CC_INITIALIZER(0x0130, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_CreatePrimary) + TPMA_CC_INITIALIZER(0x0131, 0, 0, 0, 0, 1, 1, 0, 0), +#endif +#if (PAD_LIST || CC_NV_GlobalWriteLock) + TPMA_CC_INITIALIZER(0x0132, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_GetCommandAuditDigest) + TPMA_CC_INITIALIZER(0x0133, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_Increment) + TPMA_CC_INITIALIZER(0x0134, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_SetBits) + TPMA_CC_INITIALIZER(0x0135, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_Extend) + TPMA_CC_INITIALIZER(0x0136, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_Write) + TPMA_CC_INITIALIZER(0x0137, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_WriteLock) + TPMA_CC_INITIALIZER(0x0138, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_DictionaryAttackLockReset) + TPMA_CC_INITIALIZER(0x0139, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_DictionaryAttackParameters) + TPMA_CC_INITIALIZER(0x013a, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_ChangeAuth) + TPMA_CC_INITIALIZER(0x013b, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PCR_Event) + TPMA_CC_INITIALIZER(0x013c, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PCR_Reset) + TPMA_CC_INITIALIZER(0x013d, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_SequenceComplete) + TPMA_CC_INITIALIZER(0x013e, 0, 0, 0, 1, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_SetAlgorithmSet) + TPMA_CC_INITIALIZER(0x013f, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_SetCommandCodeAuditStatus) + TPMA_CC_INITIALIZER(0x0140, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_FieldUpgradeData) + TPMA_CC_INITIALIZER(0x0141, 0, 1, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_IncrementalSelfTest) + TPMA_CC_INITIALIZER(0x0142, 0, 1, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_SelfTest) + TPMA_CC_INITIALIZER(0x0143, 0, 1, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Startup) + TPMA_CC_INITIALIZER(0x0144, 0, 1, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Shutdown) + TPMA_CC_INITIALIZER(0x0145, 0, 1, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_StirRandom) + TPMA_CC_INITIALIZER(0x0146, 0, 1, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ActivateCredential) + TPMA_CC_INITIALIZER(0x0147, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Certify) + TPMA_CC_INITIALIZER(0x0148, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyNV) + TPMA_CC_INITIALIZER(0x0149, 0, 0, 0, 0, 3, 0, 0, 0), +#endif +#if (PAD_LIST || CC_CertifyCreation) + TPMA_CC_INITIALIZER(0x014a, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Duplicate) + TPMA_CC_INITIALIZER(0x014b, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_GetTime) + TPMA_CC_INITIALIZER(0x014c, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_GetSessionAuditDigest) + TPMA_CC_INITIALIZER(0x014d, 0, 0, 0, 0, 3, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_Read) + TPMA_CC_INITIALIZER(0x014e, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_ReadLock) + TPMA_CC_INITIALIZER(0x014f, 0, 1, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ObjectChangeAuth) + TPMA_CC_INITIALIZER(0x0150, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicySecret) + TPMA_CC_INITIALIZER(0x0151, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Rewrap) + TPMA_CC_INITIALIZER(0x0152, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Create) + TPMA_CC_INITIALIZER(0x0153, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ECDH_ZGen) + TPMA_CC_INITIALIZER(0x0154, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || (CC_HMAC || CC_MAC)) + TPMA_CC_INITIALIZER(0x0155, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Import) + TPMA_CC_INITIALIZER(0x0156, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Load) + TPMA_CC_INITIALIZER(0x0157, 0, 0, 0, 0, 1, 1, 0, 0), +#endif +#if (PAD_LIST || CC_Quote) + TPMA_CC_INITIALIZER(0x0158, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_RSA_Decrypt) + TPMA_CC_INITIALIZER(0x0159, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST ) + TPMA_CC_INITIALIZER(0x015a, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) + TPMA_CC_INITIALIZER(0x015b, 0, 0, 0, 0, 1, 1, 0, 0), +#endif +#if (PAD_LIST || CC_SequenceUpdate) + TPMA_CC_INITIALIZER(0x015c, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Sign) + TPMA_CC_INITIALIZER(0x015d, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Unseal) + TPMA_CC_INITIALIZER(0x015e, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST ) + TPMA_CC_INITIALIZER(0x015f, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicySigned) + TPMA_CC_INITIALIZER(0x0160, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ContextLoad) + TPMA_CC_INITIALIZER(0x0161, 0, 0, 0, 0, 0, 1, 0, 0), +#endif +#if (PAD_LIST || CC_ContextSave) + TPMA_CC_INITIALIZER(0x0162, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ECDH_KeyGen) + TPMA_CC_INITIALIZER(0x0163, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_EncryptDecrypt) + TPMA_CC_INITIALIZER(0x0164, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_FlushContext) + TPMA_CC_INITIALIZER(0x0165, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST ) + TPMA_CC_INITIALIZER(0x0166, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_LoadExternal) + TPMA_CC_INITIALIZER(0x0167, 0, 0, 0, 0, 0, 1, 0, 0), +#endif +#if (PAD_LIST || CC_MakeCredential) + TPMA_CC_INITIALIZER(0x0168, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_ReadPublic) + TPMA_CC_INITIALIZER(0x0169, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyAuthorize) + TPMA_CC_INITIALIZER(0x016a, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyAuthValue) + TPMA_CC_INITIALIZER(0x016b, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyCommandCode) + TPMA_CC_INITIALIZER(0x016c, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyCounterTimer) + TPMA_CC_INITIALIZER(0x016d, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyCpHash) + TPMA_CC_INITIALIZER(0x016e, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyLocality) + TPMA_CC_INITIALIZER(0x016f, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyNameHash) + TPMA_CC_INITIALIZER(0x0170, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyOR) + TPMA_CC_INITIALIZER(0x0171, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyTicket) + TPMA_CC_INITIALIZER(0x0172, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ReadPublic) + TPMA_CC_INITIALIZER(0x0173, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_RSA_Encrypt) + TPMA_CC_INITIALIZER(0x0174, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST ) + TPMA_CC_INITIALIZER(0x0175, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_StartAuthSession) + TPMA_CC_INITIALIZER(0x0176, 0, 0, 0, 0, 2, 1, 0, 0), +#endif +#if (PAD_LIST || CC_VerifySignature) + TPMA_CC_INITIALIZER(0x0177, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ECC_Parameters) + TPMA_CC_INITIALIZER(0x0178, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_FirmwareRead) + TPMA_CC_INITIALIZER(0x0179, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_GetCapability) + TPMA_CC_INITIALIZER(0x017a, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_GetRandom) + TPMA_CC_INITIALIZER(0x017b, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_GetTestResult) + TPMA_CC_INITIALIZER(0x017c, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Hash) + TPMA_CC_INITIALIZER(0x017d, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PCR_Read) + TPMA_CC_INITIALIZER(0x017e, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyPCR) + TPMA_CC_INITIALIZER(0x017f, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyRestart) + TPMA_CC_INITIALIZER(0x0180, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ReadClock) + TPMA_CC_INITIALIZER(0x0181, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PCR_Extend) + TPMA_CC_INITIALIZER(0x0182, 0, 1, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PCR_SetAuthValue) + TPMA_CC_INITIALIZER(0x0183, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_NV_Certify) + TPMA_CC_INITIALIZER(0x0184, 0, 0, 0, 0, 3, 0, 0, 0), +#endif +#if (PAD_LIST || CC_EventSequenceComplete) + TPMA_CC_INITIALIZER(0x0185, 0, 1, 0, 1, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_HashSequenceStart) + TPMA_CC_INITIALIZER(0x0186, 0, 0, 0, 0, 0, 1, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyPhysicalPresence) + TPMA_CC_INITIALIZER(0x0187, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyDuplicationSelect) + TPMA_CC_INITIALIZER(0x0188, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyGetDigest) + TPMA_CC_INITIALIZER(0x0189, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_TestParms) + TPMA_CC_INITIALIZER(0x018a, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Commit) + TPMA_CC_INITIALIZER(0x018b, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyPassword) + TPMA_CC_INITIALIZER(0x018c, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ZGen_2Phase) + TPMA_CC_INITIALIZER(0x018d, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_EC_Ephemeral) + TPMA_CC_INITIALIZER(0x018e, 0, 0, 0, 0, 0, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyNvWritten) + TPMA_CC_INITIALIZER(0x018f, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyTemplate) + TPMA_CC_INITIALIZER(0x0190, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_CreateLoaded) + TPMA_CC_INITIALIZER(0x0191, 0, 0, 0, 0, 1, 1, 0, 0), +#endif +#if (PAD_LIST || CC_PolicyAuthorizeNV) + TPMA_CC_INITIALIZER(0x0192, 0, 0, 0, 0, 3, 0, 0, 0), +#endif +#if (PAD_LIST || CC_EncryptDecrypt2) + TPMA_CC_INITIALIZER(0x0193, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_AC_GetCapability) + TPMA_CC_INITIALIZER(0x0194, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_AC_Send) + TPMA_CC_INITIALIZER(0x0195, 0, 0, 0, 0, 3, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Policy_AC_SendSelect) + TPMA_CC_INITIALIZER(0x0196, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_CertifyX509) + TPMA_CC_INITIALIZER(0x0197, 0, 0, 0, 0, 2, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ACT_SetTimeout) + TPMA_CC_INITIALIZER(0x0198, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ECC_Encrypt) + TPMA_CC_INITIALIZER(0x0199, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_ECC_Decrypt) + TPMA_CC_INITIALIZER(0x019A, 0, 0, 0, 0, 1, 0, 0, 0), +#endif +#if (PAD_LIST || CC_Vendor_TCG_Test) + TPMA_CC_INITIALIZER(0x0000, 0, 0, 0, 0, 0, 0, 1, 0), +#endif + + TPMA_ZERO_INITIALIZER() +}; + +/* This is the command code attribute structure. */ + +const COMMAND_ATTRIBUTES s_commandAttributes [] = { +#if (PAD_LIST || CC_NV_UndefineSpaceSpecial) + (COMMAND_ATTRIBUTES)(CC_NV_UndefineSpaceSpecial * // 0x011f + (IS_IMPLEMENTED+HANDLE_1_ADMIN+HANDLE_2_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_EvictControl) + (COMMAND_ATTRIBUTES)(CC_EvictControl * // 0x0120 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_HierarchyControl) + (COMMAND_ATTRIBUTES)(CC_HierarchyControl * // 0x0121 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_NV_UndefineSpace) + (COMMAND_ATTRIBUTES)(CC_NV_UndefineSpace * // 0x0122 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST ) + (COMMAND_ATTRIBUTES)(0), // 0x0123 +#endif +#if (PAD_LIST || CC_ChangeEPS) + (COMMAND_ATTRIBUTES)(CC_ChangeEPS * // 0x0124 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_ChangePPS) + (COMMAND_ATTRIBUTES)(CC_ChangePPS * // 0x0125 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_Clear) + (COMMAND_ATTRIBUTES)(CC_Clear * // 0x0126 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_ClearControl) + (COMMAND_ATTRIBUTES)(CC_ClearControl * // 0x0127 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_ClockSet) + (COMMAND_ATTRIBUTES)(CC_ClockSet * // 0x0128 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_HierarchyChangeAuth) + (COMMAND_ATTRIBUTES)(CC_HierarchyChangeAuth * // 0x0129 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_NV_DefineSpace) + (COMMAND_ATTRIBUTES)(CC_NV_DefineSpace * // 0x012a + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_PCR_Allocate) + (COMMAND_ATTRIBUTES)(CC_PCR_Allocate * // 0x012b + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_PCR_SetAuthPolicy) + (COMMAND_ATTRIBUTES)(CC_PCR_SetAuthPolicy * // 0x012c + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_PP_Commands) + (COMMAND_ATTRIBUTES)(CC_PP_Commands * // 0x012d + (IS_IMPLEMENTED+HANDLE_1_USER+PP_REQUIRED)), +#endif +#if (PAD_LIST || CC_SetPrimaryPolicy) + (COMMAND_ATTRIBUTES)(CC_SetPrimaryPolicy * // 0x012e + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_FieldUpgradeStart) + (COMMAND_ATTRIBUTES)(CC_FieldUpgradeStart * // 0x012f + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_ClockRateAdjust) + (COMMAND_ATTRIBUTES)(CC_ClockRateAdjust * // 0x0130 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_CreatePrimary) + (COMMAND_ATTRIBUTES)(CC_CreatePrimary * // 0x0131 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND+ENCRYPT_2+R_HANDLE)), +#endif +#if (PAD_LIST || CC_NV_GlobalWriteLock) + (COMMAND_ATTRIBUTES)(CC_NV_GlobalWriteLock * // 0x0132 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_GetCommandAuditDigest) + (COMMAND_ATTRIBUTES)(CC_GetCommandAuditDigest * // 0x0133 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_NV_Increment) + (COMMAND_ATTRIBUTES)(CC_NV_Increment * // 0x0134 + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_NV_SetBits) + (COMMAND_ATTRIBUTES)(CC_NV_SetBits * // 0x0135 + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_NV_Extend) + (COMMAND_ATTRIBUTES)(CC_NV_Extend * // 0x0136 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_NV_Write) + (COMMAND_ATTRIBUTES)(CC_NV_Write * // 0x0137 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_NV_WriteLock) + (COMMAND_ATTRIBUTES)(CC_NV_WriteLock * // 0x0138 + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_DictionaryAttackLockReset) + (COMMAND_ATTRIBUTES)(CC_DictionaryAttackLockReset * // 0x0139 + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_DictionaryAttackParameters) + (COMMAND_ATTRIBUTES)(CC_DictionaryAttackParameters * // 0x013a + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_NV_ChangeAuth) + (COMMAND_ATTRIBUTES)(CC_NV_ChangeAuth * // 0x013b + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN)), +#endif +#if (PAD_LIST || CC_PCR_Event) + (COMMAND_ATTRIBUTES)(CC_PCR_Event * // 0x013c + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_PCR_Reset) + (COMMAND_ATTRIBUTES)(CC_PCR_Reset * // 0x013d + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_SequenceComplete) + (COMMAND_ATTRIBUTES)(CC_SequenceComplete * // 0x013e + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_SetAlgorithmSet) + (COMMAND_ATTRIBUTES)(CC_SetAlgorithmSet * // 0x013f + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_SetCommandCodeAuditStatus) + (COMMAND_ATTRIBUTES)(CC_SetCommandCodeAuditStatus * // 0x0140 + (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), +#endif +#if (PAD_LIST || CC_FieldUpgradeData) + (COMMAND_ATTRIBUTES)(CC_FieldUpgradeData * // 0x0141 + (IS_IMPLEMENTED+DECRYPT_2)), +#endif +#if (PAD_LIST || CC_IncrementalSelfTest) + (COMMAND_ATTRIBUTES)(CC_IncrementalSelfTest * // 0x0142 + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_SelfTest) + (COMMAND_ATTRIBUTES)(CC_SelfTest * // 0x0143 + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_Startup) + (COMMAND_ATTRIBUTES)(CC_Startup * // 0x0144 + (IS_IMPLEMENTED+NO_SESSIONS)), +#endif +#if (PAD_LIST || CC_Shutdown) + (COMMAND_ATTRIBUTES)(CC_Shutdown * // 0x0145 + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_StirRandom) + (COMMAND_ATTRIBUTES)(CC_StirRandom * // 0x0146 + (IS_IMPLEMENTED+DECRYPT_2)), +#endif +#if (PAD_LIST || CC_ActivateCredential) + (COMMAND_ATTRIBUTES)(CC_ActivateCredential * // 0x0147 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_Certify) + (COMMAND_ATTRIBUTES)(CC_Certify * // 0x0148 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_PolicyNV) + (COMMAND_ATTRIBUTES)(CC_PolicyNV * // 0x0149 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_CertifyCreation) + (COMMAND_ATTRIBUTES)(CC_CertifyCreation * // 0x014a + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_Duplicate) + (COMMAND_ATTRIBUTES)(CC_Duplicate * // 0x014b + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_DUP+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_GetTime) + (COMMAND_ATTRIBUTES)(CC_GetTime * // 0x014c + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_GetSessionAuditDigest) + (COMMAND_ATTRIBUTES)(CC_GetSessionAuditDigest * // 0x014d + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_NV_Read) + (COMMAND_ATTRIBUTES)(CC_NV_Read * // 0x014e + (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_NV_ReadLock) + (COMMAND_ATTRIBUTES)(CC_NV_ReadLock * // 0x014f + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_ObjectChangeAuth) + (COMMAND_ATTRIBUTES)(CC_ObjectChangeAuth * // 0x0150 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_PolicySecret) + (COMMAND_ATTRIBUTES)(CC_PolicySecret * // 0x0151 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ALLOW_TRIAL+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_Rewrap) + (COMMAND_ATTRIBUTES)(CC_Rewrap * // 0x0152 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_Create) + (COMMAND_ATTRIBUTES)(CC_Create * // 0x0153 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_ECDH_ZGen) + (COMMAND_ATTRIBUTES)(CC_ECDH_ZGen * // 0x0154 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || (CC_HMAC || CC_MAC)) + (COMMAND_ATTRIBUTES)((CC_HMAC || CC_MAC) * // 0x0155 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_Import) + (COMMAND_ATTRIBUTES)(CC_Import * // 0x0156 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_Load) + (COMMAND_ATTRIBUTES)(CC_Load * // 0x0157 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2+R_HANDLE)), +#endif +#if (PAD_LIST || CC_Quote) + (COMMAND_ATTRIBUTES)(CC_Quote * // 0x0158 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_RSA_Decrypt) + (COMMAND_ATTRIBUTES)(CC_RSA_Decrypt * // 0x0159 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST ) + (COMMAND_ATTRIBUTES)(0), // 0x015a +#endif +#if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) + (COMMAND_ATTRIBUTES)((CC_HMAC_Start || CC_MAC_Start) * // 0x015b + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+R_HANDLE)), +#endif +#if (PAD_LIST || CC_SequenceUpdate) + (COMMAND_ATTRIBUTES)(CC_SequenceUpdate * // 0x015c + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_Sign) + (COMMAND_ATTRIBUTES)(CC_Sign * // 0x015d + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_Unseal) + (COMMAND_ATTRIBUTES)(CC_Unseal * // 0x015e + (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST ) + (COMMAND_ATTRIBUTES)(0), // 0x015f +#endif +#if (PAD_LIST || CC_PolicySigned) + (COMMAND_ATTRIBUTES)(CC_PolicySigned * // 0x0160 + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_ContextLoad) + (COMMAND_ATTRIBUTES)(CC_ContextLoad * // 0x0161 + (IS_IMPLEMENTED+NO_SESSIONS+R_HANDLE)), +#endif +#if (PAD_LIST || CC_ContextSave) + (COMMAND_ATTRIBUTES)(CC_ContextSave * // 0x0162 + (IS_IMPLEMENTED+NO_SESSIONS)), +#endif +#if (PAD_LIST || CC_ECDH_KeyGen) + (COMMAND_ATTRIBUTES)(CC_ECDH_KeyGen * // 0x0163 + (IS_IMPLEMENTED+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_EncryptDecrypt) + (COMMAND_ATTRIBUTES)(CC_EncryptDecrypt * // 0x0164 + (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_FlushContext) + (COMMAND_ATTRIBUTES)(CC_FlushContext * // 0x0165 + (IS_IMPLEMENTED+NO_SESSIONS)), +#endif +#if (PAD_LIST ) + (COMMAND_ATTRIBUTES)(0), // 0x0166 +#endif +#if (PAD_LIST || CC_LoadExternal) + (COMMAND_ATTRIBUTES)(CC_LoadExternal * // 0x0167 + (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)), +#endif +#if (PAD_LIST || CC_MakeCredential) + (COMMAND_ATTRIBUTES)(CC_MakeCredential * // 0x0168 + (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_NV_ReadPublic) + (COMMAND_ATTRIBUTES)(CC_NV_ReadPublic * // 0x0169 + (IS_IMPLEMENTED+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_PolicyAuthorize) + (COMMAND_ATTRIBUTES)(CC_PolicyAuthorize * // 0x016a + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyAuthValue) + (COMMAND_ATTRIBUTES)(CC_PolicyAuthValue * // 0x016b + (IS_IMPLEMENTED+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyCommandCode) + (COMMAND_ATTRIBUTES)(CC_PolicyCommandCode * // 0x016c + (IS_IMPLEMENTED+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyCounterTimer) + (COMMAND_ATTRIBUTES)(CC_PolicyCounterTimer * // 0x016d + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyCpHash) + (COMMAND_ATTRIBUTES)(CC_PolicyCpHash * // 0x016e + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyLocality) + (COMMAND_ATTRIBUTES)(CC_PolicyLocality * // 0x016f + (IS_IMPLEMENTED+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyNameHash) + (COMMAND_ATTRIBUTES)(CC_PolicyNameHash * // 0x0170 + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyOR) + (COMMAND_ATTRIBUTES)(CC_PolicyOR * // 0x0171 + (IS_IMPLEMENTED+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyTicket) + (COMMAND_ATTRIBUTES)(CC_PolicyTicket * // 0x0172 + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_ReadPublic) + (COMMAND_ATTRIBUTES)(CC_ReadPublic * // 0x0173 + (IS_IMPLEMENTED+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_RSA_Encrypt) + (COMMAND_ATTRIBUTES)(CC_RSA_Encrypt * // 0x0174 + (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), +#endif +#if (PAD_LIST ) + (COMMAND_ATTRIBUTES)(0), // 0x0175 +#endif +#if (PAD_LIST || CC_StartAuthSession) + (COMMAND_ATTRIBUTES)(CC_StartAuthSession * // 0x0176 + (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)), +#endif +#if (PAD_LIST || CC_VerifySignature) + (COMMAND_ATTRIBUTES)(CC_VerifySignature * // 0x0177 + (IS_IMPLEMENTED+DECRYPT_2)), +#endif +#if (PAD_LIST || CC_ECC_Parameters) + (COMMAND_ATTRIBUTES)(CC_ECC_Parameters * // 0x0178 + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_FirmwareRead) + (COMMAND_ATTRIBUTES)(CC_FirmwareRead * // 0x0179 + (IS_IMPLEMENTED+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_GetCapability) + (COMMAND_ATTRIBUTES)(CC_GetCapability * // 0x017a + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_GetRandom) + (COMMAND_ATTRIBUTES)(CC_GetRandom * // 0x017b + (IS_IMPLEMENTED+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_GetTestResult) + (COMMAND_ATTRIBUTES)(CC_GetTestResult * // 0x017c + (IS_IMPLEMENTED+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_Hash) + (COMMAND_ATTRIBUTES)(CC_Hash * // 0x017d + (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_PCR_Read) + (COMMAND_ATTRIBUTES)(CC_PCR_Read * // 0x017e + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_PolicyPCR) + (COMMAND_ATTRIBUTES)(CC_PolicyPCR * // 0x017f + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyRestart) + (COMMAND_ATTRIBUTES)(CC_PolicyRestart * // 0x0180 + (IS_IMPLEMENTED+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_ReadClock) + (COMMAND_ATTRIBUTES)(CC_ReadClock * // 0x0181 + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_PCR_Extend) + (COMMAND_ATTRIBUTES)(CC_PCR_Extend * // 0x0182 + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_PCR_SetAuthValue) + (COMMAND_ATTRIBUTES)(CC_PCR_SetAuthValue * // 0x0183 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_NV_Certify) + (COMMAND_ATTRIBUTES)(CC_NV_Certify * // 0x0184 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_EventSequenceComplete) + (COMMAND_ATTRIBUTES)(CC_EventSequenceComplete * // 0x0185 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER)), +#endif +#if (PAD_LIST || CC_HashSequenceStart) + (COMMAND_ATTRIBUTES)(CC_HashSequenceStart * // 0x0186 + (IS_IMPLEMENTED+DECRYPT_2+R_HANDLE)), +#endif +#if (PAD_LIST || CC_PolicyPhysicalPresence) + (COMMAND_ATTRIBUTES)(CC_PolicyPhysicalPresence * // 0x0187 + (IS_IMPLEMENTED+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyDuplicationSelect) + (COMMAND_ATTRIBUTES)(CC_PolicyDuplicationSelect * // 0x0188 + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyGetDigest) + (COMMAND_ATTRIBUTES)(CC_PolicyGetDigest * // 0x0189 + (IS_IMPLEMENTED+ALLOW_TRIAL+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_TestParms) + (COMMAND_ATTRIBUTES)(CC_TestParms * // 0x018a + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_Commit) + (COMMAND_ATTRIBUTES)(CC_Commit * // 0x018b + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_PolicyPassword) + (COMMAND_ATTRIBUTES)(CC_PolicyPassword * // 0x018c + (IS_IMPLEMENTED+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_ZGen_2Phase) + (COMMAND_ATTRIBUTES)(CC_ZGen_2Phase * // 0x018d + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_EC_Ephemeral) + (COMMAND_ATTRIBUTES)(CC_EC_Ephemeral * // 0x018e + (IS_IMPLEMENTED+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_PolicyNvWritten) + (COMMAND_ATTRIBUTES)(CC_PolicyNvWritten * // 0x018f + (IS_IMPLEMENTED+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_PolicyTemplate) + (COMMAND_ATTRIBUTES)(CC_PolicyTemplate * // 0x0190 + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_CreateLoaded) + (COMMAND_ATTRIBUTES)(CC_CreateLoaded * // 0x0191 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND+ENCRYPT_2+R_HANDLE)), +#endif +#if (PAD_LIST || CC_PolicyAuthorizeNV) + (COMMAND_ATTRIBUTES)(CC_PolicyAuthorizeNV * // 0x0192 + (IS_IMPLEMENTED+HANDLE_1_USER+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_EncryptDecrypt2) + (COMMAND_ATTRIBUTES)(CC_EncryptDecrypt2 * // 0x0193 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_AC_GetCapability) + (COMMAND_ATTRIBUTES)(CC_AC_GetCapability * // 0x0194 + (IS_IMPLEMENTED)), +#endif +#if (PAD_LIST || CC_AC_Send) + (COMMAND_ATTRIBUTES)(CC_AC_Send * // 0x0195 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_DUP+HANDLE_2_USER)), +#endif +#if (PAD_LIST || CC_Policy_AC_SendSelect) + (COMMAND_ATTRIBUTES)(CC_Policy_AC_SendSelect * // 0x0196 + (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), +#endif +#if (PAD_LIST || CC_CertifyX509) + (COMMAND_ATTRIBUTES)(CC_CertifyX509 * // 0x0197 + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_ACT_SetTimeout) + (COMMAND_ATTRIBUTES)(CC_ACT_SetTimeout * // 0x0198 + (IS_IMPLEMENTED+HANDLE_1_USER)), +#endif +#if (PAD_LIST || CC_ECC_Encrypt) + (COMMAND_ATTRIBUTES)(CC_ECC_Encrypt * // 0x0199 + (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_ECC_Decrypt) + (COMMAND_ATTRIBUTES)(CC_ECC_Decrypt * // 0x019A + (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), +#endif +#if (PAD_LIST || CC_Vendor_TCG_Test) + (COMMAND_ATTRIBUTES)(CC_Vendor_TCG_Test * // 0x0000 + (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), +#endif + + 0 +}; + +#endif // _COMMAND_CODE_ATTRIBUTES_ diff --git a/src/tpm2/CommandAttributes.h b/src/tpm2/CommandAttributes.h new file mode 100644 index 0000000..d7b6d67 --- /dev/null +++ b/src/tpm2/CommandAttributes.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* Command Attributes */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandAttributes.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +#ifndef COMMANDATTRIBUTES_H +#define COMMANDATTRIBUTES_H + +/* 5.7 CommandAttributes.h */ +/* The attributes defined in this file are produced by the parser that creates the structure + definitions from Part 3. The attributes are defined in that parser and should track the + attributes being tested in CommandCodeAttributes.c. Generally, when an attribute is added to this + list, new code will be needed in CommandCodeAttributes.c to test it. */ + +typedef UINT16 COMMAND_ATTRIBUTES; +#define NOT_IMPLEMENTED (COMMAND_ATTRIBUTES)(0) +#define ENCRYPT_2 ((COMMAND_ATTRIBUTES)1 << 0) +#define ENCRYPT_4 ((COMMAND_ATTRIBUTES)1 << 1) +#define DECRYPT_2 ((COMMAND_ATTRIBUTES)1 << 2) +#define DECRYPT_4 ((COMMAND_ATTRIBUTES)1 << 3) +#define HANDLE_1_USER ((COMMAND_ATTRIBUTES)1 << 4) +#define HANDLE_1_ADMIN ((COMMAND_ATTRIBUTES)1 << 5) +#define HANDLE_1_DUP ((COMMAND_ATTRIBUTES)1 << 6) +#define HANDLE_2_USER ((COMMAND_ATTRIBUTES)1 << 7) +#define PP_COMMAND ((COMMAND_ATTRIBUTES)1 << 8) +#define IS_IMPLEMENTED ((COMMAND_ATTRIBUTES)1 << 9) +#define NO_SESSIONS ((COMMAND_ATTRIBUTES)1 << 10) +#define NV_COMMAND ((COMMAND_ATTRIBUTES)1 << 11) +#define PP_REQUIRED ((COMMAND_ATTRIBUTES)1 << 12) +#define R_HANDLE ((COMMAND_ATTRIBUTES)1 << 13) +#define ALLOW_TRIAL ((COMMAND_ATTRIBUTES)1 << 14) +#endif // COMMAND_ATTRIBUTES_H diff --git a/src/tpm2/CommandAudit.c b/src/tpm2/CommandAudit.c new file mode 100644 index 0000000..1358c98 --- /dev/null +++ b/src/tpm2/CommandAudit.c @@ -0,0 +1,262 @@ +/********************************************************************************/ +/* */ +/* Functions That Support Command Audit */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandAudit.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 8.1 CommandAudit.c */ +/* 8.1.1 Introduction */ +/* This file contains the functions that support command audit. */ +/* 8.1.2 Includes */ +#include "Tpm.h" +/* 8.1.3 Functions */ +/* 8.1.3.1 CommandAuditPreInstall_Init() */ +/* This function initializes the command audit list. This function simulates the behavior of + manufacturing. A function is used instead of a structure definition because this is easier than + figuring out the initialization value for a bit array. */ +/* This function would not be implemented outside of a manufacturing or simulation environment. */ +void +CommandAuditPreInstall_Init( + void + ) +{ + // Clear all the audit commands + MemorySet(gp.auditCommands, 0x00, sizeof(gp.auditCommands)); + // TPM_CC_SetCommandCodeAuditStatus always being audited + CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus); + // Set initial command audit hash algorithm to be context integrity hash + // algorithm + gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG; + // Set up audit counter to be 0 + gp.auditCounter = 0; + // Write command audit persistent data to NV + NV_SYNC_PERSISTENT(auditCommands); + NV_SYNC_PERSISTENT(auditHashAlg); + NV_SYNC_PERSISTENT(auditCounter); + return; +} +/* 8.1.3.2 CommandAuditStartup() */ +/* This function clears the command audit digest on a TPM Reset. */ +BOOL +CommandAuditStartup( + STARTUP_TYPE type // IN: start up type + ) +{ + if((type != SU_RESTART) && (type != SU_RESUME)) + { + // Reset the digest size to initialize the digest + gr.commandAuditDigest.t.size = 0; + } + return TRUE; +} +/* 8.1.3.3 CommandAuditSet() */ +/* This function will SET the audit flag for a command. This function will not SET the audit flag + for a command that is not implemented. This ensures that the audit status is not SET when + TPM2_GetCapability() is used to read the list of audited commands. */ +/* This function is only used by TPM2_SetCommandCodeAuditStatus(). */ +/* The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to + NV after it is setting and clearing bits. */ +/* Return Values Meaning */ +/* TRUE the command code audit status was changed */ +/* FALSE the command code audit status was not changed */ +BOOL +CommandAuditSet( + TPM_CC commandCode // IN: command code + ) +{ + COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); + // Only SET a bit if the corresponding command is implemented + if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) + { + // Can't audit shutdown + if(commandCode != TPM_CC_Shutdown) + { + if(!TEST_BIT(commandIndex, gp.auditCommands)) + { + // Set bit + SET_BIT(commandIndex, gp.auditCommands); + return TRUE; + } + } + } + // No change + return FALSE; +} +/* 8.1.3.4 CommandAuditClear() */ +/* This function will CLEAR the audit flag for a command. It will not CLEAR the audit flag for + TPM_CC_SetCommandCodeAuditStatus(). */ +/* This function is only used by TPM2_SetCommandCodeAuditStatus(). */ +/* The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to + NV after it is setting and clearing bits. */ +/* Return Values Meaning */ +/* TRUE the command code audit status was changed */ +/* FALSE the command code audit status was not changed */ +BOOL +CommandAuditClear( + TPM_CC commandCode // IN: command code + ) +{ + COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); + // Do nothing if the command is not implemented + if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) + { + // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be + // cleared + if(commandCode != TPM_CC_SetCommandCodeAuditStatus) + { + if(TEST_BIT(commandIndex, gp.auditCommands)) + { + // Clear bit + CLEAR_BIT(commandIndex, gp.auditCommands); + return TRUE; + } + } + } + // No change + return FALSE; +} +/* 8.1.3.5 CommandAuditIsRequired() */ +/* This function indicates if the audit flag is SET for a command. */ +/* Return Values Meaning */ +/* TRUE if command is audited */ +/* FALSE if command is not audited */ +BOOL +CommandAuditIsRequired( + COMMAND_INDEX commandIndex // IN: command index + ) +{ + // Check the bit map. If the bit is SET, command audit is required + return(TEST_BIT(commandIndex, gp.auditCommands)); +} +/* 8.1.3.6 CommandAuditCapGetCCList() */ +/* This function returns a list of commands that have their audit bit SET. */ +/* The list starts at the input commandCode. */ +/* Return Values Meaning */ +/* YES if there are more command code available */ +/* NO all the available command code has been returned */ +TPMI_YES_NO +CommandAuditCapGetCCList( + TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: count of returned TPM_CC + TPML_CC *commandList // OUT: list of TPM_CC + ) +{ + TPMI_YES_NO more = NO; + COMMAND_INDEX commandIndex; + // Initialize output handle list + commandList->count = 0; + // The maximum count of command we may return is MAX_CAP_CC + if(count > MAX_CAP_CC) count = MAX_CAP_CC; + // Find the implemented command that has a command code that is the same or + // higher than the input + // Collect audit commands + for(commandIndex = GetClosestCommandIndex(commandCode); + commandIndex != UNIMPLEMENTED_COMMAND_INDEX; + commandIndex = GetNextCommandIndex(commandIndex)) + { + if(CommandAuditIsRequired(commandIndex)) + { + if(commandList->count < count) + { + // If we have not filled up the return list, add this command + // code to its + TPM_CC cc = GET_ATTRIBUTE(s_ccAttr[commandIndex], + TPMA_CC, commandIndex); + if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) + cc += (1 << 29); + commandList->commandCodes[commandList->count] = cc; + commandList->count++; + } + else + { + // If the return list is full but we still have command + // available, report this and stop iterating + more = YES; + break; + } + } + } + return more; +} +/* 8.1.3.7 CommandAuditGetDigest */ +/* This command is used to create a digest of the commands being audited. The commands are processed + in ascending numeric order with a list of TPM_CC being added to a hash. This operates as if all + the audited command codes were concatenated and then hashed. */ +void +CommandAuditGetDigest( + TPM2B_DIGEST *digest // OUT: command digest + ) +{ + TPM_CC commandCode; + COMMAND_INDEX commandIndex; + HASH_STATE hashState; + // Start hash + digest->t.size = CryptHashStart(&hashState, gp.auditHashAlg); + // Add command code + for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++) + { + if(CommandAuditIsRequired(commandIndex)) + { + commandCode = GetCommandCode(commandIndex); + CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); + } + } + // Complete hash + CryptHashEnd2B(&hashState, &digest->b); + return; +} diff --git a/src/tpm2/CommandAudit_fp.h b/src/tpm2/CommandAudit_fp.h new file mode 100644 index 0000000..aa43331 --- /dev/null +++ b/src/tpm2/CommandAudit_fp.h @@ -0,0 +1,97 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandAudit_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef COMMANDAUDIT_FP_H +#define COMMANDAUDIT_FP_H + +void +CommandAuditPreInstall_Init( + void + ); +BOOL +CommandAuditStartup( + STARTUP_TYPE type // IN: start up type + ); +BOOL +CommandAuditSet( + TPM_CC commandCode // IN: command code + ); +BOOL +CommandAuditClear( + TPM_CC commandCode // IN: command code + ); +BOOL +CommandAuditIsRequired( + COMMAND_INDEX commandIndex // IN: command index + ); +TPMI_YES_NO +CommandAuditCapGetCCList( + TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: count of returned TPM_CC + TPML_CC *commandList // OUT: list of TPM_CC + ); +void +CommandAuditGetDigest( + TPM2B_DIGEST *digest // OUT: command digest + ); + + +#endif diff --git a/src/tpm2/CommandCodeAttributes.c b/src/tpm2/CommandCodeAttributes.c new file mode 100644 index 0000000..f6d0f8d --- /dev/null +++ b/src/tpm2/CommandCodeAttributes.c @@ -0,0 +1,559 @@ +/********************************************************************************/ +/* */ +/* Functions for testing various command properties */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandCodeAttributes.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 9.3 CommandCodeAttributes.c */ +/* 9.3.1 Introduction */ +/* This file contains the functions for testing various command properties. */ +/* 9.3.2 Includes and Defines */ +#include "Tpm.h" +#include "CommandCodeAttributes_fp.h" +/* Set the default value for CC_VEND if not already set */ +#ifndef CC_VEND +#define CC_VEND (TPM_CC)(0x20000000) +#endif +typedef UINT16 ATTRIBUTE_TYPE; +/* The following file is produced from the command tables in part 3 of the specification. It defines + the attributes for each of the commands. */ +/* NOTE: This file is currently produced by an automated process. Files produced from Part 2 or Part + 3 tables through automated processes are not included in the specification so that there is no + ambiguity about the table containing the information being the normative definition. */ +#define _COMMAND_CODE_ATTRIBUTES_ +#include "CommandAttributeData.h" +/* 9.3.3 Command Attribute Functions */ +/* 9.3.3.1 NextImplementedIndex() */ +/* This function is used when the lists are not compressed. In a compressed list, only the + implemented commands are present. So, a search might find a value but that value may not be + implemented. This function checks to see if the input commandIndex points to an implemented + command and, if not, it searches upwards until it finds one. When the list is compressed, this + function gets defined as a no-op. */ +/* Return Value Meaning */ +/* UNIMPLEMENTED_COMMAND_INDEX command is not implemented */ +/* other index of the command */ + +#if !COMPRESSED_LISTS +static COMMAND_INDEX +NextImplementedIndex( + COMMAND_INDEX commandIndex + ) +{ + for(;commandIndex < COMMAND_COUNT; commandIndex++) + { + if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED) + return commandIndex; + } + return UNIMPLEMENTED_COMMAND_INDEX; +} +#else +#define NextImplementedIndex(x) (x) +#endif +/* 9.3.3.2 GetClosestCommandIndex() */ +/* This function returns the command index for the command with a value that is equal to or greater + than the input value */ +/* Return Value Meaning */ +/* UNIMPLEMENTED_COMMAND_INDEX command is not implemented */ +/* other index of the command */ + +COMMAND_INDEX +GetClosestCommandIndex( + TPM_CC commandCode // IN: the command code to start at + ) +{ + BOOL vendor = (commandCode & CC_VEND) != 0; + COMMAND_INDEX searchIndex = (COMMAND_INDEX)commandCode; + // The commandCode is a UINT32 and the search index is UINT16. We are going to + // search for a match but need to make sure that the commandCode value is not + // out of range. To do this, need to clear the vendor bit of the commandCode + // (if set) and compare the result to the 16-bit searchIndex value. If it is + // out of range, indicate that the command is not implemented + if((commandCode & ~CC_VEND) != searchIndex) + return UNIMPLEMENTED_COMMAND_INDEX; + // if there is at least one vendor command, the last entry in the array will + // have the v bit set. If the input commandCode is larger than the last + // vendor-command, then it is out of range. + if(vendor) + { +#if VENDOR_COMMAND_ARRAY_SIZE > 0 + COMMAND_INDEX commandIndex; + COMMAND_INDEX min; + COMMAND_INDEX max; + int diff; +#if LIBRARY_COMMAND_ARRAY_SIZE == COMMAND_COUNT +#error "Constants are not consistent." +#endif + // Check to see if the value is equal to or below the minimum + // entry. + // Note: Put this check first so that the typical case of only one vendor- + // specific command doesn't waste any more time. + if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE], TPMA_CC, + commandIndex) >= searchIndex) + { + // the vendor array is always assumed to be packed so there is + // no need to check to see if the command is implemented + return LIBRARY_COMMAND_ARRAY_SIZE; + } + // See if this is out of range on the top + if(GET_ATTRIBUTE(s_ccAttr[COMMAND_COUNT - 1], TPMA_CC, commandIndex) + < searchIndex) + { + return UNIMPLEMENTED_COMMAND_INDEX; + } + commandIndex = UNIMPLEMENTED_COMMAND_INDEX; // Needs initialization to keep + // compiler happy + min = LIBRARY_COMMAND_ARRAY_SIZE; // first vendor command + max = COMMAND_COUNT - 1; // last vendor command + diff = 1; // needs initialization to keep + // compiler happy + while(min <= max) + { + commandIndex = (min + max + 1) / 2; + diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex) + - searchIndex; + if(diff == 0) + return commandIndex; + if(diff > 0) + max = commandIndex - 1; + else + min = commandIndex + 1; + } + // didn't find and exact match. commandIndex will be pointing at the last + // item tested. If 'diff' is positive, then the last item tested was + // larger index of the command code so it is the smallest value + // larger than the requested value. + if(diff > 0) + return commandIndex; + // if 'diff' is negative, then the value tested was smaller than + // the commandCode index and the next higher value is the correct one. + // Note: this will necessarily be in range because of the earlier check + // that the index was within range. + return commandIndex + 1; +#else + // If there are no vendor commands so anything with the vendor bit set is out + // of range + return UNIMPLEMENTED_COMMAND_INDEX; +#endif + } + // Get here if the V-Bit was not set in 'commandCode' + if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE - 1], TPMA_CC, + commandIndex) < searchIndex) + { + // requested index is out of the range to the top +#if VENDOR_COMMAND_ARRAY_SIZE > 0 + // If there are vendor commands, then the first vendor command + // is the next value greater than the commandCode. + // NOTE: we got here if the starting index did not have the V bit but we + // reached the end of the array of library commands (non-vendor). Since + // there is at least one vendor command, and vendor commands are always + // in a compressed list that starts after the library list, the next + // index value contains a valid vendor command. + return LIBRARY_COMMAND_ARRAY_SIZE; +#else + // if there are no vendor commands, then this is out of range + return UNIMPLEMENTED_COMMAND_INDEX; +#endif + } + // If the request is lower than any value in the array, then return + // the lowest value (needs to be an index for an implemented command + if(GET_ATTRIBUTE(s_ccAttr[0], TPMA_CC, commandIndex) >= searchIndex) + { + return NextImplementedIndex(0); + } + else + { +#if COMPRESSED_LISTS + COMMAND_INDEX commandIndex = UNIMPLEMENTED_COMMAND_INDEX; + COMMAND_INDEX min = 0; + COMMAND_INDEX max = LIBRARY_COMMAND_ARRAY_SIZE - 1; + int diff = 1; +#if LIBRARY_COMMAND_ARRAY_SIZE == 0 +#error "Something is terribly wrong" +#endif + // The s_ccAttr array contains an extra entry at the end (a zero value). + // Don't count this as an array entry. This means that max should start + // out pointing to the last valid entry in the array which is - 2 + pAssert(max == (sizeof(s_ccAttr) / sizeof(TPMA_CC) + - VENDOR_COMMAND_ARRAY_SIZE - 2)); + while(min <= max) + { + commandIndex = (min + max + 1) / 2; + diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, + commandIndex) - searchIndex; + if(diff == 0) + return commandIndex; + if(diff > 0) + max = commandIndex - 1; + else + min = commandIndex + 1; + } + // didn't find and exact match. commandIndex will be pointing at the + // last item tested. If diff is positive, then the last item tested was + // larger index of the command code so it is the smallest value + // larger than the requested value. + if(diff > 0) + return commandIndex; + // if diff is negative, then the value tested was smaller than + // the commandCode index and the next higher value is the correct one. + // Note: this will necessarily be in range because of the earlier check + // that the index was within range. + return commandIndex + 1; +#else + // The list is not compressed so offset into the array by the command + // code value of the first entry in the list. Then go find the first + // implemented command. + return NextImplementedIndex(searchIndex + - (COMMAND_INDEX)s_ccAttr[0].commandIndex); +#endif + } +} +/* 9.3.3.3 CommandCodeToComandIndex() */ +/* This function returns the index in the various attributes arrays of the command. */ +/* Return Values Meaning */ +/* UNIMPLEMENTED_COMMAND_INDEX command is not implemented */ +/* other index of the command */ +COMMAND_INDEX +CommandCodeToCommandIndex( + TPM_CC commandCode // IN: the command code to look up + ) +{ + // Extract the low 16-bits of the command code to get the starting search index + COMMAND_INDEX searchIndex = (COMMAND_INDEX)commandCode; + BOOL vendor = (commandCode & CC_VEND) != 0; + COMMAND_INDEX commandIndex; +#if !COMPRESSED_LISTS + if(!vendor) + { + commandIndex = searchIndex - (COMMAND_INDEX)s_ccAttr[0].commandIndex; + // Check for out of range or unimplemented. + // Note, since a COMMAND_INDEX is unsigned, if searchIndex is smaller than + // the lowest value of command, it will become a 'negative' number making + // it look like a large unsigned number, this will cause it to fail + // the unsigned check below. + if(commandIndex >= LIBRARY_COMMAND_ARRAY_SIZE + || (s_commandAttributes[commandIndex] & IS_IMPLEMENTED) == 0) + return UNIMPLEMENTED_COMMAND_INDEX; + return commandIndex; + } +#endif + // Need this code for any vendor code lookup or for compressed lists + commandIndex = GetClosestCommandIndex(commandCode); + // Look at the returned value from get closest. If it isn't the one that was + // requested, then the command is not implemented. + if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) + { + if((GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex) + != searchIndex) + || (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) != vendor) + commandIndex = UNIMPLEMENTED_COMMAND_INDEX; + } + return commandIndex; +} +/* 9.3.3.4 GetNextCommandIndex() */ +/* This function returns the index of the next implemented command. */ +/* Return Values Meaning */ +/* UNIMPLEMENTED_COMMAND_INDEX no more implemented commands */ +/* other the index of the next implemented command */ +COMMAND_INDEX +GetNextCommandIndex( + COMMAND_INDEX commandIndex // IN: the starting index + ) +{ + while(++commandIndex < COMMAND_COUNT) + { +#if !COMPRESSED_LISTS + if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED) +#endif + return commandIndex; + } + return UNIMPLEMENTED_COMMAND_INDEX; +} +/* 9.3.3.5 GetCommandCode() */ +/* This function returns the commandCode associated with the command index */ +TPM_CC +GetCommandCode( + COMMAND_INDEX commandIndex // IN: the command index + ) +{ + TPM_CC commandCode = GET_ATTRIBUTE(s_ccAttr[commandIndex], + TPMA_CC, commandIndex); + if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) + commandCode += CC_VEND; + return commandCode; +} +/* 9.3.3.6 CommandAuthRole() */ +/* This function returns the authorization role required of a handle. */ +/* Return Values Meaning */ +/* AUTH_NONE no authorization is required */ +/* AUTH_USER user role authorization is required */ +/* AUTH_ADMIN admin role authorization is required */ +/* AUTH_DUP duplication role authorization is required */ +AUTH_ROLE +CommandAuthRole( + COMMAND_INDEX commandIndex, // IN: command index + UINT32 handleIndex // IN: handle index (zero based) + ) +{ + if(0 == handleIndex) + { + // Any authorization role set? + COMMAND_ATTRIBUTES properties = s_commandAttributes[commandIndex]; + if(properties & HANDLE_1_USER) + return AUTH_USER; + if(properties & HANDLE_1_ADMIN) + return AUTH_ADMIN; + if(properties & HANDLE_1_DUP) + return AUTH_DUP; + } + else if(1 == handleIndex) + { + if(s_commandAttributes[commandIndex] & HANDLE_2_USER) + return AUTH_USER; + } + return AUTH_NONE; +} +/* 9.3.3.7 EncryptSize() */ +/* This function returns the size of the decrypt size field. This function returns 0 if encryption + is not allowed */ +/* Return Values Meaning */ +/* 0 encryption not allowed */ +/* 2 size field is two bytes */ +/* 4 size field is four bytes */ + +int +EncryptSize( + COMMAND_INDEX commandIndex // IN: command index + ) +{ + return ((s_commandAttributes[commandIndex] & ENCRYPT_2) ? 2 : + (s_commandAttributes[commandIndex] & ENCRYPT_4) ? 4 : 0); +} + +/* 9.3.3.8 DecryptSize() */ +/* This function returns the size of the decrypt size field. This function returns 0 if decryption + is not allowed */ +/* Return Values Meaning */ +/* 0 encryption not allowed */ +/* 2 size field is two bytes */ +/* 4 size field is four bytes */ + +int +DecryptSize( + COMMAND_INDEX commandIndex // IN: command index + ) +{ + return ((s_commandAttributes[commandIndex] & DECRYPT_2) ? 2 : + (s_commandAttributes[commandIndex] & DECRYPT_4) ? 4 : 0); +} + +/* 9.3.3.9 IsSessionAllowed() */ +/* This function indicates if the command is allowed to have sessions. */ +/* This function must not be called if the command is not known to be implemented. */ +/* Return Values Meaning */ +/* TRUE session is allowed with this command */ +/* FALSE session is not allowed with this command */ + +BOOL +IsSessionAllowed( + COMMAND_INDEX commandIndex // IN: the command to be checked + ) +{ + return ((s_commandAttributes[commandIndex] & NO_SESSIONS) == 0); +} + +/* 9.3.3.10 IsHandleInResponse() */ +/* This function determines if a command has a handle in the response */ + +BOOL +IsHandleInResponse( + COMMAND_INDEX commandIndex + ) +{ + return ((s_commandAttributes[commandIndex] & R_HANDLE) != 0); +} + +/* 9.3.3.11 IsWriteOperation() */ +/* Checks to see if an operation will write to an NV Index and is subject to being blocked by + read-lock */ +BOOL +IsWriteOperation( + COMMAND_INDEX commandIndex // IN: Command to check + ) +{ +#ifdef WRITE_LOCK + return ((s_commandAttributes[commandIndex] & WRITE_LOCK) != 0); +#else + if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) + { + switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)) + { + case TPM_CC_NV_Write: +#if CC_NV_Increment + case TPM_CC_NV_Increment: +#endif +#if CC_NV_SetBits + case TPM_CC_NV_SetBits: +#endif +#if CC_NV_Extend + case TPM_CC_NV_Extend: +#endif +#if CC_AC_Send + case TPM_CC_AC_Send: +#endif + // NV write lock counts as a write operation for authorization purposes. + // We check to see if the NV is write locked before we do the + // authorization. If it is locked, we fail the command early. + case TPM_CC_NV_WriteLock: + return TRUE; + default: + break; + } + } + return FALSE; +#endif +} +/* 9.3.3.12 IsReadOperation() */ +/* Checks to see if an operation will write to an NV Index and is subject to being blocked by + write-lock. */ +BOOL +IsReadOperation( + COMMAND_INDEX commandIndex // IN: Command to check + ) +{ +#ifdef READ_LOCK + return ((s_commandAttributes[commandIndex] & READ_LOCK) != 0); +#else + if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) + { + switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)) + { + case TPM_CC_NV_Read: + case TPM_CC_PolicyNV: + case TPM_CC_NV_Certify: + // NV read lock counts as a read operation for authorization purposes. + // We check to see if the NV is read locked before we do the + // authorization. If it is locked, we fail the command early. + case TPM_CC_NV_ReadLock: + return TRUE; + default: + break; + } + } + return FALSE; +#endif +} +/* 9.3.3.13 CommandCapGetCCList() */ +/* This function returns a list of implemented commands and command attributes starting from the + command in commandCode. */ +/* Return Values Meaning */ +/* YES more command attributes are available */ +/* NO no more command attributes are available */ +TPMI_YES_NO +CommandCapGetCCList( + TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: maximum count for number of entries in + // 'commandList' + TPML_CCA *commandList // OUT: list of TPMA_CC + ) +{ + TPMI_YES_NO more = NO; + COMMAND_INDEX commandIndex; + // initialize output handle list count + commandList->count = 0; + for(commandIndex = GetClosestCommandIndex(commandCode); + commandIndex != UNIMPLEMENTED_COMMAND_INDEX; + commandIndex = GetNextCommandIndex(commandIndex)) + { +#if !COMPRESSED_LISTS + // this check isn't needed for compressed lists. + if(!(s_commandAttributes[commandIndex] & IS_IMPLEMENTED)) + continue; +#endif + if(commandList->count < count) + { + // If the list is not full, add the attributes for this command. + commandList->commandAttributes[commandList->count] + = s_ccAttr[commandIndex]; + commandList->count++; + } + else + { + // If the list is full but there are more commands to report, + // indicate this and return. + more = YES; + break; + } + } + return more; +} +#if 0 /* libtpms added */ +/* 9.3.3.14 IsVendorCommand() */ +/* Function indicates if a command index references a vendor command. */ +/* Return Values Meaning */ +/* TRUE command is a vendor command */ +/* FALSE command is not a vendor command */ + +BOOL +IsVendorCommand( + COMMAND_INDEX commandIndex // IN: command index to check + ) +{ + return (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)); +} +#endif /* libtpms added */ + diff --git a/src/tpm2/CommandCodeAttributes_fp.h b/src/tpm2/CommandCodeAttributes_fp.h new file mode 100644 index 0000000..18755b1 --- /dev/null +++ b/src/tpm2/CommandCodeAttributes_fp.h @@ -0,0 +1,125 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandCodeAttributes_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef COMMANDCODEATTRIBUTES_FP_H +#define COMMANDCODEATTRIBUTES_FP_H + +COMMAND_INDEX +GetClosestCommandIndex( + TPM_CC commandCode // IN: the command code to start at + ); +COMMAND_INDEX +CommandCodeToCommandIndex( + TPM_CC commandCode // IN: the command code to look up + ); +COMMAND_INDEX +GetNextCommandIndex( + COMMAND_INDEX commandIndex // IN: the starting index + ); +TPM_CC +GetCommandCode( + COMMAND_INDEX commandIndex // IN: the command index + ); +AUTH_ROLE +CommandAuthRole( + COMMAND_INDEX commandIndex, // IN: command index + UINT32 handleIndex // IN: handle index (zero based) + ); +int +EncryptSize( + COMMAND_INDEX commandIndex // IN: command index + ); +int +DecryptSize( + COMMAND_INDEX commandIndex // IN: command index + ); +BOOL +IsSessionAllowed( + COMMAND_INDEX commandIndex // IN: the command to be checked + ); +BOOL +IsHandleInResponse( + COMMAND_INDEX commandIndex + ); +BOOL +IsWriteOperation( + COMMAND_INDEX commandIndex // IN: Command to check + ); +BOOL +IsReadOperation( + COMMAND_INDEX commandIndex // IN: Command to check + ); +TPMI_YES_NO +CommandCapGetCCList( + TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: maximum count for number of entries in + // 'commandList' + TPML_CCA *commandList // OUT: list of TPMA_CC + ); +#if 0 /* libtpms added */ +BOOL +IsVendorCommand( + COMMAND_INDEX commandIndex // IN: command index to check + ); +#endif /* libtpms added */ + + +#endif diff --git a/src/tpm2/CommandDispatchData.h b/src/tpm2/CommandDispatchData.h new file mode 100644 index 0000000..b11096c --- /dev/null +++ b/src/tpm2/CommandDispatchData.h @@ -0,0 +1,4623 @@ +/********************************************************************************/ +/* */ +/* Command DIspatch Data */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandDispatchData.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* This file should only be included by CommandCodeAttibutes.c */ +#ifdef _COMMAND_TABLE_DISPATCH_ + +#define END_OF_LIST 0xff +#define ADD_FLAG 0x80 + +/* These macros provide some variability in how the data is encoded. They also make the lines a + little shorter. ;-) */ + +#if TABLE_DRIVEN_MARSHAL +# define UNMARSHAL_DISPATCH(name) (marshalIndex_t)name##_MARSHAL_REF +# define MARSHAL_DISPATCH(name) (marshalIndex_t)name##_MARSHAL_REF +# define _UNMARSHAL_T_ marshalIndex_t +# define _MARSHAL_T_ marshalIndex_t +# +#else +# define UNMARSHAL_DISPATCH(name) (UNMARSHAL_t)name##_Unmarshal +# define MARSHAL_DISPATCH(name) (MARSHAL_t)name##_Marshal +# define _UNMARSHAL_T_ UNMARSHAL_t +# define _MARSHAL_T_ MARSHAL_t +#endif + +const _UNMARSHAL_T_ unmarshalArray[] = { +#define TPMI_DH_CONTEXT_H_UNMARSHAL 0 + UNMARSHAL_DISPATCH(TPMI_DH_CONTEXT), +#define TPMI_RH_AC_H_UNMARSHAL (TPMI_DH_CONTEXT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_AC), +#define TPMI_RH_ACT_H_UNMARSHAL (TPMI_RH_AC_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_ACT), +#define TPMI_RH_CLEAR_H_UNMARSHAL (TPMI_RH_ACT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_CLEAR), +#define TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL (TPMI_RH_CLEAR_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY_AUTH), +#define TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL \ + (TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY_POLICY), +#define TPMI_RH_LOCKOUT_H_UNMARSHAL \ + (TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_LOCKOUT), +#define TPMI_RH_NV_AUTH_H_UNMARSHAL (TPMI_RH_LOCKOUT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_NV_AUTH), +#define TPMI_RH_NV_INDEX_H_UNMARSHAL (TPMI_RH_NV_AUTH_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_NV_INDEX), +#define TPMI_RH_PLATFORM_H_UNMARSHAL (TPMI_RH_NV_INDEX_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_PLATFORM), +#define TPMI_RH_PROVISION_H_UNMARSHAL (TPMI_RH_PLATFORM_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_PROVISION), +#define TPMI_SH_HMAC_H_UNMARSHAL (TPMI_RH_PROVISION_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_SH_HMAC), +#define TPMI_SH_POLICY_H_UNMARSHAL (TPMI_SH_HMAC_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_SH_POLICY), + // HANDLE_FIRST_FLAG_TYPE is the first handle that needs a flag when called. +#define HANDLE_FIRST_FLAG_TYPE (TPMI_SH_POLICY_H_UNMARSHAL + 1) +#define TPMI_DH_ENTITY_H_UNMARSHAL (TPMI_SH_POLICY_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_ENTITY), +#define TPMI_DH_OBJECT_H_UNMARSHAL (TPMI_DH_ENTITY_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_OBJECT), +#define TPMI_DH_PARENT_H_UNMARSHAL (TPMI_DH_OBJECT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_PARENT), +#define TPMI_DH_PCR_H_UNMARSHAL (TPMI_DH_PARENT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_PCR), +#define TPMI_RH_ENDORSEMENT_H_UNMARSHAL (TPMI_DH_PCR_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_ENDORSEMENT), +#define TPMI_RH_HIERARCHY_H_UNMARSHAL \ + (TPMI_RH_ENDORSEMENT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY), + // PARAMETER_FIRST_TYPE marks the end of the handle list. +#define PARAMETER_FIRST_TYPE (TPMI_RH_HIERARCHY_H_UNMARSHAL + 1) +#define TPM2B_DATA_P_UNMARSHAL (TPMI_RH_HIERARCHY_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_DATA), +#define TPM2B_DIGEST_P_UNMARSHAL (TPM2B_DATA_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_DIGEST), +#define TPM2B_ECC_PARAMETER_P_UNMARSHAL (TPM2B_DIGEST_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_ECC_PARAMETER), +#define TPM2B_ECC_POINT_P_UNMARSHAL \ + (TPM2B_ECC_PARAMETER_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_ECC_POINT), +#define TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL (TPM2B_ECC_POINT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_ENCRYPTED_SECRET), +#define TPM2B_EVENT_P_UNMARSHAL \ + (TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_EVENT), +#define TPM2B_ID_OBJECT_P_UNMARSHAL (TPM2B_EVENT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_ID_OBJECT), +#define TPM2B_IV_P_UNMARSHAL (TPM2B_ID_OBJECT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_IV), +#define TPM2B_MAX_BUFFER_P_UNMARSHAL (TPM2B_IV_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_MAX_BUFFER), +#define TPM2B_MAX_NV_BUFFER_P_UNMARSHAL (TPM2B_MAX_BUFFER_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_MAX_NV_BUFFER), +#define TPM2B_NAME_P_UNMARSHAL \ + (TPM2B_MAX_NV_BUFFER_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_NAME), +#define TPM2B_NV_PUBLIC_P_UNMARSHAL (TPM2B_NAME_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_NV_PUBLIC), +#define TPM2B_PRIVATE_P_UNMARSHAL (TPM2B_NV_PUBLIC_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_PRIVATE), +#define TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL (TPM2B_PRIVATE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_PUBLIC_KEY_RSA), +#define TPM2B_SENSITIVE_P_UNMARSHAL \ + (TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_SENSITIVE), +#define TPM2B_SENSITIVE_CREATE_P_UNMARSHAL (TPM2B_SENSITIVE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_SENSITIVE_CREATE), +#define TPM2B_SENSITIVE_DATA_P_UNMARSHAL \ + (TPM2B_SENSITIVE_CREATE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_SENSITIVE_DATA), +#define TPM2B_TEMPLATE_P_UNMARSHAL \ + (TPM2B_SENSITIVE_DATA_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_TEMPLATE), +#define TPM2B_TIMEOUT_P_UNMARSHAL (TPM2B_TEMPLATE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_TIMEOUT), +#define TPMI_DH_CONTEXT_P_UNMARSHAL (TPM2B_TIMEOUT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_CONTEXT), +#define TPMI_DH_PERSISTENT_P_UNMARSHAL (TPMI_DH_CONTEXT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_PERSISTENT), +#define TPMI_ECC_CURVE_P_UNMARSHAL (TPMI_DH_PERSISTENT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ECC_CURVE), +#define TPMI_YES_NO_P_UNMARSHAL (TPMI_ECC_CURVE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_YES_NO), +#define TPML_ALG_P_UNMARSHAL (TPMI_YES_NO_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_ALG), +#define TPML_CC_P_UNMARSHAL (TPML_ALG_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_CC), +#define TPML_DIGEST_P_UNMARSHAL (TPML_CC_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_DIGEST), +#define TPML_DIGEST_VALUES_P_UNMARSHAL (TPML_DIGEST_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_DIGEST_VALUES), +#define TPML_PCR_SELECTION_P_UNMARSHAL (TPML_DIGEST_VALUES_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_PCR_SELECTION), +#define TPMS_CONTEXT_P_UNMARSHAL (TPML_PCR_SELECTION_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMS_CONTEXT), +#define TPMT_PUBLIC_PARMS_P_UNMARSHAL (TPMS_CONTEXT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_PUBLIC_PARMS), +#define TPMT_TK_AUTH_P_UNMARSHAL (TPMT_PUBLIC_PARMS_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_TK_AUTH), +#define TPMT_TK_CREATION_P_UNMARSHAL (TPMT_TK_AUTH_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_TK_CREATION), +#define TPMT_TK_HASHCHECK_P_UNMARSHAL (TPMT_TK_CREATION_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_TK_HASHCHECK), +#define TPMT_TK_VERIFIED_P_UNMARSHAL (TPMT_TK_HASHCHECK_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_TK_VERIFIED), +#define TPM_AT_P_UNMARSHAL (TPMT_TK_VERIFIED_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_AT), +#define TPM_CAP_P_UNMARSHAL (TPM_AT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_CAP), +#define TPM_CLOCK_ADJUST_P_UNMARSHAL (TPM_CAP_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_CLOCK_ADJUST), +#define TPM_EO_P_UNMARSHAL (TPM_CLOCK_ADJUST_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_EO), +#define TPM_SE_P_UNMARSHAL (TPM_EO_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_SE), +#define TPM_SU_P_UNMARSHAL (TPM_SE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_SU), +#define UINT16_P_UNMARSHAL (TPM_SU_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(UINT16), +#define UINT32_P_UNMARSHAL (UINT16_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(UINT32), +#define UINT64_P_UNMARSHAL (UINT32_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(UINT64), +#define UINT8_P_UNMARSHAL (UINT64_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(UINT8), + // PARAMETER_FIRST_FLAG_TYPE is the first parameter to need a flag. +#define PARAMETER_FIRST_FLAG_TYPE (UINT8_P_UNMARSHAL + 1) +#define TPM2B_PUBLIC_P_UNMARSHAL (UINT8_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_PUBLIC), +#define TPMI_ALG_CIPHER_MODE_P_UNMARSHAL (TPM2B_PUBLIC_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ALG_CIPHER_MODE), +#define TPMI_ALG_HASH_P_UNMARSHAL \ + (TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ALG_HASH), +#define TPMI_ALG_MAC_SCHEME_P_UNMARSHAL (TPMI_ALG_HASH_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ALG_MAC_SCHEME), +#define TPMI_DH_PCR_P_UNMARSHAL \ + (TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_PCR), +#define TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL (TPMI_DH_PCR_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ECC_KEY_EXCHANGE), +#define TPMI_RH_ENABLES_P_UNMARSHAL \ + (TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_ENABLES), +#define TPMI_RH_HIERARCHY_P_UNMARSHAL (TPMI_RH_ENABLES_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY), +#define TPMT_KDF_SCHEME_P_UNMARSHAL (TPMI_RH_HIERARCHY_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_KDF_SCHEME), +#define TPMT_RSA_DECRYPT_P_UNMARSHAL (TPMT_KDF_SCHEME_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_RSA_DECRYPT), +#define TPMT_SIGNATURE_P_UNMARSHAL (TPMT_RSA_DECRYPT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_SIGNATURE), +#define TPMT_SIG_SCHEME_P_UNMARSHAL (TPMT_SIGNATURE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_SIG_SCHEME), +#define TPMT_SYM_DEF_P_UNMARSHAL (TPMT_SIG_SCHEME_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_SYM_DEF), +#define TPMT_SYM_DEF_OBJECT_P_UNMARSHAL (TPMT_SYM_DEF_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_SYM_DEF_OBJECT) + // PARAMETER_LAST_TYPE is the end of the command parameter list. + + // PARAMETER_LAST_TYPE is the end of the command parameter list. +#define PARAMETER_LAST_TYPE (TPMT_SYM_DEF_OBJECT_P_UNMARSHAL) + +}; + + +const _MARSHAL_T_ marshalArray[] = { + +#define UINT32_H_MARSHAL 0 + MARSHAL_DISPATCH(UINT32), + // RESPONSE_PARAMETER_FIRST_TYPE marks the end of the response handles. +#define RESPONSE_PARAMETER_FIRST_TYPE (UINT32_H_MARSHAL + 1) +#define TPM2B_ATTEST_P_MARSHAL (UINT32_H_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_ATTEST), +#define TPM2B_CREATION_DATA_P_MARSHAL (TPM2B_ATTEST_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_CREATION_DATA), +#define TPM2B_DATA_P_MARSHAL (TPM2B_CREATION_DATA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_DATA), +#define TPM2B_DIGEST_P_MARSHAL (TPM2B_DATA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_DIGEST), +#define TPM2B_ECC_POINT_P_MARSHAL (TPM2B_DIGEST_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_ECC_POINT), +#define TPM2B_ENCRYPTED_SECRET_P_MARSHAL (TPM2B_ECC_POINT_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_ENCRYPTED_SECRET), +#define TPM2B_ID_OBJECT_P_MARSHAL \ + (TPM2B_ENCRYPTED_SECRET_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_ID_OBJECT), +#define TPM2B_IV_P_MARSHAL (TPM2B_ID_OBJECT_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_IV), +#define TPM2B_MAX_BUFFER_P_MARSHAL (TPM2B_IV_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_MAX_BUFFER), +#define TPM2B_MAX_NV_BUFFER_P_MARSHAL (TPM2B_MAX_BUFFER_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_MAX_NV_BUFFER), +#define TPM2B_NAME_P_MARSHAL (TPM2B_MAX_NV_BUFFER_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_NAME), +#define TPM2B_NV_PUBLIC_P_MARSHAL (TPM2B_NAME_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_NV_PUBLIC), +#define TPM2B_PRIVATE_P_MARSHAL (TPM2B_NV_PUBLIC_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_PRIVATE), +#define TPM2B_PUBLIC_P_MARSHAL (TPM2B_PRIVATE_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_PUBLIC), +#define TPM2B_PUBLIC_KEY_RSA_P_MARSHAL (TPM2B_PUBLIC_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_PUBLIC_KEY_RSA), +#define TPM2B_SENSITIVE_DATA_P_MARSHAL (TPM2B_PUBLIC_KEY_RSA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_SENSITIVE_DATA), +#define TPM2B_TIMEOUT_P_MARSHAL (TPM2B_SENSITIVE_DATA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_TIMEOUT), +#define UINT8_P_MARSHAL (TPM2B_TIMEOUT_P_MARSHAL + 1) + MARSHAL_DISPATCH(UINT8), +#define TPML_AC_CAPABILITIES_P_MARSHAL (UINT8_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_AC_CAPABILITIES), +#define TPML_ALG_P_MARSHAL (TPML_AC_CAPABILITIES_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_ALG), +#define TPML_DIGEST_P_MARSHAL (TPML_ALG_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_DIGEST), +#define TPML_DIGEST_VALUES_P_MARSHAL (TPML_DIGEST_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_DIGEST_VALUES), +#define TPML_PCR_SELECTION_P_MARSHAL (TPML_DIGEST_VALUES_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_PCR_SELECTION), +#define TPMS_AC_OUTPUT_P_MARSHAL (TPML_PCR_SELECTION_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_AC_OUTPUT), +#define TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL (TPMS_AC_OUTPUT_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_ALGORITHM_DETAIL_ECC), +#define TPMS_CAPABILITY_DATA_P_MARSHAL \ + (TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_CAPABILITY_DATA), +#define TPMS_CONTEXT_P_MARSHAL (TPMS_CAPABILITY_DATA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_CONTEXT), +#define TPMS_TIME_INFO_P_MARSHAL (TPMS_CONTEXT_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_TIME_INFO), +#define TPMT_HA_P_MARSHAL (TPMS_TIME_INFO_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_HA), +#define TPMT_SIGNATURE_P_MARSHAL (TPMT_HA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_SIGNATURE), +#define TPMT_TK_AUTH_P_MARSHAL (TPMT_SIGNATURE_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_TK_AUTH), +#define TPMT_TK_CREATION_P_MARSHAL (TPMT_TK_AUTH_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_TK_CREATION), +#define TPMT_TK_HASHCHECK_P_MARSHAL (TPMT_TK_CREATION_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_TK_HASHCHECK), +#define TPMT_TK_VERIFIED_P_MARSHAL (TPMT_TK_HASHCHECK_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_TK_VERIFIED), +#define UINT32_P_MARSHAL (TPMT_TK_VERIFIED_P_MARSHAL + 1) + MARSHAL_DISPATCH(UINT32), +#define UINT16_P_MARSHAL (UINT32_P_MARSHAL + 1) + MARSHAL_DISPATCH(UINT16) + +#define RESPONSE_PARAMETER_LAST_TYPE (UINT16_P_MARSHAL) +}; + +/* This list of aliases allows the types in the _COMMAND_DESCRIPTOR_T to match the types in the + command/response templates of part 3. */ +#define INT32_P_UNMARSHAL UINT32_P_UNMARSHAL +#define TPM2B_AUTH_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL +#define TPM2B_NONCE_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL +#define TPM2B_OPERAND_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL +#define TPMA_LOCALITY_P_UNMARSHAL UINT8_P_UNMARSHAL +#define TPM_CC_P_UNMARSHAL UINT32_P_UNMARSHAL +#define TPMI_DH_CONTEXT_H_MARSHAL UINT32_H_MARSHAL +#define TPMI_DH_OBJECT_H_MARSHAL UINT32_H_MARSHAL +#define TPMI_SH_AUTH_SESSION_H_MARSHAL UINT32_H_MARSHAL +#define TPM_HANDLE_H_MARSHAL UINT32_H_MARSHAL +#define TPM2B_NONCE_P_MARSHAL TPM2B_DIGEST_P_MARSHAL +#define TPMI_YES_NO_P_MARSHAL UINT8_P_MARSHAL +#define TPM_RC_P_MARSHAL UINT32_P_MARSHAL + +#if CC_Startup +#include "Startup_fp.h" +typedef TPM_RC (Startup_Entry)( + Startup_In *in + ); +typedef const struct { + Startup_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} Startup_COMMAND_DESCRIPTOR_t; +Startup_COMMAND_DESCRIPTOR_t _StartupData = { + /* entry */ &TPM2_Startup, + /* inSize */ (UINT16)(sizeof(Startup_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(Startup_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPM_SU_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _StartupDataAddress (&_StartupData) +#else +#define _StartupDataAddress 0 +#endif +#if CC_Shutdown +#include "Shutdown_fp.h" +typedef TPM_RC (Shutdown_Entry)( + Shutdown_In *in + ); +typedef const struct { + Shutdown_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} Shutdown_COMMAND_DESCRIPTOR_t; +Shutdown_COMMAND_DESCRIPTOR_t _ShutdownData = { + /* entry */ &TPM2_Shutdown, + /* inSize */ (UINT16)(sizeof(Shutdown_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(Shutdown_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPM_SU_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _ShutdownDataAddress (&_ShutdownData) +#else +#define _ShutdownDataAddress 0 +#endif +#if CC_SelfTest +#include "SelfTest_fp.h" +typedef TPM_RC (SelfTest_Entry)( + SelfTest_In *in + ); +typedef const struct { + SelfTest_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} SelfTest_COMMAND_DESCRIPTOR_t; +SelfTest_COMMAND_DESCRIPTOR_t _SelfTestData = { + /* entry */ &TPM2_SelfTest, + /* inSize */ (UINT16)(sizeof(SelfTest_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SelfTest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _SelfTestDataAddress (&_SelfTestData) +#else +#define _SelfTestDataAddress 0 +#endif +#if CC_IncrementalSelfTest +#include "IncrementalSelfTest_fp.h" +typedef TPM_RC (IncrementalSelfTest_Entry)( + IncrementalSelfTest_In *in, + IncrementalSelfTest_Out *out + ); +typedef const struct { + IncrementalSelfTest_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} IncrementalSelfTest_COMMAND_DESCRIPTOR_t; +IncrementalSelfTest_COMMAND_DESCRIPTOR_t _IncrementalSelfTestData = { + /* entry */ &TPM2_IncrementalSelfTest, + /* inSize */ (UINT16)(sizeof(IncrementalSelfTest_In)), + /* outSize */ (UINT16)(sizeof(IncrementalSelfTest_Out)), + /* offsetOfTypes */ offsetof(IncrementalSelfTest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPML_ALG_P_UNMARSHAL, + END_OF_LIST, + TPML_ALG_P_MARSHAL, + END_OF_LIST} +}; +#define _IncrementalSelfTestDataAddress (&_IncrementalSelfTestData) +#else +#define _IncrementalSelfTestDataAddress 0 +#endif +#if CC_GetTestResult +#include "GetTestResult_fp.h" +typedef TPM_RC (GetTestResult_Entry)( + GetTestResult_Out *out + ); +typedef const struct { + GetTestResult_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} GetTestResult_COMMAND_DESCRIPTOR_t; +GetTestResult_COMMAND_DESCRIPTOR_t _GetTestResultData = { + /* entry */ &TPM2_GetTestResult, + /* inSize */ 0, + /* outSize */ (UINT16)(sizeof(GetTestResult_Out)), + /* offsetOfTypes */ offsetof(GetTestResult_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(GetTestResult_Out, testResult))}, + /* types */ {END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM_RC_P_MARSHAL, + END_OF_LIST} +}; +#define _GetTestResultDataAddress (&_GetTestResultData) +#else +#define _GetTestResultDataAddress 0 +#endif +#if CC_StartAuthSession +#include "StartAuthSession_fp.h" +typedef TPM_RC (StartAuthSession_Entry)( + StartAuthSession_In *in, + StartAuthSession_Out *out + ); +typedef const struct { + StartAuthSession_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[7]; + BYTE types[11]; +} StartAuthSession_COMMAND_DESCRIPTOR_t; +StartAuthSession_COMMAND_DESCRIPTOR_t _StartAuthSessionData = { + /* entry */ &TPM2_StartAuthSession, + /* inSize */ (UINT16)(sizeof(StartAuthSession_In)), + /* outSize */ (UINT16)(sizeof(StartAuthSession_Out)), + /* offsetOfTypes */ offsetof(StartAuthSession_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(StartAuthSession_In, bind)), + (UINT16)(offsetof(StartAuthSession_In, nonceCaller)), + (UINT16)(offsetof(StartAuthSession_In, encryptedSalt)), + (UINT16)(offsetof(StartAuthSession_In, sessionType)), + (UINT16)(offsetof(StartAuthSession_In, symmetric)), + (UINT16)(offsetof(StartAuthSession_In, authHash)), + (UINT16)(offsetof(StartAuthSession_Out, nonceTPM))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_DH_ENTITY_H_UNMARSHAL + ADD_FLAG, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, + TPM_SE_P_UNMARSHAL, + TPMT_SYM_DEF_P_UNMARSHAL + ADD_FLAG, + TPMI_ALG_HASH_P_UNMARSHAL, + END_OF_LIST, + TPMI_SH_AUTH_SESSION_H_MARSHAL, + TPM2B_NONCE_P_MARSHAL, + END_OF_LIST} +}; +#define _StartAuthSessionDataAddress (&_StartAuthSessionData) +#else +#define _StartAuthSessionDataAddress 0 +#endif +#if CC_PolicyRestart +#include "PolicyRestart_fp.h" +typedef TPM_RC (PolicyRestart_Entry)( + PolicyRestart_In *in + ); +typedef const struct { + PolicyRestart_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PolicyRestart_COMMAND_DESCRIPTOR_t; +PolicyRestart_COMMAND_DESCRIPTOR_t _PolicyRestartData = { + /* entry */ &TPM2_PolicyRestart, + /* inSize */ (UINT16)(sizeof(PolicyRestart_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyRestart_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyRestartDataAddress (&_PolicyRestartData) +#else +#define _PolicyRestartDataAddress 0 +#endif +#if CC_Create +#include "Create_fp.h" +typedef TPM_RC (Create_Entry)( + Create_In *in, + Create_Out *out + ); +typedef const struct { + Create_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[8]; + BYTE types[12]; +} Create_COMMAND_DESCRIPTOR_t; +Create_COMMAND_DESCRIPTOR_t _CreateData = { + /* entry */ &TPM2_Create, + /* inSize */ (UINT16)(sizeof(Create_In)), + /* outSize */ (UINT16)(sizeof(Create_Out)), + /* offsetOfTypes */ offsetof(Create_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Create_In, inSensitive)), + (UINT16)(offsetof(Create_In, inPublic)), + (UINT16)(offsetof(Create_In, outsideInfo)), + (UINT16)(offsetof(Create_In, creationPCR)), + (UINT16)(offsetof(Create_Out, outPublic)), + (UINT16)(offsetof(Create_Out, creationData)), + (UINT16)(offsetof(Create_Out, creationHash)), + (UINT16)(offsetof(Create_Out, creationTicket))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PRIVATE_P_MARSHAL, + TPM2B_PUBLIC_P_MARSHAL, + TPM2B_CREATION_DATA_P_MARSHAL, + TPM2B_DIGEST_P_MARSHAL, + TPMT_TK_CREATION_P_MARSHAL, + END_OF_LIST} +}; +#define _CreateDataAddress (&_CreateData) +#else +#define _CreateDataAddress 0 +#endif +#if CC_Load +#include "Load_fp.h" +typedef TPM_RC (Load_Entry)( + Load_In *in, + Load_Out *out + ); +typedef const struct { + Load_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} Load_COMMAND_DESCRIPTOR_t; +Load_COMMAND_DESCRIPTOR_t _LoadData = { + /* entry */ &TPM2_Load, + /* inSize */ (UINT16)(sizeof(Load_In)), + /* outSize */ (UINT16)(sizeof(Load_Out)), + /* offsetOfTypes */ offsetof(Load_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Load_In, inPrivate)), + (UINT16)(offsetof(Load_In, inPublic)), + (UINT16)(offsetof(Load_Out, name))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_PRIVATE_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL, + END_OF_LIST, + TPM_HANDLE_H_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST} +}; +#define _LoadDataAddress (&_LoadData) +#else +#define _LoadDataAddress 0 +#endif +#if CC_LoadExternal +#include "LoadExternal_fp.h" +typedef TPM_RC (LoadExternal_Entry)( + LoadExternal_In *in, + LoadExternal_Out *out + ); +typedef const struct { + LoadExternal_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} LoadExternal_COMMAND_DESCRIPTOR_t; +LoadExternal_COMMAND_DESCRIPTOR_t _LoadExternalData = { + /* entry */ &TPM2_LoadExternal, + /* inSize */ (UINT16)(sizeof(LoadExternal_In)), + /* outSize */ (UINT16)(sizeof(LoadExternal_Out)), + /* offsetOfTypes */ offsetof(LoadExternal_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(LoadExternal_In, inPublic)), + (UINT16)(offsetof(LoadExternal_In, hierarchy)), + (UINT16)(offsetof(LoadExternal_Out, name))}, + /* types */ {TPM2B_SENSITIVE_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL + ADD_FLAG, + TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM_HANDLE_H_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST} +}; +#define _LoadExternalDataAddress (&_LoadExternalData) +#else +#define _LoadExternalDataAddress 0 +#endif +#if CC_ReadPublic +#include "ReadPublic_fp.h" +typedef TPM_RC (ReadPublic_Entry)( + ReadPublic_In *in, + ReadPublic_Out *out + ); +typedef const struct { + ReadPublic_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} ReadPublic_COMMAND_DESCRIPTOR_t; +ReadPublic_COMMAND_DESCRIPTOR_t _ReadPublicData = { + /* entry */ &TPM2_ReadPublic, + /* inSize */ (UINT16)(sizeof(ReadPublic_In)), + /* outSize */ (UINT16)(sizeof(ReadPublic_Out)), + /* offsetOfTypes */ offsetof(ReadPublic_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ReadPublic_Out, name)), + (UINT16)(offsetof(ReadPublic_Out, qualifiedName))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + END_OF_LIST, + TPM2B_PUBLIC_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST} +}; +#define _ReadPublicDataAddress (&_ReadPublicData) +#else +#define _ReadPublicDataAddress 0 +#endif +#if CC_ActivateCredential +#include "ActivateCredential_fp.h" +typedef TPM_RC (ActivateCredential_Entry)( + ActivateCredential_In *in, + ActivateCredential_Out *out + ); +typedef const struct { + ActivateCredential_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} ActivateCredential_COMMAND_DESCRIPTOR_t; +ActivateCredential_COMMAND_DESCRIPTOR_t _ActivateCredentialData = { + /* entry */ &TPM2_ActivateCredential, + /* inSize */ (UINT16)(sizeof(ActivateCredential_In)), + /* outSize */ (UINT16)(sizeof(ActivateCredential_Out)), + /* offsetOfTypes */ offsetof(ActivateCredential_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ActivateCredential_In, keyHandle)), + (UINT16)(offsetof(ActivateCredential_In, credentialBlob)), + (UINT16)(offsetof(ActivateCredential_In, secret))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ID_OBJECT_P_UNMARSHAL, + TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST} +}; +#define _ActivateCredentialDataAddress (&_ActivateCredentialData) +#else +#define _ActivateCredentialDataAddress 0 +#endif +#if CC_MakeCredential +#include "MakeCredential_fp.h" +typedef TPM_RC (MakeCredential_Entry)( + MakeCredential_In *in, + MakeCredential_Out *out + ); +typedef const struct { + MakeCredential_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} MakeCredential_COMMAND_DESCRIPTOR_t; +MakeCredential_COMMAND_DESCRIPTOR_t _MakeCredentialData = { + /* entry */ &TPM2_MakeCredential, + /* inSize */ (UINT16)(sizeof(MakeCredential_In)), + /* outSize */ (UINT16)(sizeof(MakeCredential_Out)), + /* offsetOfTypes */ offsetof(MakeCredential_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(MakeCredential_In, credential)), + (UINT16)(offsetof(MakeCredential_In, objectName)), + (UINT16)(offsetof(MakeCredential_Out, secret))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ID_OBJECT_P_MARSHAL, + TPM2B_ENCRYPTED_SECRET_P_MARSHAL, + END_OF_LIST} +}; +#define _MakeCredentialDataAddress (&_MakeCredentialData) +#else +#define _MakeCredentialDataAddress 0 +#endif +#if CC_Unseal +#include "Unseal_fp.h" +typedef TPM_RC (Unseal_Entry)( + Unseal_In *in, + Unseal_Out *out + ); +typedef const struct { + Unseal_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} Unseal_COMMAND_DESCRIPTOR_t; +Unseal_COMMAND_DESCRIPTOR_t _UnsealData = { + /* entry */ &TPM2_Unseal, + /* inSize */ (UINT16)(sizeof(Unseal_In)), + /* outSize */ (UINT16)(sizeof(Unseal_Out)), + /* offsetOfTypes */ offsetof(Unseal_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + END_OF_LIST, + TPM2B_SENSITIVE_DATA_P_MARSHAL, + END_OF_LIST} +}; +#define _UnsealDataAddress (&_UnsealData) +#else +#define _UnsealDataAddress 0 +#endif +#if CC_ObjectChangeAuth +#include "ObjectChangeAuth_fp.h" +typedef TPM_RC (ObjectChangeAuth_Entry)( + ObjectChangeAuth_In *in, + ObjectChangeAuth_Out *out + ); +typedef const struct { + ObjectChangeAuth_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} ObjectChangeAuth_COMMAND_DESCRIPTOR_t; +ObjectChangeAuth_COMMAND_DESCRIPTOR_t _ObjectChangeAuthData = { + /* entry */ &TPM2_ObjectChangeAuth, + /* inSize */ (UINT16)(sizeof(ObjectChangeAuth_In)), + /* outSize */ (UINT16)(sizeof(ObjectChangeAuth_Out)), + /* offsetOfTypes */ offsetof(ObjectChangeAuth_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ObjectChangeAuth_In, parentHandle)), + (UINT16)(offsetof(ObjectChangeAuth_In, newAuth))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PRIVATE_P_MARSHAL, + END_OF_LIST} +}; +#define _ObjectChangeAuthDataAddress (&_ObjectChangeAuthData) +#else +#define _ObjectChangeAuthDataAddress 0 +#endif +#if CC_CreateLoaded +#include "CreateLoaded_fp.h" +typedef TPM_RC (CreateLoaded_Entry)( + CreateLoaded_In *in, + CreateLoaded_Out *out + ); +typedef const struct { + CreateLoaded_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} CreateLoaded_COMMAND_DESCRIPTOR_t; +CreateLoaded_COMMAND_DESCRIPTOR_t _CreateLoadedData = { + /* entry */ &TPM2_CreateLoaded, + /* inSize */ (UINT16)(sizeof(CreateLoaded_In)), + /* outSize */ (UINT16)(sizeof(CreateLoaded_Out)), + /* offsetOfTypes */ offsetof(CreateLoaded_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(CreateLoaded_In, inSensitive)), + (UINT16)(offsetof(CreateLoaded_In, inPublic)), + (UINT16)(offsetof(CreateLoaded_Out, outPrivate)), + (UINT16)(offsetof(CreateLoaded_Out, outPublic)), + (UINT16)(offsetof(CreateLoaded_Out, name))}, + /* types */ {TPMI_DH_PARENT_H_UNMARSHAL + ADD_FLAG, + TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, + TPM2B_TEMPLATE_P_UNMARSHAL, + END_OF_LIST, + TPM_HANDLE_H_MARSHAL, + TPM2B_PRIVATE_P_MARSHAL, + TPM2B_PUBLIC_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST} +}; +#define _CreateLoadedDataAddress (&_CreateLoadedData) +#else +#define _CreateLoadedDataAddress 0 +#endif +#if CC_Duplicate +#include "Duplicate_fp.h" +typedef TPM_RC (Duplicate_Entry)( + Duplicate_In *in, + Duplicate_Out *out + ); +typedef const struct { + Duplicate_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} Duplicate_COMMAND_DESCRIPTOR_t; +Duplicate_COMMAND_DESCRIPTOR_t _DuplicateData = { + /* entry */ &TPM2_Duplicate, + /* inSize */ (UINT16)(sizeof(Duplicate_In)), + /* outSize */ (UINT16)(sizeof(Duplicate_Out)), + /* offsetOfTypes */ offsetof(Duplicate_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Duplicate_In, newParentHandle)), + (UINT16)(offsetof(Duplicate_In, encryptionKeyIn)), + (UINT16)(offsetof(Duplicate_In, symmetricAlg)), + (UINT16)(offsetof(Duplicate_Out, duplicate)), + (UINT16)(offsetof(Duplicate_Out, outSymSeed))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SYM_DEF_OBJECT_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DATA_P_MARSHAL, + TPM2B_PRIVATE_P_MARSHAL, + TPM2B_ENCRYPTED_SECRET_P_MARSHAL, + END_OF_LIST} +}; +#define _DuplicateDataAddress (&_DuplicateData) +#else +#define _DuplicateDataAddress 0 +#endif +#if CC_Rewrap +#include "Rewrap_fp.h" +typedef TPM_RC (Rewrap_Entry)( + Rewrap_In *in, + Rewrap_Out *out + ); +typedef const struct { + Rewrap_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} Rewrap_COMMAND_DESCRIPTOR_t; +Rewrap_COMMAND_DESCRIPTOR_t _RewrapData = { + /* entry */ &TPM2_Rewrap, + /* inSize */ (UINT16)(sizeof(Rewrap_In)), + /* outSize */ (UINT16)(sizeof(Rewrap_Out)), + /* offsetOfTypes */ offsetof(Rewrap_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Rewrap_In, newParent)), + (UINT16)(offsetof(Rewrap_In, inDuplicate)), + (UINT16)(offsetof(Rewrap_In, name)), + (UINT16)(offsetof(Rewrap_In, inSymSeed)), + (UINT16)(offsetof(Rewrap_Out, outSymSeed))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_PRIVATE_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PRIVATE_P_MARSHAL, + TPM2B_ENCRYPTED_SECRET_P_MARSHAL, + END_OF_LIST} +}; +#define _RewrapDataAddress (&_RewrapData) +#else +#define _RewrapDataAddress 0 +#endif +#if CC_Import +#include "Import_fp.h" +typedef TPM_RC (Import_Entry)( + Import_In *in, + Import_Out *out + ); +typedef const struct { + Import_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} Import_COMMAND_DESCRIPTOR_t; +Import_COMMAND_DESCRIPTOR_t _ImportData = { + /* entry */ &TPM2_Import, + /* inSize */ (UINT16)(sizeof(Import_In)), + /* outSize */ (UINT16)(sizeof(Import_Out)), + /* offsetOfTypes */ offsetof(Import_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Import_In, encryptionKey)), + (UINT16)(offsetof(Import_In, objectPublic)), + (UINT16)(offsetof(Import_In, duplicate)), + (UINT16)(offsetof(Import_In, inSymSeed)), + (UINT16)(offsetof(Import_In, symmetricAlg))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL, + TPM2B_PRIVATE_P_UNMARSHAL, + TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, + TPMT_SYM_DEF_OBJECT_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_PRIVATE_P_MARSHAL, + END_OF_LIST} +}; +#define _ImportDataAddress (&_ImportData) +#else +#define _ImportDataAddress 0 +#endif +#if CC_RSA_Encrypt +#include "RSA_Encrypt_fp.h" +typedef TPM_RC (RSA_Encrypt_Entry)( + RSA_Encrypt_In *in, + RSA_Encrypt_Out *out + ); +typedef const struct { + RSA_Encrypt_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} RSA_Encrypt_COMMAND_DESCRIPTOR_t; +RSA_Encrypt_COMMAND_DESCRIPTOR_t _RSA_EncryptData = { + /* entry */ &TPM2_RSA_Encrypt, + /* inSize */ (UINT16)(sizeof(RSA_Encrypt_In)), + /* outSize */ (UINT16)(sizeof(RSA_Encrypt_Out)), + /* offsetOfTypes */ offsetof(RSA_Encrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(RSA_Encrypt_In, message)), + (UINT16)(offsetof(RSA_Encrypt_In, inScheme)), + (UINT16)(offsetof(RSA_Encrypt_In, label))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL, + TPMT_RSA_DECRYPT_P_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PUBLIC_KEY_RSA_P_MARSHAL, + END_OF_LIST} +}; +#define _RSA_EncryptDataAddress (&_RSA_EncryptData) +#else +#define _RSA_EncryptDataAddress 0 +#endif +#if CC_RSA_Decrypt +#include "RSA_Decrypt_fp.h" +typedef TPM_RC (RSA_Decrypt_Entry)( + RSA_Decrypt_In *in, + RSA_Decrypt_Out *out + ); +typedef const struct { + RSA_Decrypt_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} RSA_Decrypt_COMMAND_DESCRIPTOR_t; +RSA_Decrypt_COMMAND_DESCRIPTOR_t _RSA_DecryptData = { + /* entry */ &TPM2_RSA_Decrypt, + /* inSize */ (UINT16)(sizeof(RSA_Decrypt_In)), + /* outSize */ (UINT16)(sizeof(RSA_Decrypt_Out)), + /* offsetOfTypes */ offsetof(RSA_Decrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(RSA_Decrypt_In, cipherText)), + (UINT16)(offsetof(RSA_Decrypt_In, inScheme)), + (UINT16)(offsetof(RSA_Decrypt_In, label))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL, + TPMT_RSA_DECRYPT_P_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PUBLIC_KEY_RSA_P_MARSHAL, + END_OF_LIST} +}; +#define _RSA_DecryptDataAddress (&_RSA_DecryptData) +#else +#define _RSA_DecryptDataAddress 0 +#endif +#if CC_ECDH_KeyGen +#include "ECDH_KeyGen_fp.h" +typedef TPM_RC (ECDH_KeyGen_Entry)( + ECDH_KeyGen_In *in, + ECDH_KeyGen_Out *out + ); +typedef const struct { + ECDH_KeyGen_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} ECDH_KeyGen_COMMAND_DESCRIPTOR_t; +ECDH_KeyGen_COMMAND_DESCRIPTOR_t _ECDH_KeyGenData = { + /* entry */ &TPM2_ECDH_KeyGen, + /* inSize */ (UINT16)(sizeof(ECDH_KeyGen_In)), + /* outSize */ (UINT16)(sizeof(ECDH_KeyGen_Out)), + /* offsetOfTypes */ offsetof(ECDH_KeyGen_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ECDH_KeyGen_Out, pubPoint))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_ECC_POINT_P_MARSHAL, + END_OF_LIST} +}; +#define _ECDH_KeyGenDataAddress (&_ECDH_KeyGenData) +#else +#define _ECDH_KeyGenDataAddress 0 +#endif +#if CC_ECDH_ZGen +#include "ECDH_ZGen_fp.h" +typedef TPM_RC (ECDH_ZGen_Entry)( + ECDH_ZGen_In *in, + ECDH_ZGen_Out *out + ); +typedef const struct { + ECDH_ZGen_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} ECDH_ZGen_COMMAND_DESCRIPTOR_t; +ECDH_ZGen_COMMAND_DESCRIPTOR_t _ECDH_ZGenData = { + /* entry */ &TPM2_ECDH_ZGen, + /* inSize */ (UINT16)(sizeof(ECDH_ZGen_In)), + /* outSize */ (UINT16)(sizeof(ECDH_ZGen_Out)), + /* offsetOfTypes */ offsetof(ECDH_ZGen_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ECDH_ZGen_In, inPoint))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + END_OF_LIST} +}; +#define _ECDH_ZGenDataAddress (&_ECDH_ZGenData) +#else +#define _ECDH_ZGenDataAddress 0 +#endif + +#if CC_ECC_Encrypt + +#include "ECC_Encrypt_fp.h" + +typedef TPM_RC (ECC_Encrypt_Entry)( + ECC_Encrypt_In *in, + ECC_Encrypt_Out *out + ); + +typedef const struct { + ECC_Encrypt_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} ECC_Encrypt_COMMAND_DESCRIPTOR_t; + +ECC_Encrypt_COMMAND_DESCRIPTOR_t _ECC_EncryptData = { + /* entry */ &TPM2_ECC_Encrypt, + /* inSize */ (UINT16)(sizeof(ECC_Encrypt_In)), + /* outSize */ (UINT16)(sizeof(ECC_Encrypt_Out)), + /* offsetOfTypes */ offsetof(ECC_Encrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ECC_Encrypt_In, plainText)), + (UINT16)(offsetof(ECC_Encrypt_In, inScheme)), + (UINT16)(offsetof(ECC_Encrypt_Out, C2)), + (UINT16)(offsetof(ECC_Encrypt_Out, C3))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMT_KDF_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST} +}; + +#define _ECC_EncryptDataAddress (&_ECC_EncryptData) +#else +#define _ECC_EncryptDataAddress 0 +#endif // CC_ECC_Encrypt + +#if CC_ECC_Decrypt + +#include "ECC_Decrypt_fp.h" + +typedef TPM_RC (ECC_Decrypt_Entry)( + ECC_Decrypt_In *in, + ECC_Decrypt_Out *out + ); + +typedef const struct { + ECC_Decrypt_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} ECC_Decrypt_COMMAND_DESCRIPTOR_t; + +ECC_Decrypt_COMMAND_DESCRIPTOR_t _ECC_DecryptData = { + /* entry */ &TPM2_ECC_Decrypt, + /* inSize */ (UINT16)(sizeof(ECC_Decrypt_In)), + /* outSize */ (UINT16)(sizeof(ECC_Decrypt_Out)), + /* offsetOfTypes */ offsetof(ECC_Decrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ECC_Decrypt_In, C1)), + (UINT16)(offsetof(ECC_Decrypt_In, C2)), + (UINT16)(offsetof(ECC_Decrypt_In, C3)), + (UINT16)(offsetof(ECC_Decrypt_In, inScheme))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_KDF_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + END_OF_LIST} +}; + +#define _ECC_DecryptDataAddress (&_ECC_DecryptData) +#else +#define _ECC_DecryptDataAddress 0 +#endif // CC_ECC_Decrypt + +#if CC_ECC_Parameters +#include "ECC_Parameters_fp.h" +typedef TPM_RC (ECC_Parameters_Entry)( + ECC_Parameters_In *in, + ECC_Parameters_Out *out + ); +typedef const struct { + ECC_Parameters_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} ECC_Parameters_COMMAND_DESCRIPTOR_t; +ECC_Parameters_COMMAND_DESCRIPTOR_t _ECC_ParametersData = { + /* entry */ &TPM2_ECC_Parameters, + /* inSize */ (UINT16)(sizeof(ECC_Parameters_In)), + /* outSize */ (UINT16)(sizeof(ECC_Parameters_Out)), + /* offsetOfTypes */ offsetof(ECC_Parameters_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_ECC_CURVE_P_UNMARSHAL, + END_OF_LIST, + TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL, + END_OF_LIST} +}; +#define _ECC_ParametersDataAddress (&_ECC_ParametersData) +#else +#define _ECC_ParametersDataAddress 0 +#endif +#if CC_ZGen_2Phase +#include "ZGen_2Phase_fp.h" +typedef TPM_RC (ZGen_2Phase_Entry)( + ZGen_2Phase_In *in, + ZGen_2Phase_Out *out + ); +typedef const struct { + ZGen_2Phase_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} ZGen_2Phase_COMMAND_DESCRIPTOR_t; +ZGen_2Phase_COMMAND_DESCRIPTOR_t _ZGen_2PhaseData = { + /* entry */ &TPM2_ZGen_2Phase, + /* inSize */ (UINT16)(sizeof(ZGen_2Phase_In)), + /* outSize */ (UINT16)(sizeof(ZGen_2Phase_Out)), + /* offsetOfTypes */ offsetof(ZGen_2Phase_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ZGen_2Phase_In, inQsB)), + (UINT16)(offsetof(ZGen_2Phase_In, inQeB)), + (UINT16)(offsetof(ZGen_2Phase_In, inScheme)), + (UINT16)(offsetof(ZGen_2Phase_In, counter)), + (UINT16)(offsetof(ZGen_2Phase_Out, outZ2))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_ECC_POINT_P_MARSHAL, + END_OF_LIST} +}; +#define _ZGen_2PhaseDataAddress (&_ZGen_2PhaseData) +#else +#define _ZGen_2PhaseDataAddress 0 +#endif +#if CC_EncryptDecrypt +#include "EncryptDecrypt_fp.h" +typedef TPM_RC (EncryptDecrypt_Entry)( + EncryptDecrypt_In *in, + EncryptDecrypt_Out *out + ); +typedef const struct { + EncryptDecrypt_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} EncryptDecrypt_COMMAND_DESCRIPTOR_t; +EncryptDecrypt_COMMAND_DESCRIPTOR_t _EncryptDecryptData = { + /* entry */ &TPM2_EncryptDecrypt, + /* inSize */ (UINT16)(sizeof(EncryptDecrypt_In)), + /* outSize */ (UINT16)(sizeof(EncryptDecrypt_Out)), + /* offsetOfTypes */ offsetof(EncryptDecrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(EncryptDecrypt_In, decrypt)), + (UINT16)(offsetof(EncryptDecrypt_In, mode)), + (UINT16)(offsetof(EncryptDecrypt_In, ivIn)), + (UINT16)(offsetof(EncryptDecrypt_In, inData)), + (UINT16)(offsetof(EncryptDecrypt_Out, ivOut))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG, + TPM2B_IV_P_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM2B_IV_P_MARSHAL, + END_OF_LIST} +}; +#define _EncryptDecryptDataAddress (&_EncryptDecryptData) +#else +#define _EncryptDecryptDataAddress 0 +#endif +#if CC_EncryptDecrypt2 +#include "EncryptDecrypt2_fp.h" +typedef TPM_RC (EncryptDecrypt2_Entry)( + EncryptDecrypt2_In *in, + EncryptDecrypt2_Out *out + ); +typedef const struct { + EncryptDecrypt2_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} EncryptDecrypt2_COMMAND_DESCRIPTOR_t; +EncryptDecrypt2_COMMAND_DESCRIPTOR_t _EncryptDecrypt2Data = { + /* entry */ &TPM2_EncryptDecrypt2, + /* inSize */ (UINT16)(sizeof(EncryptDecrypt2_In)), + /* outSize */ (UINT16)(sizeof(EncryptDecrypt2_Out)), + /* offsetOfTypes */ offsetof(EncryptDecrypt2_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(EncryptDecrypt2_In, inData)), + (UINT16)(offsetof(EncryptDecrypt2_In, decrypt)), + (UINT16)(offsetof(EncryptDecrypt2_In, mode)), + (UINT16)(offsetof(EncryptDecrypt2_In, ivIn)), + (UINT16)(offsetof(EncryptDecrypt2_Out, ivOut))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG, + TPM2B_IV_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM2B_IV_P_MARSHAL, + END_OF_LIST} +}; +#define _EncryptDecrypt2DataAddress (&_EncryptDecrypt2Data) +#else +#define _EncryptDecrypt2DataAddress 0 +#endif +#if CC_Hash +#include "Hash_fp.h" +typedef TPM_RC (Hash_Entry)( + Hash_In *in, + Hash_Out *out + ); +typedef const struct { + Hash_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} Hash_COMMAND_DESCRIPTOR_t; +Hash_COMMAND_DESCRIPTOR_t _HashData = { + /* entry */ &TPM2_Hash, + /* inSize */ (UINT16)(sizeof(Hash_In)), + /* outSize */ (UINT16)(sizeof(Hash_Out)), + /* offsetOfTypes */ offsetof(Hash_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Hash_In, hashAlg)), + (UINT16)(offsetof(Hash_In, hierarchy)), + (UINT16)(offsetof(Hash_Out, validation))}, + /* types */ {TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL, + TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + TPMT_TK_HASHCHECK_P_MARSHAL, + END_OF_LIST} +}; +#define _HashDataAddress (&_HashData) +#else +#define _HashDataAddress 0 +#endif +#if CC_HMAC +#include "HMAC_fp.h" +typedef TPM_RC (HMAC_Entry)( + HMAC_In *in, + HMAC_Out *out + ); +typedef const struct { + HMAC_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} HMAC_COMMAND_DESCRIPTOR_t; +HMAC_COMMAND_DESCRIPTOR_t _HMACData = { + /* entry */ &TPM2_HMAC, + /* inSize */ (UINT16)(sizeof(HMAC_In)), + /* outSize */ (UINT16)(sizeof(HMAC_Out)), + /* offsetOfTypes */ offsetof(HMAC_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(HMAC_In, buffer)), + (UINT16)(offsetof(HMAC_In, hashAlg))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST} +}; +#define _HMACDataAddress (&_HMACData) +#else +#define _HMACDataAddress 0 +#endif +#if CC_MAC +#include "MAC_fp.h" +typedef TPM_RC (MAC_Entry)( + MAC_In *in, + MAC_Out *out + ); +typedef const struct { + MAC_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} MAC_COMMAND_DESCRIPTOR_t; +MAC_COMMAND_DESCRIPTOR_t _MACData = { + /* entry */ &TPM2_MAC, + /* inSize */ (UINT16)(sizeof(MAC_In)), + /* outSize */ (UINT16)(sizeof(MAC_Out)), + /* offsetOfTypes */ offsetof(MAC_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(MAC_In, buffer)), + (UINT16)(offsetof(MAC_In, inScheme))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST} +}; +#define _MACDataAddress (&_MACData) +#else +#define _MACDataAddress 0 +#endif +#if CC_GetRandom +#include "GetRandom_fp.h" +typedef TPM_RC (GetRandom_Entry)( + GetRandom_In *in, + GetRandom_Out *out + ); +typedef const struct { + GetRandom_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} GetRandom_COMMAND_DESCRIPTOR_t; +GetRandom_COMMAND_DESCRIPTOR_t _GetRandomData = { + /* entry */ &TPM2_GetRandom, + /* inSize */ (UINT16)(sizeof(GetRandom_In)), + /* outSize */ (UINT16)(sizeof(GetRandom_Out)), + /* offsetOfTypes */ offsetof(GetRandom_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {UINT16_P_UNMARSHAL, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST} +}; +#define _GetRandomDataAddress (&_GetRandomData) +#else +#define _GetRandomDataAddress 0 +#endif +#if CC_StirRandom +#include "StirRandom_fp.h" +typedef TPM_RC (StirRandom_Entry)( + StirRandom_In *in + ); +typedef const struct { + StirRandom_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} StirRandom_COMMAND_DESCRIPTOR_t; +StirRandom_COMMAND_DESCRIPTOR_t _StirRandomData = { + /* entry */ &TPM2_StirRandom, + /* inSize */ (UINT16)(sizeof(StirRandom_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(StirRandom_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPM2B_SENSITIVE_DATA_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _StirRandomDataAddress (&_StirRandomData) +#else +#define _StirRandomDataAddress 0 +#endif +#if CC_HMAC_Start +#include "HMAC_Start_fp.h" +typedef TPM_RC (HMAC_Start_Entry)( + HMAC_Start_In *in, + HMAC_Start_Out *out + ); +typedef const struct { + HMAC_Start_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} HMAC_Start_COMMAND_DESCRIPTOR_t; +HMAC_Start_COMMAND_DESCRIPTOR_t _HMAC_StartData = { + /* entry */ &TPM2_HMAC_Start, + /* inSize */ (UINT16)(sizeof(HMAC_Start_In)), + /* outSize */ (UINT16)(sizeof(HMAC_Start_Out)), + /* offsetOfTypes */ offsetof(HMAC_Start_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(HMAC_Start_In, auth)), + (UINT16)(offsetof(HMAC_Start_In, hashAlg))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPMI_DH_OBJECT_H_MARSHAL, + END_OF_LIST} +}; +#define _HMAC_StartDataAddress (&_HMAC_StartData) +#else +#define _HMAC_StartDataAddress 0 +#endif +#if CC_MAC_Start +#include "MAC_Start_fp.h" +typedef TPM_RC (MAC_Start_Entry)( + MAC_Start_In *in, + MAC_Start_Out *out + ); +typedef const struct { + MAC_Start_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} MAC_Start_COMMAND_DESCRIPTOR_t; +MAC_Start_COMMAND_DESCRIPTOR_t _MAC_StartData = { + /* entry */ &TPM2_MAC_Start, + /* inSize */ (UINT16)(sizeof(MAC_Start_In)), + /* outSize */ (UINT16)(sizeof(MAC_Start_Out)), + /* offsetOfTypes */ offsetof(MAC_Start_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(MAC_Start_In, auth)), + (UINT16)(offsetof(MAC_Start_In, inScheme))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPMI_DH_OBJECT_H_MARSHAL, + END_OF_LIST} +}; +#define _MAC_StartDataAddress (&_MAC_StartData) +#else +#define _MAC_StartDataAddress 0 +#endif +#if CC_HashSequenceStart +#include "HashSequenceStart_fp.h" +typedef TPM_RC (HashSequenceStart_Entry)( + HashSequenceStart_In *in, + HashSequenceStart_Out *out + ); +typedef const struct { + HashSequenceStart_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} HashSequenceStart_COMMAND_DESCRIPTOR_t; +HashSequenceStart_COMMAND_DESCRIPTOR_t _HashSequenceStartData = { + /* entry */ &TPM2_HashSequenceStart, + /* inSize */ (UINT16)(sizeof(HashSequenceStart_In)), + /* outSize */ (UINT16)(sizeof(HashSequenceStart_Out)), + /* offsetOfTypes */ offsetof(HashSequenceStart_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(HashSequenceStart_In, hashAlg))}, + /* types */ {TPM2B_AUTH_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPMI_DH_OBJECT_H_MARSHAL, + END_OF_LIST} +}; +#define _HashSequenceStartDataAddress (&_HashSequenceStartData) +#else +#define _HashSequenceStartDataAddress 0 +#endif +#if CC_SequenceUpdate +#include "SequenceUpdate_fp.h" +typedef TPM_RC (SequenceUpdate_Entry)( + SequenceUpdate_In *in + ); +typedef const struct { + SequenceUpdate_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} SequenceUpdate_COMMAND_DESCRIPTOR_t; +SequenceUpdate_COMMAND_DESCRIPTOR_t _SequenceUpdateData = { + /* entry */ &TPM2_SequenceUpdate, + /* inSize */ (UINT16)(sizeof(SequenceUpdate_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SequenceUpdate_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(SequenceUpdate_In, buffer))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _SequenceUpdateDataAddress (&_SequenceUpdateData) +#else +#define _SequenceUpdateDataAddress 0 +#endif +#if CC_SequenceComplete +#include "SequenceComplete_fp.h" +typedef TPM_RC (SequenceComplete_Entry)( + SequenceComplete_In *in, + SequenceComplete_Out *out + ); +typedef const struct { + SequenceComplete_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} SequenceComplete_COMMAND_DESCRIPTOR_t; +SequenceComplete_COMMAND_DESCRIPTOR_t _SequenceCompleteData = { + /* entry */ &TPM2_SequenceComplete, + /* inSize */ (UINT16)(sizeof(SequenceComplete_In)), + /* outSize */ (UINT16)(sizeof(SequenceComplete_Out)), + /* offsetOfTypes */ offsetof(SequenceComplete_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(SequenceComplete_In, buffer)), + (UINT16)(offsetof(SequenceComplete_In, hierarchy)), + (UINT16)(offsetof(SequenceComplete_Out, validation))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + TPMT_TK_HASHCHECK_P_MARSHAL, + END_OF_LIST} +}; +#define _SequenceCompleteDataAddress (&_SequenceCompleteData) +#else +#define _SequenceCompleteDataAddress 0 +#endif +#if CC_EventSequenceComplete +#include "EventSequenceComplete_fp.h" +typedef TPM_RC (EventSequenceComplete_Entry)( + EventSequenceComplete_In *in, + EventSequenceComplete_Out *out + ); +typedef const struct { + EventSequenceComplete_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} EventSequenceComplete_COMMAND_DESCRIPTOR_t; +EventSequenceComplete_COMMAND_DESCRIPTOR_t _EventSequenceCompleteData = { + /* entry */ &TPM2_EventSequenceComplete, + /* inSize */ (UINT16)(sizeof(EventSequenceComplete_In)), + /* outSize */ (UINT16)(sizeof(EventSequenceComplete_Out)), + /* offsetOfTypes */ offsetof(EventSequenceComplete_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(EventSequenceComplete_In, sequenceHandle)), + (UINT16)(offsetof(EventSequenceComplete_In, buffer))}, + /* types */ {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPML_DIGEST_VALUES_P_MARSHAL, + END_OF_LIST} +}; +#define _EventSequenceCompleteDataAddress (&_EventSequenceCompleteData) +#else +#define _EventSequenceCompleteDataAddress 0 +#endif +#if CC_Certify +#include "Certify_fp.h" +typedef TPM_RC (Certify_Entry)( + Certify_In *in, + Certify_Out *out + ); +typedef const struct { + Certify_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} Certify_COMMAND_DESCRIPTOR_t; +Certify_COMMAND_DESCRIPTOR_t _CertifyData = { + /* entry */ &TPM2_Certify, + /* inSize */ (UINT16)(sizeof(Certify_In)), + /* outSize */ (UINT16)(sizeof(Certify_Out)), + /* offsetOfTypes */ offsetof(Certify_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Certify_In, signHandle)), + (UINT16)(offsetof(Certify_In, qualifyingData)), + (UINT16)(offsetof(Certify_In, inScheme)), + (UINT16)(offsetof(Certify_Out, signature))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _CertifyDataAddress (&_CertifyData) +#else +#define _CertifyDataAddress 0 +#endif +#if CC_CertifyCreation +#include "CertifyCreation_fp.h" +typedef TPM_RC (CertifyCreation_Entry)( + CertifyCreation_In *in, + CertifyCreation_Out *out + ); +typedef const struct { + CertifyCreation_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[6]; + BYTE types[10]; +} CertifyCreation_COMMAND_DESCRIPTOR_t; +CertifyCreation_COMMAND_DESCRIPTOR_t _CertifyCreationData = { + /* entry */ &TPM2_CertifyCreation, + /* inSize */ (UINT16)(sizeof(CertifyCreation_In)), + /* outSize */ (UINT16)(sizeof(CertifyCreation_Out)), + /* offsetOfTypes */ offsetof(CertifyCreation_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(CertifyCreation_In, objectHandle)), + (UINT16)(offsetof(CertifyCreation_In, qualifyingData)), + (UINT16)(offsetof(CertifyCreation_In, creationHash)), + (UINT16)(offsetof(CertifyCreation_In, inScheme)), + (UINT16)(offsetof(CertifyCreation_In, creationTicket)), + (UINT16)(offsetof(CertifyCreation_Out, signature))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + TPMT_TK_CREATION_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _CertifyCreationDataAddress (&_CertifyCreationData) +#else +#define _CertifyCreationDataAddress 0 +#endif +#if CC_Quote +#include "Quote_fp.h" +typedef TPM_RC (Quote_Entry)( + Quote_In *in, + Quote_Out *out + ); +typedef const struct { + Quote_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} Quote_COMMAND_DESCRIPTOR_t; +Quote_COMMAND_DESCRIPTOR_t _QuoteData = { + /* entry */ &TPM2_Quote, + /* inSize */ (UINT16)(sizeof(Quote_In)), + /* outSize */ (UINT16)(sizeof(Quote_Out)), + /* offsetOfTypes */ offsetof(Quote_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Quote_In, qualifyingData)), + (UINT16)(offsetof(Quote_In, inScheme)), + (UINT16)(offsetof(Quote_In, PCRselect)), + (UINT16)(offsetof(Quote_Out, signature))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _QuoteDataAddress (&_QuoteData) +#else +#define _QuoteDataAddress 0 +#endif +#if CC_GetSessionAuditDigest +#include "GetSessionAuditDigest_fp.h" +typedef TPM_RC (GetSessionAuditDigest_Entry)( + GetSessionAuditDigest_In *in, + GetSessionAuditDigest_Out *out + ); +typedef const struct { + GetSessionAuditDigest_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} GetSessionAuditDigest_COMMAND_DESCRIPTOR_t; +GetSessionAuditDigest_COMMAND_DESCRIPTOR_t _GetSessionAuditDigestData = { + /* entry */ &TPM2_GetSessionAuditDigest, + /* inSize */ (UINT16)(sizeof(GetSessionAuditDigest_In)), + /* outSize */ (UINT16)(sizeof(GetSessionAuditDigest_Out)), + /* offsetOfTypes */ offsetof(GetSessionAuditDigest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(GetSessionAuditDigest_In, signHandle)), + (UINT16)(offsetof(GetSessionAuditDigest_In, sessionHandle)), + (UINT16)(offsetof(GetSessionAuditDigest_In, qualifyingData)), + (UINT16)(offsetof(GetSessionAuditDigest_In, inScheme)), + (UINT16)(offsetof(GetSessionAuditDigest_Out, signature))}, + /* types */ {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_SH_HMAC_H_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _GetSessionAuditDigestDataAddress (&_GetSessionAuditDigestData) +#else +#define _GetSessionAuditDigestDataAddress 0 +#endif +#if CC_GetCommandAuditDigest +#include "GetCommandAuditDigest_fp.h" +typedef TPM_RC (GetCommandAuditDigest_Entry)( + GetCommandAuditDigest_In *in, + GetCommandAuditDigest_Out *out + ); +typedef const struct { + GetCommandAuditDigest_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} GetCommandAuditDigest_COMMAND_DESCRIPTOR_t; +GetCommandAuditDigest_COMMAND_DESCRIPTOR_t _GetCommandAuditDigestData = { + /* entry */ &TPM2_GetCommandAuditDigest, + /* inSize */ (UINT16)(sizeof(GetCommandAuditDigest_In)), + /* outSize */ (UINT16)(sizeof(GetCommandAuditDigest_Out)), + /* offsetOfTypes */ offsetof(GetCommandAuditDigest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(GetCommandAuditDigest_In, signHandle)), + (UINT16)(offsetof(GetCommandAuditDigest_In, qualifyingData)), + (UINT16)(offsetof(GetCommandAuditDigest_In, inScheme)), + (UINT16)(offsetof(GetCommandAuditDigest_Out, signature))}, + /* types */ {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _GetCommandAuditDigestDataAddress (&_GetCommandAuditDigestData) +#else +#define _GetCommandAuditDigestDataAddress 0 +#endif +#if CC_GetTime +#include "GetTime_fp.h" +typedef TPM_RC (GetTime_Entry)( + GetTime_In *in, + GetTime_Out *out + ); +typedef const struct { + GetTime_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} GetTime_COMMAND_DESCRIPTOR_t; +GetTime_COMMAND_DESCRIPTOR_t _GetTimeData = { + /* entry */ &TPM2_GetTime, + /* inSize */ (UINT16)(sizeof(GetTime_In)), + /* outSize */ (UINT16)(sizeof(GetTime_Out)), + /* offsetOfTypes */ offsetof(GetTime_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(GetTime_In, signHandle)), + (UINT16)(offsetof(GetTime_In, qualifyingData)), + (UINT16)(offsetof(GetTime_In, inScheme)), + (UINT16)(offsetof(GetTime_Out, signature))}, + /* types */ {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _GetTimeDataAddress (&_GetTimeData) +#else +#define _GetTimeDataAddress 0 +#endif +#if CC_CertifyX509 +#include "CertifyX509_fp.h" +typedef TPM_RC (CertifyX509_Entry)( + CertifyX509_In *in, + CertifyX509_Out *out + ); +typedef const struct { + CertifyX509_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[6]; + BYTE types[10]; +} CertifyX509_COMMAND_DESCRIPTOR_t; +CertifyX509_COMMAND_DESCRIPTOR_t _CertifyX509Data = { + /* entry */ &TPM2_CertifyX509, + /* inSize */ (UINT16)(sizeof(CertifyX509_In)), + /* outSize */ (UINT16)(sizeof(CertifyX509_Out)), + /* offsetOfTypes */ offsetof(CertifyX509_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(CertifyX509_In, signHandle)), + (UINT16)(offsetof(CertifyX509_In, reserved)), + (UINT16)(offsetof(CertifyX509_In, inScheme)), + (UINT16)(offsetof(CertifyX509_In, partialCertificate)), + (UINT16)(offsetof(CertifyX509_Out, tbsDigest)), + (UINT16)(offsetof(CertifyX509_Out, signature))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM2B_DIGEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _CertifyX509DataAddress (&_CertifyX509Data) +#else +#define _CertifyX509DataAddress 0 +#endif // CC_CertifyX509 +#if CC_Commit +#include "Commit_fp.h" +typedef TPM_RC (Commit_Entry)( + Commit_In *in, + Commit_Out *out + ); +typedef const struct { + Commit_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[6]; + BYTE types[10]; +} Commit_COMMAND_DESCRIPTOR_t; +Commit_COMMAND_DESCRIPTOR_t _CommitData = { + /* entry */ &TPM2_Commit, + /* inSize */ (UINT16)(sizeof(Commit_In)), + /* outSize */ (UINT16)(sizeof(Commit_Out)), + /* offsetOfTypes */ offsetof(Commit_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Commit_In, P1)), + (UINT16)(offsetof(Commit_In, s2)), + (UINT16)(offsetof(Commit_In, y2)), + (UINT16)(offsetof(Commit_Out, L)), + (UINT16)(offsetof(Commit_Out, E)), + (UINT16)(offsetof(Commit_Out, counter))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + TPM2B_SENSITIVE_DATA_P_UNMARSHAL, + TPM2B_ECC_PARAMETER_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_ECC_POINT_P_MARSHAL, + UINT16_P_MARSHAL, + END_OF_LIST} +}; +#define _CommitDataAddress (&_CommitData) +#else +#define _CommitDataAddress 0 +#endif +#if CC_EC_Ephemeral +#include "EC_Ephemeral_fp.h" +typedef TPM_RC (EC_Ephemeral_Entry)( + EC_Ephemeral_In *in, + EC_Ephemeral_Out *out + ); +typedef const struct { + EC_Ephemeral_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} EC_Ephemeral_COMMAND_DESCRIPTOR_t; +EC_Ephemeral_COMMAND_DESCRIPTOR_t _EC_EphemeralData = { + /* entry */ &TPM2_EC_Ephemeral, + /* inSize */ (UINT16)(sizeof(EC_Ephemeral_In)), + /* outSize */ (UINT16)(sizeof(EC_Ephemeral_Out)), + /* offsetOfTypes */ offsetof(EC_Ephemeral_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(EC_Ephemeral_Out, counter))}, + /* types */ {TPMI_ECC_CURVE_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + UINT16_P_MARSHAL, + END_OF_LIST} +}; +#define _EC_EphemeralDataAddress (&_EC_EphemeralData) +#else +#define _EC_EphemeralDataAddress 0 +#endif +#if CC_VerifySignature +#include "VerifySignature_fp.h" +typedef TPM_RC (VerifySignature_Entry)( + VerifySignature_In *in, + VerifySignature_Out *out + ); +typedef const struct { + VerifySignature_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} VerifySignature_COMMAND_DESCRIPTOR_t; +VerifySignature_COMMAND_DESCRIPTOR_t _VerifySignatureData = { + /* entry */ &TPM2_VerifySignature, + /* inSize */ (UINT16)(sizeof(VerifySignature_In)), + /* outSize */ (UINT16)(sizeof(VerifySignature_Out)), + /* offsetOfTypes */ offsetof(VerifySignature_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(VerifySignature_In, digest)), + (UINT16)(offsetof(VerifySignature_In, signature))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_SIGNATURE_P_UNMARSHAL, + END_OF_LIST, + TPMT_TK_VERIFIED_P_MARSHAL, + END_OF_LIST} +}; +#define _VerifySignatureDataAddress (&_VerifySignatureData) +#else +#define _VerifySignatureDataAddress 0 +#endif +#if CC_Sign +#include "Sign_fp.h" +typedef TPM_RC (Sign_Entry)( + Sign_In *in, + Sign_Out *out + ); +typedef const struct { + Sign_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} Sign_COMMAND_DESCRIPTOR_t; +Sign_COMMAND_DESCRIPTOR_t _SignData = { + /* entry */ &TPM2_Sign, + /* inSize */ (UINT16)(sizeof(Sign_In)), + /* outSize */ (UINT16)(sizeof(Sign_Out)), + /* offsetOfTypes */ offsetof(Sign_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Sign_In, digest)), + (UINT16)(offsetof(Sign_In, inScheme)), + (UINT16)(offsetof(Sign_In, validation))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + TPMT_TK_HASHCHECK_P_UNMARSHAL, + END_OF_LIST, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _SignDataAddress (&_SignData) +#else +#define _SignDataAddress 0 +#endif +#if CC_SetCommandCodeAuditStatus +#include "SetCommandCodeAuditStatus_fp.h" +typedef TPM_RC (SetCommandCodeAuditStatus_Entry)( + SetCommandCodeAuditStatus_In *in + ); +typedef const struct { + SetCommandCodeAuditStatus_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t; +SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t _SetCommandCodeAuditStatusData = { + /* entry */ &TPM2_SetCommandCodeAuditStatus, + /* inSize */ (UINT16)(sizeof(SetCommandCodeAuditStatus_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(SetCommandCodeAuditStatus_In, auditAlg)), + (UINT16)(offsetof(SetCommandCodeAuditStatus_In, setList)), + (UINT16)(offsetof(SetCommandCodeAuditStatus_In, clearList))}, + /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + TPML_CC_P_UNMARSHAL, + TPML_CC_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _SetCommandCodeAuditStatusDataAddress (&_SetCommandCodeAuditStatusData) +#else +#define _SetCommandCodeAuditStatusDataAddress 0 +#endif +#if CC_PCR_Extend +#include "PCR_Extend_fp.h" +typedef TPM_RC (PCR_Extend_Entry)( + PCR_Extend_In *in + ); +typedef const struct { + PCR_Extend_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PCR_Extend_COMMAND_DESCRIPTOR_t; +PCR_Extend_COMMAND_DESCRIPTOR_t _PCR_ExtendData = { + /* entry */ &TPM2_PCR_Extend, + /* inSize */ (UINT16)(sizeof(PCR_Extend_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PCR_Extend_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_Extend_In, digests))}, + /* types */ {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, + TPML_DIGEST_VALUES_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PCR_ExtendDataAddress (&_PCR_ExtendData) +#else +#define _PCR_ExtendDataAddress 0 +#endif +#if CC_PCR_Event +#include "PCR_Event_fp.h" +typedef TPM_RC (PCR_Event_Entry)( + PCR_Event_In *in, + PCR_Event_Out *out + ); +typedef const struct { + PCR_Event_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} PCR_Event_COMMAND_DESCRIPTOR_t; +PCR_Event_COMMAND_DESCRIPTOR_t _PCR_EventData = { + /* entry */ &TPM2_PCR_Event, + /* inSize */ (UINT16)(sizeof(PCR_Event_In)), + /* outSize */ (UINT16)(sizeof(PCR_Event_Out)), + /* offsetOfTypes */ offsetof(PCR_Event_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_Event_In, eventData))}, + /* types */ {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, + TPM2B_EVENT_P_UNMARSHAL, + END_OF_LIST, + TPML_DIGEST_VALUES_P_MARSHAL, + END_OF_LIST} +}; +#define _PCR_EventDataAddress (&_PCR_EventData) +#else +#define _PCR_EventDataAddress 0 +#endif +#if CC_PCR_Read +#include "PCR_Read_fp.h" +typedef TPM_RC (PCR_Read_Entry)( + PCR_Read_In *in, + PCR_Read_Out *out + ); +typedef const struct { + PCR_Read_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} PCR_Read_COMMAND_DESCRIPTOR_t; +PCR_Read_COMMAND_DESCRIPTOR_t _PCR_ReadData = { + /* entry */ &TPM2_PCR_Read, + /* inSize */ (UINT16)(sizeof(PCR_Read_In)), + /* outSize */ (UINT16)(sizeof(PCR_Read_Out)), + /* offsetOfTypes */ offsetof(PCR_Read_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_Read_Out, pcrSelectionOut)), + (UINT16)(offsetof(PCR_Read_Out, pcrValues))}, + /* types */ {TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + UINT32_P_MARSHAL, + TPML_PCR_SELECTION_P_MARSHAL, + TPML_DIGEST_P_MARSHAL, + END_OF_LIST} +}; +#define _PCR_ReadDataAddress (&_PCR_ReadData) +#else +#define _PCR_ReadDataAddress 0 +#endif +#if CC_PCR_Allocate +#include "PCR_Allocate_fp.h" +typedef TPM_RC (PCR_Allocate_Entry)( + PCR_Allocate_In *in, + PCR_Allocate_Out *out + ); +typedef const struct { + PCR_Allocate_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} PCR_Allocate_COMMAND_DESCRIPTOR_t; +PCR_Allocate_COMMAND_DESCRIPTOR_t _PCR_AllocateData = { + /* entry */ &TPM2_PCR_Allocate, + /* inSize */ (UINT16)(sizeof(PCR_Allocate_In)), + /* outSize */ (UINT16)(sizeof(PCR_Allocate_Out)), + /* offsetOfTypes */ offsetof(PCR_Allocate_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_Allocate_In, pcrAllocation)), + (UINT16)(offsetof(PCR_Allocate_Out, maxPCR)), + (UINT16)(offsetof(PCR_Allocate_Out, sizeNeeded)), + (UINT16)(offsetof(PCR_Allocate_Out, sizeAvailable))}, + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + TPMI_YES_NO_P_MARSHAL, + UINT32_P_MARSHAL, + UINT32_P_MARSHAL, + UINT32_P_MARSHAL, + END_OF_LIST} +}; +#define _PCR_AllocateDataAddress (&_PCR_AllocateData) +#else +#define _PCR_AllocateDataAddress 0 +#endif +#if CC_PCR_SetAuthPolicy +#include "PCR_SetAuthPolicy_fp.h" +typedef TPM_RC (PCR_SetAuthPolicy_Entry)( + PCR_SetAuthPolicy_In *in + ); +typedef const struct { + PCR_SetAuthPolicy_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t; +PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t _PCR_SetAuthPolicyData = { + /* entry */ &TPM2_PCR_SetAuthPolicy, + /* inSize */ (UINT16)(sizeof(PCR_SetAuthPolicy_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_SetAuthPolicy_In, authPolicy)), + (UINT16)(offsetof(PCR_SetAuthPolicy_In, hashAlg)), + (UINT16)(offsetof(PCR_SetAuthPolicy_In, pcrNum))}, + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + TPMI_DH_PCR_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PCR_SetAuthPolicyDataAddress (&_PCR_SetAuthPolicyData) +#else +#define _PCR_SetAuthPolicyDataAddress 0 +#endif +#if CC_PCR_SetAuthValue +#include "PCR_SetAuthValue_fp.h" +typedef TPM_RC (PCR_SetAuthValue_Entry)( + PCR_SetAuthValue_In *in + ); +typedef const struct { + PCR_SetAuthValue_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PCR_SetAuthValue_COMMAND_DESCRIPTOR_t; +PCR_SetAuthValue_COMMAND_DESCRIPTOR_t _PCR_SetAuthValueData = { + /* entry */ &TPM2_PCR_SetAuthValue, + /* inSize */ (UINT16)(sizeof(PCR_SetAuthValue_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PCR_SetAuthValue_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_SetAuthValue_In, auth))}, + /* types */ {TPMI_DH_PCR_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PCR_SetAuthValueDataAddress (&_PCR_SetAuthValueData) +#else +#define _PCR_SetAuthValueDataAddress 0 +#endif +#if CC_PCR_Reset +#include "PCR_Reset_fp.h" +typedef TPM_RC (PCR_Reset_Entry)( + PCR_Reset_In *in + ); +typedef const struct { + PCR_Reset_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PCR_Reset_COMMAND_DESCRIPTOR_t; +PCR_Reset_COMMAND_DESCRIPTOR_t _PCR_ResetData = { + /* entry */ &TPM2_PCR_Reset, + /* inSize */ (UINT16)(sizeof(PCR_Reset_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PCR_Reset_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_DH_PCR_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PCR_ResetDataAddress (&_PCR_ResetData) +#else +#define _PCR_ResetDataAddress 0 +#endif +#if CC_PolicySigned +#include "PolicySigned_fp.h" +typedef TPM_RC (PolicySigned_Entry)( + PolicySigned_In *in, + PolicySigned_Out *out + ); +typedef const struct { + PolicySigned_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[7]; + BYTE types[11]; +} PolicySigned_COMMAND_DESCRIPTOR_t; +PolicySigned_COMMAND_DESCRIPTOR_t _PolicySignedData = { + /* entry */ &TPM2_PolicySigned, + /* inSize */ (UINT16)(sizeof(PolicySigned_In)), + /* outSize */ (UINT16)(sizeof(PolicySigned_Out)), + /* offsetOfTypes */ offsetof(PolicySigned_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicySigned_In, policySession)), + (UINT16)(offsetof(PolicySigned_In, nonceTPM)), + (UINT16)(offsetof(PolicySigned_In, cpHashA)), + (UINT16)(offsetof(PolicySigned_In, policyRef)), + (UINT16)(offsetof(PolicySigned_In, expiration)), + (UINT16)(offsetof(PolicySigned_In, auth)), + (UINT16)(offsetof(PolicySigned_Out, policyTicket))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + INT32_P_UNMARSHAL, + TPMT_SIGNATURE_P_UNMARSHAL, + END_OF_LIST, + TPM2B_TIMEOUT_P_MARSHAL, + TPMT_TK_AUTH_P_MARSHAL, + END_OF_LIST} +}; +#define _PolicySignedDataAddress (&_PolicySignedData) +#else +#define _PolicySignedDataAddress 0 +#endif +#if CC_PolicySecret +#include "PolicySecret_fp.h" +typedef TPM_RC (PolicySecret_Entry)( + PolicySecret_In *in, + PolicySecret_Out *out + ); +typedef const struct { + PolicySecret_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[6]; + BYTE types[10]; +} PolicySecret_COMMAND_DESCRIPTOR_t; +PolicySecret_COMMAND_DESCRIPTOR_t _PolicySecretData = { + /* entry */ &TPM2_PolicySecret, + /* inSize */ (UINT16)(sizeof(PolicySecret_In)), + /* outSize */ (UINT16)(sizeof(PolicySecret_Out)), + /* offsetOfTypes */ offsetof(PolicySecret_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicySecret_In, policySession)), + (UINT16)(offsetof(PolicySecret_In, nonceTPM)), + (UINT16)(offsetof(PolicySecret_In, cpHashA)), + (UINT16)(offsetof(PolicySecret_In, policyRef)), + (UINT16)(offsetof(PolicySecret_In, expiration)), + (UINT16)(offsetof(PolicySecret_Out, policyTicket))}, + /* types */ {TPMI_DH_ENTITY_H_UNMARSHAL, + TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + INT32_P_UNMARSHAL, + END_OF_LIST, + TPM2B_TIMEOUT_P_MARSHAL, + TPMT_TK_AUTH_P_MARSHAL, + END_OF_LIST} +}; +#define _PolicySecretDataAddress (&_PolicySecretData) +#else +#define _PolicySecretDataAddress 0 +#endif +#if CC_PolicyTicket +#include "PolicyTicket_fp.h" +typedef TPM_RC (PolicyTicket_Entry)( + PolicyTicket_In *in + ); +typedef const struct { + PolicyTicket_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[8]; +} PolicyTicket_COMMAND_DESCRIPTOR_t; +PolicyTicket_COMMAND_DESCRIPTOR_t _PolicyTicketData = { + /* entry */ &TPM2_PolicyTicket, + /* inSize */ (UINT16)(sizeof(PolicyTicket_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyTicket_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyTicket_In, timeout)), + (UINT16)(offsetof(PolicyTicket_In, cpHashA)), + (UINT16)(offsetof(PolicyTicket_In, policyRef)), + (UINT16)(offsetof(PolicyTicket_In, authName)), + (UINT16)(offsetof(PolicyTicket_In, ticket))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_TIMEOUT_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPMT_TK_AUTH_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyTicketDataAddress (&_PolicyTicketData) +#else +#define _PolicyTicketDataAddress 0 +#endif +#if CC_PolicyOR +#include "PolicyOR_fp.h" +typedef TPM_RC (PolicyOR_Entry)( + PolicyOR_In *in + ); +typedef const struct { + PolicyOR_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyOR_COMMAND_DESCRIPTOR_t; +PolicyOR_COMMAND_DESCRIPTOR_t _PolicyORData = { + /* entry */ &TPM2_PolicyOR, + /* inSize */ (UINT16)(sizeof(PolicyOR_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyOR_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyOR_In, pHashList))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPML_DIGEST_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyORDataAddress (&_PolicyORData) +#else +#define _PolicyORDataAddress 0 +#endif +#if CC_PolicyPCR +#include "PolicyPCR_fp.h" +typedef TPM_RC (PolicyPCR_Entry)( + PolicyPCR_In *in + ); +typedef const struct { + PolicyPCR_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} PolicyPCR_COMMAND_DESCRIPTOR_t; +PolicyPCR_COMMAND_DESCRIPTOR_t _PolicyPCRData = { + /* entry */ &TPM2_PolicyPCR, + /* inSize */ (UINT16)(sizeof(PolicyPCR_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyPCR_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyPCR_In, pcrDigest)), + (UINT16)(offsetof(PolicyPCR_In, pcrs))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyPCRDataAddress (&_PolicyPCRData) +#else +#define _PolicyPCRDataAddress 0 +#endif +#if CC_PolicyLocality +#include "PolicyLocality_fp.h" +typedef TPM_RC (PolicyLocality_Entry)( + PolicyLocality_In *in + ); +typedef const struct { + PolicyLocality_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyLocality_COMMAND_DESCRIPTOR_t; +PolicyLocality_COMMAND_DESCRIPTOR_t _PolicyLocalityData = { + /* entry */ &TPM2_PolicyLocality, + /* inSize */ (UINT16)(sizeof(PolicyLocality_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyLocality_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyLocality_In, locality))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPMA_LOCALITY_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyLocalityDataAddress (&_PolicyLocalityData) +#else +#define _PolicyLocalityDataAddress 0 +#endif +#if CC_PolicyNV +#include "PolicyNV_fp.h" +typedef TPM_RC (PolicyNV_Entry)( + PolicyNV_In *in + ); +typedef const struct { + PolicyNV_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[8]; +} PolicyNV_COMMAND_DESCRIPTOR_t; +PolicyNV_COMMAND_DESCRIPTOR_t _PolicyNVData = { + /* entry */ &TPM2_PolicyNV, + /* inSize */ (UINT16)(sizeof(PolicyNV_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyNV_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyNV_In, nvIndex)), + (UINT16)(offsetof(PolicyNV_In, policySession)), + (UINT16)(offsetof(PolicyNV_In, operandB)), + (UINT16)(offsetof(PolicyNV_In, offset)), + (UINT16)(offsetof(PolicyNV_In, operation))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_OPERAND_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + TPM_EO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyNVDataAddress (&_PolicyNVData) +#else +#define _PolicyNVDataAddress 0 +#endif +#if CC_PolicyCounterTimer +#include "PolicyCounterTimer_fp.h" +typedef TPM_RC (PolicyCounterTimer_Entry)( + PolicyCounterTimer_In *in + ); +typedef const struct { + PolicyCounterTimer_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} PolicyCounterTimer_COMMAND_DESCRIPTOR_t; +PolicyCounterTimer_COMMAND_DESCRIPTOR_t _PolicyCounterTimerData = { + /* entry */ &TPM2_PolicyCounterTimer, + /* inSize */ (UINT16)(sizeof(PolicyCounterTimer_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyCounterTimer_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyCounterTimer_In, operandB)), + (UINT16)(offsetof(PolicyCounterTimer_In, offset)), + (UINT16)(offsetof(PolicyCounterTimer_In, operation))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_OPERAND_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + TPM_EO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyCounterTimerDataAddress (&_PolicyCounterTimerData) +#else +#define _PolicyCounterTimerDataAddress 0 +#endif +#if CC_PolicyCommandCode +#include "PolicyCommandCode_fp.h" +typedef TPM_RC (PolicyCommandCode_Entry)( + PolicyCommandCode_In *in + ); +typedef const struct { + PolicyCommandCode_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyCommandCode_COMMAND_DESCRIPTOR_t; +PolicyCommandCode_COMMAND_DESCRIPTOR_t _PolicyCommandCodeData = { + /* entry */ &TPM2_PolicyCommandCode, + /* inSize */ (UINT16)(sizeof(PolicyCommandCode_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyCommandCode_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyCommandCode_In, code))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM_CC_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyCommandCodeDataAddress (&_PolicyCommandCodeData) +#else +#define _PolicyCommandCodeDataAddress 0 +#endif +#if CC_PolicyPhysicalPresence +#include "PolicyPhysicalPresence_fp.h" +typedef TPM_RC (PolicyPhysicalPresence_Entry)( + PolicyPhysicalPresence_In *in + ); +typedef const struct { + PolicyPhysicalPresence_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t; +PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t _PolicyPhysicalPresenceData = { + /* entry */ &TPM2_PolicyPhysicalPresence, + /* inSize */ (UINT16)(sizeof(PolicyPhysicalPresence_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyPhysicalPresenceDataAddress (&_PolicyPhysicalPresenceData) +#else +#define _PolicyPhysicalPresenceDataAddress 0 +#endif +#if CC_PolicyCpHash +#include "PolicyCpHash_fp.h" +typedef TPM_RC (PolicyCpHash_Entry)( + PolicyCpHash_In *in + ); +typedef const struct { + PolicyCpHash_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyCpHash_COMMAND_DESCRIPTOR_t; +PolicyCpHash_COMMAND_DESCRIPTOR_t _PolicyCpHashData = { + /* entry */ &TPM2_PolicyCpHash, + /* inSize */ (UINT16)(sizeof(PolicyCpHash_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyCpHash_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyCpHash_In, cpHashA))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyCpHashDataAddress (&_PolicyCpHashData) +#else +#define _PolicyCpHashDataAddress 0 +#endif +#if CC_PolicyNameHash +#include "PolicyNameHash_fp.h" +typedef TPM_RC (PolicyNameHash_Entry)( + PolicyNameHash_In *in + ); +typedef const struct { + PolicyNameHash_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyNameHash_COMMAND_DESCRIPTOR_t; +PolicyNameHash_COMMAND_DESCRIPTOR_t _PolicyNameHashData = { + /* entry */ &TPM2_PolicyNameHash, + /* inSize */ (UINT16)(sizeof(PolicyNameHash_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyNameHash_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyNameHash_In, nameHash))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyNameHashDataAddress (&_PolicyNameHashData) +#else +#define _PolicyNameHashDataAddress 0 +#endif +#if CC_PolicyDuplicationSelect +#include "PolicyDuplicationSelect_fp.h" +typedef TPM_RC (PolicyDuplicationSelect_Entry)( + PolicyDuplicationSelect_In *in + ); +typedef const struct { + PolicyDuplicationSelect_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t; +PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t _PolicyDuplicationSelectData = { + /* entry */ &TPM2_PolicyDuplicationSelect, + /* inSize */ (UINT16)(sizeof(PolicyDuplicationSelect_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyDuplicationSelect_In, objectName)), + (UINT16)(offsetof(PolicyDuplicationSelect_In, newParentName)), + (UINT16)(offsetof(PolicyDuplicationSelect_In, includeObject))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyDuplicationSelectDataAddress (&_PolicyDuplicationSelectData) +#else +#define _PolicyDuplicationSelectDataAddress 0 +#endif +#if CC_PolicyAuthorize +#include "PolicyAuthorize_fp.h" +typedef TPM_RC (PolicyAuthorize_Entry)( + PolicyAuthorize_In *in + ); +typedef const struct { + PolicyAuthorize_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[7]; +} PolicyAuthorize_COMMAND_DESCRIPTOR_t; +PolicyAuthorize_COMMAND_DESCRIPTOR_t _PolicyAuthorizeData = { + /* entry */ &TPM2_PolicyAuthorize, + /* inSize */ (UINT16)(sizeof(PolicyAuthorize_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyAuthorize_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyAuthorize_In, approvedPolicy)), + (UINT16)(offsetof(PolicyAuthorize_In, policyRef)), + (UINT16)(offsetof(PolicyAuthorize_In, keySign)), + (UINT16)(offsetof(PolicyAuthorize_In, checkTicket))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPMT_TK_VERIFIED_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyAuthorizeDataAddress (&_PolicyAuthorizeData) +#else +#define _PolicyAuthorizeDataAddress 0 +#endif +#if CC_PolicyAuthValue +#include "PolicyAuthValue_fp.h" +typedef TPM_RC (PolicyAuthValue_Entry)( + PolicyAuthValue_In *in + ); +typedef const struct { + PolicyAuthValue_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PolicyAuthValue_COMMAND_DESCRIPTOR_t; +PolicyAuthValue_COMMAND_DESCRIPTOR_t _PolicyAuthValueData = { + /* entry */ &TPM2_PolicyAuthValue, + /* inSize */ (UINT16)(sizeof(PolicyAuthValue_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyAuthValue_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyAuthValueDataAddress (&_PolicyAuthValueData) +#else +#define _PolicyAuthValueDataAddress 0 +#endif +#if CC_PolicyPassword +#include "PolicyPassword_fp.h" +typedef TPM_RC (PolicyPassword_Entry)( + PolicyPassword_In *in + ); +typedef const struct { + PolicyPassword_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PolicyPassword_COMMAND_DESCRIPTOR_t; +PolicyPassword_COMMAND_DESCRIPTOR_t _PolicyPasswordData = { + /* entry */ &TPM2_PolicyPassword, + /* inSize */ (UINT16)(sizeof(PolicyPassword_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyPassword_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyPasswordDataAddress (&_PolicyPasswordData) +#else +#define _PolicyPasswordDataAddress 0 +#endif +#if CC_PolicyGetDigest +#include "PolicyGetDigest_fp.h" +typedef TPM_RC (PolicyGetDigest_Entry)( + PolicyGetDigest_In *in, + PolicyGetDigest_Out *out + ); +typedef const struct { + PolicyGetDigest_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} PolicyGetDigest_COMMAND_DESCRIPTOR_t; +PolicyGetDigest_COMMAND_DESCRIPTOR_t _PolicyGetDigestData = { + /* entry */ &TPM2_PolicyGetDigest, + /* inSize */ (UINT16)(sizeof(PolicyGetDigest_In)), + /* outSize */ (UINT16)(sizeof(PolicyGetDigest_Out)), + /* offsetOfTypes */ offsetof(PolicyGetDigest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST} +}; +#define _PolicyGetDigestDataAddress (&_PolicyGetDigestData) +#else +#define _PolicyGetDigestDataAddress 0 +#endif +#if CC_PolicyNvWritten +#include "PolicyNvWritten_fp.h" +typedef TPM_RC (PolicyNvWritten_Entry)( + PolicyNvWritten_In *in + ); +typedef const struct { + PolicyNvWritten_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyNvWritten_COMMAND_DESCRIPTOR_t; +PolicyNvWritten_COMMAND_DESCRIPTOR_t _PolicyNvWrittenData = { + /* entry */ &TPM2_PolicyNvWritten, + /* inSize */ (UINT16)(sizeof(PolicyNvWritten_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyNvWritten_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyNvWritten_In, writtenSet))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyNvWrittenDataAddress (&_PolicyNvWrittenData) +#else +#define _PolicyNvWrittenDataAddress 0 +#endif +#if CC_PolicyTemplate +#include "PolicyTemplate_fp.h" +typedef TPM_RC (PolicyTemplate_Entry)( + PolicyTemplate_In *in + ); +typedef const struct { + PolicyTemplate_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyTemplate_COMMAND_DESCRIPTOR_t; +PolicyTemplate_COMMAND_DESCRIPTOR_t _PolicyTemplateData = { + /* entry */ &TPM2_PolicyTemplate, + /* inSize */ (UINT16)(sizeof(PolicyTemplate_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyTemplate_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyTemplate_In, templateHash))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyTemplateDataAddress (&_PolicyTemplateData) +#else +#define _PolicyTemplateDataAddress 0 +#endif +#if CC_PolicyAuthorizeNV +#include "PolicyAuthorizeNV_fp.h" +typedef TPM_RC (PolicyAuthorizeNV_Entry)( + PolicyAuthorizeNV_In *in + ); +typedef const struct { + PolicyAuthorizeNV_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t; +PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t _PolicyAuthorizeNVData = { + /* entry */ &TPM2_PolicyAuthorizeNV, + /* inSize */ (UINT16)(sizeof(PolicyAuthorizeNV_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyAuthorizeNV_In, nvIndex)), + (UINT16)(offsetof(PolicyAuthorizeNV_In, policySession))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPMI_SH_POLICY_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PolicyAuthorizeNVDataAddress (&_PolicyAuthorizeNVData) +#else +#define _PolicyAuthorizeNVDataAddress 0 +#endif +#if CC_CreatePrimary +#include "CreatePrimary_fp.h" +typedef TPM_RC (CreatePrimary_Entry)( + CreatePrimary_In *in, + CreatePrimary_Out *out + ); +typedef const struct { + CreatePrimary_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[9]; + BYTE types[13]; +} CreatePrimary_COMMAND_DESCRIPTOR_t; +CreatePrimary_COMMAND_DESCRIPTOR_t _CreatePrimaryData = { + /* entry */ &TPM2_CreatePrimary, + /* inSize */ (UINT16)(sizeof(CreatePrimary_In)), + /* outSize */ (UINT16)(sizeof(CreatePrimary_Out)), + /* offsetOfTypes */ offsetof(CreatePrimary_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(CreatePrimary_In, inSensitive)), + (UINT16)(offsetof(CreatePrimary_In, inPublic)), + (UINT16)(offsetof(CreatePrimary_In, outsideInfo)), + (UINT16)(offsetof(CreatePrimary_In, creationPCR)), + (UINT16)(offsetof(CreatePrimary_Out, outPublic)), + (UINT16)(offsetof(CreatePrimary_Out, creationData)), + (UINT16)(offsetof(CreatePrimary_Out, creationHash)), + (UINT16)(offsetof(CreatePrimary_Out, creationTicket)), + (UINT16)(offsetof(CreatePrimary_Out, name))}, + /* types */ {TPMI_RH_HIERARCHY_H_UNMARSHAL + ADD_FLAG, + TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + TPM_HANDLE_H_MARSHAL, + TPM2B_PUBLIC_P_MARSHAL, + TPM2B_CREATION_DATA_P_MARSHAL, + TPM2B_DIGEST_P_MARSHAL, + TPMT_TK_CREATION_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST} +}; +#define _CreatePrimaryDataAddress (&_CreatePrimaryData) +#else +#define _CreatePrimaryDataAddress 0 +#endif +#if CC_HierarchyControl +#include "HierarchyControl_fp.h" +typedef TPM_RC (HierarchyControl_Entry)( + HierarchyControl_In *in + ); +typedef const struct { + HierarchyControl_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} HierarchyControl_COMMAND_DESCRIPTOR_t; +HierarchyControl_COMMAND_DESCRIPTOR_t _HierarchyControlData = { + /* entry */ &TPM2_HierarchyControl, + /* inSize */ (UINT16)(sizeof(HierarchyControl_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(HierarchyControl_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(HierarchyControl_In, enable)), + (UINT16)(offsetof(HierarchyControl_In, state))}, + /* types */ {TPMI_RH_HIERARCHY_H_UNMARSHAL, + TPMI_RH_ENABLES_P_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _HierarchyControlDataAddress (&_HierarchyControlData) +#else +#define _HierarchyControlDataAddress 0 +#endif +#if CC_SetPrimaryPolicy +#include "SetPrimaryPolicy_fp.h" +typedef TPM_RC (SetPrimaryPolicy_Entry)( + SetPrimaryPolicy_In *in + ); +typedef const struct { + SetPrimaryPolicy_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} SetPrimaryPolicy_COMMAND_DESCRIPTOR_t; +SetPrimaryPolicy_COMMAND_DESCRIPTOR_t _SetPrimaryPolicyData = { + /* entry */ &TPM2_SetPrimaryPolicy, + /* inSize */ (UINT16)(sizeof(SetPrimaryPolicy_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SetPrimaryPolicy_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(SetPrimaryPolicy_In, authPolicy)), + (UINT16)(offsetof(SetPrimaryPolicy_In, hashAlg))}, + /* types */ {TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + END_OF_LIST} +}; +#define _SetPrimaryPolicyDataAddress (&_SetPrimaryPolicyData) +#else +#define _SetPrimaryPolicyDataAddress 0 +#endif +#if CC_ChangePPS +#include "ChangePPS_fp.h" +typedef TPM_RC (ChangePPS_Entry)( + ChangePPS_In *in + ); +typedef const struct { + ChangePPS_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} ChangePPS_COMMAND_DESCRIPTOR_t; +ChangePPS_COMMAND_DESCRIPTOR_t _ChangePPSData = { + /* entry */ &TPM2_ChangePPS, + /* inSize */ (UINT16)(sizeof(ChangePPS_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ChangePPS_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _ChangePPSDataAddress (&_ChangePPSData) +#else +#define _ChangePPSDataAddress 0 +#endif +#if CC_ChangeEPS +#include "ChangeEPS_fp.h" +typedef TPM_RC (ChangeEPS_Entry)( + ChangeEPS_In *in + ); +typedef const struct { + ChangeEPS_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} ChangeEPS_COMMAND_DESCRIPTOR_t; +ChangeEPS_COMMAND_DESCRIPTOR_t _ChangeEPSData = { + /* entry */ &TPM2_ChangeEPS, + /* inSize */ (UINT16)(sizeof(ChangeEPS_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ChangeEPS_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _ChangeEPSDataAddress (&_ChangeEPSData) +#else +#define _ChangeEPSDataAddress 0 +#endif +#if CC_Clear +#include "Clear_fp.h" +typedef TPM_RC (Clear_Entry)( + Clear_In *in + ); +typedef const struct { + Clear_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} Clear_COMMAND_DESCRIPTOR_t; +Clear_COMMAND_DESCRIPTOR_t _ClearData = { + /* entry */ &TPM2_Clear, + /* inSize */ (UINT16)(sizeof(Clear_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(Clear_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_RH_CLEAR_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _ClearDataAddress (&_ClearData) +#else +#define _ClearDataAddress 0 +#endif +#if CC_ClearControl +#include "ClearControl_fp.h" +typedef TPM_RC (ClearControl_Entry)( + ClearControl_In *in + ); +typedef const struct { + ClearControl_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} ClearControl_COMMAND_DESCRIPTOR_t; +ClearControl_COMMAND_DESCRIPTOR_t _ClearControlData = { + /* entry */ &TPM2_ClearControl, + /* inSize */ (UINT16)(sizeof(ClearControl_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ClearControl_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ClearControl_In, disable))}, + /* types */ {TPMI_RH_CLEAR_H_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _ClearControlDataAddress (&_ClearControlData) +#else +#define _ClearControlDataAddress 0 +#endif +#if CC_HierarchyChangeAuth +#include "HierarchyChangeAuth_fp.h" +typedef TPM_RC (HierarchyChangeAuth_Entry)( + HierarchyChangeAuth_In *in + ); +typedef const struct { + HierarchyChangeAuth_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} HierarchyChangeAuth_COMMAND_DESCRIPTOR_t; +HierarchyChangeAuth_COMMAND_DESCRIPTOR_t _HierarchyChangeAuthData = { + /* entry */ &TPM2_HierarchyChangeAuth, + /* inSize */ (UINT16)(sizeof(HierarchyChangeAuth_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(HierarchyChangeAuth_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(HierarchyChangeAuth_In, newAuth))}, + /* types */ {TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _HierarchyChangeAuthDataAddress (&_HierarchyChangeAuthData) +#else +#define _HierarchyChangeAuthDataAddress 0 +#endif +#if CC_DictionaryAttackLockReset +#include "DictionaryAttackLockReset_fp.h" +typedef TPM_RC (DictionaryAttackLockReset_Entry)( + DictionaryAttackLockReset_In *in + ); +typedef const struct { + DictionaryAttackLockReset_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t; +DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t _DictionaryAttackLockResetData = { + /* entry */ &TPM2_DictionaryAttackLockReset, + /* inSize */ (UINT16)(sizeof(DictionaryAttackLockReset_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_RH_LOCKOUT_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _DictionaryAttackLockResetDataAddress (&_DictionaryAttackLockResetData) +#else +#define _DictionaryAttackLockResetDataAddress 0 +#endif +#if CC_DictionaryAttackParameters +#include "DictionaryAttackParameters_fp.h" +typedef TPM_RC (DictionaryAttackParameters_Entry)( + DictionaryAttackParameters_In *in + ); +typedef const struct { + DictionaryAttackParameters_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} DictionaryAttackParameters_COMMAND_DESCRIPTOR_t; +DictionaryAttackParameters_COMMAND_DESCRIPTOR_t _DictionaryAttackParametersData = { + /* entry */ &TPM2_DictionaryAttackParameters, + /* inSize */ (UINT16)(sizeof(DictionaryAttackParameters_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(DictionaryAttackParameters_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(DictionaryAttackParameters_In, newMaxTries)), + (UINT16)(offsetof(DictionaryAttackParameters_In, newRecoveryTime)), + (UINT16)(offsetof(DictionaryAttackParameters_In, lockoutRecovery))}, + /* types */ {TPMI_RH_LOCKOUT_H_UNMARSHAL, + UINT32_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _DictionaryAttackParametersDataAddress (&_DictionaryAttackParametersData) +#else +#define _DictionaryAttackParametersDataAddress 0 +#endif +#if CC_PP_Commands +#include "PP_Commands_fp.h" +typedef TPM_RC (PP_Commands_Entry)( + PP_Commands_In *in + ); +typedef const struct { + PP_Commands_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} PP_Commands_COMMAND_DESCRIPTOR_t; +PP_Commands_COMMAND_DESCRIPTOR_t _PP_CommandsData = { + /* entry */ &TPM2_PP_Commands, + /* inSize */ (UINT16)(sizeof(PP_Commands_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PP_Commands_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PP_Commands_In, setList)), + (UINT16)(offsetof(PP_Commands_In, clearList))}, + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, + TPML_CC_P_UNMARSHAL, + TPML_CC_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _PP_CommandsDataAddress (&_PP_CommandsData) +#else +#define _PP_CommandsDataAddress 0 +#endif +#if CC_SetAlgorithmSet +#include "SetAlgorithmSet_fp.h" +typedef TPM_RC (SetAlgorithmSet_Entry)( + SetAlgorithmSet_In *in + ); +typedef const struct { + SetAlgorithmSet_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} SetAlgorithmSet_COMMAND_DESCRIPTOR_t; +SetAlgorithmSet_COMMAND_DESCRIPTOR_t _SetAlgorithmSetData = { + /* entry */ &TPM2_SetAlgorithmSet, + /* inSize */ (UINT16)(sizeof(SetAlgorithmSet_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SetAlgorithmSet_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(SetAlgorithmSet_In, algorithmSet))}, + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, + UINT32_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _SetAlgorithmSetDataAddress (&_SetAlgorithmSetData) +#else +#define _SetAlgorithmSetDataAddress 0 +#endif +#if CC_FieldUpgradeStart +#include "FieldUpgradeStart_fp.h" +typedef TPM_RC (FieldUpgradeStart_Entry)( + FieldUpgradeStart_In *in + ); +typedef const struct { + FieldUpgradeStart_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} FieldUpgradeStart_COMMAND_DESCRIPTOR_t; +FieldUpgradeStart_COMMAND_DESCRIPTOR_t _FieldUpgradeStartData = { + /* entry */ &TPM2_FieldUpgradeStart, + /* inSize */ (UINT16)(sizeof(FieldUpgradeStart_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(FieldUpgradeStart_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(FieldUpgradeStart_In, keyHandle)), + (UINT16)(offsetof(FieldUpgradeStart_In, fuDigest)), + (UINT16)(offsetof(FieldUpgradeStart_In, manifestSignature))}, + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_SIGNATURE_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _FieldUpgradeStartDataAddress (&_FieldUpgradeStartData) +#else +#define _FieldUpgradeStartDataAddress 0 +#endif +#if CC_FieldUpgradeData +#include "FieldUpgradeData_fp.h" +typedef TPM_RC (FieldUpgradeData_Entry)( + FieldUpgradeData_In *in, + FieldUpgradeData_Out *out + ); +typedef const struct { + FieldUpgradeData_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} FieldUpgradeData_COMMAND_DESCRIPTOR_t; +FieldUpgradeData_COMMAND_DESCRIPTOR_t _FieldUpgradeDataData = { + /* entry */ &TPM2_FieldUpgradeData, + /* inSize */ (UINT16)(sizeof(FieldUpgradeData_In)), + /* outSize */ (UINT16)(sizeof(FieldUpgradeData_Out)), + /* offsetOfTypes */ offsetof(FieldUpgradeData_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(FieldUpgradeData_Out, firstDigest))}, + /* types */ {TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPMT_HA_P_MARSHAL, + TPMT_HA_P_MARSHAL, + END_OF_LIST} +}; +#define _FieldUpgradeDataDataAddress (&_FieldUpgradeDataData) +#else +#define _FieldUpgradeDataDataAddress 0 +#endif +#if CC_FirmwareRead +#include "FirmwareRead_fp.h" +typedef TPM_RC (FirmwareRead_Entry)( + FirmwareRead_In *in, + FirmwareRead_Out *out + ); +typedef const struct { + FirmwareRead_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} FirmwareRead_COMMAND_DESCRIPTOR_t; +FirmwareRead_COMMAND_DESCRIPTOR_t _FirmwareReadData = { + /* entry */ &TPM2_FirmwareRead, + /* inSize */ (UINT16)(sizeof(FirmwareRead_In)), + /* outSize */ (UINT16)(sizeof(FirmwareRead_Out)), + /* offsetOfTypes */ offsetof(FirmwareRead_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {UINT32_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + END_OF_LIST} +}; +#define _FirmwareReadDataAddress (&_FirmwareReadData) +#else +#define _FirmwareReadDataAddress 0 +#endif +#if CC_ContextSave +#include "ContextSave_fp.h" +typedef TPM_RC (ContextSave_Entry)( + ContextSave_In *in, + ContextSave_Out *out + ); +typedef const struct { + ContextSave_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} ContextSave_COMMAND_DESCRIPTOR_t; +ContextSave_COMMAND_DESCRIPTOR_t _ContextSaveData = { + /* entry */ &TPM2_ContextSave, + /* inSize */ (UINT16)(sizeof(ContextSave_In)), + /* outSize */ (UINT16)(sizeof(ContextSave_Out)), + /* offsetOfTypes */ offsetof(ContextSave_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_DH_CONTEXT_H_UNMARSHAL, + END_OF_LIST, + TPMS_CONTEXT_P_MARSHAL, + END_OF_LIST} +}; +#define _ContextSaveDataAddress (&_ContextSaveData) +#else +#define _ContextSaveDataAddress 0 +#endif +#if CC_ContextLoad +#include "ContextLoad_fp.h" +typedef TPM_RC (ContextLoad_Entry)( + ContextLoad_In *in, + ContextLoad_Out *out + ); +typedef const struct { + ContextLoad_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} ContextLoad_COMMAND_DESCRIPTOR_t; +ContextLoad_COMMAND_DESCRIPTOR_t _ContextLoadData = { + /* entry */ &TPM2_ContextLoad, + /* inSize */ (UINT16)(sizeof(ContextLoad_In)), + /* outSize */ (UINT16)(sizeof(ContextLoad_Out)), + /* offsetOfTypes */ offsetof(ContextLoad_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMS_CONTEXT_P_UNMARSHAL, + END_OF_LIST, + TPMI_DH_CONTEXT_H_MARSHAL, + END_OF_LIST} +}; +#define _ContextLoadDataAddress (&_ContextLoadData) +#else +#define _ContextLoadDataAddress 0 +#endif +#if CC_FlushContext +#include "FlushContext_fp.h" +typedef TPM_RC (FlushContext_Entry)( + FlushContext_In *in + ); +typedef const struct { + FlushContext_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} FlushContext_COMMAND_DESCRIPTOR_t; +FlushContext_COMMAND_DESCRIPTOR_t _FlushContextData = { + /* entry */ &TPM2_FlushContext, + /* inSize */ (UINT16)(sizeof(FlushContext_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(FlushContext_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_DH_CONTEXT_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _FlushContextDataAddress (&_FlushContextData) +#else +#define _FlushContextDataAddress 0 +#endif +#if CC_EvictControl +#include "EvictControl_fp.h" +typedef TPM_RC (EvictControl_Entry)( + EvictControl_In *in + ); +typedef const struct { + EvictControl_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} EvictControl_COMMAND_DESCRIPTOR_t; +EvictControl_COMMAND_DESCRIPTOR_t _EvictControlData = { + /* entry */ &TPM2_EvictControl, + /* inSize */ (UINT16)(sizeof(EvictControl_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(EvictControl_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(EvictControl_In, objectHandle)), + (UINT16)(offsetof(EvictControl_In, persistentHandle))}, + /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_PERSISTENT_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _EvictControlDataAddress (&_EvictControlData) +#else +#define _EvictControlDataAddress 0 +#endif +#if CC_ReadClock +#include "ReadClock_fp.h" +typedef TPM_RC (ReadClock_Entry)( + ReadClock_Out *out + ); +typedef const struct { + ReadClock_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} ReadClock_COMMAND_DESCRIPTOR_t; +ReadClock_COMMAND_DESCRIPTOR_t _ReadClockData = { + /* entry */ &TPM2_ReadClock, + /* inSize */ 0, + /* outSize */ (UINT16)(sizeof(ReadClock_Out)), + /* offsetOfTypes */ offsetof(ReadClock_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {END_OF_LIST, + TPMS_TIME_INFO_P_MARSHAL, + END_OF_LIST} +}; +#define _ReadClockDataAddress (&_ReadClockData) +#else +#define _ReadClockDataAddress 0 +#endif +#if CC_ClockSet +#include "ClockSet_fp.h" +typedef TPM_RC (ClockSet_Entry)( + ClockSet_In *in + ); +typedef const struct { + ClockSet_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} ClockSet_COMMAND_DESCRIPTOR_t; +ClockSet_COMMAND_DESCRIPTOR_t _ClockSetData = { + /* entry */ &TPM2_ClockSet, + /* inSize */ (UINT16)(sizeof(ClockSet_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ClockSet_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ClockSet_In, newTime))}, + /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, + UINT64_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _ClockSetDataAddress (&_ClockSetData) +#else +#define _ClockSetDataAddress 0 +#endif +#if CC_ClockRateAdjust +#include "ClockRateAdjust_fp.h" +typedef TPM_RC (ClockRateAdjust_Entry)( + ClockRateAdjust_In *in + ); +typedef const struct { + ClockRateAdjust_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} ClockRateAdjust_COMMAND_DESCRIPTOR_t; +ClockRateAdjust_COMMAND_DESCRIPTOR_t _ClockRateAdjustData = { + /* entry */ &TPM2_ClockRateAdjust, + /* inSize */ (UINT16)(sizeof(ClockRateAdjust_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ClockRateAdjust_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ClockRateAdjust_In, rateAdjust))}, + /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, + TPM_CLOCK_ADJUST_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _ClockRateAdjustDataAddress (&_ClockRateAdjustData) +#else +#define _ClockRateAdjustDataAddress 0 +#endif +#if CC_GetCapability +#include "GetCapability_fp.h" +typedef TPM_RC (GetCapability_Entry)( + GetCapability_In *in, + GetCapability_Out *out + ); +typedef const struct { + GetCapability_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} GetCapability_COMMAND_DESCRIPTOR_t; +GetCapability_COMMAND_DESCRIPTOR_t _GetCapabilityData = { + /* entry */ &TPM2_GetCapability, + /* inSize */ (UINT16)(sizeof(GetCapability_In)), + /* outSize */ (UINT16)(sizeof(GetCapability_Out)), + /* offsetOfTypes */ offsetof(GetCapability_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(GetCapability_In, property)), + (UINT16)(offsetof(GetCapability_In, propertyCount)), + (UINT16)(offsetof(GetCapability_Out, capabilityData))}, + /* types */ {TPM_CAP_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + END_OF_LIST, + TPMI_YES_NO_P_MARSHAL, + TPMS_CAPABILITY_DATA_P_MARSHAL, + END_OF_LIST} +}; +#define _GetCapabilityDataAddress (&_GetCapabilityData) +#else +#define _GetCapabilityDataAddress 0 +#endif +#if CC_TestParms +#include "TestParms_fp.h" +typedef TPM_RC (TestParms_Entry)( + TestParms_In *in + ); +typedef const struct { + TestParms_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} TestParms_COMMAND_DESCRIPTOR_t; +TestParms_COMMAND_DESCRIPTOR_t _TestParmsData = { + /* entry */ &TPM2_TestParms, + /* inSize */ (UINT16)(sizeof(TestParms_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(TestParms_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMT_PUBLIC_PARMS_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _TestParmsDataAddress (&_TestParmsData) +#else +#define _TestParmsDataAddress 0 +#endif +#if CC_NV_DefineSpace +#include "NV_DefineSpace_fp.h" +typedef TPM_RC (NV_DefineSpace_Entry)( + NV_DefineSpace_In *in + ); +typedef const struct { + NV_DefineSpace_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} NV_DefineSpace_COMMAND_DESCRIPTOR_t; +NV_DefineSpace_COMMAND_DESCRIPTOR_t _NV_DefineSpaceData = { + /* entry */ &TPM2_NV_DefineSpace, + /* inSize */ (UINT16)(sizeof(NV_DefineSpace_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_DefineSpace_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_DefineSpace_In, auth)), + (UINT16)(offsetof(NV_DefineSpace_In, publicInfo))}, + /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + TPM2B_NV_PUBLIC_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_DefineSpaceDataAddress (&_NV_DefineSpaceData) +#else +#define _NV_DefineSpaceDataAddress 0 +#endif +#if CC_NV_UndefineSpace +#include "NV_UndefineSpace_fp.h" +typedef TPM_RC (NV_UndefineSpace_Entry)( + NV_UndefineSpace_In *in + ); +typedef const struct { + NV_UndefineSpace_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_UndefineSpace_COMMAND_DESCRIPTOR_t; +NV_UndefineSpace_COMMAND_DESCRIPTOR_t _NV_UndefineSpaceData = { + /* entry */ &TPM2_NV_UndefineSpace, + /* inSize */ (UINT16)(sizeof(NV_UndefineSpace_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_UndefineSpace_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_UndefineSpace_In, nvIndex))}, + /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_UndefineSpaceDataAddress (&_NV_UndefineSpaceData) +#else +#define _NV_UndefineSpaceDataAddress 0 +#endif +#if CC_NV_UndefineSpaceSpecial +#include "NV_UndefineSpaceSpecial_fp.h" +typedef TPM_RC (NV_UndefineSpaceSpecial_Entry)( + NV_UndefineSpaceSpecial_In *in + ); +typedef const struct { + NV_UndefineSpaceSpecial_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t; +NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t _NV_UndefineSpaceSpecialData = { + /* entry */ &TPM2_NV_UndefineSpaceSpecial, + /* inSize */ (UINT16)(sizeof(NV_UndefineSpaceSpecial_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_UndefineSpaceSpecial_In, platform))}, + /* types */ {TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPMI_RH_PLATFORM_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_UndefineSpaceSpecialDataAddress (&_NV_UndefineSpaceSpecialData) +#else +#define _NV_UndefineSpaceSpecialDataAddress 0 +#endif +#if CC_NV_ReadPublic +#include "NV_ReadPublic_fp.h" +typedef TPM_RC (NV_ReadPublic_Entry)( + NV_ReadPublic_In *in, + NV_ReadPublic_Out *out + ); +typedef const struct { + NV_ReadPublic_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} NV_ReadPublic_COMMAND_DESCRIPTOR_t; +NV_ReadPublic_COMMAND_DESCRIPTOR_t _NV_ReadPublicData = { + /* entry */ &TPM2_NV_ReadPublic, + /* inSize */ (UINT16)(sizeof(NV_ReadPublic_In)), + /* outSize */ (UINT16)(sizeof(NV_ReadPublic_Out)), + /* offsetOfTypes */ offsetof(NV_ReadPublic_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_ReadPublic_Out, nvName))}, + /* types */ {TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + TPM2B_NV_PUBLIC_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST} +}; +#define _NV_ReadPublicDataAddress (&_NV_ReadPublicData) +#else +#define _NV_ReadPublicDataAddress 0 +#endif +#if CC_NV_Write +#include "NV_Write_fp.h" +typedef TPM_RC (NV_Write_Entry)( + NV_Write_In *in + ); +typedef const struct { + NV_Write_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} NV_Write_COMMAND_DESCRIPTOR_t; +NV_Write_COMMAND_DESCRIPTOR_t _NV_WriteData = { + /* entry */ &TPM2_NV_Write, + /* inSize */ (UINT16)(sizeof(NV_Write_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_Write_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_Write_In, nvIndex)), + (UINT16)(offsetof(NV_Write_In, data)), + (UINT16)(offsetof(NV_Write_In, offset))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPM2B_MAX_NV_BUFFER_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_WriteDataAddress (&_NV_WriteData) +#else +#define _NV_WriteDataAddress 0 +#endif +#if CC_NV_Increment +#include "NV_Increment_fp.h" +typedef TPM_RC (NV_Increment_Entry)( + NV_Increment_In *in + ); +typedef const struct { + NV_Increment_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_Increment_COMMAND_DESCRIPTOR_t; +NV_Increment_COMMAND_DESCRIPTOR_t _NV_IncrementData = { + /* entry */ &TPM2_NV_Increment, + /* inSize */ (UINT16)(sizeof(NV_Increment_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_Increment_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_Increment_In, nvIndex))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_IncrementDataAddress (&_NV_IncrementData) +#else +#define _NV_IncrementDataAddress 0 +#endif +#if CC_NV_Extend +#include "NV_Extend_fp.h" +typedef TPM_RC (NV_Extend_Entry)( + NV_Extend_In *in + ); +typedef const struct { + NV_Extend_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} NV_Extend_COMMAND_DESCRIPTOR_t; +NV_Extend_COMMAND_DESCRIPTOR_t _NV_ExtendData = { + /* entry */ &TPM2_NV_Extend, + /* inSize */ (UINT16)(sizeof(NV_Extend_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_Extend_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_Extend_In, nvIndex)), + (UINT16)(offsetof(NV_Extend_In, data))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPM2B_MAX_NV_BUFFER_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_ExtendDataAddress (&_NV_ExtendData) +#else +#define _NV_ExtendDataAddress 0 +#endif +#if CC_NV_SetBits +#include "NV_SetBits_fp.h" +typedef TPM_RC (NV_SetBits_Entry)( + NV_SetBits_In *in + ); +typedef const struct { + NV_SetBits_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} NV_SetBits_COMMAND_DESCRIPTOR_t; +NV_SetBits_COMMAND_DESCRIPTOR_t _NV_SetBitsData = { + /* entry */ &TPM2_NV_SetBits, + /* inSize */ (UINT16)(sizeof(NV_SetBits_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_SetBits_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_SetBits_In, nvIndex)), + (UINT16)(offsetof(NV_SetBits_In, bits))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + UINT64_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_SetBitsDataAddress (&_NV_SetBitsData) +#else +#define _NV_SetBitsDataAddress 0 +#endif +#if CC_NV_WriteLock +#include "NV_WriteLock_fp.h" +typedef TPM_RC (NV_WriteLock_Entry)( + NV_WriteLock_In *in + ); +typedef const struct { + NV_WriteLock_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_WriteLock_COMMAND_DESCRIPTOR_t; +NV_WriteLock_COMMAND_DESCRIPTOR_t _NV_WriteLockData = { + /* entry */ &TPM2_NV_WriteLock, + /* inSize */ (UINT16)(sizeof(NV_WriteLock_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_WriteLock_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_WriteLock_In, nvIndex))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_WriteLockDataAddress (&_NV_WriteLockData) +#else +#define _NV_WriteLockDataAddress 0 +#endif +#if CC_NV_GlobalWriteLock +#include "NV_GlobalWriteLock_fp.h" +typedef TPM_RC (NV_GlobalWriteLock_Entry)( + NV_GlobalWriteLock_In *in + ); +typedef const struct { + NV_GlobalWriteLock_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t; +NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t _NV_GlobalWriteLockData = { + /* entry */ &TPM2_NV_GlobalWriteLock, + /* inSize */ (UINT16)(sizeof(NV_GlobalWriteLock_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_GlobalWriteLockDataAddress (&_NV_GlobalWriteLockData) +#else +#define _NV_GlobalWriteLockDataAddress 0 +#endif +#if CC_NV_Read +#include "NV_Read_fp.h" +typedef TPM_RC (NV_Read_Entry)( + NV_Read_In *in, + NV_Read_Out *out + ); +typedef const struct { + NV_Read_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} NV_Read_COMMAND_DESCRIPTOR_t; +NV_Read_COMMAND_DESCRIPTOR_t _NV_ReadData = { + /* entry */ &TPM2_NV_Read, + /* inSize */ (UINT16)(sizeof(NV_Read_In)), + /* outSize */ (UINT16)(sizeof(NV_Read_Out)), + /* offsetOfTypes */ offsetof(NV_Read_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_Read_In, nvIndex)), + (UINT16)(offsetof(NV_Read_In, size)), + (UINT16)(offsetof(NV_Read_In, offset))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + UINT16_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_NV_BUFFER_P_MARSHAL, + END_OF_LIST} +}; +#define _NV_ReadDataAddress (&_NV_ReadData) +#else +#define _NV_ReadDataAddress 0 +#endif +#if CC_NV_ReadLock +#include "NV_ReadLock_fp.h" +typedef TPM_RC (NV_ReadLock_Entry)( + NV_ReadLock_In *in + ); +typedef const struct { + NV_ReadLock_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_ReadLock_COMMAND_DESCRIPTOR_t; +NV_ReadLock_COMMAND_DESCRIPTOR_t _NV_ReadLockData = { + /* entry */ &TPM2_NV_ReadLock, + /* inSize */ (UINT16)(sizeof(NV_ReadLock_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_ReadLock_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_ReadLock_In, nvIndex))}, + /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_ReadLockDataAddress (&_NV_ReadLockData) +#else +#define _NV_ReadLockDataAddress 0 +#endif +#if CC_NV_ChangeAuth +#include "NV_ChangeAuth_fp.h" +typedef TPM_RC (NV_ChangeAuth_Entry)( + NV_ChangeAuth_In *in + ); +typedef const struct { + NV_ChangeAuth_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_ChangeAuth_COMMAND_DESCRIPTOR_t; +NV_ChangeAuth_COMMAND_DESCRIPTOR_t _NV_ChangeAuthData = { + /* entry */ &TPM2_NV_ChangeAuth, + /* inSize */ (UINT16)(sizeof(NV_ChangeAuth_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_ChangeAuth_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_ChangeAuth_In, newAuth))}, + /* types */ {TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _NV_ChangeAuthDataAddress (&_NV_ChangeAuthData) +#else +#define _NV_ChangeAuthDataAddress 0 +#endif +#if CC_NV_Certify +#include "NV_Certify_fp.h" +typedef TPM_RC (NV_Certify_Entry)( + NV_Certify_In *in, + NV_Certify_Out *out + ); +typedef const struct { + NV_Certify_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[7]; + BYTE types[11]; +} NV_Certify_COMMAND_DESCRIPTOR_t; +NV_Certify_COMMAND_DESCRIPTOR_t _NV_CertifyData = { + /* entry */ &TPM2_NV_Certify, + /* inSize */ (UINT16)(sizeof(NV_Certify_In)), + /* outSize */ (UINT16)(sizeof(NV_Certify_Out)), + /* offsetOfTypes */ offsetof(NV_Certify_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_Certify_In, authHandle)), + (UINT16)(offsetof(NV_Certify_In, nvIndex)), + (UINT16)(offsetof(NV_Certify_In, qualifyingData)), + (UINT16)(offsetof(NV_Certify_In, inScheme)), + (UINT16)(offsetof(NV_Certify_In, size)), + (UINT16)(offsetof(NV_Certify_In, offset)), + (UINT16)(offsetof(NV_Certify_Out, signature))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + UINT16_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST} +}; +#define _NV_CertifyDataAddress (&_NV_CertifyData) +#else +#define _NV_CertifyDataAddress 0 +#endif + +#if CC_AC_GetCapability +#include "AC_GetCapability_fp.h" +typedef TPM_RC (AC_GetCapability_Entry)( + AC_GetCapability_In *in, + AC_GetCapability_Out *out + ); +typedef const struct { + AC_GetCapability_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} AC_GetCapability_COMMAND_DESCRIPTOR_t; +AC_GetCapability_COMMAND_DESCRIPTOR_t _AC_GetCapabilityData = { + /* entry */ &TPM2_AC_GetCapability, + /* inSize */ (UINT16)(sizeof(AC_GetCapability_In)), + /* outSize */ (UINT16)(sizeof(AC_GetCapability_Out)), + /* offsetOfTypes */ offsetof(AC_GetCapability_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(AC_GetCapability_In, capability)), + (UINT16)(offsetof(AC_GetCapability_In, count)), + (UINT16)(offsetof(AC_GetCapability_Out, capabilitiesData))}, + /* types */ {TPMI_RH_AC_H_UNMARSHAL, + TPM_AT_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + END_OF_LIST, + TPMI_YES_NO_P_MARSHAL, + TPML_AC_CAPABILITIES_P_MARSHAL, + END_OF_LIST} +}; +#define _AC_GetCapabilityDataAddress (&_AC_GetCapabilityData) +#else +#define _AC_GetCapabilityDataAddress 0 +#endif + +#if CC_AC_Send +#include "AC_Send_fp.h" +typedef TPM_RC (AC_Send_Entry)( + AC_Send_In *in, + AC_Send_Out *out + ); +typedef const struct { + AC_Send_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} AC_Send_COMMAND_DESCRIPTOR_t; +AC_Send_COMMAND_DESCRIPTOR_t _AC_SendData = { + /* entry */ &TPM2_AC_Send, + /* inSize */ (UINT16)(sizeof(AC_Send_In)), + /* outSize */ (UINT16)(sizeof(AC_Send_Out)), + /* offsetOfTypes */ offsetof(AC_Send_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(AC_Send_In, authHandle)), + (UINT16)(offsetof(AC_Send_In, ac)), + (UINT16)(offsetof(AC_Send_In, acDataIn))}, + /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_AC_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPMS_AC_OUTPUT_P_MARSHAL, + END_OF_LIST} +}; +#define _AC_SendDataAddress (&_AC_SendData) +#else +#define _AC_SendDataAddress 0 +#endif + +#if CC_Policy_AC_SendSelect +#include "Policy_AC_SendSelect_fp.h" +typedef TPM_RC (Policy_AC_SendSelect_Entry)( + Policy_AC_SendSelect_In *in + ); +typedef const struct { + Policy_AC_SendSelect_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[7]; +} Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t; +Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t _Policy_AC_SendSelectData = { + /* entry */ &TPM2_Policy_AC_SendSelect, + /* inSize */ (UINT16)(sizeof(Policy_AC_SendSelect_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(Policy_AC_SendSelect_In, objectName)), + (UINT16)(offsetof(Policy_AC_SendSelect_In, authHandleName)), + (UINT16)(offsetof(Policy_AC_SendSelect_In, acName)), + (UINT16)(offsetof(Policy_AC_SendSelect_In, includeObject))}, + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _Policy_AC_SendSelectDataAddress (&_Policy_AC_SendSelectData) +#else +#define _Policy_AC_SendSelectDataAddress 0 +#endif + +#if CC_ACT_SetTimeout +#include "ACT_SetTimeout_fp.h" +typedef TPM_RC (ACT_SetTimeout_Entry)( + ACT_SetTimeout_In *in + ); +typedef const struct { + ACT_SetTimeout_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} ACT_SetTimeout_COMMAND_DESCRIPTOR_t; +ACT_SetTimeout_COMMAND_DESCRIPTOR_t _ACT_SetTimeoutData = { + /* entry */ &TPM2_ACT_SetTimeout, + /* inSize */ (UINT16)(sizeof(ACT_SetTimeout_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ACT_SetTimeout_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ACT_SetTimeout_In, startTimeout))}, + /* types */ {TPMI_RH_ACT_H_UNMARSHAL, + UINT32_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST} +}; +#define _ACT_SetTimeoutDataAddress (&_ACT_SetTimeoutData) +#else +#define _ACT_SetTimeoutDataAddress 0 +#endif // CC_ACT_SetTimeout + +#if CC_Vendor_TCG_Test +#include "Vendor_TCG_Test_fp.h" +typedef TPM_RC (Vendor_TCG_Test_Entry)( + Vendor_TCG_Test_In *in, + Vendor_TCG_Test_Out *out + ); +typedef const struct { + Vendor_TCG_Test_Entry *entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} Vendor_TCG_Test_COMMAND_DESCRIPTOR_t; +Vendor_TCG_Test_COMMAND_DESCRIPTOR_t _Vendor_TCG_TestData = { + /* entry */ &TPM2_Vendor_TCG_Test, + /* inSize */ (UINT16)(sizeof(Vendor_TCG_Test_In)), + /* outSize */ (UINT16)(sizeof(Vendor_TCG_Test_Out)), + /* offsetOfTypes */ offsetof(Vendor_TCG_Test_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets + /* types */ {TPM2B_DATA_P_UNMARSHAL, + END_OF_LIST, + TPM2B_DATA_P_MARSHAL, + END_OF_LIST} +}; +#define _Vendor_TCG_TestDataAddress (&_Vendor_TCG_TestData) +#else +#define _Vendor_TCG_TestDataAddress 0 +#endif + +COMMAND_DESCRIPTOR_t *s_CommandDataArray[] = { +#if (PAD_LIST || CC_NV_UndefineSpaceSpecial) + (COMMAND_DESCRIPTOR_t *)_NV_UndefineSpaceSpecialDataAddress, +#endif +#if (PAD_LIST || CC_EvictControl) + (COMMAND_DESCRIPTOR_t *)_EvictControlDataAddress, +#endif +#if (PAD_LIST || CC_HierarchyControl) + (COMMAND_DESCRIPTOR_t *)_HierarchyControlDataAddress, +#endif +#if (PAD_LIST || CC_NV_UndefineSpace) + (COMMAND_DESCRIPTOR_t *)_NV_UndefineSpaceDataAddress, +#endif +#if (PAD_LIST) + (COMMAND_DESCRIPTOR_t *)0, +#endif +#if (PAD_LIST || CC_ChangeEPS) + (COMMAND_DESCRIPTOR_t *)_ChangeEPSDataAddress, +#endif +#if (PAD_LIST || CC_ChangePPS) + (COMMAND_DESCRIPTOR_t *)_ChangePPSDataAddress, +#endif +#if (PAD_LIST || CC_Clear) + (COMMAND_DESCRIPTOR_t *)_ClearDataAddress, +#endif +#if (PAD_LIST || CC_ClearControl) + (COMMAND_DESCRIPTOR_t *)_ClearControlDataAddress, +#endif +#if (PAD_LIST || CC_ClockSet) + (COMMAND_DESCRIPTOR_t *)_ClockSetDataAddress, +#endif +#if (PAD_LIST || CC_HierarchyChangeAuth) + (COMMAND_DESCRIPTOR_t *)_HierarchyChangeAuthDataAddress, +#endif +#if (PAD_LIST || CC_NV_DefineSpace) + (COMMAND_DESCRIPTOR_t *)_NV_DefineSpaceDataAddress, +#endif +#if (PAD_LIST || CC_PCR_Allocate) + (COMMAND_DESCRIPTOR_t *)_PCR_AllocateDataAddress, +#endif +#if (PAD_LIST || CC_PCR_SetAuthPolicy) + (COMMAND_DESCRIPTOR_t *)_PCR_SetAuthPolicyDataAddress, +#endif +#if (PAD_LIST || CC_PP_Commands) + (COMMAND_DESCRIPTOR_t *)_PP_CommandsDataAddress, +#endif +#if (PAD_LIST || CC_SetPrimaryPolicy) + (COMMAND_DESCRIPTOR_t *)_SetPrimaryPolicyDataAddress, +#endif +#if (PAD_LIST || CC_FieldUpgradeStart) + (COMMAND_DESCRIPTOR_t *)_FieldUpgradeStartDataAddress, +#endif +#if (PAD_LIST || CC_ClockRateAdjust) + (COMMAND_DESCRIPTOR_t *)_ClockRateAdjustDataAddress, +#endif +#if (PAD_LIST || CC_CreatePrimary) + (COMMAND_DESCRIPTOR_t *)_CreatePrimaryDataAddress, +#endif +#if (PAD_LIST || CC_NV_GlobalWriteLock) + (COMMAND_DESCRIPTOR_t *)_NV_GlobalWriteLockDataAddress, +#endif +#if (PAD_LIST || CC_GetCommandAuditDigest) + (COMMAND_DESCRIPTOR_t *)_GetCommandAuditDigestDataAddress, +#endif +#if (PAD_LIST || CC_NV_Increment) + (COMMAND_DESCRIPTOR_t *)_NV_IncrementDataAddress, +#endif +#if (PAD_LIST || CC_NV_SetBits) + (COMMAND_DESCRIPTOR_t *)_NV_SetBitsDataAddress, +#endif +#if (PAD_LIST || CC_NV_Extend) + (COMMAND_DESCRIPTOR_t *)_NV_ExtendDataAddress, +#endif +#if (PAD_LIST || CC_NV_Write) + (COMMAND_DESCRIPTOR_t *)_NV_WriteDataAddress, +#endif +#if (PAD_LIST || CC_NV_WriteLock) + (COMMAND_DESCRIPTOR_t *)_NV_WriteLockDataAddress, +#endif +#if (PAD_LIST || CC_DictionaryAttackLockReset) + (COMMAND_DESCRIPTOR_t *)_DictionaryAttackLockResetDataAddress, +#endif +#if (PAD_LIST || CC_DictionaryAttackParameters) + (COMMAND_DESCRIPTOR_t *)_DictionaryAttackParametersDataAddress, +#endif +#if (PAD_LIST || CC_NV_ChangeAuth) + (COMMAND_DESCRIPTOR_t *)_NV_ChangeAuthDataAddress, +#endif +#if (PAD_LIST || CC_PCR_Event) + (COMMAND_DESCRIPTOR_t *)_PCR_EventDataAddress, +#endif +#if (PAD_LIST || CC_PCR_Reset) + (COMMAND_DESCRIPTOR_t *)_PCR_ResetDataAddress, +#endif +#if (PAD_LIST || CC_SequenceComplete) + (COMMAND_DESCRIPTOR_t *)_SequenceCompleteDataAddress, +#endif +#if (PAD_LIST || CC_SetAlgorithmSet) + (COMMAND_DESCRIPTOR_t *)_SetAlgorithmSetDataAddress, +#endif +#if (PAD_LIST || CC_SetCommandCodeAuditStatus) + (COMMAND_DESCRIPTOR_t *)_SetCommandCodeAuditStatusDataAddress, +#endif +#if (PAD_LIST || CC_FieldUpgradeData) + (COMMAND_DESCRIPTOR_t *)_FieldUpgradeDataDataAddress, +#endif +#if (PAD_LIST || CC_IncrementalSelfTest) + (COMMAND_DESCRIPTOR_t *)_IncrementalSelfTestDataAddress, +#endif +#if (PAD_LIST || CC_SelfTest) + (COMMAND_DESCRIPTOR_t *)_SelfTestDataAddress, +#endif +#if (PAD_LIST || CC_Startup) + (COMMAND_DESCRIPTOR_t *)_StartupDataAddress, +#endif +#if (PAD_LIST || CC_Shutdown) + (COMMAND_DESCRIPTOR_t *)_ShutdownDataAddress, +#endif +#if (PAD_LIST || CC_StirRandom) + (COMMAND_DESCRIPTOR_t *)_StirRandomDataAddress, +#endif +#if (PAD_LIST || CC_ActivateCredential) + (COMMAND_DESCRIPTOR_t *)_ActivateCredentialDataAddress, +#endif +#if (PAD_LIST || CC_Certify) + (COMMAND_DESCRIPTOR_t *)_CertifyDataAddress, +#endif +#if (PAD_LIST || CC_PolicyNV) + (COMMAND_DESCRIPTOR_t *)_PolicyNVDataAddress, +#endif +#if (PAD_LIST || CC_CertifyCreation) + (COMMAND_DESCRIPTOR_t *)_CertifyCreationDataAddress, +#endif +#if (PAD_LIST || CC_Duplicate) + (COMMAND_DESCRIPTOR_t *)_DuplicateDataAddress, +#endif +#if (PAD_LIST || CC_GetTime) + (COMMAND_DESCRIPTOR_t *)_GetTimeDataAddress, +#endif +#if (PAD_LIST || CC_GetSessionAuditDigest) + (COMMAND_DESCRIPTOR_t *)_GetSessionAuditDigestDataAddress, +#endif +#if (PAD_LIST || CC_NV_Read) + (COMMAND_DESCRIPTOR_t *)_NV_ReadDataAddress, +#endif +#if (PAD_LIST || CC_NV_ReadLock) + (COMMAND_DESCRIPTOR_t *)_NV_ReadLockDataAddress, +#endif +#if (PAD_LIST || CC_ObjectChangeAuth) + (COMMAND_DESCRIPTOR_t *)_ObjectChangeAuthDataAddress, +#endif +#if (PAD_LIST || CC_PolicySecret) + (COMMAND_DESCRIPTOR_t *)_PolicySecretDataAddress, +#endif +#if (PAD_LIST || CC_Rewrap) + (COMMAND_DESCRIPTOR_t *)_RewrapDataAddress, +#endif +#if (PAD_LIST || CC_Create) + (COMMAND_DESCRIPTOR_t *)_CreateDataAddress, +#endif +#if (PAD_LIST || CC_ECDH_ZGen) + (COMMAND_DESCRIPTOR_t *)_ECDH_ZGenDataAddress, +#endif +#if (PAD_LIST || (CC_HMAC || CC_MAC)) +# if CC_HMAC + (COMMAND_DESCRIPTOR_t *)_HMACDataAddress, +# endif +# if CC_MAC + (COMMAND_DESCRIPTOR_t *)_MACDataAddress, +# endif +# if (CC_HMAC || CC_MAC) > 1 +# error "More than one aliased command defined" +# endif +#endif // CC_HMAC CC_MAC +#if (PAD_LIST || CC_Import) + (COMMAND_DESCRIPTOR_t *)_ImportDataAddress, +#endif +#if (PAD_LIST || CC_Load) + (COMMAND_DESCRIPTOR_t *)_LoadDataAddress, +#endif +#if (PAD_LIST || CC_Quote) + (COMMAND_DESCRIPTOR_t *)_QuoteDataAddress, +#endif +#if (PAD_LIST || CC_RSA_Decrypt) + (COMMAND_DESCRIPTOR_t *)_RSA_DecryptDataAddress, +#endif +#if (PAD_LIST) + (COMMAND_DESCRIPTOR_t *)0, +#endif +#if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) +# if CC_HMAC_Start + (COMMAND_DESCRIPTOR_t *)_HMAC_StartDataAddress, +# endif +# if CC_MAC_Start + (COMMAND_DESCRIPTOR_t *)_MAC_StartDataAddress, +# endif +# if (CC_HMAC_Start || CC_MAC_Start) > 1 +# error "More than one aliased command defined" +# endif +#endif // CC_HMAC_Start CC_MAC_Start +#if (PAD_LIST || CC_SequenceUpdate) + (COMMAND_DESCRIPTOR_t *)_SequenceUpdateDataAddress, +#endif +#if (PAD_LIST || CC_Sign) + (COMMAND_DESCRIPTOR_t *)_SignDataAddress, +#endif +#if (PAD_LIST || CC_Unseal) + (COMMAND_DESCRIPTOR_t *)_UnsealDataAddress, +#endif +#if (PAD_LIST) + (COMMAND_DESCRIPTOR_t *)0, +#endif +#if (PAD_LIST || CC_PolicySigned) + (COMMAND_DESCRIPTOR_t *)_PolicySignedDataAddress, +#endif +#if (PAD_LIST || CC_ContextLoad) + (COMMAND_DESCRIPTOR_t *)_ContextLoadDataAddress, +#endif +#if (PAD_LIST || CC_ContextSave) + (COMMAND_DESCRIPTOR_t *)_ContextSaveDataAddress, +#endif +#if (PAD_LIST || CC_ECDH_KeyGen) + (COMMAND_DESCRIPTOR_t *)_ECDH_KeyGenDataAddress, +#endif +#if (PAD_LIST || CC_EncryptDecrypt) + (COMMAND_DESCRIPTOR_t *)_EncryptDecryptDataAddress, +#endif +#if (PAD_LIST || CC_FlushContext) + (COMMAND_DESCRIPTOR_t *)_FlushContextDataAddress, +#endif +#if (PAD_LIST) + (COMMAND_DESCRIPTOR_t *)0, +#endif +#if (PAD_LIST || CC_LoadExternal) + (COMMAND_DESCRIPTOR_t *)_LoadExternalDataAddress, +#endif +#if (PAD_LIST || CC_MakeCredential) + (COMMAND_DESCRIPTOR_t *)_MakeCredentialDataAddress, +#endif +#if (PAD_LIST || CC_NV_ReadPublic) + (COMMAND_DESCRIPTOR_t *)_NV_ReadPublicDataAddress, +#endif +#if (PAD_LIST || CC_PolicyAuthorize) + (COMMAND_DESCRIPTOR_t *)_PolicyAuthorizeDataAddress, +#endif +#if (PAD_LIST || CC_PolicyAuthValue) + (COMMAND_DESCRIPTOR_t *)_PolicyAuthValueDataAddress, +#endif +#if (PAD_LIST || CC_PolicyCommandCode) + (COMMAND_DESCRIPTOR_t *)_PolicyCommandCodeDataAddress, +#endif +#if (PAD_LIST || CC_PolicyCounterTimer) + (COMMAND_DESCRIPTOR_t *)_PolicyCounterTimerDataAddress, +#endif +#if (PAD_LIST || CC_PolicyCpHash) + (COMMAND_DESCRIPTOR_t *)_PolicyCpHashDataAddress, +#endif +#if (PAD_LIST || CC_PolicyLocality) + (COMMAND_DESCRIPTOR_t *)_PolicyLocalityDataAddress, +#endif +#if (PAD_LIST || CC_PolicyNameHash) + (COMMAND_DESCRIPTOR_t *)_PolicyNameHashDataAddress, +#endif +#if (PAD_LIST || CC_PolicyOR) + (COMMAND_DESCRIPTOR_t *)_PolicyORDataAddress, +#endif +#if (PAD_LIST || CC_PolicyTicket) + (COMMAND_DESCRIPTOR_t *)_PolicyTicketDataAddress, +#endif +#if (PAD_LIST || CC_ReadPublic) + (COMMAND_DESCRIPTOR_t *)_ReadPublicDataAddress, +#endif +#if (PAD_LIST || CC_RSA_Encrypt) + (COMMAND_DESCRIPTOR_t *)_RSA_EncryptDataAddress, +#endif +#if (PAD_LIST) + (COMMAND_DESCRIPTOR_t *)0, +#endif +#if (PAD_LIST || CC_StartAuthSession) + (COMMAND_DESCRIPTOR_t *)_StartAuthSessionDataAddress, +#endif +#if (PAD_LIST || CC_VerifySignature) + (COMMAND_DESCRIPTOR_t *)_VerifySignatureDataAddress, +#endif +#if (PAD_LIST || CC_ECC_Parameters) + (COMMAND_DESCRIPTOR_t *)_ECC_ParametersDataAddress, +#endif +#if (PAD_LIST || CC_FirmwareRead) + (COMMAND_DESCRIPTOR_t *)_FirmwareReadDataAddress, +#endif +#if (PAD_LIST || CC_GetCapability) + (COMMAND_DESCRIPTOR_t *)_GetCapabilityDataAddress, +#endif +#if (PAD_LIST || CC_GetRandom) + (COMMAND_DESCRIPTOR_t *)_GetRandomDataAddress, +#endif +#if (PAD_LIST || CC_GetTestResult) + (COMMAND_DESCRIPTOR_t *)_GetTestResultDataAddress, +#endif +#if (PAD_LIST || CC_Hash) + (COMMAND_DESCRIPTOR_t *)_HashDataAddress, +#endif +#if (PAD_LIST || CC_PCR_Read) + (COMMAND_DESCRIPTOR_t *)_PCR_ReadDataAddress, +#endif +#if (PAD_LIST || CC_PolicyPCR) + (COMMAND_DESCRIPTOR_t *)_PolicyPCRDataAddress, +#endif +#if (PAD_LIST || CC_PolicyRestart) + (COMMAND_DESCRIPTOR_t *)_PolicyRestartDataAddress, +#endif +#if (PAD_LIST || CC_ReadClock) + (COMMAND_DESCRIPTOR_t *)_ReadClockDataAddress, +#endif +#if (PAD_LIST || CC_PCR_Extend) + (COMMAND_DESCRIPTOR_t *)_PCR_ExtendDataAddress, +#endif +#if (PAD_LIST || CC_PCR_SetAuthValue) + (COMMAND_DESCRIPTOR_t *)_PCR_SetAuthValueDataAddress, +#endif +#if (PAD_LIST || CC_NV_Certify) + (COMMAND_DESCRIPTOR_t *)_NV_CertifyDataAddress, +#endif +#if (PAD_LIST || CC_EventSequenceComplete) + (COMMAND_DESCRIPTOR_t *)_EventSequenceCompleteDataAddress, +#endif +#if (PAD_LIST || CC_HashSequenceStart) + (COMMAND_DESCRIPTOR_t *)_HashSequenceStartDataAddress, +#endif +#if (PAD_LIST || CC_PolicyPhysicalPresence) + (COMMAND_DESCRIPTOR_t *)_PolicyPhysicalPresenceDataAddress, +#endif +#if (PAD_LIST || CC_PolicyDuplicationSelect) + (COMMAND_DESCRIPTOR_t *)_PolicyDuplicationSelectDataAddress, +#endif +#if (PAD_LIST || CC_PolicyGetDigest) + (COMMAND_DESCRIPTOR_t *)_PolicyGetDigestDataAddress, +#endif +#if (PAD_LIST || CC_TestParms) + (COMMAND_DESCRIPTOR_t *)_TestParmsDataAddress, +#endif +#if (PAD_LIST || CC_Commit) + (COMMAND_DESCRIPTOR_t *)_CommitDataAddress, +#endif +#if (PAD_LIST || CC_PolicyPassword) + (COMMAND_DESCRIPTOR_t *)_PolicyPasswordDataAddress, +#endif +#if (PAD_LIST || CC_ZGen_2Phase) + (COMMAND_DESCRIPTOR_t *)_ZGen_2PhaseDataAddress, +#endif +#if (PAD_LIST || CC_EC_Ephemeral) + (COMMAND_DESCRIPTOR_t *)_EC_EphemeralDataAddress, +#endif +#if (PAD_LIST || CC_PolicyNvWritten) + (COMMAND_DESCRIPTOR_t *)_PolicyNvWrittenDataAddress, +#endif +#if (PAD_LIST || CC_PolicyTemplate) + (COMMAND_DESCRIPTOR_t *)_PolicyTemplateDataAddress, +#endif +#if (PAD_LIST || CC_CreateLoaded) + (COMMAND_DESCRIPTOR_t *)_CreateLoadedDataAddress, +#endif +#if (PAD_LIST || CC_PolicyAuthorizeNV) + (COMMAND_DESCRIPTOR_t *)_PolicyAuthorizeNVDataAddress, +#endif +#if (PAD_LIST || CC_EncryptDecrypt2) + (COMMAND_DESCRIPTOR_t *)_EncryptDecrypt2DataAddress, +#endif +#if (PAD_LIST || CC_AC_GetCapability) + (COMMAND_DESCRIPTOR_t *)_AC_GetCapabilityDataAddress, +#endif // CC_AC_GetCapability +#if (PAD_LIST || CC_AC_Send) + (COMMAND_DESCRIPTOR_t *)_AC_SendDataAddress, +#endif // CC_AC_Send +#if (PAD_LIST || CC_Policy_AC_SendSelect) + (COMMAND_DESCRIPTOR_t *)_Policy_AC_SendSelectDataAddress, +#endif // CC_Policy_AC_SendSelect +#if (PAD_LIST || CC_CertifyX509) + (COMMAND_DESCRIPTOR_t *)_CertifyX509DataAddress, +#endif // CC_CertifyX509 +#if (PAD_LIST || CC_ACT_SetTimeout) + (COMMAND_DESCRIPTOR_t *)_ACT_SetTimeoutDataAddress, +#endif // CC_ACT_SetTimeout +#if (PAD_LIST || CC_ECC_Encrypt) + (COMMAND_DESCRIPTOR_t *)_ECC_EncryptDataAddress, +#endif // CC_ECC_Encrypt +#if (PAD_LIST || CC_ECC_Decrypt) + (COMMAND_DESCRIPTOR_t *)_ECC_DecryptDataAddress, +#endif // CC_ECC_Decrypt +#if (PAD_LIST || CC_Vendor_TCG_Test) + (COMMAND_DESCRIPTOR_t *)_Vendor_TCG_TestDataAddress, +#endif + 0 +}; + +#endif // _COMMAND_TABLE_DISPATCH_ diff --git a/src/tpm2/CommandDispatcher.c b/src/tpm2/CommandDispatcher.c new file mode 100644 index 0000000..c0464b9 --- /dev/null +++ b/src/tpm2/CommandDispatcher.c @@ -0,0 +1,409 @@ +/********************************************************************************/ +/* */ +/* Command Dispatcher */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandDispatcher.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 6.3 CommandDispatcher.c */ +/* CommandDispatcher() performs the following operations: */ +/* * unmarshals command parameters from the input buffer; */ +/* NOTE Unlike other unmarshaling functions, parmBufferStart does not advance. parmBufferSize Is + reduced. */ +/* * invokes the function that performs the command actions; */ +/* * marshals the returned handles, if any; and */ +/* * marshals the returned parameters, if any, into the output buffer putting in the + * parameterSize field if authorization sessions are present. */ +/* NOTE 1 The output buffer is the return from the MemoryGetResponseBuffer() function. It includes + the header, handles, response parameters, and authorization area. respParmSize is the response + parameter size, and does not include the header, handles, or authorization area. */ +/* NOTE 2 The reference implementation is permitted to do compare operations over a union as a byte + array. Therefore, the command parameter in structure must be initialized (e.g., zeroed) before + unmarshaling so that the compare operation is valid in cases where some bytes are unused. */ +/* 6.3.1.1 Includes and Typedefs */ +#include "Tpm.h" +// #include "Marshal.h" kgold + +#if TABLE_DRIVEN_DISPATCH +typedef TPM_RC(NoFlagFunction)(void *target, BYTE **buffer, INT32 *size); +typedef TPM_RC(FlagFunction)(void *target, BYTE **buffer, INT32 *size, BOOL flag); +typedef FlagFunction *UNMARSHAL_t; +typedef INT16(MarshalFunction)(void *source, BYTE **buffer, INT32 *size); +typedef MarshalFunction *MARSHAL_t; +typedef TPM_RC(COMMAND_NO_ARGS)(void); +typedef TPM_RC(COMMAND_IN_ARG)(void *in); +typedef TPM_RC(COMMAND_OUT_ARG)(void *out); +typedef TPM_RC(COMMAND_INOUT_ARG)(void *in, void *out); +typedef union +{ + COMMAND_NO_ARGS *noArgs; + COMMAND_IN_ARG *inArg; + COMMAND_OUT_ARG *outArg; + COMMAND_INOUT_ARG *inOutArg; +} COMMAND_t; +typedef struct +{ + COMMAND_t command; // Address of the command + UINT16 inSize; // Maximum size of the input structure + UINT16 outSize; // Maximum size of the output structure + UINT16 typesOffset; // address of the types field + UINT16 offsets[1]; +} COMMAND_DESCRIPTOR_t; +#if COMPRESSED_LISTS +# define PAD_LIST 0 +#else +# define PAD_LIST 1 +#endif +#define _COMMAND_TABLE_DISPATCH_ +#include "CommandDispatchData.h" +#define TEST_COMMAND TPM_CC_Startup +#define NEW_CC +#else +#include "Commands.h" +#endif + +/* 6.3.1.2 Marshal/Unmarshal Functions */ +/* 6.3.1.2.1 ParseHandleBuffer() */ +/* This is the table-driven version of the handle buffer unmarshaling code */ + +TPM_RC +ParseHandleBuffer( + COMMAND *command + ) +{ + TPM_RC result; +#if TABLE_DRIVEN_DISPATCH + COMMAND_DESCRIPTOR_t *desc; + BYTE *types; + BYTE type; + BYTE dType; + // Make sure that nothing strange has happened + pAssert(command->index + < sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t *)); + // Get the address of the descriptor for this command + desc = s_CommandDataArray[command->index]; + pAssert(desc != NULL); + // Get the associated list of unmarshaling data types. + types = &((BYTE *)desc)[desc->typesOffset]; + // if(s_ccAttr[commandIndex].commandIndex == TEST_COMMAND) + // commandIndex = commandIndex; + // No handles yet + command->handleNum = 0; + // Get the first type value + for(type = *types++; + // check each byte to make sure that we have not hit the start + // of the parameters + (dType = (type & 0x7F)) < PARAMETER_FIRST_TYPE; + // get the next type + type = *types++) + { +#if TABLE_DRIVEN_MARSHAL + marshalIndex_t index; + index = unmarshalArray[dType] | ((type & 0x80) ? NULL_FLAG : 0); + result = Unmarshal(index, &(command->handles[command->handleNum]), + &command->parameterBuffer, &command->parameterSize); + +#else + + // See if unmarshaling of this handle type requires a flag + if(dType < HANDLE_FIRST_FLAG_TYPE) + { + // Look up the function to do the unmarshaling + NoFlagFunction *f = (NoFlagFunction *)unmarshalArray[dType]; + // call it + result = f(&(command->handles[command->handleNum]), + &command->parameterBuffer, + &command->parameterSize); + } + else + { + // Look up the function + FlagFunction *f = unmarshalArray[dType]; + // Call it setting the flag to the appropriate value + result = f(&(command->handles[command->handleNum]), + &command->parameterBuffer, + &command->parameterSize, (type & 0x80) != 0); + } +#endif + // Got a handle + // We do this first so that the match for the handle offset of the + // response code works correctly. + command->handleNum += 1; + if(result != TPM_RC_SUCCESS) + // if the unmarshaling failed, return the response code with the + // handle indication set + return result + TPM_RC_H + (command->handleNum * TPM_RC_1); + } +#else + BYTE **handleBufferStart = &command->parameterBuffer; + INT32 *bufferRemainingSize = &command->parameterSize; + TPM_HANDLE *handles = &command->handles[0]; + UINT32 *handleCount = &command->handleNum; + *handleCount = 0; + switch(command->code) + { +#include "HandleProcess.h" +#undef handles + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } +#endif + return TPM_RC_SUCCESS; +} + +/* 6.3.1.2.2 CommandDispatcher() */ +/* Function to unmarshal the command parameters, call the selected action code, and marshal the + response parameters. */ + +TPM_RC +CommandDispatcher( + COMMAND *command + ) +{ +#if !TABLE_DRIVEN_DISPATCH + TPM_RC result; + BYTE **paramBuffer = &command->parameterBuffer; + INT32 *paramBufferSize = &command->parameterSize; + BYTE **responseBuffer = &command->responseBuffer; + INT32 *respParmSize = &command->parameterSize; + INT32 rSize; + TPM_HANDLE *handles = &command->handles[0]; + + command->handleNum = 0; /* The command-specific code knows how many handles there are. This + is for cataloging the number of response handles */ + MemoryIoBufferAllocationReset(); /* Initialize so that allocation will work properly */ + switch(GetCommandCode(command->index)) + { +#include "CommandDispatcher.h" + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + Exit: + MemoryIoBufferZero(); + return result; +#else + COMMAND_DESCRIPTOR_t *desc; + BYTE *types; + BYTE type; + UINT16 *offsets; + UINT16 offset = 0; + UINT32 maxInSize; + BYTE *commandIn; + INT32 maxOutSize; + BYTE *commandOut; + COMMAND_t cmd; + TPM_HANDLE *handles; + UINT32 hasInParameters = 0; + BOOL hasOutParameters = FALSE; + UINT32 pNum = 0; + BYTE dType; // dispatch type + TPM_RC result; + // + // Get the address of the descriptor for this command + pAssert(command->index + < sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t *)); + desc = s_CommandDataArray[command->index]; + // Get the list of parameter types for this command + pAssert(desc != NULL); + types = &((BYTE *)desc)[desc->typesOffset]; + // Get a pointer to the list of parameter offsets + offsets = &desc->offsets[0]; + // pointer to handles + handles = command->handles; + // Get the size required to hold all the unmarshaled parameters for this command + maxInSize = desc->inSize; + // and the size of the output parameter structure returned by this command + maxOutSize = desc->outSize; + MemoryIoBufferAllocationReset(); + // Get a buffer for the input parameters + commandIn = MemoryGetInBuffer(maxInSize); + // And the output parameters + commandOut = (BYTE *)MemoryGetOutBuffer((UINT32)maxOutSize); + // Get the address of the action code dispatch + cmd = desc->command; + // Copy any handles into the input buffer + for(type = *types++; (type & 0x7F) < PARAMETER_FIRST_TYPE; type = *types++) + { + // 'offset' was initialized to zero so the first unmarshaling will always + // be to the start of the data structure + *(TPM_HANDLE *)&(commandIn[offset]) = *handles++; + // This check is used so that we don't have to add an additional offset + // value to the offsets list to correspond to the stop value in the + // command parameter list. + if(*types != 0xFF) + offset = *offsets++; + // maxInSize -= sizeof(TPM_HANDLE); + hasInParameters++; + } + // Exit loop with type containing the last value read from types + // maxInSize has the amount of space remaining in the command action input + // buffer. Make sure that we don't have more data to unmarshal than is going to + // fit. + // type contains the last value read from types so it is not necessary to + // reload it, which is good because *types now points to the next value + for(; (dType = (type & 0x7F)) <= PARAMETER_LAST_TYPE; type = *types++) + { + pNum++; +#if TABLE_DRIVEN_MARSHAL + { + marshalIndex_t index = unmarshalArray[dType]; + index |= (type & 0x80) ? NULL_FLAG : 0; + result = Unmarshal(index, &commandIn[offset], &command->parameterBuffer, + &command->parameterSize); + } +#else + if(dType < PARAMETER_FIRST_FLAG_TYPE) + { + NoFlagFunction *f = (NoFlagFunction *)unmarshalArray[dType]; + result = f(&commandIn[offset], &command->parameterBuffer, + &command->parameterSize); + } + else + { + FlagFunction *f = unmarshalArray[dType]; + result = f(&commandIn[offset], &command->parameterBuffer, + &command->parameterSize, + (type & 0x80) != 0); + } +#endif + if(result != TPM_RC_SUCCESS) + { + result += TPM_RC_P + (TPM_RC_1 * pNum); + goto Exit; + } + // This check is used so that we don't have to add an additional offset + // value to the offsets list to correspond to the stop value in the + // command parameter list. + if(*types != 0xFF) + offset = *offsets++; + hasInParameters++; + } + // Should have used all the bytes in the input + if(command->parameterSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + // The command parameter unmarshaling stopped when it hit a value that was out + // of range for unmarshaling values and left *types pointing to the first + // marshaling type. If that type happens to be the STOP value, then there + // are no response parameters. So, set the flag to indicate if there are + // output parameters. + hasOutParameters = *types != 0xFF; + // There are four cases for calling, with and without input parameters and with + // and without output parameters. + if(hasInParameters > 0) + { + if(hasOutParameters) + result = cmd.inOutArg(commandIn, commandOut); + else + result = cmd.inArg(commandIn); + } + else + { + if(hasOutParameters) + result = cmd.outArg(commandOut); + else + result = cmd.noArgs(); + } + if(result != TPM_RC_SUCCESS) + goto Exit; + // Offset in the marshaled output structure + offset = 0; + // Process the return handles, if any + command->handleNum = 0; + // Could make this a loop to process output handles but there is only ever + // one handle in the outputs (for now). + type = *types++; + if((dType = (type & 0x7F)) < RESPONSE_PARAMETER_FIRST_TYPE) + { + // The out->handle value was referenced as TPM_HANDLE in the + // action code so it has to be properly aligned. + command->handles[command->handleNum++] = + *((TPM_HANDLE *)&(commandOut[offset])); + maxOutSize -= sizeof(UINT32); + type = *types++; + offset = *offsets++; + } + // Use the size of the command action output buffer as the maximum for the + // number of bytes that can get marshaled. Since the marshaling code has + // no pointers to data, all of the data being returned has to be in the + // command action output buffer. If we try to marshal more bytes than + // could fit into the output buffer, we need to fail. + for(;(dType = (type & 0x7F)) <= RESPONSE_PARAMETER_LAST_TYPE + && !g_inFailureMode; type = *types++) + { +#if TABLE_DRIVEN_MARSHAL + marshalIndex_t index = marshalArray[dType]; + command->parameterSize += Marshal(index, &commandOut[offset], + &command->responseBuffer, + &maxOutSize); +#else + const MARSHAL_t f = marshalArray[dType]; + command->parameterSize += f(&commandOut[offset], &command->responseBuffer, + &maxOutSize); +#endif + offset = *offsets++; + } + result = (maxOutSize < 0) ? TPM_RC_FAILURE : TPM_RC_SUCCESS; + Exit: + MemoryIoBufferZero(); + return result; +#endif +} diff --git a/src/tpm2/CommandDispatcher_fp.h b/src/tpm2/CommandDispatcher_fp.h new file mode 100644 index 0000000..6065ace --- /dev/null +++ b/src/tpm2/CommandDispatcher_fp.h @@ -0,0 +1,75 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CommandDispatcher_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef COMMANDDISPATCHER_FP_H +#define COMMANDDISPATCHER_FP_H + +TPM_RC +CommandDispatcher( + COMMAND *command + ); +TPM_RC +ParseHandleBuffer( + COMMAND *command + ); + + +#endif diff --git a/src/tpm2/Commit_fp.h b/src/tpm2/Commit_fp.h new file mode 100644 index 0000000..6233eaf --- /dev/null +++ b/src/tpm2/Commit_fp.h @@ -0,0 +1,94 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Commit_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef COMMIT_FP_H +#define COMMIT_FP_H + +typedef struct { + TPMI_DH_OBJECT signHandle; + TPM2B_ECC_POINT P1; + TPM2B_SENSITIVE_DATA s2; + TPM2B_ECC_PARAMETER y2; +} Commit_In; + +#define RC_Commit_signHandle (TPM_RC_H + TPM_RC_1) +#define RC_Commit_P1 (TPM_RC_P + TPM_RC_1) +#define RC_Commit_s2 (TPM_RC_P + TPM_RC_2) +#define RC_Commit_y2 (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPM2B_ECC_POINT K; + TPM2B_ECC_POINT L; + TPM2B_ECC_POINT E; + UINT16 counter; +} Commit_Out; + +TPM_RC +TPM2_Commit( + Commit_In *in, // IN: input parameter list + Commit_Out *out // OUT: output parameter list + ); + + + +#endif diff --git a/src/tpm2/CompilerDependencies.h b/src/tpm2/CompilerDependencies.h new file mode 100644 index 0000000..60ad954 --- /dev/null +++ b/src/tpm2/CompilerDependencies.h @@ -0,0 +1,193 @@ +/********************************************************************************/ +/* */ +/* Compiler Dependencies */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CompilerDependencies.h 1453 2019-04-05 16:43:36Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef COMPILERDEPEDENCIES_H +#define COMPILERDEPEDENCIES_H + +/* kgold - Not in the original code. A user reported that it was required for a non-Visual Studio + environment. +*/ + +#ifdef TPM_WINDOWS +#include +#include +#endif + +/* 5.10 CompilerDependencies.h */ +#ifdef GCC +# undef _MSC_VER +# undef WIN32 +#endif + +#ifdef _MSC_VER + +// These definitions are for the Microsoft compiler Endian conversion for aligned structures +# define REVERSE_ENDIAN_16(_Number) _byteswap_ushort(_Number) +# define REVERSE_ENDIAN_32(_Number) _byteswap_ulong(_Number) +# define REVERSE_ENDIAN_64(_Number) _byteswap_uint64(_Number) + +// Avoid compiler warning for in line of stdio (or not) + +// #define _NO_CRT_STDIO_INLINE + +// This macro is used to handle LIB_EXPORT of function and variable names in lieu of a .def +// file. Visual Studio requires that functions be explicitly exported and imported. + +# define LIB_EXPORT __declspec(dllexport) // VS compatible version +# define LIB_IMPORT __declspec(dllimport) + +// This is defined to indicate a function that does not return. Microsoft compilers do not +// support the _Noretrun() function parameter. + +# define NORETURN __declspec(noreturn) +# if _MSC_VER >= 1400 // SAL processing when needed +# include +# endif +# ifdef _WIN64 +# define _INTPTR 2 +# else +# define _INTPTR 1 +# endif +# define NOT_REFERENCED(x) (x) + +// Lower the compiler error warning for system include files. They tend not to be that clean and +// there is no reason to sort through all the spurious errors that they generate when the normal +// error level is set to /Wall + +# define _REDUCE_WARNING_LEVEL_(n) \ + __pragma(warning(push, n)) + +// Restore the compiler warning level + +# define _NORMAL_WARNING_LEVEL_ \ + __pragma(warning(pop)) +# include +#endif // _MSC_VER + +#ifndef _MSC_VER +#ifndef WINAPI +# define WINAPI +#endif +# define __pragma(x) + /* libtpms added begin */ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 2) +# define REVERSE_ENDIAN_16(_Number) __builtin_bswap16(_Number) +# define REVERSE_ENDIAN_32(_Number) __builtin_bswap32(_Number) +# define REVERSE_ENDIAN_64(_Number) __builtin_bswap64(_Number) +# else +# if defined __linux__ || defined __CYGWIN__ +# include +# define REVERSE_ENDIAN_16(_Number) bswap_16(_Number) +# define REVERSE_ENDIAN_32(_Number) bswap_32(_Number) +# define REVERSE_ENDIAN_64(_Number) bswap_64(_Number) +# elif defined __OpenBSD__ +# include +# define REVERSE_ENDIAN_16(_Number) swap16(_Number) +# define REVERSE_ENDIAN_32(_Number) swap32(_Number) +# define REVERSE_ENDIAN_64(_Number) swap64(_Number) +# elif defined __APPLE__ +# include +# define REVERSE_ENDIAN_16(_Number) _OSSwapInt16(_Number) +# define REVERSE_ENDIAN_32(_Number) _OSSwapInt32(_Number) +# define REVERSE_ENDIAN_64(_Number) _OSSwapInt64(_Number) +# elif defined __FreeBSD__ +# include +# define REVERSE_ENDIAN_16(_Number) bswap16(_Number) +# define REVERSE_ENDIAN_32(_Number) bswap32(_Number) +# define REVERSE_ENDIAN_64(_Number) bswap64(_Number) +# else +# error Unsupported OS +# endif +# endif + /* libtpms added end */ +#endif +#if defined(__GNUC__) +# define NORETURN __attribute__((noreturn)) +# include +#endif + +// Things that are not defined should be defined as NULL +#ifndef NORETURN +# define NORETURN +#endif +#ifndef LIB_EXPORT +# define LIB_EXPORT +#endif +#ifndef LIB_IMPORT +# define LIB_IMPORT +#endif +#ifndef _REDUCE_WARNING_LEVEL_ +# define _REDUCE_WARNING_LEVEL_(n) +#endif +#ifndef _NORMAL_WARNING_LEVEL_ +# define _NORMAL_WARNING_LEVEL_ +#endif +#ifndef NOT_REFERENCED +# define NOT_REFERENCED(x) (x = x) +#endif +#ifdef _POSIX_ +typedef int SOCKET; +#endif +// #ifdef TPM_POSIX +// typedef int SOCKET; +// #endif +#endif // _COMPILER_DEPENDENCIES_H_ + diff --git a/src/tpm2/ContextCommands.c b/src/tpm2/ContextCommands.c new file mode 100644 index 0000000..c557c88 --- /dev/null +++ b/src/tpm2/ContextCommands.c @@ -0,0 +1,458 @@ +/********************************************************************************/ +/* */ +/* Context Management */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ContextCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "ContextSave_fp.h" +#include "NVMarshal.h" // libtpms added +#if CC_ContextSave // Conditional expansion of this file +#include "Context_spt_fp.h" +/* Error Returns Meaning */ +/* TPM_RC_CONTEXT_GAP a contextID could not be assigned for a session context save */ +/* TPM_RC_TOO_MANY_CONTEXTS no more contexts can be saved as the counter has maxed out */ +TPM_RC +TPM2_ContextSave( + ContextSave_In *in, // IN: input parameter list + ContextSave_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + UINT16 fingerprintSize; // The size of fingerprint in context + // blob. + UINT64 contextID = 0; // session context ID + TPM2B_SYM_KEY symKey; + TPM2B_IV iv; + TPM2B_DIGEST integrity; + UINT16 integritySize; + BYTE *buffer; + // This command may cause the orderlyState to be cleared due to + // the update of state reset data. If the state is orderly and + // cannot be changed, exit early. + RETURN_IF_ORDERLY; + + // Internal Data Update + + // This implementation does not do things in quite the same way as described in + // Part 2 of the specification. In Part 2, it indicates that the + // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is + // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to + // determine the amount of data in the encrypted data. That part is not + // independently sized. This makes the actual size 2 bytes smaller than + // calculated using Part 2. Since this is opaque to the caller, it is not + // necessary to fix. The actual size is returned by TPM2_GetCapabilties(). + + // Initialize output handle. At the end of command action, the output + // handle of an object will be replaced, while the output handle + // for a session will be the same as input + out->context.savedHandle = in->saveHandle; + // Get the size of fingerprint in context blob. The sequence value in + // TPMS_CONTEXT structure is used as the fingerprint + fingerprintSize = sizeof(out->context.sequence); + // Compute the integrity size at the beginning of context blob + integritySize = sizeof(integrity.t.size) + + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); + // Perform object or session specific context save + switch(HandleGetType(in->saveHandle)) + { + case TPM_HT_TRANSIENT: + { + OBJECT *object = HandleToObject(in->saveHandle); + ANY_OBJECT_BUFFER *outObject; + unsigned char buffer[sizeof(OBJECT) * 2]; // libtpms changed begin + BYTE *bufptr = &buffer[0]; + INT32 size = sizeof(buffer); + UINT16 written = ANY_OBJECT_Marshal(object, &bufptr, &size); + UINT16 objectSize = written; // libtpms changed end + outObject = (ANY_OBJECT_BUFFER *)(out->context.contextBlob.t.buffer + + integritySize + fingerprintSize); + // Set size of the context data. The contents of context blob is vendor + // defined. In this implementation, the size is size of integrity + // plus fingerprint plus the whole internal OBJECT structure + out->context.contextBlob.t.size = integritySize + + fingerprintSize + objectSize; + // Make sure things fit + pAssert(out->context.contextBlob.t.size + <= sizeof(out->context.contextBlob.t.buffer)); + // Copy the whole internal OBJECT structure to context blob + MemoryCopy(outObject, buffer, written); // libtpms changed + // Increment object context ID + gr.objectContextID++; + // If object context ID overflows, TPM should be put in failure mode + if(gr.objectContextID == 0) + FAIL(FATAL_ERROR_INTERNAL); + // Fill in other return values for an object. + out->context.sequence = gr.objectContextID; + // For regular object, savedHandle is 0x80000000. For sequence object, + // savedHandle is 0x80000001. For object with stClear, savedHandle + // is 0x80000002 + if(ObjectIsSequence(object)) + { + out->context.savedHandle = 0x80000001; + /* ANY_OBJECT_Marshal already wrote it // libtpms changed begin + SequenceDataExport((HASH_OBJECT *)object, + (HASH_OBJECT_BUFFER *)outObject); + */ // libtpms changed end + } + else + out->context.savedHandle = (object->attributes.stClear == SET) + ? 0x80000002 : 0x80000000; + // Get object hierarchy + out->context.hierarchy = ObjectGetHierarchy(object); + break; + } + case TPM_HT_HMAC_SESSION: + case TPM_HT_POLICY_SESSION: + { + SESSION *session = SessionGet(in->saveHandle); + // Set size of the context data. The contents of context blob is vendor + // defined. In this implementation, the size of context blob is the + // size of a internal session structure plus the size of + // fingerprint plus the size of integrity + out->context.contextBlob.t.size = integritySize + + fingerprintSize + sizeof(*session); + // Make sure things fit + pAssert(out->context.contextBlob.t.size + < sizeof(out->context.contextBlob.t.buffer)); + // Copy the whole internal SESSION structure to context blob. + // Save space for fingerprint at the beginning of the buffer + // This is done before anything else so that the actual context + // can be reclaimed after this call + pAssert(sizeof(*session) <= sizeof(out->context.contextBlob.t.buffer) + - integritySize - fingerprintSize); + MemoryCopy(out->context.contextBlob.t.buffer + integritySize + + fingerprintSize, session, sizeof(*session)); + // Fill in the other return parameters for a session + // Get a context ID and set the session tracking values appropriately + // TPM_RC_CONTEXT_GAP is a possible error. + // SessionContextSave() will flush the in-memory context + // so no additional errors may occur after this call. + result = SessionContextSave(out->context.savedHandle, &contextID); + if(result != TPM_RC_SUCCESS) + return result; + // sequence number is the current session contextID + out->context.sequence = contextID; + // use TPM_RH_NULL as hierarchy for session context + out->context.hierarchy = TPM_RH_NULL; + break; + } + default: + // SaveContext may only take an object handle or a session handle. + // All the other handle type should be filtered out at unmarshal + FAIL(FATAL_ERROR_INTERNAL); + break; + } + // Save fingerprint at the beginning of encrypted area of context blob. + // Reserve the integrity space + pAssert(sizeof(out->context.sequence) <= + sizeof(out->context.contextBlob.t.buffer) - integritySize); + MemoryCopy(out->context.contextBlob.t.buffer + integritySize, + &out->context.sequence, sizeof(out->context.sequence)); + // Compute context encryption key + ComputeContextProtectionKey(&out->context, &symKey, &iv); + // Encrypt context blob + CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize, + CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS, + symKey.t.buffer, &iv, TPM_ALG_CFB, + out->context.contextBlob.t.size - integritySize, + out->context.contextBlob.t.buffer + integritySize); + // Compute integrity hash for the object + // In this implementation, the same routine is used for both sessions + // and objects. + ComputeContextIntegrity(&out->context, &integrity); + // add integrity at the beginning of context blob + buffer = out->context.contextBlob.t.buffer; + TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); + // orderly state should be cleared because of the update of state reset and + // state clear data + g_clearOrderly = TRUE; + return result; +} +#endif // CC_ContextSave +#include "Tpm.h" +#include "ContextLoad_fp.h" +#if CC_ContextLoad // Conditional expansion of this file +#include "Context_spt_fp.h" +TPM_RC +TPM2_ContextLoad( + ContextLoad_In *in, // IN: input parameter list + ContextLoad_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + TPM2B_DIGEST integrityToCompare; + TPM2B_DIGEST integrity; + BYTE *buffer; // defined to save some typing + INT32 size; // defined to save some typing + TPM_HT handleType; + TPM2B_SYM_KEY symKey; + TPM2B_IV iv; + // Input Validation + + // See discussion about the context format in TPM2_ContextSave Detailed Actions + + // IF this is a session context, make sure that the sequence number is + // consistent with the version in the slot + // Check context blob size + handleType = HandleGetType(in->context.savedHandle); + // Get integrity from context blob + buffer = in->context.contextBlob.t.buffer; + size = (INT32)in->context.contextBlob.t.size; + result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); + if(result != TPM_RC_SUCCESS) + return result; + // the size of the integrity value has to match the size of digest produced + // by the integrity hash + if(integrity.t.size != CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG)) + return TPM_RCS_SIZE + RC_ContextLoad_context; + // Make sure that the context blob has enough space for the fingerprint. This + // is elastic pants to go with the belt and suspenders we already have to make + // sure that the context is complete and untampered. + if((unsigned)size < sizeof(in->context.sequence)) + return TPM_RCS_SIZE + RC_ContextLoad_context; + // After unmarshaling the integrity value, 'buffer' is pointing at the first + // byte of the integrity protected and encrypted buffer and 'size' is the number + // of integrity protected and encrypted bytes. + // Compute context integrity + ComputeContextIntegrity(&in->context, &integrityToCompare); + // Compare integrity + if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) + return TPM_RCS_INTEGRITY + RC_ContextLoad_context; + // Compute context encryption key + ComputeContextProtectionKey(&in->context, &symKey, &iv); + // Decrypt context data in place + CryptSymmetricDecrypt(buffer, CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS, + symKey.t.buffer, &iv, TPM_ALG_CFB, size, buffer); + // See if the fingerprint value matches. If not, it is symptomatic of either + // a broken TPM or that the TPM is under attack so go into failure mode. + if(!MemoryEqual(buffer, &in->context.sequence, sizeof(in->context.sequence))) + FAIL(FATAL_ERROR_INTERNAL); + // step over fingerprint + buffer += sizeof(in->context.sequence); + // set the remaining size of the context + size -= sizeof(in->context.sequence); + // Perform object or session specific input check + switch(handleType) + { + case TPM_HT_TRANSIENT: + { + OBJECT *outObject; + if(size > (INT32)sizeof(OBJECT)) + FAIL(FATAL_ERROR_INTERNAL); + // Discard any changes to the handle that the TRM might have made + in->context.savedHandle = TRANSIENT_FIRST; + // If hierarchy is disabled, no object context can be loaded in this + // hierarchy + if(!HierarchyIsEnabled(in->context.hierarchy)) + return TPM_RCS_HIERARCHY + RC_ContextLoad_context; + // Restore object. If there is no empty space, indicate as much + outObject = ObjectContextLoadLibtpms(buffer, size, // libtpms changed + &out->loadedHandle); + if(outObject == NULL) + return TPM_RC_OBJECT_MEMORY; + break; + } + case TPM_HT_POLICY_SESSION: + case TPM_HT_HMAC_SESSION: + { + if(size != sizeof(SESSION)) + FAIL(FATAL_ERROR_INTERNAL); + // This command may cause the orderlyState to be cleared due to + // the update of state reset data. If this is the case, check if NV is + // available first + RETURN_IF_ORDERLY; + // Check if input handle points to a valid saved session and that the + // sequence number makes sense + if(!SequenceNumberForSavedContextIsValid(&in->context)) + return TPM_RCS_HANDLE + RC_ContextLoad_context; + // Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error + // may be returned at this point + result = SessionContextLoad((SESSION_BUF *)buffer, + &in->context.savedHandle); + if(result != TPM_RC_SUCCESS) + return result; + out->loadedHandle = in->context.savedHandle; + // orderly state should be cleared because of the update of state + // reset and state clear data + g_clearOrderly = TRUE; + break; + } + default: + // Context blob may only have an object handle or a session handle. + // All the other handle type should be filtered out at unmarshal + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return TPM_RC_SUCCESS; +} +#endif // CC_ContextLoad +#include "Tpm.h" +#include "FlushContext_fp.h" +#if CC_FlushContext // Conditional expansion of this file +TPM_RC +TPM2_FlushContext( + FlushContext_In *in // IN: input parameter list + ) +{ + // Internal Data Update + // Call object or session specific routine to flush + switch(HandleGetType(in->flushHandle)) + { + case TPM_HT_TRANSIENT: + if(!IsObjectPresent(in->flushHandle)) + return TPM_RCS_HANDLE + RC_FlushContext_flushHandle; + // Flush object + FlushObject(in->flushHandle); + break; + case TPM_HT_HMAC_SESSION: + case TPM_HT_POLICY_SESSION: + if(!SessionIsLoaded(in->flushHandle) + && !SessionIsSaved(in->flushHandle) + ) + return TPM_RCS_HANDLE + RC_FlushContext_flushHandle; + // If the session to be flushed is the exclusive audit session, then + // indicate that there is no exclusive audit session any longer. + if(in->flushHandle == g_exclusiveAuditSession) + g_exclusiveAuditSession = TPM_RH_UNASSIGNED; + // Flush session + SessionFlush(in->flushHandle); + break; + default: + // This command only takes object or session handle. Other handles + // should be filtered out at handle unmarshal + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return TPM_RC_SUCCESS; +} +#endif // CC_FlushContext +#include "Tpm.h" +#include "EvictControl_fp.h" +#if CC_EvictControl // Conditional expansion of this file +TPM_RC +TPM2_EvictControl( + EvictControl_In *in // IN: input parameter list + ) +{ + TPM_RC result; + OBJECT *evictObject; + // Input Validation + // Get internal object pointer + evictObject = HandleToObject(in->objectHandle); + // Temporary, stClear or public only objects can not be made persistent + if(evictObject->attributes.temporary == SET + || evictObject->attributes.stClear == SET + || evictObject->attributes.publicOnly == SET) + return TPM_RCS_ATTRIBUTES + RC_EvictControl_objectHandle; + // If objectHandle refers to a persistent object, it should be the same as + // input persistentHandle + if(evictObject->attributes.evict == SET + && evictObject->evictHandle != in->persistentHandle) + return TPM_RCS_HANDLE + RC_EvictControl_objectHandle; + // Additional authorization validation + if(in->auth == TPM_RH_PLATFORM) + { + // To make persistent + if(evictObject->attributes.evict == CLEAR) + { + // PlatformAuth can not set evict object in storage or endorsement + // hierarchy + if(evictObject->attributes.ppsHierarchy == CLEAR) + return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle; + // Platform cannot use a handle outside of platform persistent range. + if(!NvIsPlatformPersistentHandle(in->persistentHandle)) + return TPM_RCS_RANGE + RC_EvictControl_persistentHandle; + } + // PlatformAuth can delete any persistent object + } + else if(in->auth == TPM_RH_OWNER) + { + // OwnerAuth can not set or clear evict object in platform hierarchy + if(evictObject->attributes.ppsHierarchy == SET) + return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle; + // Owner cannot use a handle outside of owner persistent range. + if(evictObject->attributes.evict == CLEAR + && !NvIsOwnerPersistentHandle(in->persistentHandle)) + return TPM_RCS_RANGE + RC_EvictControl_persistentHandle; + } + else + { + // Other authorization is not allowed in this command and should have been + // filtered out in unmarshal process + FAIL(FATAL_ERROR_INTERNAL); + } + // Internal Data Update + // Change evict state + if(evictObject->attributes.evict == CLEAR) + { + // Make object persistent + if(NvFindHandle(in->persistentHandle) != 0) + return TPM_RC_NV_DEFINED; + // A TPM_RC_NV_HANDLE or TPM_RC_NV_SPACE error may be returned at this + // point + result = NvAddEvictObject(in->persistentHandle, evictObject); + } + else + { + // Delete the persistent object in NV + result = NvDeleteEvict(evictObject->evictHandle); + } + return result; +} +#endif // CC_EvictControl diff --git a/src/tpm2/ContextLoad_fp.h b/src/tpm2/ContextLoad_fp.h new file mode 100644 index 0000000..79e8800 --- /dev/null +++ b/src/tpm2/ContextLoad_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ContextLoad_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CONTEXTLOAD_FP_H +#define CONTEXTLOAD_FP_H + +typedef struct { + TPMS_CONTEXT context; +} ContextLoad_In; + +#define RC_ContextLoad_context (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPMI_DH_CONTEXT loadedHandle; +} ContextLoad_Out; + +TPM_RC +TPM2_ContextLoad( + ContextLoad_In *in, // IN: input parameter list + ContextLoad_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/ContextSave_fp.h b/src/tpm2/ContextSave_fp.h new file mode 100644 index 0000000..631ee91 --- /dev/null +++ b/src/tpm2/ContextSave_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ContextSave_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CONTEXTSAVE_FP_H +#define CONTEXTSAVE_FP_H + +typedef struct { + TPMI_DH_CONTEXT saveHandle; +} ContextSave_In; + +#define RC_ContextSave_saveHandle (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPMS_CONTEXT context; +} ContextSave_Out; + +TPM_RC +TPM2_ContextSave( + ContextSave_In *in, // IN: input parameter list + ContextSave_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/Context_spt.c b/src/tpm2/Context_spt.c new file mode 100644 index 0000000..a46d730 --- /dev/null +++ b/src/tpm2/Context_spt.c @@ -0,0 +1,204 @@ +/********************************************************************************/ +/* */ +/* Context Management Command Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Context_spt.c 1603 2020-04-03 17:48:43Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 7.3.1 Includes */ +#include "Tpm.h" +#include "Context_spt_fp.h" +/* 7.3.2 Functions */ +/* 7.3.2.1 ComputeContextProtectionKey() */ +/* This function retrieves the symmetric protection key for context encryption It is used by + TPM2_ContextSave() and TPM2_ContextLoad() to create the symmetric encryption key and iv */ +void +ComputeContextProtectionKey( + TPMS_CONTEXT *contextBlob, // IN: context blob + TPM2B_SYM_KEY *symKey, // OUT: the symmetric key + TPM2B_IV *iv // OUT: the IV. + ) +{ + UINT16 symKeyBits; // number of bits in the parent's + // symmetric key + TPM2B_PROOF *proof = NULL; // the proof value to use. Is null for + // everything but a primary object in + // the Endorsement Hierarchy + BYTE kdfResult[sizeof(TPMU_HA) * 2];// Value produced by the KDF + TPM2B_DATA sequence2B, handle2B; + // Get proof value + proof = HierarchyGetProof(contextBlob->hierarchy); + + // Get sequence value in 2B format + sequence2B.t.size = sizeof(contextBlob->sequence); + cAssert(sequence2B.t.size <= sizeof(sequence2B.t.buffer)); + MemoryCopy(sequence2B.t.buffer, &contextBlob->sequence, sequence2B.t.size); + + // Get handle value in 2B format + handle2B.t.size = sizeof(contextBlob->savedHandle); + cAssert(handle2B.t.size <= sizeof(handle2B.t.buffer)); + MemoryCopy(handle2B.t.buffer, &contextBlob->savedHandle, handle2B.t.size); + + // Get the symmetric encryption key size + symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; + symKeyBits = CONTEXT_ENCRYPT_KEY_BITS; + // Get the size of the IV for the algorithm + iv->t.size = CryptGetSymmetricBlockSize(CONTEXT_ENCRYPT_ALG, symKeyBits); + // KDFa to generate symmetric key and IV value + CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &proof->b, CONTEXT_KEY, &sequence2B.b, + &handle2B.b, (symKey->t.size + iv->t.size) * 8, kdfResult, NULL, + FALSE); + // Copy part of the returned value as the key + pAssert(symKey->t.size <= sizeof(symKey->t.buffer)); + MemoryCopy(symKey->t.buffer, kdfResult, symKey->t.size); + // Copy the rest as the IV + pAssert(iv->t.size <= sizeof(iv->t.buffer)); + MemoryCopy(iv->t.buffer, &kdfResult[symKey->t.size], iv->t.size); + return; +} +/* 7.3.2.2 ComputeContextIntegrity() */ +/* Generate the integrity hash for a context It is used by TPM2_ContextSave() to create an integrity + hash and by TPM2_ContextLoad() to compare an integrity hash */ +void +ComputeContextIntegrity( + TPMS_CONTEXT *contextBlob, // IN: context blob + TPM2B_DIGEST *integrity // OUT: integrity + ) +{ + HMAC_STATE hmacState; + TPM2B_PROOF *proof; + UINT16 integritySize; + // Get proof value + proof = HierarchyGetProof(contextBlob->hierarchy); + // Start HMAC + integrity->t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, + &proof->b); + // Compute integrity size at the beginning of context blob + integritySize = sizeof(integrity->t.size) + integrity->t.size; + // Adding total reset counter so that the context cannot be + // used after a TPM Reset + CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount), + gp.totalResetCount); + // If this is a ST_CLEAR object, add the clear count + // so that this contest cannot be loaded after a TPM Restart + if(contextBlob->savedHandle == 0x80000002) + CryptDigestUpdateInt(&hmacState.hashState, sizeof(gr.clearCount), + gr.clearCount); + // Adding sequence number to the HMAC to make sure that it doesn't + // get changed + CryptDigestUpdateInt(&hmacState.hashState, sizeof(contextBlob->sequence), + contextBlob->sequence); + // Protect the handle + CryptDigestUpdateInt(&hmacState.hashState, sizeof(contextBlob->savedHandle), + contextBlob->savedHandle); + // Adding sensitive contextData, skip the leading integrity area + CryptDigestUpdate(&hmacState.hashState, + contextBlob->contextBlob.t.size - integritySize, + contextBlob->contextBlob.t.buffer + integritySize); + // Complete HMAC + CryptHmacEnd2B(&hmacState, &integrity->b); + return; +} +#if 0 +/* 7.3.2.3 SequenceDataExport() */ +/* This function is used scan through the sequence object and either modify the hash state data for + export (contextSave) or to import it into the internal format (contextLoad). This function should + only be called after the sequence object has been copied to the context buffer (contextSave) or + from the context buffer into the sequence object. The presumption is that the context buffer + version of the data is the same size as the internal representation so nothing outsize of the + hash context area gets modified. */ +void +SequenceDataExport( + HASH_OBJECT *object, // IN: an internal hash object + HASH_OBJECT_BUFFER *exportObject // OUT: a sequence context in a buffer + ) +{ + // If the hash object is not an event, then only one hash context is needed + int count = (object->attributes.eventSeq) ? HASH_COUNT : 1; + for(count--; count >= 0; count--) + { + HASH_STATE *hash = &object->state.hashState[count]; + size_t offset = (BYTE *)hash - (BYTE *)object; + BYTE *exportHash = &((BYTE *)exportObject)[offset]; + CryptHashExportState(hash, (EXPORT_HASH_STATE *)exportHash); + } +} +/* 7.3.2.4 SequenceDataImport() */ +/* This function is used scan through the sequence object and either modify the hash state data for + export (contextSave) or to import it into the internal format (contextLoad). This function should + only be called after the sequence object has been copied to the context buffer (contextSave) or + from the context buffer into the sequence object. The presumption is that the context buffer + version of the data is the same size as the internal representation so nothing outsize of the + hash context area gets modified. */ +void +SequenceDataImport( + HASH_OBJECT *object, // IN/OUT: an internal hash object + HASH_OBJECT_BUFFER *exportObject // IN/OUT: a sequence context in a buffer + ) +{ + // If the hash object is not an event, then only one hash context is needed + int count = (object->attributes.eventSeq) ? HASH_COUNT : 1; + for(count--; count >= 0; count--) + { + HASH_STATE *hash = &object->state.hashState[count]; + size_t offset = (BYTE *)hash - (BYTE *)object; + BYTE *importHash = &((BYTE *)exportObject)[offset]; + // + CryptHashImportState(hash, (EXPORT_HASH_STATE *)importHash); + } +} +#endif diff --git a/src/tpm2/Context_spt_fp.h b/src/tpm2/Context_spt_fp.h new file mode 100644 index 0000000..19b9576 --- /dev/null +++ b/src/tpm2/Context_spt_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Context_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef CONTEXT_SPT_H +#define CONTEXT_SPT_H + +void +ComputeContextProtectionKey( + TPMS_CONTEXT *contextBlob, // IN: context blob + TPM2B_SYM_KEY *symKey, // OUT: the symmetric key + TPM2B_IV *iv // OUT: the IV. + ); +void +ComputeContextIntegrity( + TPMS_CONTEXT *contextBlob, // IN: context blob + TPM2B_DIGEST *integrity // OUT: integrity + ); +void +SequenceDataExport( + HASH_OBJECT *object, // IN: an internal hash object + HASH_OBJECT_BUFFER *exportObject // OUT: a sequence context in a buffer + ); +void +SequenceDataImport( + HASH_OBJECT *object, // IN/OUT: an internal hash object + HASH_OBJECT_BUFFER *exportObject // IN/OUT: a sequence context in a buffer + ); + + +#endif diff --git a/src/tpm2/CreateLoaded_fp.h b/src/tpm2/CreateLoaded_fp.h new file mode 100644 index 0000000..302e606 --- /dev/null +++ b/src/tpm2/CreateLoaded_fp.h @@ -0,0 +1,90 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CreateLoaded_fp.h 1600 2020-03-30 22:08:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +#ifndef CREATELOADED_FP_H +#define CREATELOADED_FP_H + +/* rev 136 */ + +typedef struct { + TPMI_DH_PARENT parentHandle; + TPM2B_SENSITIVE_CREATE inSensitive; + TPM2B_TEMPLATE inPublic; +} CreateLoaded_In; + +#define RC_CreateLoaded_parentHandle (TPM_RC_H + TPM_RC_1) +#define RC_CreateLoaded_inSensitive (TPM_RC_P + TPM_RC_1) +#define RC_CreateLoaded_inPublic (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM_HANDLE objectHandle; + TPM2B_PRIVATE outPrivate; + TPM2B_PUBLIC outPublic; + TPM2B_NAME name; +} CreateLoaded_Out; + +TPM_RC +TPM2_CreateLoaded( + CreateLoaded_In *in, // IN: input parameter list + CreateLoaded_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/CreatePrimary_fp.h b/src/tpm2/CreatePrimary_fp.h new file mode 100644 index 0000000..724d1bc --- /dev/null +++ b/src/tpm2/CreatePrimary_fp.h @@ -0,0 +1,96 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CreatePrimary_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef CREATEPRIMARY_FP_H +#define CREATEPRIMARY_FP_H + +typedef struct { + TPMI_RH_HIERARCHY primaryHandle; + TPM2B_SENSITIVE_CREATE inSensitive; + TPM2B_PUBLIC inPublic; + TPM2B_DATA outsideInfo; + TPML_PCR_SELECTION creationPCR; +} CreatePrimary_In; + +#define RC_CreatePrimary_primaryHandle (TPM_RC_H + TPM_RC_1) +#define RC_CreatePrimary_inSensitive (TPM_RC_P + TPM_RC_1) +#define RC_CreatePrimary_inPublic (TPM_RC_P + TPM_RC_2) +#define RC_CreatePrimary_outsideInfo (TPM_RC_P + TPM_RC_3) +#define RC_CreatePrimary_creationPCR (TPM_RC_P + TPM_RC_4) + +typedef struct { + TPM_HANDLE objectHandle; + TPM2B_PUBLIC outPublic; + TPM2B_CREATION_DATA creationData; + TPM2B_DIGEST creationHash; + TPMT_TK_CREATION creationTicket; + TPM2B_NAME name; +} CreatePrimary_Out; + +TPM_RC +TPM2_CreatePrimary( + CreatePrimary_In *in, // IN: input parameter list + CreatePrimary_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/Create_fp.h b/src/tpm2/Create_fp.h new file mode 100644 index 0000000..69752a1 --- /dev/null +++ b/src/tpm2/Create_fp.h @@ -0,0 +1,96 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Create_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 137 */ + +#ifndef CREATE_FP_H +#define CREATE_FP_H + +typedef struct { + TPMI_DH_OBJECT parentHandle; + TPM2B_SENSITIVE_CREATE inSensitive; + TPM2B_PUBLIC inPublic; + TPM2B_DATA outsideInfo; + TPML_PCR_SELECTION creationPCR; +} Create_In; + +#define RC_Create_parentHandle (TPM_RC_H + TPM_RC_1) +#define RC_Create_inSensitive (TPM_RC_P + TPM_RC_1) +#define RC_Create_inPublic (TPM_RC_P + TPM_RC_2) +#define RC_Create_outsideInfo (TPM_RC_P + TPM_RC_3) +#define RC_Create_creationPCR (TPM_RC_P + TPM_RC_4) + +typedef struct { + TPM2B_PRIVATE outPrivate; + TPM2B_PUBLIC outPublic; + TPM2B_CREATION_DATA creationData; + TPM2B_DIGEST creationHash; + TPMT_TK_CREATION creationTicket; +} Create_Out; + +TPM_RC +TPM2_Create( + Create_In *in, // IN: input parameter list + Create_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/CryptEccData.c b/src/tpm2/CryptEccData.c new file mode 100644 index 0000000..d7bac18 --- /dev/null +++ b/src/tpm2/CryptEccData.c @@ -0,0 +1,618 @@ +/********************************************************************************/ +/* */ +/* ECC curve data */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEccData.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2018 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.8 CryptEccData.c */ +#include "Tpm.h" +#include "OIDs.h" +/* This file contains the ECC curve data. The format of the data depends on the setting of + USE_BN_ECC_DATA. If it is defined, then the TPM's BigNum() format is used. Otherwise, it is kept + in TPM2B format. The purpose of having the data in BigNum() format is so that it does not have to + be reformatted before being used by the crypto library. */ +#if ALG_ECC +#if USE_BN_ECC_DATA +# define TO_ECC_64 TO_CRYPT_WORD_64 +# define TO_ECC_56(a, b, c, d, e, f, g) TO_ECC_64(0, a, b, c, d, e, f, g) +# define TO_ECC_48(a, b, c, d, e, f) TO_ECC_64(0, 0, a, b, c, d, e, f) +# define TO_ECC_40(a, b, c, d, e) TO_ECC_64(0, 0, 0, a, b, c, d, e) +# if RADIX_BITS > 32 +# define TO_ECC_32(a, b, c, d) TO_ECC_64(0, 0, 0, 0, a, b, c, d) +# define TO_ECC_24(a, b, c) TO_ECC_64(0, 0, 0, 0, 0, a, b, c) +# define TO_ECC_16(a, b) TO_ECC_64(0, 0, 0, 0, 0, 0, a, b) +# define TO_ECC_8(a) TO_ECC_64(0, 0, 0, 0, 0, 0, 0, a) +# else // RADIX_BITS == 32 +# define TO_ECC_32 BIG_ENDIAN_BYTES_TO_UINT32 +# define TO_ECC_24(a, b, c) TO_ECC_32(0, a, b, c) +# define TO_ECC_16(a, b) TO_ECC_32(0, 0, a, b) +# define TO_ECC_8(a) TO_ECC_32(0, 0, 0, a) +# endif +#else // TPM2B_ +# define TO_ECC_64(a, b, c, d, e, f, g, h) a, b, c, d, e, f, g, h +# define TO_ECC_56(a, b, c, d, e, f, g) a, b, c, d, e, f, g +# define TO_ECC_48(a, b, c, d, e, f) a, b, c, d, e, f +# define TO_ECC_40(a, b, c, d, e) a, b, c, d, e +# define TO_ECC_32(a, b, c, d) a, b, c, d +# define TO_ECC_24(a, b, c) a, b, c +# define TO_ECC_16(a, b) a, b +# define TO_ECC_8(a) a +#endif +#if USE_BN_ECC_DATA +#define BN_MIN_ALLOC(bytes) \ + (BYTES_TO_CRYPT_WORDS(bytes) == 0) ? 1 : BYTES_TO_CRYPT_WORDS(bytes) +# define ECC_CONST(NAME, bytes, initializer) \ + const struct { \ + crypt_uword_t allocate, size, d[BN_MIN_ALLOC(bytes)]; \ + } NAME = {BN_MIN_ALLOC(bytes), BYTES_TO_CRYPT_WORDS(bytes),{initializer}} + ECC_CONST(ECC_ZERO, 0, 0); +#else +# define ECC_CONST(NAME, bytes, initializer) \ + const TPM2B_##bytes##_BYTE_VALUE NAME = {bytes, {initializer}} +/* Have to special case ECC_ZERO */ +TPM2B_BYTE_VALUE(1); +TPM2B_1_BYTE_VALUE ECC_ZERO = {1, {0}}; +#endif +ECC_CONST(ECC_ONE, 1, 1); +#if !USE_BN_ECC_DATA +TPM2B_BYTE_VALUE(24); +#define TO_ECC_192(a, b, c) a, b, c +TPM2B_BYTE_VALUE(28); +#define TO_ECC_224(a, b, c, d) a, b, c, d +TPM2B_BYTE_VALUE(32); +#define TO_ECC_256(a, b, c, d) a, b, c, d +TPM2B_BYTE_VALUE(48); +#define TO_ECC_384(a, b, c, d, e, f) a, b, c, d, e, f +TPM2B_BYTE_VALUE(66); +#define TO_ECC_528(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i +TPM2B_BYTE_VALUE(80); +#define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) a, b, c, d, e, f, g, h, i, j +#else +#define TO_ECC_192(a, b, c) c, b, a +#define TO_ECC_224(a, b, c, d) d, c, b, a +#define TO_ECC_256(a, b, c, d) d, c, b, a +#define TO_ECC_384(a, b, c, d, e, f) f, e, d, c, b, a +#define TO_ECC_528(a, b, c, d, e, f, g, h, i) i, h, g, f, e, d, c, b, a +#define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) j, i, h, g, f, e, d, c, b, a +#endif // !USE_BN_ECC_DATA +#if ECC_NIST_P192 +ECC_CONST(NIST_P192_p, 24, TO_ECC_192( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(NIST_P192_a, 24, TO_ECC_192( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(NIST_P192_b, 24, TO_ECC_192( + TO_ECC_64(0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7), + TO_ECC_64(0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49), + TO_ECC_64(0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1))); +ECC_CONST(NIST_P192_gX, 24, TO_ECC_192( + TO_ECC_64(0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6), + TO_ECC_64(0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00), + TO_ECC_64(0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12))); +ECC_CONST(NIST_P192_gY, 24, TO_ECC_192( + TO_ECC_64(0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78), + TO_ECC_64(0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5), + TO_ECC_64(0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11))); +ECC_CONST(NIST_P192_n, 24, TO_ECC_192( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36), + TO_ECC_64(0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31))); +#define NIST_P192_h ECC_ONE +#define NIST_P192_gZ ECC_ONE +#if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P192 = { + (bigNum)&NIST_P192_p, (bigNum)&NIST_P192_n, (bigNum)&NIST_P192_h, + (bigNum)&NIST_P192_a, (bigNum)&NIST_P192_b, + {(bigNum)&NIST_P192_gX, (bigNum)&NIST_P192_gY, (bigNum)&NIST_P192_gZ}}; +#else +const ECC_CURVE_DATA NIST_P192 = { + &NIST_P192_p.b, &NIST_P192_n.b, &NIST_P192_h.b, + &NIST_P192_a.b, &NIST_P192_b.b, + {&NIST_P192_gX.b, &NIST_P192_gY.b, &NIST_P192_gZ.b}}; +#endif // USE_BN_ECC_DATA +#endif // ECC_NIST_P192 +#if ECC_NIST_P224 +ECC_CONST(NIST_P224_p, 28, TO_ECC_224( + TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01))); +ECC_CONST(NIST_P224_a, 28, TO_ECC_224( + TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE))); +ECC_CONST(NIST_P224_b, 28, TO_ECC_224( + TO_ECC_32(0xB4, 0x05, 0x0A, 0x85), + TO_ECC_64(0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56), + TO_ECC_64(0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA), + TO_ECC_64(0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4))); +ECC_CONST(NIST_P224_gX, 28, TO_ECC_224( + TO_ECC_32(0xB7, 0x0E, 0x0C, 0xBD), + TO_ECC_64(0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9), + TO_ECC_64(0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22), + TO_ECC_64(0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21))); +ECC_CONST(NIST_P224_gY, 28, TO_ECC_224( + TO_ECC_32(0xBD, 0x37, 0x63, 0x88), + TO_ECC_64(0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6), + TO_ECC_64(0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64), + TO_ECC_64(0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34))); +ECC_CONST(NIST_P224_n, 28, TO_ECC_224( + TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E), + TO_ECC_64(0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D))); +#define NIST_P224_h ECC_ONE +#define NIST_P224_gZ ECC_ONE +#if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P224 = { + (bigNum)&NIST_P224_p, (bigNum)&NIST_P224_n, (bigNum)&NIST_P224_h, + (bigNum)&NIST_P224_a, (bigNum)&NIST_P224_b, + {(bigNum)&NIST_P224_gX, (bigNum)&NIST_P224_gY, (bigNum)&NIST_P224_gZ}}; +#else +const ECC_CURVE_DATA NIST_P224 = { + &NIST_P224_p.b, &NIST_P224_n.b, &NIST_P224_h.b, + &NIST_P224_a.b, &NIST_P224_b.b, + {&NIST_P224_gX.b, &NIST_P224_gY.b, &NIST_P224_gZ.b}}; +#endif // USE_BN_ECC_DATA +#endif // ECC_NIST_P224 +#if ECC_NIST_P256 +ECC_CONST(NIST_P256_p, 32, TO_ECC_256( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(NIST_P256_a, 32, TO_ECC_256( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(NIST_P256_b, 32, TO_ECC_256( + TO_ECC_64(0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7), + TO_ECC_64(0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC), + TO_ECC_64(0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6), + TO_ECC_64(0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B))); +ECC_CONST(NIST_P256_gX, 32, TO_ECC_256( + TO_ECC_64(0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47), + TO_ECC_64(0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2), + TO_ECC_64(0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0), + TO_ECC_64(0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96))); +ECC_CONST(NIST_P256_gY, 32, TO_ECC_256( + TO_ECC_64(0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B), + TO_ECC_64(0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16), + TO_ECC_64(0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE), + TO_ECC_64(0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5))); +ECC_CONST(NIST_P256_n, 32, TO_ECC_256( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84), + TO_ECC_64(0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51))); +#define NIST_P256_h ECC_ONE +#define NIST_P256_gZ ECC_ONE +#if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P256 = { + (bigNum)&NIST_P256_p, (bigNum)&NIST_P256_n, (bigNum)&NIST_P256_h, + (bigNum)&NIST_P256_a, (bigNum)&NIST_P256_b, + {(bigNum)&NIST_P256_gX, (bigNum)&NIST_P256_gY, (bigNum)&NIST_P256_gZ}}; +#else +const ECC_CURVE_DATA NIST_P256 = { + &NIST_P256_p.b, &NIST_P256_n.b, &NIST_P256_h.b, + &NIST_P256_a.b, &NIST_P256_b.b, + {&NIST_P256_gX.b, &NIST_P256_gY.b, &NIST_P256_gZ.b}}; +#endif // USE_BN_ECC_DATA +#endif // ECC_NIST_P256 +#if ECC_NIST_P384 +ECC_CONST(NIST_P384_p, 48, TO_ECC_384( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(NIST_P384_a, 48, TO_ECC_384( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(NIST_P384_b, 48, TO_ECC_384( + TO_ECC_64(0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4), + TO_ECC_64(0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19), + TO_ECC_64(0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12), + TO_ECC_64(0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A), + TO_ECC_64(0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D), + TO_ECC_64(0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF))); +ECC_CONST(NIST_P384_gX, 48, TO_ECC_384( + TO_ECC_64(0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37), + TO_ECC_64(0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74), + TO_ECC_64(0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98), + TO_ECC_64(0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38), + TO_ECC_64(0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C), + TO_ECC_64(0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7))); +ECC_CONST(NIST_P384_gY, 48, TO_ECC_384( + TO_ECC_64(0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F), + TO_ECC_64(0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29), + TO_ECC_64(0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C), + TO_ECC_64(0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0), + TO_ECC_64(0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D), + TO_ECC_64(0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F))); +ECC_CONST(NIST_P384_n, 48, TO_ECC_384( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF), + TO_ECC_64(0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A), + TO_ECC_64(0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73))); +#define NIST_P384_h ECC_ONE +#define NIST_P384_gZ ECC_ONE +#if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P384 = { + (bigNum)&NIST_P384_p, (bigNum)&NIST_P384_n, (bigNum)&NIST_P384_h, + (bigNum)&NIST_P384_a, (bigNum)&NIST_P384_b, + {(bigNum)&NIST_P384_gX, (bigNum)&NIST_P384_gY, (bigNum)&NIST_P384_gZ}}; +#else +const ECC_CURVE_DATA NIST_P384 = { + &NIST_P384_p.b, &NIST_P384_n.b, &NIST_P384_h.b, + &NIST_P384_a.b, &NIST_P384_b.b, + {&NIST_P384_gX.b, &NIST_P384_gY.b, &NIST_P384_gZ.b}}; +#endif // USE_BN_ECC_DATA +#endif // ECC_NIST_P384 +#if ECC_NIST_P521 +ECC_CONST(NIST_P521_p, 66, TO_ECC_528( + TO_ECC_16(0x01, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(NIST_P521_a, 66, TO_ECC_528( + TO_ECC_16(0x01, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(NIST_P521_b, 66, TO_ECC_528( + TO_ECC_16(0x00, 0x51), + TO_ECC_64(0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F), + TO_ECC_64(0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE), + TO_ECC_64(0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3), + TO_ECC_64(0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1), + TO_ECC_64(0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B), + TO_ECC_64(0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, 0xBF, 0x07), + TO_ECC_64(0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1), + TO_ECC_64(0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00))); +ECC_CONST(NIST_P521_gX, 66, TO_ECC_528( + TO_ECC_16(0x00, 0xC6), + TO_ECC_64(0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD), + TO_ECC_64(0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42), + TO_ECC_64(0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21), + TO_ECC_64(0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA), + TO_ECC_64(0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28), + TO_ECC_64(0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, 0xA8, 0xDE), + TO_ECC_64(0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B), + TO_ECC_64(0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66))); +ECC_CONST(NIST_P521_gY, 66, TO_ECC_528( + TO_ECC_16(0x01, 0x18), + TO_ECC_64(0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04), + TO_ECC_64(0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9), + TO_ECC_64(0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68), + TO_ECC_64(0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C), + TO_ECC_64(0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40), + TO_ECC_64(0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, 0x07, 0x61), + TO_ECC_64(0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40), + TO_ECC_64(0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50))); +ECC_CONST(NIST_P521_n, 66, TO_ECC_528( + TO_ECC_16(0x01, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA), + TO_ECC_64(0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B), + TO_ECC_64(0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, 0xA5, 0xD0), + TO_ECC_64(0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE), + TO_ECC_64(0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09))); +#define NIST_P521_h ECC_ONE +#define NIST_P521_gZ ECC_ONE +#if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P521 = { + (bigNum)&NIST_P521_p, (bigNum)&NIST_P521_n, (bigNum)&NIST_P521_h, + (bigNum)&NIST_P521_a, (bigNum)&NIST_P521_b, + {(bigNum)&NIST_P521_gX, (bigNum)&NIST_P521_gY, (bigNum)&NIST_P521_gZ}}; +#else +const ECC_CURVE_DATA NIST_P521 = { + &NIST_P521_p.b, &NIST_P521_n.b, &NIST_P521_h.b, + &NIST_P521_a.b, &NIST_P521_b.b, + {&NIST_P521_gX.b, &NIST_P521_gY.b, &NIST_P521_gZ.b}}; +#endif // USE_BN_ECC_DATA +#endif // ECC_NIST_P521 +#if ECC_BN_P256 +ECC_CONST(BN_P256_p, 32, TO_ECC_256( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD), + TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9F), + TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98, 0x0A, 0x82), + TO_ECC_64(0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x13))); +#define BN_P256_a ECC_ZERO +ECC_CONST(BN_P256_b, 1, TO_ECC_8(3)); +#define BN_P256_gX ECC_ONE +ECC_CONST(BN_P256_gY, 1, TO_ECC_8(2)); +ECC_CONST(BN_P256_n, 32, TO_ECC_256( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD), + TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E), + TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A), + TO_ECC_64(0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0D))); +#define BN_P256_h ECC_ONE +#define BN_P256_gZ ECC_ONE +#if USE_BN_ECC_DATA +const ECC_CURVE_DATA BN_P256 = { + (bigNum)&BN_P256_p, (bigNum)&BN_P256_n, (bigNum)&BN_P256_h, + (bigNum)&BN_P256_a, (bigNum)&BN_P256_b, + {(bigNum)&BN_P256_gX, (bigNum)&BN_P256_gY, (bigNum)&BN_P256_gZ}}; +#else +const ECC_CURVE_DATA BN_P256 = { + &BN_P256_p.b, &BN_P256_n.b, &BN_P256_h.b, + &BN_P256_a.b, &BN_P256_b.b, + {&BN_P256_gX.b, &BN_P256_gY.b, &BN_P256_gZ.b}}; +#endif // USE_BN_ECC_DATA +#endif // ECC_BN_P256 +#if ECC_BN_P638 +ECC_CONST(BN_P638_p, 80, TO_ECC_640( + TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), + TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), + TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), + TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), + TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), + TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B), + TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80), + TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67))); +#define BN_P638_a ECC_ZERO +ECC_CONST(BN_P638_b, 2, TO_ECC_16(0x01,0x01)); +ECC_CONST(BN_P638_gX, 80, TO_ECC_640( + TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), + TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), + TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), + TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), + TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), + TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B), + TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80), + TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66))); +ECC_CONST(BN_P638_gY, 1, TO_ECC_8(0x10)); +ECC_CONST(BN_P638_n, 80, TO_ECC_640( + TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), + TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), + TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), + TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), + TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), + TO_ECC_64(0x60, 0x00, 0x86, 0x55, 0x00, 0x21, 0xE5, 0x55), + TO_ECC_64(0xFF, 0xFF, 0xF5, 0x4F, 0xFF, 0xF4, 0xEA, 0xC0), + TO_ECC_64(0x00, 0x00, 0x00, 0x49, 0x80, 0x01, 0x54, 0xD9), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xA0), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61))); +#define BN_P638_h ECC_ONE +#define BN_P638_gZ ECC_ONE +#if USE_BN_ECC_DATA +const ECC_CURVE_DATA BN_P638 = { + (bigNum)&BN_P638_p, (bigNum)&BN_P638_n, (bigNum)&BN_P638_h, + (bigNum)&BN_P638_a, (bigNum)&BN_P638_b, + {(bigNum)&BN_P638_gX, (bigNum)&BN_P638_gY, (bigNum)&BN_P638_gZ}}; +#else +const ECC_CURVE_DATA BN_P638 = { + &BN_P638_p.b, &BN_P638_n.b, &BN_P638_h.b, + &BN_P638_a.b, &BN_P638_b.b, + {&BN_P638_gX.b, &BN_P638_gY.b, &BN_P638_gZ.b}}; +#endif // USE_BN_ECC_DATA +#endif // ECC_BN_P638 +#if ECC_SM2_P256 +ECC_CONST(SM2_P256_p, 32, TO_ECC_256( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(SM2_P256_a, 32, TO_ECC_256( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(SM2_P256_b, 32, TO_ECC_256( + TO_ECC_64(0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34), + TO_ECC_64(0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7), + TO_ECC_64(0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92), + TO_ECC_64(0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93))); +ECC_CONST(SM2_P256_gX, 32, TO_ECC_256( + TO_ECC_64(0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19), + TO_ECC_64(0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94), + TO_ECC_64(0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1), + TO_ECC_64(0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7))); +ECC_CONST(SM2_P256_gY, 32, TO_ECC_256( + TO_ECC_64(0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C), + TO_ECC_64(0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53), + TO_ECC_64(0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40), + TO_ECC_64(0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0))); +ECC_CONST(SM2_P256_n, 32, TO_ECC_256( + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B), + TO_ECC_64(0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23))); +#define SM2_P256_h ECC_ONE +#define SM2_P256_gZ ECC_ONE +#if USE_BN_ECC_DATA +const ECC_CURVE_DATA SM2_P256 = { + (bigNum)&SM2_P256_p, (bigNum)&SM2_P256_n, (bigNum)&SM2_P256_h, + (bigNum)&SM2_P256_a, (bigNum)&SM2_P256_b, + {(bigNum)&SM2_P256_gX, (bigNum)&SM2_P256_gY, (bigNum)&SM2_P256_gZ}}; +#else +const ECC_CURVE_DATA SM2_P256 = { + &SM2_P256_p.b, &SM2_P256_n.b, &SM2_P256_h.b, + &SM2_P256_a.b, &SM2_P256_b.b, + {&SM2_P256_gX.b, &SM2_P256_gY.b, &SM2_P256_gZ.b}}; +#endif // USE_BN_ECC_DATA +#endif // ECC_SM2_P256 +#define comma +const ECC_CURVE eccCurves[] = { +#if ECC_NIST_P192 + comma + {TPM_ECC_NIST_P192, + 192, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P192, + OID_ECC_NIST_P192 + CURVE_NAME("NIST_P192")} +# undef comma +# define comma , +#endif // ECC_NIST_P192 +#if ECC_NIST_P224 + comma + {TPM_ECC_NIST_P224, + 224, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P224, + OID_ECC_NIST_P224 + CURVE_NAME("NIST_P224")} +# undef comma +# define comma , +#endif // ECC_NIST_P224 +#if ECC_NIST_P256 + comma + {TPM_ECC_NIST_P256, + 256, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P256, + OID_ECC_NIST_P256 + CURVE_NAME("NIST_P256")} +# undef comma +# define comma , +#endif // ECC_NIST_P256 +#if ECC_NIST_P384 + comma + {TPM_ECC_NIST_P384, + 384, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA384}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P384, + OID_ECC_NIST_P384 + CURVE_NAME("NIST_P384")} +# undef comma +# define comma , +#endif // ECC_NIST_P384 +#if ECC_NIST_P521 + comma + {TPM_ECC_NIST_P521, + 521, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA512}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P521, + OID_ECC_NIST_P521 + CURVE_NAME("NIST_P521")} +# undef comma +# define comma , +#endif // ECC_NIST_P521 +#if ECC_BN_P256 + comma + {TPM_ECC_BN_P256, + 256, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &BN_P256, + OID_ECC_BN_P256 + CURVE_NAME("BN_P256")} +# undef comma +# define comma , +#endif // ECC_BN_P256 +#if ECC_BN_P638 + comma + {TPM_ECC_BN_P638, + 638, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &BN_P638, + OID_ECC_BN_P638 + CURVE_NAME("BN_P638")} +# undef comma +# define comma , +#endif // ECC_BN_P638 +#if ECC_SM2_P256 + comma + {TPM_ECC_SM2_P256, + 256, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SM3_256}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &SM2_P256, + OID_ECC_SM2_P256 + CURVE_NAME("SM2_P256")} +# undef comma +# define comma , +#endif // ECC_SM2_P256 +}; +#endif // TPM_ALG_ECC diff --git a/src/tpm2/CryptSelfTest.c b/src/tpm2/CryptSelfTest.c new file mode 100644 index 0000000..7a25511 --- /dev/null +++ b/src/tpm2/CryptSelfTest.c @@ -0,0 +1,225 @@ +/********************************************************************************/ +/* */ +/* Self-Test of Cryptographic Functions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptSelfTest.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 10.2.7 CryptSelfTest.c */ +/* 10.2.7.1 Introduction */ +/* The functions in this file are designed to support self-test of cryptographic functions in the + TPM. The TPM allows the user to decide whether to run self-test on a demand basis or to run all + the self-tests before proceeding. */ +/* The self-tests are controlled by a set of bit vectors. The g_untestedDecryptionAlgorithms vector + has a bit for each decryption algorithm that needs to be tested and + g_untestedEncryptionAlgorithms has a bit for each encryption algorithm that needs to be + tested. Before an algorithm is used, the appropriate vector is checked (indexed using the + algorithm ID). If the bit is 1, then the test function should be called. */ +/* For more information, see TpmSelfTests().txt */ +#include "Tpm.h" +/* 10.2.7.2 Functions */ +/* 10.2.7.2.1 RunSelfTest() */ +/* Local function to run self-test */ +static TPM_RC +CryptRunSelfTests( + ALGORITHM_VECTOR *toTest // IN: the vector of the algorithms to test + ) +{ + TPM_ALG_ID alg; + // For each of the algorithms that are in the toTestVecor, need to run a + // test + for(alg = TPM_ALG_FIRST; alg <= TPM_ALG_LAST; alg++) + { + if(TEST_BIT(alg, *toTest)) + { + TPM_RC result = CryptTestAlgorithm(alg, toTest); + if(result != TPM_RC_SUCCESS) + return result; + } + } + return TPM_RC_SUCCESS; +} +/* 10.2.7.2.2 CryptSelfTest() */ +/* This function is called to start/complete a full self-test. If fullTest is NO, then only the + untested algorithms will be run. If fullTest is YES, then g_untestedDecryptionAlgorithms is + reinitialized and then all tests are run. This implementation of the reference design does not + support processing outside the framework of a TPM command. As a consequence, this command does + not complete until all tests are done. Since this can take a long time, the TPM will check after + each test to see if the command is canceled. If so, then the TPM will returned + TPM_RC_CANCELLED. To continue with the self-tests, call TPM2_SelfTest(fullTest == No) and the TPM + will complete the testing. */ +/* Error Returns Meaning */ +/* TPM_RC_CANCELED if the command is canceled */ +LIB_EXPORT +TPM_RC +CryptSelfTest( + TPMI_YES_NO fullTest // IN: if full test is required + ) +{ +#if SIMULATION + if(g_forceFailureMode) + FAIL(FATAL_ERROR_FORCED); +#endif + // If the caller requested a full test, then reset the to test vector so that + // all the tests will be run + if(fullTest == YES) + { + MemoryCopy(g_toTest, + g_implementedAlgorithms, + sizeof(g_toTest)); + } + return CryptRunSelfTests(&g_toTest); +} +/* 10.2.7.2.3 CryptIncrementalSelfTest() */ +/* This function is used to perform an incremental self-test. This implementation will perform the + toTest values before returning. That is, it assumes that the TPM cannot perform background tasks + between commands. */ +/* This command may be canceled. If it is, then there is no return result. However, this command can + be run again and the incremental progress will not be lost. */ +/* Error Returns Meaning */ +/* TPM_RC_CANCELED processing of this command was canceled */ +/* TPM_RC_TESTING if toTest list is not empty */ +/* TPM_RC_VALUE an algorithm in the toTest list is not implemented */ +TPM_RC +CryptIncrementalSelfTest( + TPML_ALG *toTest, // IN: list of algorithms to be tested + TPML_ALG *toDoList // OUT: list of algorithms needing test + ) +{ + ALGORITHM_VECTOR toTestVector = {0}; + TPM_ALG_ID alg; + UINT32 i; + pAssert(toTest != NULL && toDoList != NULL); + if(toTest->count > 0) + { + // Transcribe the toTest list into the toTestVector + for(i = 0; i < toTest->count; i++) + { + alg = toTest->algorithms[i]; + // make sure that the algorithm value is not out of range + if((alg > TPM_ALG_LAST) || !TEST_BIT(alg, g_implementedAlgorithms)) + return TPM_RC_VALUE; + SET_BIT(alg, toTestVector); + } + // Run the test + if(CryptRunSelfTests(&toTestVector) == TPM_RC_CANCELED) + return TPM_RC_CANCELED; + } + // Fill in the toDoList with the algorithms that are still untested + toDoList->count = 0; + for(alg = TPM_ALG_FIRST; + toDoList->count < MAX_ALG_LIST_SIZE && alg <= TPM_ALG_LAST; + alg++) + { + if(TEST_BIT(alg, g_toTest)) + toDoList->algorithms[toDoList->count++] = alg; + } + return TPM_RC_SUCCESS; +} +/* 10.2.7.2.4 CryptInitializeToTest() */ +/* This function will initialize the data structures for testing all the algorithms. This should not + be called unless CryptAlgsSetImplemented() has been called */ +void +CryptInitializeToTest( + void + ) +{ + // Indicate that nothing has been tested + memset(&g_cryptoSelfTestState, 0, sizeof(g_cryptoSelfTestState)); + // Copy the implemented algorithm vector + MemoryCopy(g_toTest, g_implementedAlgorithms, sizeof(g_toTest)); + // Setting the algorithm to null causes the test function to just clear + // out any algorithms for which there is no test. + CryptTestAlgorithm(TPM_ALG_ERROR, &g_toTest); + return; +} +/* 10.2.7.2.5 CryptTestAlgorithm() */ +/* Only point of contact with the actual self tests. If a self-test fails, there is no return and + the TPM goes into failure mode. The call to TestAlgorithm() uses an algorithm selector and a bit + vector. When the test is run, the corresponding bit in toTest and in g_toTest is CLEAR. If toTest + is NULL, then only the bit in g_toTest is CLEAR. There is a special case for the call to + TestAlgorithm(). When alg is TPM_ALG_ERROR, TestAlgorithm() will CLEAR any bit in toTest for + which it has no test. This allows the knowledge about which algorithms have test to be accessed + through the interface that provides the test. */ +/* Error Returns Meaning */ +/* TPM_RC_CANCELED test was canceled */ +LIB_EXPORT +TPM_RC +CryptTestAlgorithm( + TPM_ALG_ID alg, + ALGORITHM_VECTOR *toTest + ) +{ + TPM_RC result; +#if SELF_TEST + result = TestAlgorithm(alg, toTest); +#else + // If this is an attempt to determine the algorithms for which there is a + // self test, pretend that all of them do. We do that by not clearing any + // of the algorithm bits. When/if this function is called to run tests, it + // will over report. This can be changed so that any call to check on which + // algorithms have tests, 'toTest' can be cleared. + if(alg != TPM_ALG_ERROR) + { + CLEAR_BIT(alg, g_toTest); + if(toTest != NULL) + CLEAR_BIT(alg, *toTest); + } + result = TPM_RC_SUCCESS; +#endif + return result; +} diff --git a/src/tpm2/CryptSelfTest_fp.h b/src/tpm2/CryptSelfTest_fp.h new file mode 100644 index 0000000..8dd3822 --- /dev/null +++ b/src/tpm2/CryptSelfTest_fp.h @@ -0,0 +1,87 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptSelfTest_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTSELFTEST_FP_H +#define CRYPTSELFTEST_FP_H + +LIB_EXPORT +TPM_RC +CryptSelfTest( + TPMI_YES_NO fullTest // IN: if full test is required + ); +TPM_RC +CryptIncrementalSelfTest( + TPML_ALG *toTest, // IN: list of algorithms to be tested + TPML_ALG *toDoList // OUT: list of algorithms needing test + ); +void +CryptInitializeToTest( + void + ); +LIB_EXPORT +TPM_RC +CryptTestAlgorithm( + TPM_ALG_ID alg, + ALGORITHM_VECTOR *toTest + ); + + +#endif diff --git a/src/tpm2/CryptUtil.c b/src/tpm2/CryptUtil.c new file mode 100644 index 0000000..9879f91 --- /dev/null +++ b/src/tpm2/CryptUtil.c @@ -0,0 +1,1739 @@ +/********************************************************************************/ +/* */ +/* Interfaces to the Crypto Engine */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptUtil.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.6 CryptUtil.c */ +/* 10.2.6.1 Introduction */ +/* This module contains the interfaces to the CryptoEngine() and provides miscellaneous + cryptographic functions in support of the TPM. */ +/* 10.2.6.2 Includes */ +#include "Tpm.h" +/* 10.2.6.3 Hash/HMAC Functions */ +/* 10.2.6.3.1 CryptHmacSign() */ +/* Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message. */ +/* Error Returns Meaning */ +/* TPM_RC_HASH not a valid hash */ +static TPM_RC +CryptHmacSign( + TPMT_SIGNATURE *signature, // OUT: signature + OBJECT *signKey, // IN: HMAC key sign the hash + TPM2B_DIGEST *hashData // IN: hash to be signed + ) +{ + HMAC_STATE hmacState; + UINT32 digestSize; + digestSize = CryptHmacStart2B(&hmacState, signature->signature.any.hashAlg, + &signKey->sensitive.sensitive.bits.b); + CryptDigestUpdate2B(&hmacState.hashState, &hashData->b); + CryptHmacEnd(&hmacState, digestSize, + (BYTE *)&signature->signature.hmac.digest); + return TPM_RC_SUCCESS; +} +/* 10.2.6.3.2 CryptHMACVerifySignature() */ +/* This function will verify a signature signed by a HMAC key. Note that a caller needs to prepare + signature with the signature algorithm (TPM_ALG_HMAC) and the hash algorithm to use. This + function then builds a signature of that type. */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME not the proper scheme for this key type */ +/* TPM_RC_SIGNATURE if invalid input or signature is not genuine */ +static TPM_RC +CryptHMACVerifySignature( + OBJECT *signKey, // IN: HMAC key signed the hash + TPM2B_DIGEST *hashData, // IN: digest being verified + TPMT_SIGNATURE *signature // IN: signature to be verified + ) +{ + TPMT_SIGNATURE test; + TPMT_KEYEDHASH_SCHEME *keyScheme = + &signKey->publicArea.parameters.keyedHashDetail.scheme; + // + if((signature->sigAlg != TPM_ALG_HMAC) + || (signature->signature.hmac.hashAlg == TPM_ALG_NULL)) + return TPM_RC_SCHEME; + // This check is not really needed for verification purposes. However, it does + // prevent someone from trying to validate a signature using a weaker hash + // algorithm than otherwise allowed by the key. That is, a key with a scheme + // other than TMP_ALG_NULL can only be used to validate signatures that have + // a matching scheme. + if((keyScheme->scheme != TPM_ALG_NULL) + && ((keyScheme->scheme != signature->sigAlg) + || (keyScheme->details.hmac.hashAlg != signature->signature.any.hashAlg))) + return TPM_RC_SIGNATURE; + test.sigAlg = signature->sigAlg; + test.signature.hmac.hashAlg = signature->signature.hmac.hashAlg; + CryptHmacSign(&test, signKey, hashData); + // Compare digest + if(!MemoryEqual(&test.signature.hmac.digest, + &signature->signature.hmac.digest, + CryptHashGetDigestSize(signature->signature.any.hashAlg))) + return TPM_RC_SIGNATURE; + return TPM_RC_SUCCESS; +} +/* 10.2.6.3.3 CryptGenerateKeyedHash() */ +/* This function creates a keyedHash object. */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT cannot get values from random number generator */ +/* TPM_RC_SIZE sensitive data size is larger than allowed for the scheme */ +static TPM_RC +CryptGenerateKeyedHash( + TPMT_PUBLIC *publicArea, // IN/OUT: the public area template + // for the new key. + TPMT_SENSITIVE *sensitive, // OUT: sensitive area + TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data + RAND_STATE *rand // IN: "entropy" source + ) +{ + TPMT_KEYEDHASH_SCHEME *scheme; + TPM_ALG_ID hashAlg; + UINT16 digestSize; + + scheme = &publicArea->parameters.keyedHashDetail.scheme; + + if(publicArea->type != TPM_ALG_KEYEDHASH) + return TPM_RC_FAILURE; + // Pick the limiting hash algorithm + if(scheme->scheme == TPM_ALG_NULL) + hashAlg = publicArea->nameAlg; + else if(scheme->scheme == TPM_ALG_XOR) + hashAlg = scheme->details.xorr.hashAlg; + else + hashAlg = scheme->details.hmac.hashAlg; + /* hashBlockSize = CryptHashGetBlockSize(hashAlg); */ + digestSize = CryptHashGetDigestSize(hashAlg); + + // if this is a signing or a decryption key, then the limit + // for the data size is the block size of the hash. This limit + // is set because larger values have lower entropy because of the + // HMAC function. The lower limit is 1/2 the size of the digest + // + //If the user provided the key, check that it is a proper size + if(sensitiveCreate->data.t.size != 0) + { + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) + || IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + { + if(sensitiveCreate->data.t.size > CryptHashGetBlockSize(hashAlg)) + return TPM_RC_SIZE; +#if 0 // May make this a FIPS-mode requirement + if(sensitiveCreate->data.t.size < (digestSize / 2)) + return TPM_RC_SIZE; +#endif + } + // If this is a data blob, then anything that will get past the unmarshaling + // is OK + MemoryCopy2B(&sensitive->sensitive.bits.b, &sensitiveCreate->data.b, + sizeof(sensitive->sensitive.bits.t.buffer)); + } + else + { + // The TPM is going to generate the data so set the size to be the + // size of the digest of the algorithm + sensitive->sensitive.bits.t.size = + DRBG_Generate(rand, sensitive->sensitive.bits.t.buffer, digestSize); + if(sensitive->sensitive.bits.t.size == 0) + return (g_inFailureMode) ? TPM_RC_FAILURE : TPM_RC_NO_RESULT; + } + return TPM_RC_SUCCESS; +} +/* 10.2.6.3.4 CryptIsSchemeAnonymous() */ +/* This function is used to test a scheme to see if it is an anonymous scheme The only anonymous + scheme is ECDAA. ECDAA can be used to do things like U-Prove. */ +BOOL +CryptIsSchemeAnonymous( + TPM_ALG_ID scheme // IN: the scheme algorithm to test + ) +{ + return scheme == TPM_ALG_ECDAA; +} +/* 10.2.6.4 Symmetric Functions */ +/* 10.2.6.4.1 ParmDecryptSym() */ +/* This function performs parameter decryption using symmetric block cipher. */ +void +ParmDecryptSym( + TPM_ALG_ID symAlg, // IN: the symmetric algorithm + TPM_ALG_ID hash, // IN: hash algorithm for KDFa + UINT16 keySizeInBits, // IN: the key size in bits + TPM2B *key, // IN: KDF HMAC key + TPM2B *nonceCaller, // IN: nonce caller + TPM2B *nonceTpm, // IN: nonce TPM + UINT32 dataSize, // IN: size of parameter buffer + BYTE *data // OUT: buffer to be decrypted + ) +{ + // KDF output buffer + // It contains parameters for the CFB encryption + // From MSB to LSB, they are the key and iv + BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; + // Symmetric key size in byte + UINT16 keySize = (keySizeInBits + 7) / 8; + TPM2B_IV iv; + iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits); + // If there is decryption to do... + if(iv.t.size > 0) + { + // Generate key and iv + CryptKDFa(hash, key, CFB_KEY, nonceCaller, nonceTpm, + keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE); + MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size); + CryptSymmetricDecrypt(data, symAlg, keySizeInBits, symParmString, + &iv, TPM_ALG_CFB, dataSize, data); + } + return; +} +/* 10.2.6.4.2 ParmEncryptSym() */ +/* This function performs parameter encryption using symmetric block cipher. */ +void +ParmEncryptSym( + TPM_ALG_ID symAlg, // IN: symmetric algorithm + TPM_ALG_ID hash, // IN: hash algorithm for KDFa + UINT16 keySizeInBits, // IN: AES symmetric key size in bits + TPM2B *key, // IN: KDF HMAC key + TPM2B *nonceCaller, // IN: nonce caller + TPM2B *nonceTpm, // IN: nonce TPM + UINT32 dataSize, // IN: size of parameter buffer + BYTE *data // OUT: buffer to be encrypted + ) +{ + // KDF output buffer + // It contains parameters for the CFB encryption + BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; + // Symmetric key size in bytes + UINT16 keySize = (keySizeInBits + 7) / 8; + TPM2B_IV iv; + iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits); + // See if there is any encryption to do + if(iv.t.size > 0) + { + // Generate key and iv + CryptKDFa(hash, key, CFB_KEY, nonceTpm, nonceCaller, + keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE); + MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size); + CryptSymmetricEncrypt(data, symAlg, keySizeInBits, symParmString, &iv, + TPM_ALG_CFB, dataSize, data); + } + return; +} +/* 10.2.6.4.3 CryptGenerateKeySymmetric() */ +/* This function generates a symmetric cipher key. The derivation process is determined by the type + of the provided rand */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT cannot get a random value */ +/* TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive creation + area */ +/* TPM_RC_KEY provided key value is not allowed */ +static TPM_RC +CryptGenerateKeySymmetric( + TPMT_PUBLIC *publicArea, // IN/OUT: The public area template + // for the new key. + TPMT_SENSITIVE *sensitive, // OUT: sensitive area + TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data + RAND_STATE *rand // IN: the "entropy" source for + ) +{ + UINT16 keyBits = publicArea->parameters.symDetail.sym.keyBits.sym; + TPM_RC result; + // + // only do multiples of RADIX_BITS + if((keyBits % RADIX_BITS) != 0) + return TPM_RC_KEY_SIZE; + // If this is not a new key, then the provided key data must be the right size + if(sensitiveCreate->data.t.size != 0) + { + result = CryptSymKeyValidate(&publicArea->parameters.symDetail.sym, + (TPM2B_SYM_KEY *)&sensitiveCreate->data); + if(result == TPM_RC_SUCCESS) + MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b, + sizeof(sensitive->sensitive.sym.t.buffer)); + } +#if ALG_TDES + else if(publicArea->parameters.symDetail.sym.algorithm == TPM_ALG_TDES) + { + sensitive->sensitive.sym.t.size = keyBits / 8; + result = CryptGenerateKeyDes(publicArea, sensitive, rand); + } +#endif + else + { + sensitive->sensitive.sym.t.size = + DRBG_Generate(rand, sensitive->sensitive.sym.t.buffer, + BITS_TO_BYTES(keyBits)); + if(g_inFailureMode) + result = TPM_RC_FAILURE; + else if(sensitive->sensitive.sym.t.size == 0) + result = TPM_RC_NO_RESULT; + else + result = TPM_RC_SUCCESS; + } + return result; +} +/* 10.2.6.4.4 CryptXORObfuscation() */ +/* This function implements XOR obfuscation. It should not be called if the hash algorithm is not + implemented. The only return value from this function is TPM_RC_SUCCESS. */ +void +CryptXORObfuscation( + TPM_ALG_ID hash, // IN: hash algorithm for KDF + TPM2B *key, // IN: KDF key + TPM2B *contextU, // IN: contextU + TPM2B *contextV, // IN: contextV + UINT32 dataSize, // IN: size of data buffer + BYTE *data // IN/OUT: data to be XORed in place + ) +{ + BYTE mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer + BYTE *pm; + UINT32 i; + UINT32 counter = 0; + UINT16 hLen = CryptHashGetDigestSize(hash); + UINT32 requestSize = dataSize * 8; + INT32 remainBytes = (INT32)dataSize; + pAssert((key != NULL) && (data != NULL) && (hLen != 0)); + // Call KDFa to generate XOR mask + for(; remainBytes > 0; remainBytes -= hLen) + { + // Make a call to KDFa to get next iteration + CryptKDFa(hash, key, XOR_KEY, contextU, contextV, + requestSize, mask, &counter, TRUE); + // XOR next piece of the data + pm = mask; + for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--) + *data++ ^= *pm++; + } + return; +} +/* 10.2.6.5 Initialization and shut down */ +/* 10.2.6.5.1 CryptInit() */ +/* This function is called when the TPM receives a _TPM_Init() indication. */ +/* NOTE: The hash algorithms do not have to be tested, they just need to be available. They have to + be tested before the TPM can accept HMAC authorization or return any result that relies on a hash + algorithm. */ +/* Return Values Meaning */ +/* TRUE initializations succeeded */ +/* FALSE initialization failed and caller should place the TPM into Failure Mode */ +BOOL +CryptInit( + void + ) +{ + BOOL ok; + // Initialize the vector of implemented algorithms + AlgorithmGetImplementedVector(&g_implementedAlgorithms); + // Indicate that all test are necessary + CryptInitializeToTest(); + // Do any library initializations that are necessary. If any fails, + // the caller should go into failure mode; + ok = SupportLibInit(); + ok = ok && CryptSymInit(); + ok = ok && CryptRandInit(); + ok = ok && CryptHashInit(); +#if ALG_RSA + ok = ok && CryptRsaInit(); +#endif // TPM_ALG_RSA +#if ALG_ECC + ok = ok && CryptEccInit(); +#endif // TPM_ALG_ECC + return ok; +} +/* 10.2.6.5.2 CryptStartup() */ +/* This function is called by TPM2_Startup() to initialize the functions in this cryptographic + library and in the provided CryptoLibrary(). This function and CryptUtilInit() are both provided + so that the implementation may move the initialization around to get the best interaction. */ +/* Return Values Meaning */ +/* TRUE startup succeeded */ +/* FALSE startup failed and caller should place the TPM into Failure Mode */ +BOOL +CryptStartup( + STARTUP_TYPE type // IN: the startup type + ) +{ + BOOL OK; + NOT_REFERENCED(type); + OK = CryptSymStartup(); + OK = OK && CryptRandStartup(); + OK = OK && CryptHashStartup(); +#if ALG_RSA + OK = OK && CryptRsaStartup(); +#endif // TPM_ALG_RSA +#if ALG_ECC + OK = OK && CryptEccStartup(); +#endif // TPM_ALG_ECC + ; +#if ALG_ECC + // Don't directly check for SU_RESET because that is the default + if(OK && (type != SU_RESTART) && (type != SU_RESUME)) + { + // If the shutdown was orderly, then the values recovered from NV will + // be OK to use. + // Get a new random commit nonce + gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer); + CryptRandomGenerate(gr.commitNonce.t.size, gr.commitNonce.t.buffer); + // Reset the counter and commit array + gr.commitCounter = 0; + MemorySet(gr.commitArray, 0, sizeof(gr.commitArray)); + } +#endif // TPM_ALG_ECC + return OK; +} +/* 10.2.6.6 Algorithm-Independent Functions */ +/* 10.2.6.6.1 Introduction */ +/* These functions are used generically when a function of a general type (e.g., symmetric + encryption) is required. The functions will modify the parameters as required to interface to + the indicated algorithms. */ +/* 10.2.6.6.2 CryptIsAsymAlgorithm() */ +/* This function indicates if an algorithm is an asymmetric algorithm. */ +/* Return Values Meaning */ +/* TRUE if it is an asymmetric algorithm */ +/* FALSE if it is not an asymmetric algorithm */ +BOOL +CryptIsAsymAlgorithm( + TPM_ALG_ID algID // IN: algorithm ID + ) +{ + switch(algID) + { +#if ALG_RSA + case TPM_ALG_RSA: +#endif +#if ALG_ECC + case TPM_ALG_ECC: +#endif + return TRUE; + break; + default: + break; + } + return FALSE; +} +/* 10.2.6.6.3 CryptSecretEncrypt() */ +/* This function creates a secret value and its associated secret structure using an asymmetric + algorithm. */ +/* This function is used by TPM2_Rewrap() TPM2_MakeCredential(), and TPM2_Duplicate(). */ +/* Error Returns Meaning */ +/* TPM_RC_ATTRIBUTES keyHandle does not reference a valid decryption key */ +/* TPM_RC_KEY invalid ECC key (public point is not on the curve) */ +/* TPM_RC_SCHEME RSA key with an unsupported padding scheme */ +/* TPM_RC_VALUE numeric value of the data to be decrypted is greater than the RSA key modulus */ +TPM_RC +CryptSecretEncrypt( + OBJECT *encryptKey, // IN: encryption key object + const TPM2B *label, // IN: a null-terminated string as L + TPM2B_DATA *data, // OUT: secret value + TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure + ) +{ + TPMT_RSA_DECRYPT scheme; + TPM_RC result = TPM_RC_SUCCESS; + // + if(data == NULL || secret == NULL) + return TPM_RC_FAILURE; + // The output secret value has the size of the digest produced by the nameAlg. + data->t.size = CryptHashGetDigestSize(encryptKey->publicArea.nameAlg); + // The encryption scheme is OAEP using the nameAlg of the encrypt key. + scheme.scheme = TPM_ALG_OAEP; + scheme.details.anySig.hashAlg = encryptKey->publicArea.nameAlg; + if(!IS_ATTRIBUTE(encryptKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RC_ATTRIBUTES; + switch(encryptKey->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + { + // Create secret data from RNG + CryptRandomGenerate(data->t.size, data->t.buffer); + // Encrypt the data by RSA OAEP into encrypted secret + result = CryptRsaEncrypt((TPM2B_PUBLIC_KEY_RSA *)secret, &data->b, + encryptKey, &scheme, label, NULL); + } + break; +#endif //TPM_ALG_RSA +#if ALG_ECC + case TPM_ALG_ECC: + { + TPMS_ECC_POINT eccPublic; + TPM2B_ECC_PARAMETER eccPrivate; + TPMS_ECC_POINT eccSecret; + BYTE *buffer = secret->t.secret; + // Need to make sure that the public point of the key is on the + // curve defined by the key. + if(!CryptEccIsPointOnCurve( + encryptKey->publicArea.parameters.eccDetail.curveID, + &encryptKey->publicArea.unique.ecc)) + result = TPM_RC_KEY; + else + { + // Call crypto engine to create an auxiliary ECC key + // We assume crypt engine initialization should always success. + // Otherwise, TPM should go to failure mode. + CryptEccNewKeyPair(&eccPublic, &eccPrivate, + encryptKey->publicArea.parameters.eccDetail.curveID); + // Marshal ECC public to secret structure. This will be used by the + // recipient to decrypt the secret with their private key. + secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL); + // Compute ECDH shared secret which is R = [d]Q where d is the + // private part of the ephemeral key and Q is the public part of a + // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret + // because the auxiliary ECC key is just created according to the + // parameters of input ECC encrypt key. + if(CryptEccPointMultiply(&eccSecret, + encryptKey->publicArea.parameters.eccDetail.curveID, + &encryptKey->publicArea.unique.ecc, &eccPrivate, + NULL, NULL) != TPM_RC_SUCCESS) + result = TPM_RC_KEY; + else + { + // The secret value is computed from Z using KDFe as: + // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits) + // Where: + // HashID the nameAlg of the decrypt key + // Z the x coordinate (Px) of the product (P) of the point + // (Q) of the secret and the private x coordinate (de,V) + // of the decryption key + // Use a null-terminated string containing "SECRET" + // PartyUInfo the x coordinate of the point in the secret + // (Qe,U ) + // PartyVInfo the x coordinate of the public key (Qs,V ) + // bits the number of bits in the digest of HashID + // Retrieve seed from KDFe + CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b, + label, &eccPublic.x.b, + &encryptKey->publicArea.unique.ecc.x.b, + data->t.size * 8, data->t.buffer); + } + } + } + break; +#endif //TPM_ALG_ECC + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return result; +} +/* 10.2.6.6.4 CryptSecretDecrypt() */ +/* Decrypt a secret value by asymmetric (or symmetric) algorithm This function is used for + ActivateCredential() and Import for asymmetric decryption, and StartAuthSession() for both + asymmetric and symmetric decryption process */ +/* Error Returns Meaning */ +/* TPM_RC_ATTRIBUTES RSA key is not a decryption key */ +/* TPM_RC_BINDING Invalid RSA key (public and private parts are not cryptographically bound. */ +/* TPM_RC_ECC_POINT ECC point in the secret is not on the curve */ +/* TPM_RC_INSUFFICIENT failed to retrieve ECC point from the secret */ +/* TPM_RC_NO_RESULT multiplication resulted in ECC point at infinity */ +/* TPM_RC_SIZE data to decrypt is not of the same size as RSA key */ +/* TPM_RC_VALUE For RSA key, numeric value of the encrypted data is greater than the modulus, or the + recovered data is larger than the output buffer. For keyedHash or symmetric key, the secret is + larger than the size of the digest produced by the name algorithm. */ +/* TPM_RC_FAILURE internal error */ +TPM_RC +CryptSecretDecrypt( + OBJECT *decryptKey, // IN: decrypt key + TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for + // symmetric decryption. For + // asymmetric decryption, this + // parameter is NULL + const TPM2B *label, // IN: a value for L + TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret + TPM2B_DATA *data // OUT: decrypted secret value + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + // Decryption for secret + switch(decryptKey->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + { + TPMT_RSA_DECRYPT scheme; + TPMT_RSA_SCHEME *keyScheme + = &decryptKey->publicArea.parameters.rsaDetail.scheme; + UINT16 digestSize; + scheme = *(TPMT_RSA_DECRYPT *)keyScheme; + // If the key scheme is TPM_ALG_NULL, set the scheme to OAEP and + // set the algorithm to the name algorithm. + if(scheme.scheme == TPM_ALG_NULL) + { + // Use OAEP scheme + scheme.scheme = TPM_ALG_OAEP; + scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg; + } + // use the digestSize as an indicator of whether or not the scheme + // is using a supported hash algorithm. + // Note: depending on the scheme used for encryption, a hashAlg might + // not be needed. However, the return value has to have some upper + // limit on the size. In this case, it is the size of the digest of the + // hash algorithm. It is checked after the decryption is done but, there + // is no point in doing the decryption if the size is going to be + // 'wrong' anyway. + digestSize = CryptHashGetDigestSize(scheme.details.oaep.hashAlg); + if(scheme.scheme != TPM_ALG_OAEP || digestSize == 0) + return TPM_RC_SCHEME; + // Set the output buffer capacity + data->t.size = sizeof(data->t.buffer); + // Decrypt seed by RSA OAEP + result = CryptRsaDecrypt(&data->b, &secret->b, + decryptKey, &scheme, label); + if((result == TPM_RC_SUCCESS) && (data->t.size > digestSize)) + result = TPM_RC_VALUE; + } + break; +#endif //TPM_ALG_RSA +#if ALG_ECC + case TPM_ALG_ECC: + { + TPMS_ECC_POINT eccPublic; + TPMS_ECC_POINT eccSecret; + BYTE *buffer = secret->t.secret; + INT32 size = secret->t.size; + // Retrieve ECC point from secret buffer + result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size); + if(result == TPM_RC_SUCCESS) + { + result = CryptEccPointMultiply(&eccSecret, + decryptKey->publicArea.parameters.eccDetail.curveID, + &eccPublic, &decryptKey->sensitive.sensitive.ecc, + NULL, NULL); + if(result == TPM_RC_SUCCESS) + { + // Set the size of the "recovered" secret value to be the size + // of the digest produced by the nameAlg. + data->t.size = + CryptHashGetDigestSize(decryptKey->publicArea.nameAlg); + // The secret value is computed from Z using KDFe as: + // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits) + // Where: + // HashID -- the nameAlg of the decrypt key + // Z -- the x coordinate (Px) of the product (P) of the point + // (Q) of the secret and the private x coordinate (de,V) + // of the decryption key + // Use -- a null-terminated string containing "SECRET" + // PartyUInfo -- the x coordinate of the point in the secret + // (Qe,U ) + // PartyVInfo -- the x coordinate of the public key (Qs,V ) + // bits -- the number of bits in the digest of HashID + // Retrieve seed from KDFe + CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label, + &eccPublic.x.b, + &decryptKey->publicArea.unique.ecc.x.b, + data->t.size * 8, data->t.buffer); + } + } + } + break; +#endif //TPM_ALG_ECC +#if !ALG_KEYEDHASH +# error "KEYEDHASH support is required" +#endif + case TPM_ALG_KEYEDHASH: + // The seed size can not be bigger than the digest size of nameAlg + if(secret->t.size > + CryptHashGetDigestSize(decryptKey->publicArea.nameAlg)) + result = TPM_RC_VALUE; + else + { + // Retrieve seed by XOR Obfuscation: + // seed = XOR(secret, hash, key, nonceCaller, nullNonce) + // where: + // secret the secret parameter from the TPM2_StartAuthHMAC + // command that contains the seed value + // hash nameAlg of tpmKey + // key the key or data value in the object referenced by + // entityHandle in the TPM2_StartAuthHMAC command + // nonceCaller the parameter from the TPM2_StartAuthHMAC command + // nullNonce a zero-length nonce + // XOR Obfuscation in place + CryptXORObfuscation(decryptKey->publicArea.nameAlg, + &decryptKey->sensitive.sensitive.bits.b, + &nonceCaller->b, NULL, + secret->t.size, secret->t.secret); + // Copy decrypted seed + MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer)); + } + break; + case TPM_ALG_SYMCIPHER: + { + TPM2B_IV iv = {{0}}; + TPMT_SYM_DEF_OBJECT *symDef; + // The seed size can not be bigger than the digest size of nameAlg + if(secret->t.size > + CryptHashGetDigestSize(decryptKey->publicArea.nameAlg)) + result = TPM_RC_VALUE; + else + { + symDef = &decryptKey->publicArea.parameters.symDetail.sym; + iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm, + symDef->keyBits.sym); + if(iv.t.size == 0) + return TPM_RC_FAILURE; + if(nonceCaller->t.size >= iv.t.size) + { + MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size); + } + else + { + if(nonceCaller->t.size > sizeof(iv.t.buffer)) + return TPM_RC_FAILURE; + MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, // libtpms changed: use iv.t.buffer + nonceCaller->t.size); + } + // make sure secret will fit + if(secret->t.size > data->t.size) + return TPM_RC_FAILURE; + data->t.size = secret->t.size; + // CFB decrypt, using nonceCaller as iv + CryptSymmetricDecrypt(data->t.buffer, symDef->algorithm, + symDef->keyBits.sym, + decryptKey->sensitive.sensitive.sym.t.buffer, + &iv, TPM_ALG_CFB, secret->t.size, + secret->t.secret); + } + } + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return result; +} +/* 10.2.6.6.5 CryptParameterEncryption() */ +/* This function does in-place encryption of a response parameter. */ +void +CryptParameterEncryption( + TPM_HANDLE handle, // IN: encrypt session handle + TPM2B *nonceCaller, // IN: nonce caller + UINT16 leadingSizeInByte, // IN: the size of the leading size field in + // bytes + TPM2B_AUTH *extraKey, // IN: additional key material other than + // sessionAuth + BYTE *buffer // IN/OUT: parameter buffer to be encrypted + ) +{ + SESSION *session = SessionGet(handle); // encrypt session + TPM2B_TYPE(TEMP_KEY, (sizeof(extraKey->t.buffer) + + sizeof(session->sessionKey.t.buffer))); + TPM2B_TEMP_KEY key; // encryption key + UINT32 cipherSize = 0; // size of cipher text + // Retrieve encrypted data size. + if(leadingSizeInByte == 2) + { + // Extract the first two bytes as the size field as the data size + // encrypt + cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer); + // advance the buffer + buffer = &buffer[2]; + } +#ifdef TPM4B + else if(leadingSizeInByte == 4) + { + // use the first four bytes to indicate the number of bytes to encrypt + cipherSize = BYTE_ARRAY_TO_UINT32(buffer); + //advance pointer + buffer = &buffer[4]; + } +#endif + else + { + FAIL(FATAL_ERROR_INTERNAL); + } + // Compute encryption key by concatenating sessionKey with extra key + MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); + MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer)); + if(session->symmetric.algorithm == TPM_ALG_XOR) + // XOR parameter encryption formulation: + // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder) + CryptXORObfuscation(session->authHashAlg, &(key.b), + &(session->nonceTPM.b), + nonceCaller, cipherSize, buffer); + else + ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg, + session->symmetric.keyBits.aes, &(key.b), + nonceCaller, &(session->nonceTPM.b), + cipherSize, buffer); + return; +} +/* 10.2.6.6.6 CryptParameterDecryption() */ +/* This function does in-place decryption of a command parameter. */ +/* Error Returns Meaning */ +/* TPM_RC_SIZE The number of bytes in the input buffer is less than the number of bytes to be + decrypted. */ +TPM_RC +CryptParameterDecryption( + TPM_HANDLE handle, // IN: encrypted session handle + TPM2B *nonceCaller, // IN: nonce caller + UINT32 bufferSize, // IN: size of parameter buffer + UINT16 leadingSizeInByte, // IN: the size of the leading size field in + // byte + TPM2B_AUTH *extraKey, // IN: the authValue + BYTE *buffer // IN/OUT: parameter buffer to be decrypted + ) +{ + SESSION *session = SessionGet(handle); // encrypt session + // The HMAC key is going to be the concatenation of the session key and any + // additional key material (like the authValue). The size of both of these + // is the size of the buffer which can contain a TPMT_HA. + TPM2B_TYPE(HMAC_KEY, (sizeof(extraKey->t.buffer) + + sizeof(session->sessionKey.t.buffer))); + TPM2B_HMAC_KEY key; // decryption key + UINT32 cipherSize = 0; // size of cipher text + // Retrieve encrypted data size. + if(leadingSizeInByte == 2) + { + // The first two bytes of the buffer are the size of the + // data to be decrypted + cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer); + buffer = &buffer[2]; // advance the buffer + } +#ifdef TPM4B + else if(leadingSizeInByte == 4) + { + // the leading size is four bytes so get the four byte size field + cipherSize = BYTE_ARRAY_TO_UINT32(buffer); + buffer = &buffer[4]; //advance pointer + } +#endif + else + { + FAIL(FATAL_ERROR_INTERNAL); + } + if(cipherSize > bufferSize) + return TPM_RC_SIZE; + // Compute decryption key by concatenating sessionAuth with extra input key + MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); + MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer)); + if(session->symmetric.algorithm == TPM_ALG_XOR) + // XOR parameter decryption formulation: + // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder) + // Call XOR obfuscation function + CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller, + &(session->nonceTPM.b), cipherSize, buffer); + else + // Assume that it is one of the symmetric block ciphers. + ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg, + session->symmetric.keyBits.sym, + &key.b, nonceCaller, &session->nonceTPM.b, + cipherSize, buffer); + return TPM_RC_SUCCESS; +} +/* 10.2.6.6.7 CryptComputeSymmetricUnique() */ +/* This function computes the unique field in public area for symmetric objects. */ +void +CryptComputeSymmetricUnique( + TPMT_PUBLIC *publicArea, // IN: the object's public area + TPMT_SENSITIVE *sensitive, // IN: the associated sensitive area + TPM2B_DIGEST *unique // OUT: unique buffer + ) +{ + // For parents (symmetric and derivation), use an HMAC to compute + // the 'unique' field + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) + && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)) + { + // Unique field is HMAC(sensitive->seedValue, sensitive->sensitive) + HMAC_STATE hmacState; + unique->b.size = CryptHmacStart2B(&hmacState, publicArea->nameAlg, + &sensitive->seedValue.b); + CryptDigestUpdate2B(&hmacState.hashState, + &sensitive->sensitive.any.b); + CryptHmacEnd2B(&hmacState, &unique->b); + } + else + { + HASH_STATE hashState; + // Unique := Hash(sensitive->seedValue || sensitive->sensitive) + unique->t.size = CryptHashStart(&hashState, publicArea->nameAlg); + CryptDigestUpdate2B(&hashState, &sensitive->seedValue.b); + CryptDigestUpdate2B(&hashState, &sensitive->sensitive.any.b); + CryptHashEnd2B(&hashState, &unique->b); + } + return; +} +/* 10.2.6.6.8 CryptCreateObject() */ +/* This function creates an object. For an asymmetric key, it will create a key pair and, for a + parent key, a seed value for child protections. */ +/* For an symmetric object, (TPM_ALG_SYMCIPHER or TPM_ALG_KEYEDHASH), it will create a secret key if + the caller did not provide one. It will create a random secret seed value that is hashed with the + secret value to create the public unique value. */ +/* publicArea, sensitive, and sensitiveCreate are the only required parameters and are the only ones + that are used by TPM2_Create(). The other parameters are optional and are used when the generated + Object needs to be deterministic. This is the case for both Primary Objects and Derived + Objects. */ +/* When a seed value is provided, a RAND_STATE will be populated and used for all operations in the + object generation that require a random number. In the simplest case, TPM2_CreatePrimary() will + use seed, label and context with context being the hash of the template. If the Primary Object is + in the Endorsement hierarchy, it will also populate proof with ehProof. */ +/* For derived keys, seed will be the secret value from the parent, label and context will be set + according to the parameters of TPM2_CreateLoaded() and hashAlg will be set which causes the RAND_STATE + to be a KDF generator. */ +/* Error Returns Meaning */ +/* TPM_RC_KEY a provided key is not an allowed value */ +/* TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive creation + area for a symmetric key */ +/* TPM_RC_NO_RESULT unable to get random values (only in derivation) */ +/* TPM_RC_RANGE for an RSA key, the exponent is not supported */ +/* TPM_RC_SIZE sensitive data size is larger than allowed for the scheme for a keyed hash object */ +/* TPM_RC_VALUE exponent is not prime or could not find a prime using the provided parameters for an + RSA key; unsupported name algorithm for an ECC key */ +TPM_RC +CryptCreateObject( + OBJECT *object, // IN: new object structure pointer + TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation + RAND_STATE *rand // IN: the random number generator + // to use + ) +{ + TPMT_PUBLIC *publicArea = &object->publicArea; + TPMT_SENSITIVE *sensitive = &object->sensitive; + TPM_RC result = TPM_RC_SUCCESS; + // + // Set the sensitive type for the object + sensitive->sensitiveType = publicArea->type; + // For all objects, copy the initial authorization data + sensitive->authValue = sensitiveCreate->userAuth; + // If the TPM is the source of the data, set the size of the provided data to + // zero so that there's no confusion about what to do. + if(IS_ATTRIBUTE(publicArea->objectAttributes, + TPMA_OBJECT, sensitiveDataOrigin)) + sensitiveCreate->data.t.size = 0; + // Generate the key and unique fields for the asymmetric keys and just the + // sensitive value for symmetric object + switch(publicArea->type) + { +#if ALG_RSA + // Create RSA key + case TPM_ALG_RSA: + // RSA uses full object so that it has a place to put the private + // exponent + result = CryptRsaGenerateKey(object, rand); + break; +#endif // TPM_ALG_RSA +#if ALG_ECC + // Create ECC key + case TPM_ALG_ECC: + result = CryptEccGenerateKey(publicArea, sensitive, rand); + break; +#endif // TPM_ALG_ECC + case TPM_ALG_SYMCIPHER: + result = CryptGenerateKeySymmetric(publicArea, sensitive, + sensitiveCreate, rand); + break; + case TPM_ALG_KEYEDHASH: + result = CryptGenerateKeyedHash(publicArea, sensitive, + sensitiveCreate, rand); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + if(result != TPM_RC_SUCCESS) + return result; + // Create the sensitive seed value + // If this is a primary key in the endorsement hierarchy, stir the DRBG state + // This implementation uses both shProof and ehProof to make sure that there + // is no leakage of either. + if(object->attributes.primary && object->attributes.epsHierarchy) + { + DRBG_AdditionalData((DRBG_STATE *)rand, &gp.shProof.b); + DRBG_AdditionalData((DRBG_STATE *)rand, &gp.ehProof.b); + } + // Generate a seedValue that is the size of the digest produced by nameAlg + sensitive->seedValue.t.size = + DRBG_Generate(rand, object->sensitive.seedValue.t.buffer, + CryptHashGetDigestSize(publicArea->nameAlg)); + if(g_inFailureMode) + return TPM_RC_FAILURE; + else if(sensitive->seedValue.t.size == 0) + return TPM_RC_NO_RESULT; + // For symmetric objects, need to compute the unique value for the public area + if(publicArea->type == TPM_ALG_SYMCIPHER + || publicArea->type == TPM_ALG_KEYEDHASH) + { + CryptComputeSymmetricUnique(publicArea, sensitive, + &publicArea->unique.sym); + } + else + { + // if this is an asymmetric key and it isn't a parent, then + // get rid of the seed. + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign) + || !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + memset(&sensitive->seedValue, 0, + sizeof(sensitive->seedValue)); + } + // Compute the name + PublicMarshalAndComputeName(publicArea, &object->name); + return result; +} +/* 10.2.6.6.9 CryptGetSignHashAlg() */ +/* Get the hash algorithm of signature from a TPMT_SIGNATURE structure. It assumes the signature is + not NULL This is a function for easy access */ +TPMI_ALG_HASH +CryptGetSignHashAlg( + TPMT_SIGNATURE *auth // IN: signature + ) +{ + if(auth->sigAlg == TPM_ALG_NULL) + FAIL(FATAL_ERROR_INTERNAL); + // Get authHash algorithm based on signing scheme + switch(auth->sigAlg) + { +#if ALG_RSA + // If RSA is supported, both RSASSA and RSAPSS are required +# if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS +# error "RSASSA and RSAPSS are required for RSA" +# endif + case TPM_ALG_RSASSA: + return auth->signature.rsassa.hash; + case TPM_ALG_RSAPSS: + return auth->signature.rsapss.hash; +#endif //TPM_ALG_RSA +#if ALG_ECC + // If ECC is defined, ECDSA is mandatory +# ifndef TPM_ALG_ECDSA +# error "ECDSA is required for ECC" +# endif + case TPM_ALG_ECDSA: + // SM2 and ECSCHNORR are optional +# if ALG_SM2 + case TPM_ALG_SM2: +# endif +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +# endif + //all ECC signatures look the same + return auth->signature.ecdsa.hash; +# if ALG_ECDAA + // Don't know how to verify an ECDAA signature + case TPM_ALG_ECDAA: + break; +# endif +#endif //TPM_ALG_ECC + case TPM_ALG_HMAC: + return auth->signature.hmac.hashAlg; + default: + break; + } + return TPM_ALG_NULL; +} +/* 10.2.6.6.10 CryptIsSplitSign() */ +/* This function us used to determine if the signing operation is a split signing operation that + required a TPM2_Commit(). */ +BOOL +CryptIsSplitSign( + TPM_ALG_ID scheme // IN: the algorithm selector + ) +{ + switch(scheme) + { +# if ALG_ECDAA + case TPM_ALG_ECDAA: + return TRUE; + break; +# endif // TPM_ALG_ECDAA + default: + return FALSE; + break; + } +} +/* 10.2.6.6.11 CryptIsAsymSignScheme() */ +/* This function indicates if a scheme algorithm is a sign algorithm. */ +BOOL +CryptIsAsymSignScheme( + TPMI_ALG_PUBLIC publicType, // IN: Type of the object + TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme + ) +{ + BOOL isSignScheme = TRUE; + switch(publicType) + { +#if ALG_RSA + case TPM_ALG_RSA: + switch(scheme) + { +# if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS +# error "RSASSA and PSAPSS required if RSA used." +# endif + case TPM_ALG_RSASSA: + case TPM_ALG_RSAPSS: + break; + default: + isSignScheme = FALSE; + break; + } + break; +#endif //TPM_ALG_RSA +#if ALG_ECC + // If ECC is implemented ECDSA is required + case TPM_ALG_ECC: + switch(scheme) + { + // Support for ECDSA is required for ECC + case TPM_ALG_ECDSA: +#if ALG_ECDAA // ECDAA is optional + case TPM_ALG_ECDAA: +#endif +#if ALG_ECSCHNORR // Schnorr is also optional + case TPM_ALG_ECSCHNORR: +#endif +#if ALG_SM2 // SM2 is optional + case TPM_ALG_SM2: +#endif + break; + default: + isSignScheme = FALSE; + break; + } + break; +#endif //TPM_ALG_ECC + default: + isSignScheme = FALSE; + break; + } + return isSignScheme; +} +/* 10.2.6.6.12 CryptIsAsymDecryptScheme() */ +/* This function indicate if a scheme algorithm is a decrypt algorithm. */ +BOOL +CryptIsAsymDecryptScheme( + TPMI_ALG_PUBLIC publicType, // IN: Type of the object + TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme + ) +{ + BOOL isDecryptScheme = TRUE; + switch(publicType) + { +#if ALG_RSA + case TPM_ALG_RSA: + switch(scheme) + { + case TPM_ALG_RSAES: + case TPM_ALG_OAEP: + break; + default: + isDecryptScheme = FALSE; + break; + } + break; +#endif //TPM_ALG_RSA +#if ALG_ECC + // If ECC is implemented ECDH is required + case TPM_ALG_ECC: + switch(scheme) + { +#if !ALG_ECDH +# error "ECDH is required for ECC" +#endif + case TPM_ALG_ECDH: +#if ALG_SM2 + case TPM_ALG_SM2: +#endif +#if ALG_ECMQV + case TPM_ALG_ECMQV: +#endif + break; + default: + isDecryptScheme = FALSE; + break; + } + break; +#endif //TPM_ALG_ECC + default: + isDecryptScheme = FALSE; + break; + } + return isDecryptScheme; +} +/* 10.2.6.6.13 CryptSelectSignScheme() */ +/* This function is used by the attestation and signing commands. It implements the rules for + selecting the signature scheme to use in signing. This function requires that the signing key + either be TPM_RH_NULL or be loaded. */ +/* If a default scheme is defined in object, the default scheme should be chosen, otherwise, the + input scheme should be chosen. In the case that both object and input scheme has a non-NULL + scheme algorithm, if the schemes are compatible, the input scheme will be chosen. */ +/* This function should not be called if 'signObject->publicArea.type' == TPM_ALG_SYMCIPHER. */ +/* Return Values Meaning */ +/* TRUE scheme selected */ +/* FALSE both scheme and key's default scheme are empty; or scheme is empty while key's default + scheme requires explicit input scheme (split signing); or non-empty default key scheme differs + from scheme */ +BOOL +CryptSelectSignScheme( + OBJECT *signObject, // IN: signing key + TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme + ) +{ + TPMT_SIG_SCHEME *objectScheme; + TPMT_PUBLIC *publicArea; + BOOL OK; + // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless + // of the setting of scheme + if(signObject == NULL) + { + OK = TRUE; + scheme->scheme = TPM_ALG_NULL; + scheme->details.any.hashAlg = TPM_ALG_NULL; + } + else + { + // assignment to save typing. + publicArea = &signObject->publicArea; + // A symmetric cipher can be used to encrypt and decrypt but it can't + // be used for signing + if(publicArea->type == TPM_ALG_SYMCIPHER) + return FALSE; + // Point to the scheme object + if(CryptIsAsymAlgorithm(publicArea->type)) + objectScheme = + (TPMT_SIG_SCHEME *)&publicArea->parameters.asymDetail.scheme; + else + objectScheme = + (TPMT_SIG_SCHEME *)&publicArea->parameters.keyedHashDetail.scheme; + // If the object doesn't have a default scheme, then use the + // input scheme. + if(objectScheme->scheme == TPM_ALG_NULL) + { + // Input and default can't both be NULL + OK = (scheme->scheme != TPM_ALG_NULL); + // Assume that the scheme is compatible with the key. If not, + // an error will be generated in the signing operation. + } + else if(scheme->scheme == TPM_ALG_NULL) + { + // input scheme is NULL so use default + // First, check to see if the default requires that the caller + // provided scheme data + OK = !CryptIsSplitSign(objectScheme->scheme); + if(OK) + { + // The object has a scheme and the input is TPM_ALG_NULL so copy + // the object scheme as the final scheme. It is better to use a + // structure copy than a copy of the individual fields. + *scheme = *objectScheme; + } + } + else + { + // Both input and object have scheme selectors + // If the scheme and the hash are not the same then... + // NOTE: the reason that there is no copy here is that the input + // might contain extra data for a split signing scheme and that + // data is not in the object so, it has to be preserved. + OK = (objectScheme->scheme == scheme->scheme) + && (objectScheme->details.any.hashAlg + == scheme->details.any.hashAlg); + } + } + return OK; +} +/* 10.2.6.6.14 CryptSign() */ +/* Sign a digest with asymmetric key or HMAC. This function is called by attestation commands and + the generic TPM2_Sign() command. This function checks the key scheme and digest size. It does + not check if the sign operation is allowed for restricted key. It should be checked before the + function is called. The function will assert if the key is not a signing key. */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME signScheme is not compatible with the signing key type */ +/* TPM_RC_VALUE digest value is greater than the modulus of signHandle or size of hashData does not + match hash algorithm insignScheme (for an RSA key); invalid commit status or failed to generate r + value (for an ECC key) */ +TPM_RC +CryptSign( + OBJECT *signKey, // IN: signing key + TPMT_SIG_SCHEME *signScheme, // IN: sign scheme. + TPM2B_DIGEST *digest, // IN: The digest being signed + TPMT_SIGNATURE *signature // OUT: signature + ) +{ + TPM_RC result = TPM_RC_SCHEME; + // Initialize signature scheme + signature->sigAlg = signScheme->scheme; + // If the signature algorithm is TPM_ALG_NULL or the signing key is NULL, + // then we are done + if((signature->sigAlg == TPM_ALG_NULL) || (signKey == NULL)) + return TPM_RC_SUCCESS; + // Initialize signature hash + // Note: need to do the check for TPM_ALG_NULL first because the null scheme + // doesn't have a hashAlg member. + signature->signature.any.hashAlg = signScheme->details.any.hashAlg; + // perform sign operation based on different key type + switch(signKey->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + result = CryptRsaSign(signature, signKey, digest, NULL); + break; +#endif //TPM_ALG_RSA +#if ALG_ECC + case TPM_ALG_ECC: + // The reason that signScheme is passed to CryptEccSign but not to the + // other signing methods is that the signing for ECC may be split and + // need the 'r' value that is in the scheme but not in the signature. + result = CryptEccSign(signature, signKey, digest, + (TPMT_ECC_SCHEME *)signScheme, NULL); + break; +#endif //TPM_ALG_ECC + case TPM_ALG_KEYEDHASH: + result = CryptHmacSign(signature, signKey, digest); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return result; +} +/* 10.2.6.6.15 CryptValidateSignature() */ +/* This function is used to verify a signature. It is called by TPM2_VerifySignature() and + TPM2_PolicySigned(). */ +/* Since this operation only requires use of a public key, no consistency checks are necessary for + the key to signature type because a caller can load any public key that they like with any scheme + that they like. This routine simply makes sure that the signature is correct, whatever the + type. */ +/* Error Returns Meaning */ +/* TPM_RC_SIGNATURE the signature is not genuine */ +/* TPM_RC_SCHEME the scheme is not supported */ +/* TPM_RC_HANDLE an HMAC key was selected but the private part of the key is not loaded */ +TPM_RC +CryptValidateSignature( + TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key + TPM2B_DIGEST *digest, // IN: The digest being validated + TPMT_SIGNATURE *signature // IN: signature + ) +{ + // NOTE: HandleToObject will either return a pointer to a loaded object or + // will assert. It will never return a non-valid value. This makes it save + // to initialize 'publicArea' with the return value from HandleToObject() + // without checking it first. + OBJECT *signObject = HandleToObject(keyHandle); + TPMT_PUBLIC *publicArea = &signObject->publicArea; + TPM_RC result = TPM_RC_SCHEME; + // The input unmarshaling should prevent any input signature from being + // a NULL signature, but just in case + if(signature->sigAlg == TPM_ALG_NULL) + return TPM_RC_SIGNATURE; + switch(publicArea->type) + { +#if ALG_RSA + case TPM_ALG_RSA: + { + // + // Call RSA code to verify signature + result = CryptRsaValidateSignature(signature, signObject, digest); + break; + } +#endif //TPM_ALG_RSA +#if ALG_ECC + case TPM_ALG_ECC: + result = CryptEccValidateSignature(signature, signObject, digest); + break; +#endif // TPM_ALG_ECC + case TPM_ALG_KEYEDHASH: + if(signObject->attributes.publicOnly) + result = TPM_RCS_HANDLE; + else + result = CryptHMACVerifySignature(signObject, digest, signature); + break; + default: + break; + } + return result; +} +/* 10.2.6.6.16 CryptGetTestResult */ +/* This function returns the results of a self-test function. */ +/* NOTE: the behavior in this function is NOT the correct behavior for a real TPM implementation. + An artificial behavior is placed here due to the limitation of a software simulation environment. + For the correct behavior, consult the part 3 specification for TPM2_GetTestResult(). */ +TPM_RC +CryptGetTestResult( + TPM2B_MAX_BUFFER *outData // OUT: test result data + ) +{ + outData->t.size = 0; + return TPM_RC_SUCCESS; +} +/* 10.2.6.6.17 CryptValidateKeys() */ +/* This function is used to verify that the key material of an object is valid. For a publicOnly + object, the key is verified for size and, if it is an ECC key, it is verified to be on the + specified curve. For a key with a sensitive area, the binding between the public and private + parts of the key are verified. If the nameAlg of the key is TPM_ALG_NULL, then the size of the + sensitive area is verified but the public portion is not verified, unless the key is an RSA + key. For an RSA key, the reason for loading the sensitive area is to use it. The only way to use + a private RSA key is to compute the private exponent. To compute the private exponent, the public + modulus is used. */ +/* Error Returns Meaning */ +/* TPM_RC_BINDING the public and private parts are not cryptographically bound */ +/* TPM_RC_HASH cannot have a publicOnly key with nameAlg of TPM_ALG_NULL */ +/* TPM_RC_KEY the public unique is not valid */ +/* TPM_RC_KEY_SIZE the private area key is not valid */ +/* TPM_RC_TYPE the types of the sensitive and private parts do not match */ +TPM_RC +CryptValidateKeys( + TPMT_PUBLIC *publicArea, + TPMT_SENSITIVE *sensitive, + TPM_RC blamePublic, + TPM_RC blameSensitive + ) +{ + TPM_RC result; + UINT16 keySizeInBytes; + UINT16 digestSize = CryptHashGetDigestSize(publicArea->nameAlg); + TPMU_PUBLIC_PARMS *params = &publicArea->parameters; + TPMU_PUBLIC_ID *unique = &publicArea->unique; + if(sensitive != NULL) + { + // Make sure that the types of the public and sensitive are compatible + if(publicArea->type != sensitive->sensitiveType) + return TPM_RCS_TYPE + blameSensitive; + // Make sure that the authValue is not bigger than allowed + // If there is no name algorithm, then the size just needs to be less than + // the maximum size of the buffer used for authorization. That size check + // was made during unmarshaling of the sensitive area + if((sensitive->authValue.t.size) > digestSize && (digestSize > 0)) + return TPM_RCS_SIZE + blameSensitive; + } + switch(publicArea->type) + { +#if ALG_RSA + case TPM_ALG_RSA: + keySizeInBytes = BITS_TO_BYTES(params->rsaDetail.keyBits); + // Regardless of whether there is a sensitive area, the public modulus + // needs to have the correct size. Otherwise, it can't be used for + // any public key operation nor can it be used to compute the private + // exponent. + // NOTE: This implementation only supports key sizes that are multiples + // of 1024 bits which means that the MSb of the 0th byte will always be + // SET in either a prime or the public modulus. + if((unique->rsa.t.size != keySizeInBytes) + || (unique->rsa.t.buffer[0] < 0x80)) + return TPM_RCS_KEY + blamePublic; + if(params->rsaDetail.exponent != 0 + && params->rsaDetail.exponent < 7) + return TPM_RCS_VALUE + blamePublic; + if(sensitive != NULL) + { + // If there is a sensitive area, it has to be the correct size + // including having the correct high order bit SET. + if(((sensitive->sensitive.rsa.t.size * 2) != keySizeInBytes) + || (sensitive->sensitive.rsa.t.buffer[0] < 0x80)) + return TPM_RCS_KEY_SIZE + blameSensitive; + } + break; +#endif +#if ALG_ECC + case TPM_ALG_ECC: + { + TPMI_ECC_CURVE curveId; + curveId = params->eccDetail.curveID; + keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(curveId)); + if(sensitive == NULL) + { + // Validate the public key size + if(unique->ecc.x.t.size != keySizeInBytes + || unique->ecc.y.t.size != keySizeInBytes) + return TPM_RCS_KEY + blamePublic; + if(publicArea->nameAlg != TPM_ALG_NULL) + { + if(!CryptEccIsPointOnCurve(curveId, &unique->ecc)) + return TPM_RCS_ECC_POINT + blamePublic; + } + } + else + { + // If the nameAlg is TPM_ALG_NULL, then only verify that the + // private part of the key is OK. + if(!CryptEccIsValidPrivateKey(&sensitive->sensitive.ecc, + curveId)) + return TPM_RCS_KEY_SIZE; + if(publicArea->nameAlg != TPM_ALG_NULL) + { + // Full key load, verify that the public point belongs to the + // private key. + TPMS_ECC_POINT toCompare; + result = CryptEccPointMultiply(&toCompare, curveId, NULL, + &sensitive->sensitive.ecc, + NULL, NULL); + if(result != TPM_RC_SUCCESS) + return TPM_RCS_BINDING; + else + { + // Make sure that the private key generated the public key. + // The input values and the values produced by the point + // multiply may not be the same size so adjust the computed + // value to match the size of the input value by adding or + // removing zeros. + AdjustNumberB(&toCompare.x.b, unique->ecc.x.t.size); + AdjustNumberB(&toCompare.y.b, unique->ecc.y.t.size); + if(!MemoryEqual2B(&unique->ecc.x.b, &toCompare.x.b) + || !MemoryEqual2B(&unique->ecc.y.b, &toCompare.y.b)) + return TPM_RCS_BINDING; + } + } + } + break; + } +#endif + default: + // Checks for SYMCIPHER and KEYEDHASH are largely the same + // If public area has a nameAlg, then validate the public area size + // and if there is also a sensitive area, validate the binding + // For consistency, if the object is public-only just make sure that + // the unique field is consistent with the name algorithm + if(sensitive == NULL) + { + if(unique->sym.t.size != digestSize) + return TPM_RCS_KEY + blamePublic; + } + else + { + // Make sure that the key size in the sensitive area is consistent. + if(publicArea->type == TPM_ALG_SYMCIPHER) + { + result = CryptSymKeyValidate(¶ms->symDetail.sym, + &sensitive->sensitive.sym); + if(result != TPM_RC_SUCCESS) + return result + blameSensitive; + } + else + { + // For a keyed hash object, the key has to be less than the + // smaller of the block size of the hash used in the scheme or + // 128 bytes. The worst case value is limited by the + // unmarshaling code so the only thing left to be checked is + // that it does not exceed the block size of the hash. + // by the hash algorithm of the scheme. + TPMT_KEYEDHASH_SCHEME *scheme; + UINT16 maxSize; + scheme = ¶ms->keyedHashDetail.scheme; + if(scheme->scheme == TPM_ALG_XOR) + { + maxSize = CryptHashGetBlockSize(scheme->details.xorr.hashAlg); + } + else if(scheme->scheme == TPM_ALG_HMAC) + { + maxSize = CryptHashGetBlockSize(scheme->details.hmac.hashAlg); + } + else if(scheme->scheme == TPM_ALG_NULL) + { + // Not signing or xor so must be a data block + maxSize = 128; + } + else + return TPM_RCS_SCHEME + blamePublic; + if(sensitive->sensitive.bits.t.size > maxSize) + return TPM_RCS_KEY_SIZE + blameSensitive; + } + // If there is a nameAlg, check the binding + if(publicArea->nameAlg != TPM_ALG_NULL) + { + TPM2B_DIGEST compare; + if(sensitive->seedValue.t.size != digestSize) + return TPM_RCS_KEY_SIZE + blameSensitive; + CryptComputeSymmetricUnique(publicArea, sensitive, &compare); + if(!MemoryEqual2B(&unique->sym.b, &compare.b)) + return TPM_RC_BINDING; + } + } + break; + } + // For a parent, need to check that the seedValue is the correct size for + // protections. It should be at least half the size of the nameAlg + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) + && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) + && sensitive != NULL + && publicArea->nameAlg != TPM_ALG_NULL) + { + if((sensitive->seedValue.t.size < (digestSize / 2)) + || (sensitive->seedValue.t.size > digestSize)) + return TPM_RCS_SIZE + blameSensitive; + } + return TPM_RC_SUCCESS; +} +/* 10.2.6.6.18 CryptSelectMac() */ +/* This function is used to set the MAC scheme based on the key parameters and the input scheme. */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME the scheme is not a valid mac scheme */ +/* TPM_RC_TYPE the input key is not a type that supports a mac */ +/* TPM_RC_VALUE the input scheme and the key scheme are not compatible */ +TPM_RC +CryptSelectMac( + TPMT_PUBLIC *publicArea, + TPMI_ALG_MAC_SCHEME *inMac + ) +{ + TPM_ALG_ID macAlg = TPM_ALG_NULL; + switch(publicArea->type) + { + case TPM_ALG_KEYEDHASH: + { + // Local value to keep lines from getting too long + TPMT_KEYEDHASH_SCHEME *scheme; + scheme = &publicArea->parameters.keyedHashDetail.scheme; + // Expect that the scheme is either HMAC or NULL + if(scheme->scheme != TPM_ALG_NULL) + macAlg = scheme->details.hmac.hashAlg; + break; + } + case TPM_ALG_SYMCIPHER: + { + TPMT_SYM_DEF_OBJECT *scheme; + scheme = &publicArea->parameters.symDetail.sym; + // Expect that the scheme is either valid symmetric cipher or NULL + if(scheme->algorithm != TPM_ALG_NULL) + macAlg = scheme->mode.sym; + break; + } + default: + return TPM_RCS_TYPE; + } + // If the input value is not TPM_ALG_NULL ... + if(*inMac != TPM_ALG_NULL) + { + // ... then either the scheme in the key must be TPM_ALG_NULL or the input + // value must match + if((macAlg != TPM_ALG_NULL) && (*inMac != macAlg)) + return TPM_RCS_VALUE; + } + else + { + // Since the input value is TPM_ALG_NULL, then the key value can't be + // TPM_ALG_NULL + if(macAlg == TPM_ALG_NULL) + return TPM_RCS_VALUE; + *inMac = macAlg; + } + if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE)) + return TPM_RCS_SCHEME; + return TPM_RC_SUCCESS; +} +/* 10.2.6.6.19 CryptMacIsValidForKey() */ +/* Check to see if the key type is compatible with the mac type */ +BOOL +CryptMacIsValidForKey( + TPM_ALG_ID keyType, + TPM_ALG_ID macAlg, + BOOL flag + ) +{ + switch(keyType) + { + case TPM_ALG_KEYEDHASH: + return CryptHashIsValidAlg(macAlg, flag); + break; + case TPM_ALG_SYMCIPHER: + return CryptSmacIsValidAlg(macAlg, flag); + break; + default: + break; + } + return FALSE; +} +/* 10.2.6.6.20 CryptSmacIsValidAlg() */ +/* This function is used to test if an algorithm is a supported SMAC algorithm. It needs to be + updated as new algorithms are added. */ +BOOL +CryptSmacIsValidAlg( + TPM_ALG_ID alg, + BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid + ) +{ + switch (alg) + { +#if ALG_CMAC + case TPM_ALG_CMAC: + return TRUE; + break; +#endif + case TPM_ALG_NULL: + return FLAG; + break; + default: + return FALSE; + } +} +/* 10.2.6.6.21 CryptSymModeIsValid() */ +/* Function checks to see if an algorithm ID is a valid, symmetric block cipher mode for the TPM. If + flag is SET, them TPM_ALG_NULL is a valid mode. not include the modes used for SMAC */ +BOOL +CryptSymModeIsValid( + TPM_ALG_ID mode, + BOOL flag + ) +{ + switch(mode) + { +#if ALG_CTR + case TPM_ALG_CTR: +#endif // ALG_CTR +#if ALG_OFB + case TPM_ALG_OFB: +#endif // ALG_OFB +#if ALG_CBC + case TPM_ALG_CBC: +#endif // ALG_CBC +#if ALG_CFB + case TPM_ALG_CFB: +#endif // ALG_CFB +#if ALG_ECB + case TPM_ALG_ECB: +#endif // ALG_ECB + return TRUE; + case TPM_ALG_NULL: + return flag; + break; + default: + break; + } + return FALSE; +} diff --git a/src/tpm2/DA.c b/src/tpm2/DA.c new file mode 100644 index 0000000..d61272e --- /dev/null +++ b/src/tpm2/DA.c @@ -0,0 +1,240 @@ +/********************************************************************************/ +/* */ +/* Dictionary Attack Logic. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: DA.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 8.2 DA.c */ +/* 8.2.1 Introduction */ +/* This file contains the functions and data definitions relating to the dictionary attack logic. */ +/* 8.2.2 Includes and Data Definitions */ +#define DA_C +#include "Tpm.h" +/* 8.2.3 Functions */ +/* 8.2.3.1 DAPreInstall_Init() */ +/* This function initializes the DA parameters to their manufacturer-default values. The default + values are determined by a platform-specific specification. */ +/* This function should not be called outside of a manufacturing or simulation environment. */ +/* The DA parameters will be restored to these initial values by TPM2_Clear(). */ +void +DAPreInstall_Init( + void + ) +{ + gp.failedTries = 0; + gp.maxTries = 3; + gp.recoveryTime = 1000; // in seconds (~16.67 minutes) + gp.lockoutRecovery = 1000; // in seconds + gp.lockOutAuthEnabled = TRUE; // Use of lockoutAuth is enabled + // Record persistent DA parameter changes to NV + NV_SYNC_PERSISTENT(failedTries); + NV_SYNC_PERSISTENT(maxTries); + NV_SYNC_PERSISTENT(recoveryTime); + NV_SYNC_PERSISTENT(lockoutRecovery); + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + return; +} +/* 8.2.3.2 DAStartup() */ +/* This function is called by TPM2_Startup() to initialize the DA parameters. In the case of + Startup(CLEAR), use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise, + lockoutAuth will not be enabled until the TPM has been continuously powered for the + lockoutRecovery time. */ +/* This function requires that NV be available and not rate limiting. */ +BOOL +DAStartup( + STARTUP_TYPE type // IN: startup type + ) +{ + NOT_REFERENCED(type); +#if !ACCUMULATE_SELF_HEAL_TIMER + _plat__TimerWasReset(); + s_selfHealTimer = 0; + s_lockoutTimer = 0; +#else + if(_plat__TimerWasReset()) + { + if(!NV_IS_ORDERLY) + { + // If shutdown was not orderly, then don't really know if go.time has + // any useful value so reset the timer to 0. This is what the tick + // was reset to + s_selfHealTimer = 0; + s_lockoutTimer = 0; + } + else + { + // If we know how much time was accumulated at the last orderly shutdown + // subtract that from the saved timer values so that they effectively + // have the accumulated values + s_selfHealTimer -= go.time; + s_lockoutTimer -= go.time; + } + } +#endif + // For any Startup(), if lockoutRecovery is 0, enable use of lockoutAuth. + if(gp.lockoutRecovery == 0) + { + gp.lockOutAuthEnabled = TRUE; + // Record the changes to NV + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + } + // If DA has not been disabled and the previous shutdown is not orderly + // failedTries is not already at its maximum then increment 'failedTries' + if(gp.recoveryTime != 0 + && gp.failedTries < gp.maxTries + && !IS_ORDERLY(g_prevOrderlyState)) + { +#if USE_DA_USED + gp.failedTries += g_daUsed; + g_daUsed = FALSE; +#else + gp.failedTries++; +#endif + // Record the change to NV + NV_SYNC_PERSISTENT(failedTries); + } + // Before Startup, the TPM will not do clock updates. At startup, need to + // do a time update which will do the DA update. + TimeUpdate(); + return TRUE; +} +/* 8.2.3.3 DARegisterFailure() */ +/* This function is called when an authorization failure occurs on an entity that is subject to + dictionary-attack protection. When a DA failure is triggered, register the failure by resetting + the relevant self-healing timer to the current time. */ +void +DARegisterFailure( + TPM_HANDLE handle // IN: handle for failure + ) +{ + // Reset the timer associated with lockout if the handle is the lockoutAuth. + if(handle == TPM_RH_LOCKOUT) + s_lockoutTimer = g_time; + else + s_selfHealTimer = g_time; + return; +} +/* 8.2.3.4 DASelfHeal() */ +/* This function is called to check if sufficient time has passed to allow decrement of failedTries + or to re-enable use of lockoutAuth. */ +/* This function should be called when the time interval is updated. */ +void +DASelfHeal( + void + ) +{ + // Regular authorization self healing logic + // If no failed authorization tries, do nothing. Otherwise, try to + // decrease failedTries + if(gp.failedTries != 0) + { + // if recovery time is 0, DA logic has been disabled. Clear failed tries + // immediately + if(gp.recoveryTime == 0) + { + gp.failedTries = 0; + // Update NV record + NV_SYNC_PERSISTENT(failedTries); + } + else + { + UINT64 decreaseCount; +#if 0 // Errata eliminates this code + // In the unlikely event that failedTries should become larger than + // maxTries + if(gp.failedTries > gp.maxTries) + gp.failedTries = gp.maxTries; +#endif + // How much can failedTries be decreased + // Cast s_selfHealTimer to an int in case it became negative at + // startup + decreaseCount = ((g_time - (INT64)s_selfHealTimer) / 1000) + / gp.recoveryTime; + if(gp.failedTries <= (UINT32)decreaseCount) + // should not set failedTries below zero + gp.failedTries = 0; + else + gp.failedTries -= (UINT32)decreaseCount; + // the cast prevents overflow of the product + s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000; + if(decreaseCount != 0) + // If there was a change to the failedTries, record the changes + // to NV + NV_SYNC_PERSISTENT(failedTries); + } + } + // LockoutAuth self healing logic + // If lockoutAuth is enabled, do nothing. Otherwise, try to see if we + // may enable it + if(!gp.lockOutAuthEnabled) + { + // if lockout authorization recovery time is 0, a reboot is required to + // re-enable use of lockout authorization. Self-healing would not + // apply in this case. + if(gp.lockoutRecovery != 0) + { + if(((g_time - (INT64)s_lockoutTimer) / 1000) >= gp.lockoutRecovery) + { + gp.lockOutAuthEnabled = TRUE; + // Record the changes to NV + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + } + } + } + return; +} diff --git a/src/tpm2/DA_fp.h b/src/tpm2/DA_fp.h new file mode 100644 index 0000000..bb5f464 --- /dev/null +++ b/src/tpm2/DA_fp.h @@ -0,0 +1,87 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: DA_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef DA_FP_H +#define DA_FP_H + +void +DAPreInstall_Init( + void + ); +void +DAInit( + void + ); +BOOL +DAStartup( + STARTUP_TYPE type // IN: startup type + ); +void +DARegisterFailure( + TPM_HANDLE handle // IN: handle for failure + ); +void +DASelfHeal( + void + ); + + +#endif diff --git a/src/tpm2/DebugHelpers.c b/src/tpm2/DebugHelpers.c new file mode 100644 index 0000000..eb58a29 --- /dev/null +++ b/src/tpm2/DebugHelpers.c @@ -0,0 +1,160 @@ +/********************************************************************************/ +/* */ +/* Debug Helper */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: DebugHelpers.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2021 */ +/* */ +/********************************************************************************/ + +/* C.13 DebugHelpers.c */ +/* C.13.1. Description */ +/* This file contains the NV read and write access methods. This implementation uses RAM/file and + does not manage the RAM/file as NV blocks. The implementation may become more sophisticated over + time. */ +/* C.13.2. Includes and Local */ +#include +#include +#include "Platform.h" +#include "DebugHelpers_fp.h" + +#if CERTIFYX509_DEBUG +const char *debugFileName = "DebugFile.txt"; + +/* C.13.2.1. fileOpen() */ + +/* This exists to allow use of the safe version of fopen() with a MS runtime. */ + +static FILE * +fileOpen( + const char *fn, + const char *mode + ) +{ + FILE *f; +# if defined _MSC_VER + if(fopen_s(&f, fn, mode) != 0) + f = NULL; +# else + f = fopen(fn, mode); +# endif + return f; +} +/* C.13.2.2. DebugFileInit() */ +/* This function initializes the file containing the debug data with the time of the file + creation. */ +/* This function opens the file used to hold the debug data. */ +/* Return Value Meaning */ +/* 0 success */ +/* != 0 error */ +int +DebugFileInit( + void + ) +{ + FILE *f = NULL; + time_t t = time(NULL); + // + // Get current date and time. +# if defined _MSC_VER + char timeString[100]; + ctime_s(timeString, (size_t)sizeof(timeString), &t); +# else + char *timeString; + timeString = ctime(&t); +# endif + // Try to open the debug file + f = fileOpen(debugFileName, "w"); + if(f) + { + /* Initialize the contents with the time. */ + fprintf(f, "%s\n", timeString); + fclose(f); + return 0; + } + return -1; +} + +/* C.13.2.3. DebugDumpBuffer() */ + +void +DebugDumpBuffer( + int size, + unsigned char *buf, + const char *identifier + ) +{ + int i; + // + FILE *f = fileOpen(debugFileName, "a"); + if(!f) + return; + if(identifier) + fprintf(f, "%s\n", identifier); + if(buf) + { + for(i = 0; i < size; i++) + { + if(((i % 16) == 0) && (i)) + fprintf(f, "\n"); + fprintf(f, " %02X", buf[i]); + } + if((size % 16) != 0) + fprintf(f, "\n"); + } + fclose(f); +} + +#endif // CERTIFYX509_DEBUG diff --git a/src/tpm2/DebugHelpers_fp.h b/src/tpm2/DebugHelpers_fp.h new file mode 100644 index 0000000..6e74cd4 --- /dev/null +++ b/src/tpm2/DebugHelpers_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* Debug Helper */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: DebugHelpers_fp.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2021 */ +/* */ +/********************************************************************************/ +#ifndef DEBUGHELPERS_FP_H +#define DEBUGHELPERS_FP_H + +int +DebugFileInit( + void + ); +void +DebugFileClose( + void + ); +void +DebugDumpBuffer( + int size, + unsigned char *buf, + const char *identifier + ); + + + + + +#endif diff --git a/src/tpm2/DictionaryAttackLockReset_fp.h b/src/tpm2/DictionaryAttackLockReset_fp.h new file mode 100644 index 0000000..7be9f3a --- /dev/null +++ b/src/tpm2/DictionaryAttackLockReset_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: DictionaryAttackLockReset_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef DICTIONARYATTACKLOCKRESET_FP_H +#define DICTIONARYATTACKLOCKRESET_FP_H + +typedef struct { + TPMI_RH_LOCKOUT lockHandle; +} DictionaryAttackLockReset_In; + +#define RC_DictionaryAttackLockReset_lockHandle (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_DictionaryAttackLockReset( + DictionaryAttackLockReset_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/DictionaryAttackParameters_fp.h b/src/tpm2/DictionaryAttackParameters_fp.h new file mode 100644 index 0000000..cfc6124 --- /dev/null +++ b/src/tpm2/DictionaryAttackParameters_fp.h @@ -0,0 +1,86 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: DictionaryAttackParameters_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef DICTIONARYATTACKPARAMETERS_FP_H +#define DICTIONARYATTACKPARAMETERS_FP_H + + +typedef struct { + TPMI_RH_LOCKOUT lockHandle; + UINT32 newMaxTries; + UINT32 newRecoveryTime; + UINT32 lockoutRecovery; +} DictionaryAttackParameters_In; + +#define RC_DictionaryAttackParameters_lockHandle (TPM_RC_H + TPM_RC_1) +#define RC_DictionaryAttackParameters_newMaxTries (TPM_RC_P + TPM_RC_1) +#define RC_DictionaryAttackParameters_newRecoveryTime (TPM_RC_P + TPM_RC_2) +#define RC_DictionaryAttackParameters_lockoutRecovery (TPM_RC_P + TPM_RC_3) + +TPM_RC +TPM2_DictionaryAttackParameters( + DictionaryAttackParameters_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/DictionaryCommands.c b/src/tpm2/DictionaryCommands.c new file mode 100644 index 0000000..cc21868 --- /dev/null +++ b/src/tpm2/DictionaryCommands.c @@ -0,0 +1,104 @@ +/********************************************************************************/ +/* */ +/* Dictionary Attack Functions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: DictionaryCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "DictionaryAttackLockReset_fp.h" +#if CC_DictionaryAttackLockReset // Conditional expansion of this file +TPM_RC +TPM2_DictionaryAttackLockReset( + DictionaryAttackLockReset_In *in // IN: input parameter list + ) +{ + // Input parameter is not reference in command action + NOT_REFERENCED(in); + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Internal Data Update + // Set failed tries to 0 + gp.failedTries = 0; + // Record the changes to NV + NV_SYNC_PERSISTENT(failedTries); + return TPM_RC_SUCCESS; +} +#endif // CC_DictionaryAttackLockReset +#include "Tpm.h" +#include "DictionaryAttackParameters_fp.h" +#if CC_DictionaryAttackParameters // Conditional expansion of this file +TPM_RC +TPM2_DictionaryAttackParameters( + DictionaryAttackParameters_In *in // IN: input parameter list + ) +{ + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Internal Data Update + // Set dictionary attack parameters + gp.maxTries = in->newMaxTries; + gp.recoveryTime = in->newRecoveryTime; + gp.lockoutRecovery = in->lockoutRecovery; + // Record the changes to NV + NV_SYNC_PERSISTENT(failedTries); + NV_SYNC_PERSISTENT(maxTries); + NV_SYNC_PERSISTENT(recoveryTime); + NV_SYNC_PERSISTENT(lockoutRecovery); + return TPM_RC_SUCCESS; +} +#endif // CC_DictionaryAttackParameters diff --git a/src/tpm2/Duplicate_fp.h b/src/tpm2/Duplicate_fp.h new file mode 100644 index 0000000..5deffa1 --- /dev/null +++ b/src/tpm2/Duplicate_fp.h @@ -0,0 +1,91 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Duplicate_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef DUPLICATE_FP_H +#define DUPLICATE_FP_H + +typedef struct { + TPMI_DH_OBJECT objectHandle; + TPMI_DH_OBJECT newParentHandle; + TPM2B_DATA encryptionKeyIn; + TPMT_SYM_DEF_OBJECT symmetricAlg; +} Duplicate_In; + +typedef struct { + TPM2B_DATA encryptionKeyOut; + TPM2B_PRIVATE duplicate; + TPM2B_ENCRYPTED_SECRET outSymSeed; +} Duplicate_Out; + +#define RC_Duplicate_objectHandle (TPM_RC_H + TPM_RC_1) +#define RC_Duplicate_newParentHandle (TPM_RC_H + TPM_RC_2) +#define RC_Duplicate_encryptionKeyIn (TPM_RC_P + TPM_RC_1) +#define RC_Duplicate_symmetricAlg (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_Duplicate( + Duplicate_In *in, // IN: input parameter list + Duplicate_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/DuplicationCommands.c b/src/tpm2/DuplicationCommands.c new file mode 100644 index 0000000..525ecf7 --- /dev/null +++ b/src/tpm2/DuplicationCommands.c @@ -0,0 +1,352 @@ +/********************************************************************************/ +/* */ +/* Duplication Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: DuplicationCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "Duplicate_fp.h" +#if CC_Duplicate // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_Duplicate( + Duplicate_In *in, // IN: input parameter list + Duplicate_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + TPMT_SENSITIVE sensitive; + UINT16 innerKeySize = 0; // encrypt key size for inner wrap + OBJECT *object; + OBJECT *newParent; + TPM2B_DATA data; + // Input Validation + // Get duplicate object pointer + object = HandleToObject(in->objectHandle); + // Get new parent + newParent = HandleToObject(in->newParentHandle); + // duplicate key must have fixParent bit CLEAR. + if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, fixedParent)) + return TPM_RCS_ATTRIBUTES + RC_Duplicate_objectHandle; + // Do not duplicate object with NULL nameAlg + if(object->publicArea.nameAlg == TPM_ALG_NULL) + return TPM_RCS_TYPE + RC_Duplicate_objectHandle; + // new parent key must be a storage object or TPM_RH_NULL + if(in->newParentHandle != TPM_RH_NULL + && !ObjectIsStorage(in->newParentHandle)) + return TPM_RCS_TYPE + RC_Duplicate_newParentHandle; + // If the duplicated object has encryptedDuplication SET, then there must be + // an inner wrapper and the new parent may not be TPM_RH_NULL + if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, + encryptedDuplication)) + { + if(in->symmetricAlg.algorithm == TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC + RC_Duplicate_symmetricAlg; + if(in->newParentHandle == TPM_RH_NULL) + return TPM_RCS_HIERARCHY + RC_Duplicate_newParentHandle; + } + if(in->symmetricAlg.algorithm == TPM_ALG_NULL) + { + // if algorithm is TPM_ALG_NULL, input key size must be 0 + if(in->encryptionKeyIn.t.size != 0) + return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn; + } + else + { + // Get inner wrap key size + innerKeySize = in->symmetricAlg.keyBits.sym; + // If provided the input symmetric key must match the size of the algorithm + if(in->encryptionKeyIn.t.size != 0 + && in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8) + return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn; + } + // Command Output + if(in->newParentHandle != TPM_RH_NULL) + { + // Make encrypt key and its associated secret structure. A TPM_RC_KEY + // error may be returned at this point + out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret); + result = CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data, + &out->outSymSeed); + if(result != TPM_RC_SUCCESS) + return result; + } + else + { + // Do not apply outer wrapper + data.t.size = 0; + out->outSymSeed.t.size = 0; + } + // Copy sensitive area + sensitive = object->sensitive; + // Prepare output private data from sensitive. + // Note: If there is no encryption key, one will be provided by + // SensitiveToDuplicate(). This is why the assignment of encryptionKeyIn to + // encryptionKeyOut will work properly and is not conditional. + SensitiveToDuplicate(&sensitive, &object->name.b, newParent, + object->publicArea.nameAlg, &data.b, + &in->symmetricAlg, &in->encryptionKeyIn, + &out->duplicate); + out->encryptionKeyOut = in->encryptionKeyIn; + return TPM_RC_SUCCESS; +} +#endif // CC_Duplicate +#include "Tpm.h" +#include "Rewrap_fp.h" +#if CC_Rewrap // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_Rewrap( + Rewrap_In *in, // IN: input parameter list + Rewrap_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + TPM2B_DATA data; // symmetric key + UINT16 hashSize = 0; + TPM2B_PRIVATE privateBlob; // A temporary private blob + // to transit between old + // and new wrappers + // Input Validation + if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL) + || (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL)) + return TPM_RCS_HANDLE + RC_Rewrap_oldParent; + if(in->oldParent != TPM_RH_NULL) + { + OBJECT *oldParent = HandleToObject(in->oldParent); + // old parent key must be a storage object + if(!ObjectIsStorage(in->oldParent)) + return TPM_RCS_TYPE + RC_Rewrap_oldParent; + // Decrypt input secret data via asymmetric decryption. A + // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this + // point + result = CryptSecretDecrypt(oldParent, NULL, DUPLICATE_STRING, + &in->inSymSeed, &data); + if(result != TPM_RC_SUCCESS) + return TPM_RCS_VALUE + RC_Rewrap_inSymSeed; + // Unwrap Outer + result = UnwrapOuter(oldParent, &in->name.b, + oldParent->publicArea.nameAlg, &data.b, + FALSE, + in->inDuplicate.t.size, in->inDuplicate.t.buffer); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Rewrap_inDuplicate); + // Copy unwrapped data to temporary variable, remove the integrity field + hashSize = sizeof(UINT16) + + CryptHashGetDigestSize(oldParent->publicArea.nameAlg); + privateBlob.t.size = in->inDuplicate.t.size - hashSize; + pAssert(privateBlob.t.size <= sizeof(privateBlob.t.buffer)); + MemoryCopy(privateBlob.t.buffer, in->inDuplicate.t.buffer + hashSize, + privateBlob.t.size); + } + else + { + // No outer wrap from input blob. Direct copy. + privateBlob = in->inDuplicate; + } + if(in->newParent != TPM_RH_NULL) + { + OBJECT *newParent; + newParent = HandleToObject(in->newParent); + // New parent must be a storage object + if(!ObjectIsStorage(in->newParent)) + return TPM_RCS_TYPE + RC_Rewrap_newParent; + // Make new encrypt key and its associated secret structure. A + // TPM_RC_VALUE error may be returned at this point if RSA algorithm is + // enabled in TPM + out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret); + result = CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data, + &out->outSymSeed); + if(result != TPM_RC_SUCCESS) + return result; + // Copy temporary variable to output, reserve the space for integrity + hashSize = sizeof(UINT16) + + CryptHashGetDigestSize(newParent->publicArea.nameAlg); + // Make sure that everything fits into the output buffer + // Note: this is mostly only an issue if there was no outer wrapper on + // 'inDuplicate'. It could be as large as a TPM2B_PRIVATE buffer. If we add + // a digest for an outer wrapper, it won't fit anymore. + if((privateBlob.t.size + hashSize) > sizeof(out->outDuplicate.t.buffer)) + return TPM_RCS_VALUE + RC_Rewrap_inDuplicate; + // Command output + out->outDuplicate.t.size = privateBlob.t.size; + pAssert(privateBlob.t.size + <= sizeof(out->outDuplicate.t.buffer) - hashSize); + MemoryCopy(out->outDuplicate.t.buffer + hashSize, privateBlob.t.buffer, + privateBlob.t.size); + // Produce outer wrapper for output + out->outDuplicate.t.size = ProduceOuterWrap(newParent, &in->name.b, + newParent->publicArea.nameAlg, + &data.b, + FALSE, + out->outDuplicate.t.size, + out->outDuplicate.t.buffer); + } + else // New parent is a null key so there is no seed + { + out->outSymSeed.t.size = 0; + // Copy privateBlob directly + out->outDuplicate = privateBlob; + } + return TPM_RC_SUCCESS; +} +#endif // CC_Rewrap +#include "Tpm.h" +#include "Import_fp.h" +#if CC_Import // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_Import( + Import_In *in, // IN: input parameter list + Import_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT *parentObject; + TPM2B_DATA data; // symmetric key + TPMT_SENSITIVE sensitive; + TPM2B_NAME name; + TPMA_OBJECT attributes; + UINT16 innerKeySize = 0; // encrypt key size for inner + // wrapper + // Input Validation + // to save typing + attributes = in->objectPublic.publicArea.objectAttributes; + // FixedTPM and fixedParent must be CLEAR + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) + || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)) + return TPM_RCS_ATTRIBUTES + RC_Import_objectPublic; + // Get parent pointer + parentObject = HandleToObject(in->parentHandle); + if(!ObjectIsParent(parentObject)) + return TPM_RCS_TYPE + RC_Import_parentHandle; + if(in->symmetricAlg.algorithm != TPM_ALG_NULL) + { + // Get inner wrap key size + innerKeySize = in->symmetricAlg.keyBits.sym; + // Input symmetric key must match the size of algorithm. + if(in->encryptionKey.t.size != (innerKeySize + 7) / 8) + return TPM_RCS_SIZE + RC_Import_encryptionKey; + } + else + { + // If input symmetric algorithm is NULL, input symmetric key size must + // be 0 as well + if(in->encryptionKey.t.size != 0) + return TPM_RCS_SIZE + RC_Import_encryptionKey; + // If encryptedDuplication is SET, then the object must have an inner + // wrapper + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) + return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey; + } + // See if there is an outer wrapper + if(in->inSymSeed.t.size != 0) + { + // in->inParentHandle is a parent, but in order to decrypt an outer wrapper, + // it must be able to do key exchange and a symmetric key can't do that. + if(parentObject->publicArea.type == TPM_ALG_SYMCIPHER) + return TPM_RCS_TYPE + RC_Import_parentHandle; + // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES, + // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT, + // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point + result = CryptSecretDecrypt(parentObject, NULL, DUPLICATE_STRING, + &in->inSymSeed, &data); + pAssert(result != TPM_RC_BINDING); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Import_inSymSeed); + } + else + { + // If encrytpedDuplication is set, then the object must have an outer + // wrapper + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) + return TPM_RCS_ATTRIBUTES + RC_Import_inSymSeed; + data.t.size = 0; + } + // Compute name of object + PublicMarshalAndComputeName(&(in->objectPublic.publicArea), &name); + if(name.t.size == 0) + return TPM_RCS_HASH + RC_Import_objectPublic; + // Retrieve sensitive from private. + // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here. + result = DuplicateToSensitive(&in->duplicate.b, &name.b, parentObject, + in->objectPublic.publicArea.nameAlg, + &data.b, &in->symmetricAlg, + &in->encryptionKey.b, &sensitive); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Import_duplicate); + // If the parent of this object has fixedTPM SET, then validate this + // object as if it were being loaded so that validation can be skipped + // when it is actually loaded. + if(IS_ATTRIBUTE(parentObject->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM)) + { + result = ObjectLoad(NULL, NULL, &in->objectPublic.publicArea, + &sensitive, RC_Import_objectPublic, RC_Import_duplicate, + NULL); + } + // Command output + if(result == TPM_RC_SUCCESS) + { + // Prepare output private data from sensitive + SensitiveToPrivate(&sensitive, &name, parentObject, + in->objectPublic.publicArea.nameAlg, + &out->outPrivate); + } + return result; +} +#endif // CC_Import diff --git a/src/tpm2/EACommands.c b/src/tpm2/EACommands.c new file mode 100644 index 0000000..abf6074 --- /dev/null +++ b/src/tpm2/EACommands.c @@ -0,0 +1,1164 @@ +/********************************************************************************/ +/* */ +/* Enhanced Authorization Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EACommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "Policy_spt_fp.h" +#include "PolicySigned_fp.h" +#if CC_PolicySigned // Conditional expansion of this file +/*TPM_RC_CPHASH cpHash was previously set to a different value */ +/*TPM_RC_EXPIRED expiration indicates a time in the past or expiration is non-zero but no nonceTPM + is present */ +/*TPM_RC_NONCE nonceTPM is not the nonce associated with the policySession */ +/*TPM_RC_SCHEME the signing scheme of auth is not supported by the TPM */ +/*TPM_RC_SIGNATURE the signature is not genuine */ +/*TPM_RC_SIZE input cpHash has wrong size */ +TPM_RC +TPM2_PolicySigned( + PolicySigned_In *in, // IN: input parameter list + PolicySigned_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + SESSION *session; + TPM2B_NAME entityName; + TPM2B_DIGEST authHash; + HASH_STATE hashState; + UINT64 authTimeout = 0; + // Input Validation + // Set up local pointers + session = SessionGet(in->policySession); // the session structure + // Only do input validation if this is not a trial policy session + if(session->attributes.isTrialPolicy == CLEAR) + { + authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM); + result = PolicyParameterChecks(session, authTimeout, + &in->cpHashA, &in->nonceTPM, + RC_PolicySigned_nonceTPM, + RC_PolicySigned_cpHashA, + RC_PolicySigned_expiration); + if(result != TPM_RC_SUCCESS) + return result; + // Re-compute the digest being signed + // Start hash + authHash.t.size = CryptHashStart(&hashState, + CryptGetSignHashAlg(&in->auth)); + // If there is no digest size, then we don't have a verification function + // for this algorithm (e.g. TPM_ALG_ECDAA) so indicate that it is a + // bad scheme. + if(authHash.t.size == 0) + return TPM_RCS_SCHEME + RC_PolicySigned_auth; + // nonceTPM + CryptDigestUpdate2B(&hashState, &in->nonceTPM.b); + // expiration + CryptDigestUpdateInt(&hashState, sizeof(UINT32), in->expiration); + // cpHashA + CryptDigestUpdate2B(&hashState, &in->cpHashA.b); + // policyRef + CryptDigestUpdate2B(&hashState, &in->policyRef.b); + // Complete digest + CryptHashEnd2B(&hashState, &authHash.b); + // Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE + // error may be returned at this point + result = CryptValidateSignature(in->authObject, &authHash, &in->auth); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_PolicySigned_auth); + } + // Internal Data Update + // Update policy with input policyRef and name of authorization key + // These values are updated even if the session is a trial session + PolicyContextUpdate(TPM_CC_PolicySigned, + EntityGetName(in->authObject, &entityName), + &in->policyRef, + &in->cpHashA, authTimeout, session); + // Command Output + // Create ticket and timeout buffer if in->expiration < 0 and this is not + // a trial session. + // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present + // when expiration is non-zero. + if(in->expiration < 0 + && session->attributes.isTrialPolicy == CLEAR) + { + BOOL expiresOnReset = (in->nonceTPM.t.size == 0); + // Compute policy ticket + authTimeout &= ~EXPIRATION_BIT; + TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject), + authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, + &entityName, &out->policyTicket); + // Generate timeout buffer. The format of output timeout buffer is + // TPM-specific. + // Note: In this implementation, the timeout buffer value is computed after + // the ticket is produced so, when the ticket is checked, the expiration + // flag needs to be extracted before the ticket is checked. + // In the Windows compatible version, the least-significant bit of the + // timeout value is used as a flag to indicate if the authorization expires + // on reset. The flag is the MSb. + out->timeout.t.size = sizeof(authTimeout); + if(expiresOnReset) + authTimeout |= EXPIRATION_BIT; + UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); + } + else + { + // Generate a null ticket. + // timeout buffer is null + out->timeout.t.size = 0; + // authorization ticket is null + out->policyTicket.tag = TPM_ST_AUTH_SIGNED; + out->policyTicket.hierarchy = TPM_RH_NULL; + out->policyTicket.digest.t.size = 0; + } + return TPM_RC_SUCCESS; +} +#endif // CC_PolicySigned +#include "Tpm.h" +#include "PolicySecret_fp.h" +#if CC_PolicySecret // Conditional expansion of this file +#include "Policy_spt_fp.h" +#include "NV_spt_fp.h" +/* TPM_RC_CPHASH cpHash for policy was previously set to a value that is not the same as cpHashA */ +/* TPM_RC_EXPIRED expiration indicates a time in the past */ +/* TPM_RC_NONCE nonceTPM does not match the nonce associated with policySession */ +/* TPM_RC_SIZE cpHashA is not the size of a digest for the hash associated with policySession */ +TPM_RC +TPM2_PolicySecret( + PolicySecret_In *in, // IN: input parameter list + PolicySecret_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + SESSION *session; + TPM2B_NAME entityName; + UINT64 authTimeout = 0; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + //Only do input validation if this is not a trial policy session + if(session->attributes.isTrialPolicy == CLEAR) + { + authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM); + result = PolicyParameterChecks(session, authTimeout, + &in->cpHashA, &in->nonceTPM, + RC_PolicySecret_nonceTPM, + RC_PolicySecret_cpHashA, + RC_PolicySecret_expiration); + if(result != TPM_RC_SUCCESS) + return result; + } + // Internal Data Update + // Update policy context with input policyRef and name of authorizing key + // This value is computed even for trial sessions. Possibly update the cpHash + PolicyContextUpdate(TPM_CC_PolicySecret, + EntityGetName(in->authHandle, &entityName), &in->policyRef, + &in->cpHashA, authTimeout, session); + // Command Output + // Create ticket and timeout buffer if in->expiration < 0 and this is not + // a trial session. + // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present + // when expiration is non-zero. + if(in->expiration < 0 + && session->attributes.isTrialPolicy == CLEAR + && !NvIsPinPassIndex(in->authHandle)) + { + BOOL expiresOnReset = (in->nonceTPM.t.size == 0); + // Compute policy ticket + authTimeout &= ~EXPIRATION_BIT; + TicketComputeAuth(TPM_ST_AUTH_SECRET, EntityGetHierarchy(in->authHandle), + authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, + &entityName, &out->policyTicket); + // Generate timeout buffer. The format of output timeout buffer is + // TPM-specific. + // Note: In this implementation, the timeout buffer value is computed after + // the ticket is produced so, when the ticket is checked, the expiration + // flag needs to be extracted before the ticket is checked. + out->timeout.t.size = sizeof(authTimeout); + // In the Windows compatible version, the least-significant bit of the + // timeout value is used as a flag to indicate if the authorization expires + // on reset. The flag is the MSb. + if(expiresOnReset) + authTimeout |= EXPIRATION_BIT; + UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); + } + else + { + // timeout buffer is null + out->timeout.t.size = 0; + // authorization ticket is null + out->policyTicket.tag = TPM_ST_AUTH_SECRET; + out->policyTicket.hierarchy = TPM_RH_NULL; + out->policyTicket.digest.t.size = 0; + } + return TPM_RC_SUCCESS; +} +#endif // CC_PolicySecret +#include "Tpm.h" +#include "PolicyTicket_fp.h" +#if CC_PolicyTicket // Conditional expansion of this file +#include "Policy_spt_fp.h" +/* TPM_RC_CPHASH policy's cpHash was previously set to a different value */ +/* TPM_RC_EXPIRED timeout value in the ticket is in the past and the ticket has expired */ +/* TPM_RC_SIZE timeout or cpHash has invalid size for the */ +/* TPM_RC_TICKET ticket is not valid */ +TPM_RC +TPM2_PolicyTicket( + PolicyTicket_In *in // IN: input parameter list + ) +{ + TPM_RC result; + SESSION *session; + UINT64 authTimeout; + TPMT_TK_AUTH ticketToCompare; + TPM_CC commandCode = TPM_CC_PolicySecret; + BOOL expiresOnReset; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // NOTE: A trial policy session is not allowed to use this command. + // A ticket is used in place of a previously given authorization. Since + // a trial policy doesn't actually authenticate, the validated + // ticket is not necessary and, in place of using a ticket, one + // should use the intended authorization for which the ticket + // would be a substitute. + if(session->attributes.isTrialPolicy) + return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession; + // Restore timeout data. The format of timeout buffer is TPM-specific. + // In this implementation, the most significant bit of the timeout value is + // used as the flag to indicate that the ticket expires on TPM Reset or + // TPM Restart. The flag has to be removed before the parameters and ticket + // are checked. + if(in->timeout.t.size != sizeof(UINT64)) + return TPM_RCS_SIZE + RC_PolicyTicket_timeout; + authTimeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer); + // extract the flag + expiresOnReset = (authTimeout & EXPIRATION_BIT) != 0; + authTimeout &= ~EXPIRATION_BIT; + // Do the normal checks on the cpHashA and timeout values + result = PolicyParameterChecks(session, authTimeout, + &in->cpHashA, + NULL, // no nonce + 0, // no bad nonce return + RC_PolicyTicket_cpHashA, + RC_PolicyTicket_timeout); + if(result != TPM_RC_SUCCESS) + return result; + // Validate Ticket + // Re-generate policy ticket by input parameters + TicketComputeAuth(in->ticket.tag, in->ticket.hierarchy, + authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, + &in->authName, &ticketToCompare); + // Compare generated digest with input ticket digest + if(!MemoryEqual2B(&in->ticket.digest.b, &ticketToCompare.digest.b)) + return TPM_RCS_TICKET + RC_PolicyTicket_ticket; + // Internal Data Update + // Is this ticket to take the place of a TPM2_PolicySigned() or + // a TPM2_PolicySecret()? + if(in->ticket.tag == TPM_ST_AUTH_SIGNED) + commandCode = TPM_CC_PolicySigned; + else if(in->ticket.tag == TPM_ST_AUTH_SECRET) + commandCode = TPM_CC_PolicySecret; + else + // There could only be two possible tag values. Any other value should + // be caught by the ticket validation process. + FAIL(FATAL_ERROR_INTERNAL); + // Update policy context + PolicyContextUpdate(commandCode, &in->authName, &in->policyRef, + &in->cpHashA, authTimeout, session); + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyTicket +#include "Tpm.h" +#include "PolicyOR_fp.h" +#if CC_PolicyOR // Conditional expansion of this file +#include "Policy_spt_fp.h" +TPM_RC +TPM2_PolicyOR( + PolicyOR_In *in // IN: input parameter list + ) +{ + SESSION *session; + UINT32 i; + // Input Validation and Update + // Get pointer to the session structure + session = SessionGet(in->policySession); + // Compare and Update Internal Session policy if match + for(i = 0; i < in->pHashList.count; i++) + { + if(session->attributes.isTrialPolicy == SET + || (MemoryEqual2B(&session->u2.policyDigest.b, + &in->pHashList.digests[i].b))) + { + // Found a match + HASH_STATE hashState; + TPM_CC commandCode = TPM_CC_PolicyOR; + // Start hash + session->u2.policyDigest.t.size + = CryptHashStart(&hashState, session->authHashAlg); + // Set policyDigest to 0 string and add it to hash + MemorySet(session->u2.policyDigest.t.buffer, 0, + session->u2.policyDigest.t.size); + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add command code + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // Add each of the hashes in the list + for(i = 0; i < in->pHashList.count; i++) + { + // Extend policyDigest + CryptDigestUpdate2B(&hashState, &in->pHashList.digests[i].b); + } + // Complete digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + return TPM_RC_SUCCESS; + } + } + // None of the values in the list matched the current policyDigest + return TPM_RCS_VALUE + RC_PolicyOR_pHashList; +} +#endif // CC_PolicyOR +#include "Tpm.h" +#include "PolicyPCR_fp.h" +#if CC_PolicyPCR // Conditional expansion of this file +/* TPM_RC_VALUE if provided, pcrDigest does not match the current PCR settings */ +/* TPM_RC_PCR_CHANGED a previous TPM2_PolicyPCR() set pcrCounter and it has changed */ +TPM_RC +TPM2_PolicyPCR( + PolicyPCR_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM2B_DIGEST pcrDigest; + BYTE pcrs[sizeof(TPML_PCR_SELECTION)]; + UINT32 pcrSize; + BYTE *buffer; + TPM_CC commandCode = TPM_CC_PolicyPCR; + HASH_STATE hashState; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // Compute current PCR digest + PCRComputeCurrentDigest(session->authHashAlg, &in->pcrs, &pcrDigest); + // Do validation for non trial session + if(session->attributes.isTrialPolicy == CLEAR) + { + // Make sure that this is not going to invalidate a previous PCR check + if(session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter) + return TPM_RC_PCR_CHANGED; + // If the caller specified the PCR digest and it does not + // match the current PCR settings, return an error.. + if(in->pcrDigest.t.size != 0) + { + if(!MemoryEqual2B(&in->pcrDigest.b, &pcrDigest.b)) + return TPM_RCS_VALUE + RC_PolicyPCR_pcrDigest; + } + } + else + { + // For trial session, just use the input PCR digest if one provided + // Note: It can't be too big because it is a TPM2B_DIGEST and the size + // would have been checked during unmarshaling + if(in->pcrDigest.t.size != 0) + pcrDigest = in->pcrDigest; + } + // Internal Data Update + // Update policy hash + // policyDigestnew = hash( policyDigestold || TPM_CC_PolicyPCR + // || PCRS || pcrDigest) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add PCRS + buffer = pcrs; + pcrSize = TPML_PCR_SELECTION_Marshal(&in->pcrs, &buffer, NULL); + CryptDigestUpdate(&hashState, pcrSize, pcrs); + // add PCR digest + CryptDigestUpdate2B(&hashState, &pcrDigest.b); + // complete the hash and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // update pcrCounter in session context for non trial session + if(session->attributes.isTrialPolicy == CLEAR) + { + session->pcrCounter = gr.pcrCounter; + } + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyPCR +#include "Tpm.h" +#include "PolicyLocality_fp.h" +#if CC_PolicyLocality // Conditional expansion of this file +TPM_RC +TPM2_PolicyLocality( + PolicyLocality_In *in // IN: input parameter list + ) +{ + SESSION *session; + BYTE marshalBuffer[sizeof(TPMA_LOCALITY)]; + BYTE prevSetting[sizeof(TPMA_LOCALITY)]; + UINT32 marshalSize; + BYTE *buffer; + TPM_CC commandCode = TPM_CC_PolicyLocality; + HASH_STATE hashState; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // Get new locality setting in canonical form + marshalBuffer[0] = 0; // Code analysis says that this is not initialized + buffer = marshalBuffer; + marshalSize = TPMA_LOCALITY_Marshal(&in->locality, &buffer, NULL); + // Its an error if the locality parameter is zero + if(marshalBuffer[0] == 0) + return TPM_RCS_RANGE + RC_PolicyLocality_locality; + // Get existing locality setting in canonical form + prevSetting[0] = 0; // Code analysis says that this is not initialized + buffer = prevSetting; + TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL); + // If the locality has previously been set + if(prevSetting[0] != 0 + // then the current locality setting and the requested have to be the same + // type (that is, either both normal or both extended + && ((prevSetting[0] < 32) != (marshalBuffer[0] < 32))) + return TPM_RCS_RANGE + RC_PolicyLocality_locality; + // See if the input is a regular or extended locality + if(marshalBuffer[0] < 32) + { + // if there was no previous setting, start with all normal localities + // enabled + if(prevSetting[0] == 0) + prevSetting[0] = 0x1F; + // AND the new setting with the previous setting and store it in prevSetting + prevSetting[0] &= marshalBuffer[0]; + // The result setting can not be 0 + if(prevSetting[0] == 0) + return TPM_RCS_RANGE + RC_PolicyLocality_locality; + } + else + { + // for extended locality + // if the locality has already been set, then it must match the + if(prevSetting[0] != 0 && prevSetting[0] != marshalBuffer[0]) + return TPM_RCS_RANGE + RC_PolicyLocality_locality; + // Setting is OK + prevSetting[0] = marshalBuffer[0]; + } + // Internal Data Update + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyLocality || locality) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add input locality + CryptDigestUpdate(&hashState, marshalSize, marshalBuffer); + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // update session locality by unmarshal function. The function must succeed + // because both input and existing locality setting have been validated. + buffer = prevSetting; + TPMA_LOCALITY_Unmarshal(&session->commandLocality, &buffer, + (INT32 *)&marshalSize); + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyLocality +#include "Tpm.h" +#include "PolicyNV_fp.h" +#if CC_PolicyNV // Conditional expansion of this file +#include "Policy_spt_fp.h" +TPM_RC +TPM2_PolicyNV( + PolicyNV_In *in // IN: input parameter list + ) +{ + TPM_RC result; + SESSION *session; + NV_REF locator; + NV_INDEX *nvIndex; + BYTE nvBuffer[sizeof(in->operandB.t.buffer)]; + TPM2B_NAME nvName; + TPM_CC commandCode = TPM_CC_PolicyNV; + HASH_STATE hashState; + TPM2B_DIGEST argHash; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + //If this is a trial policy, skip all validations and the operation + if(session->attributes.isTrialPolicy == CLEAR) + { + // No need to access the actual NV index information for a trial policy. + nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + // Common read access checks. NvReadAccessChecks() may return + // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED + result = NvReadAccessChecks(in->authHandle, + in->nvIndex, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // Make sure that offset is withing range + if(in->offset > nvIndex->publicArea.dataSize) + return TPM_RCS_VALUE + RC_PolicyNV_offset; + // Valid NV data size should not be smaller than input operandB size + if((nvIndex->publicArea.dataSize - in->offset) < in->operandB.t.size) + return TPM_RCS_SIZE + RC_PolicyNV_operandB; + // Get NV data. The size of NV data equals the input operand B size + NvGetIndexData(nvIndex, locator, in->offset, in->operandB.t.size, nvBuffer); + // Check to see if the condition is valid + if(!PolicySptCheckCondition(in->operation, nvBuffer, + in->operandB.t.buffer, in->operandB.t.size)) + return TPM_RC_POLICY; + } + // Internal Data Update + // Start argument hash + argHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + // add operandB + CryptDigestUpdate2B(&hashState, &in->operandB.b); + // add offset + CryptDigestUpdateInt(&hashState, sizeof(UINT16), in->offset); + // add operation + CryptDigestUpdateInt(&hashState, sizeof(TPM_EO), in->operation); + // complete argument digest + CryptHashEnd2B(&hashState, &argHash.b); + // Update policyDigest + // Start digest + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add argument digest + CryptDigestUpdate2B(&hashState, &argHash.b); + // Adding nvName + CryptDigestUpdate2B(&hashState, &EntityGetName(in->nvIndex, &nvName)->b); + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyNV +#include "Tpm.h" +#include "PolicyCounterTimer_fp.h" +#if CC_PolicyCounterTimer // Conditional expansion of this file +#include "Policy_spt_fp.h" +TPM_RC +TPM2_PolicyCounterTimer( + PolicyCounterTimer_In *in // IN: input parameter list + ) +{ + SESSION *session; + TIME_INFO infoData; // data buffer of TPMS_TIME_INFO + BYTE *pInfoData = (BYTE *)&infoData; + UINT16 infoDataSize; + TPM_CC commandCode = TPM_CC_PolicyCounterTimer; + HASH_STATE hashState; + TPM2B_DIGEST argHash; + // Input Validation + // Get a marshaled time structure + infoDataSize = TimeGetMarshaled(&infoData); + pAssert(infoDataSize <= sizeof(infoData)); // libtpms added; 25 < 32 ==> unfounded coverity complaint + // Make sure that the referenced stays within the bounds of the structure. + // NOTE: the offset checks are made even for a trial policy because the policy + // will not make any sense if the references are out of bounds of the timer + // structure. + if(in->offset > infoDataSize) + return TPM_RCS_VALUE + RC_PolicyCounterTimer_offset; + if((UINT32)in->offset + (UINT32)in->operandB.t.size > infoDataSize) + return TPM_RCS_RANGE; + // Get pointer to the session structure + session = SessionGet(in->policySession); + //If this is a trial policy, skip the check to see if the condition is met. + if(session->attributes.isTrialPolicy == CLEAR) + { + // If the command is going to use any part of the counter or timer, need + // to verify that time is advancing. + // The time and clock vales are the first two 64-bit values in the clock + if(in->offset < sizeof(UINT64) + sizeof(UINT64)) + { + // Using Clock or Time so see if clock is running. Clock doesn't + // run while NV is unavailable. + // TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned here. + RETURN_IF_NV_IS_NOT_AVAILABLE; + } + // offset to the starting position + pInfoData = (BYTE *)infoData; + // Check to see if the condition is valid + if(!PolicySptCheckCondition(in->operation, pInfoData + in->offset, + in->operandB.t.buffer, in->operandB.t.size)) + return TPM_RC_POLICY; + } + // Internal Data Update + // Start argument list hash + argHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + // add operandB + CryptDigestUpdate2B(&hashState, &in->operandB.b); + // add offset + CryptDigestUpdateInt(&hashState, sizeof(UINT16), in->offset); + // add operation + CryptDigestUpdateInt(&hashState, sizeof(TPM_EO), in->operation); + // complete argument hash + CryptHashEnd2B(&hashState, &argHash.b); + // update policyDigest + // start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add argument digest + CryptDigestUpdate2B(&hashState, &argHash.b); + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyCounterTimer +#include "Tpm.h" +#include "PolicyCommandCode_fp.h" +#if CC_PolicyCommandCode // Conditional expansion of this file +/* Error Returns Meaning */ +/* TPM_RC_VALUE commandCode of policySession previously set to a different value */ +TPM_RC +TPM2_PolicyCommandCode( + PolicyCommandCode_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM_CC commandCode = TPM_CC_PolicyCommandCode; + HASH_STATE hashState; + // Input validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + if(session->commandCode != 0 && session->commandCode != in->code) + return TPM_RCS_VALUE + RC_PolicyCommandCode_code; + if(CommandCodeToCommandIndex(in->code) == UNIMPLEMENTED_COMMAND_INDEX) + return TPM_RCS_POLICY_CC + RC_PolicyCommandCode_code; + // Internal Data Update + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCommandCode || code) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add input commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), in->code); + // complete the hash and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // update commandCode value in session context + session->commandCode = in->code; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyCommandCode +#include "Tpm.h" +#include "PolicyPhysicalPresence_fp.h" +#if CC_PolicyPhysicalPresence // Conditional expansion of this file +TPM_RC +TPM2_PolicyPhysicalPresence( + PolicyPhysicalPresence_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM_CC commandCode = TPM_CC_PolicyPhysicalPresence; + HASH_STATE hashState; + // Internal Data Update + // Get pointer to the session structure + session = SessionGet(in->policySession); + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyPhysicalPresence) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // update session attribute + session->attributes.isPPRequired = SET; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyPhysicalPresence +#include "Tpm.h" +#include "PolicyCpHash_fp.h" +#if CC_PolicyCpHash // Conditional expansion of this file +TPM_RC +TPM2_PolicyCpHash( + PolicyCpHash_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM_CC commandCode = TPM_CC_PolicyCpHash; + HASH_STATE hashState; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // A valid cpHash must have the same size as session hash digest + // NOTE: the size of the digest can't be zero because TPM_ALG_NULL + // can't be used for the authHashAlg. + if(in->cpHashA.t.size != CryptHashGetDigestSize(session->authHashAlg)) + return TPM_RCS_SIZE + RC_PolicyCpHash_cpHashA; + // error if the cpHash in session context is not empty and is not the same + // as the input or is not a cpHash + if((session->u1.cpHash.t.size != 0) + && (!session->attributes.isCpHashDefined + || !MemoryEqual2B(&in->cpHashA.b, &session->u1.cpHash.b))) + return TPM_RC_CPHASH; + // Internal Data Update + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash || cpHashA) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add cpHashA + CryptDigestUpdate2B(&hashState, &in->cpHashA.b); + // complete the digest and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // update cpHash in session context + session->u1.cpHash = in->cpHashA; + session->attributes.isCpHashDefined = SET; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyCpHash +#include "Tpm.h" +#include "PolicyNameHash_fp.h" +#if CC_PolicyNameHash // Conditional expansion of this file +TPM_RC +TPM2_PolicyNameHash( + PolicyNameHash_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM_CC commandCode = TPM_CC_PolicyNameHash; + HASH_STATE hashState; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // A valid nameHash must have the same size as session hash digest + // Since the authHashAlg for a session cannot be TPM_ALG_NULL, the digest size + // is always non-zero. + if(in->nameHash.t.size != CryptHashGetDigestSize(session->authHashAlg)) + return TPM_RCS_SIZE + RC_PolicyNameHash_nameHash; + // u1 in the policy session context cannot otherwise be occupied + if(session->u1.cpHash.b.size != 0 + || session->attributes.isBound + || session->attributes.isCpHashDefined + || session->attributes.isTemplateSet) + return TPM_RC_CPHASH; + // Internal Data Update + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNameHash || nameHash) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add nameHash + CryptDigestUpdate2B(&hashState, &in->nameHash.b); + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // update nameHash in session context + session->u1.cpHash = in->nameHash; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyNameHash +#include "Tpm.h" +#include "PolicyDuplicationSelect_fp.h" +#if CC_PolicyDuplicationSelect // Conditional expansion of this file +TPM_RC +TPM2_PolicyDuplicationSelect( + PolicyDuplicationSelect_In *in // IN: input parameter list + ) +{ + SESSION *session; + HASH_STATE hashState; + TPM_CC commandCode = TPM_CC_PolicyDuplicationSelect; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // cpHash in session context must be empty + if(session->u1.cpHash.t.size != 0) + return TPM_RC_CPHASH; + // commandCode in session context must be empty + if(session->commandCode != 0) + return TPM_RC_COMMAND_CODE; + // Internal Data Update + // Update name hash + session->u1.cpHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + // add objectName + CryptDigestUpdate2B(&hashState, &in->objectName.b); + // add new parent name + CryptDigestUpdate2B(&hashState, &in->newParentName.b); + // complete hash + CryptHashEnd2B(&hashState, &session->u1.cpHash.b); + // update policy hash + // Old policyDigest size should be the same as the new policyDigest size since + // they are using the same hash algorithm + session->u2.policyDigest.t.size + = CryptHashStart(&hashState, session->authHashAlg); + // add old policy + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add command code + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add objectName + if(in->includeObject == YES) + CryptDigestUpdate2B(&hashState, &in->objectName.b); + // add new parent name + CryptDigestUpdate2B(&hashState, &in->newParentName.b); + // add includeObject + CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->includeObject); + // complete digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // set commandCode in session context + session->commandCode = TPM_CC_Duplicate; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyDuplicationSelect +#include "Tpm.h" +#include "PolicyAuthorize_fp.h" +#if CC_PolicyAuthorize // Conditional expansion of this file +#include "Policy_spt_fp.h" +TPM_RC +TPM2_PolicyAuthorize( + PolicyAuthorize_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM2B_DIGEST authHash; + HASH_STATE hashState; + TPMT_TK_VERIFIED ticket; + TPM_ALG_ID hashAlg; + UINT16 digestSize; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // Extract from the Name of the key, the algorithm used to compute it's Name + hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name); + // 'keySign' parameter needs to use a supported hash algorithm, otherwise + // can't tell how large the digest should be + if(!CryptHashIsValidAlg(hashAlg, FALSE)) + return TPM_RCS_HASH + RC_PolicyAuthorize_keySign; + digestSize = CryptHashGetDigestSize(hashAlg); + if(digestSize != (in->keySign.t.size - 2)) + return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign; + //If this is a trial policy, skip all validations + if(session->attributes.isTrialPolicy == CLEAR) + { + // Check that "approvedPolicy" matches the current value of the + // policyDigest in policy session + if(!MemoryEqual2B(&session->u2.policyDigest.b, + &in->approvedPolicy.b)) + return TPM_RCS_VALUE + RC_PolicyAuthorize_approvedPolicy; + // Validate ticket TPMT_TK_VERIFIED + // Compute aHash. The authorizing object sign a digest + // aHash := hash(approvedPolicy || policyRef). + // Start hash + authHash.t.size = CryptHashStart(&hashState, hashAlg); + // add approvedPolicy + CryptDigestUpdate2B(&hashState, &in->approvedPolicy.b); + // add policyRef + CryptDigestUpdate2B(&hashState, &in->policyRef.b); + // complete hash + CryptHashEnd2B(&hashState, &authHash.b); + // re-compute TPMT_TK_VERIFIED + TicketComputeVerified(in->checkTicket.hierarchy, &authHash, + &in->keySign, &ticket); + // Compare ticket digest. If not match, return error + if(!MemoryEqual2B(&in->checkTicket.digest.b, &ticket.digest.b)) + return TPM_RCS_VALUE + RC_PolicyAuthorize_checkTicket; + } + // Internal Data Update + // Set policyDigest to zero digest + PolicyDigestClear(session); + // Update policyDigest + PolicyContextUpdate(TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef, + NULL, 0, session); + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyAuthorize +#include "Tpm.h" +#include "PolicyAuthValue_fp.h" +#if CC_PolicyAuthValue // Conditional expansion of this file +#include "Policy_spt_fp.h" +TPM_RC +TPM2_PolicyAuthValue( + PolicyAuthValue_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM_CC commandCode = TPM_CC_PolicyAuthValue; + HASH_STATE hashState; + // Internal Data Update + // Get pointer to the session structure + session = SessionGet(in->policySession); + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // complete the hash and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // update isAuthValueNeeded bit in the session context + session->attributes.isAuthValueNeeded = SET; + session->attributes.isPasswordNeeded = CLEAR; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyAuthValue +#include "Tpm.h" +#include "PolicyPassword_fp.h" +#if CC_PolicyPassword // Conditional expansion of this file +#include "Policy_spt_fp.h" +TPM_RC +TPM2_PolicyPassword( + PolicyPassword_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM_CC commandCode = TPM_CC_PolicyAuthValue; + HASH_STATE hashState; + // Internal Data Update + // Get pointer to the session structure + session = SessionGet(in->policySession); + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // Update isPasswordNeeded bit + session->attributes.isPasswordNeeded = SET; + session->attributes.isAuthValueNeeded = CLEAR; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyPassword +#include "Tpm.h" +#include "PolicyGetDigest_fp.h" +#if CC_PolicyGetDigest // Conditional expansion of this file +TPM_RC +TPM2_PolicyGetDigest( + PolicyGetDigest_In *in, // IN: input parameter list + PolicyGetDigest_Out *out // OUT: output parameter list + ) +{ + SESSION *session; + // Command Output + // Get pointer to the session structure + session = SessionGet(in->policySession); + out->policyDigest = session->u2.policyDigest; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyGetDigest +#include "Tpm.h" +#include "PolicyNvWritten_fp.h" +#if CC_PolicyNvWritten // Conditional expansion of this file +TPM_RC +TPM2_PolicyNvWritten( + PolicyNvWritten_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM_CC commandCode = TPM_CC_PolicyNvWritten; + HASH_STATE hashState; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // If already set is this a duplicate (the same setting)? If it + // is a conflicting setting, it is an error + if(session->attributes.checkNvWritten == SET) + { + if(((session->attributes.nvWrittenState == SET) + != (in->writtenSet == YES))) + return TPM_RCS_VALUE + RC_PolicyNvWritten_writtenSet; + } + // Internal Data Update + // Set session attributes so that the NV Index needs to be checked + session->attributes.checkNvWritten = SET; + session->attributes.nvWrittenState = (in->writtenSet == YES); + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNvWritten + // || writtenSet) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add the byte of writtenState + CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->writtenSet); + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyNvWritten +#include "Tpm.h" +#include "PolicyTemplate_fp.h" +#if CC_PolicyTemplate // Conditional expansion of this file +TPM_RC +TPM2_PolicyTemplate( + PolicyTemplate_In *in // IN: input parameter list + ) +{ + SESSION *session; + TPM_CC commandCode = TPM_CC_PolicyTemplate; + HASH_STATE hashState; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // If the template is set, make sure that it is the same as the input value + if(session->attributes.isTemplateSet) + { + if(!MemoryEqual2B(&in->templateHash.b, &session->u1.cpHash.b)) + return TPM_RCS_VALUE + RC_PolicyTemplate_templateHash; + } + // error if cpHash contains something that is not a template + else if(session->u1.templateHash.t.size != 0) + return TPM_RC_CPHASH; + // A valid templateHash must have the same size as session hash digest + if(in->templateHash.t.size != CryptHashGetDigestSize(session->authHashAlg)) + return TPM_RCS_SIZE + RC_PolicyTemplate_templateHash; + // Internal Data Update + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash + // || cpHashA.buffer) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + // add cpHashA + CryptDigestUpdate2B(&hashState, &in->templateHash.b); + // complete the digest and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // update cpHash in session context + session->u1.templateHash = in->templateHash; + session->attributes.isTemplateSet = SET; + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyTemplateHash +#include "Tpm.h" +#if CC_PolicyAuthorizeNV // Conditional expansion of this file +#include "PolicyAuthorizeNV_fp.h" +#include "Policy_spt_fp.h" +TPM_RC +TPM2_PolicyAuthorizeNV( + PolicyAuthorizeNV_In *in + ) +{ + SESSION *session; + TPM_RC result; + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPM2B_NAME name; + TPMT_HA policyInNv; + BYTE nvTemp[sizeof(TPMT_HA)]; + BYTE *buffer = nvTemp; + INT32 size; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + // Skip checks if this is a trial policy + if(!session->attributes.isTrialPolicy) + { + // Check the authorizations for reading + // Common read access checks. NvReadAccessChecks() returns + // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED + // error may be returned at this point + result = NvReadAccessChecks(in->authHandle, in->nvIndex, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // Read the contents of the index into a temp buffer + size = MIN(nvIndex->publicArea.dataSize, sizeof(TPMT_HA)); + NvGetIndexData(nvIndex, locator, 0, (UINT16)size, nvTemp); + // Unmarshal the contents of the buffer into the internal format of a + // TPMT_HA so that the hash and digest elements can be accessed from the + // structure rather than the byte array that is in the Index (written by + // user of the Index). + result = TPMT_HA_Unmarshal(&policyInNv, &buffer, &size, FALSE); + if(result != TPM_RC_SUCCESS) + return result; + // Verify that the hash is the same + if(policyInNv.hashAlg != session->authHashAlg) + return TPM_RC_HASH; + // See if the contents of the digest in the Index matches the value + // in the policy + if(!MemoryEqual(&policyInNv.digest, &session->u2.policyDigest.t.buffer, + session->u2.policyDigest.t.size)) + return TPM_RC_VALUE; + } + // Internal Data Update + // Set policyDigest to zero digest + PolicyDigestClear(session); + // Update policyDigest + PolicyContextUpdate(TPM_CC_PolicyAuthorizeNV, EntityGetName(in->nvIndex, &name), + NULL, NULL, 0, session); + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyAuthorizeNV diff --git a/src/tpm2/ECC_Parameters_fp.h b/src/tpm2/ECC_Parameters_fp.h new file mode 100644 index 0000000..75f9cdf --- /dev/null +++ b/src/tpm2/ECC_Parameters_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ECC_Parameters_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef ECC_PARAMETERS_FP_H +#define ECC_PARAMETERS_FP_H + +typedef struct { + TPMI_ECC_CURVE curveID; +} ECC_Parameters_In; + +#define RC_ECC_Parameters_curveID (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPMS_ALGORITHM_DETAIL_ECC parameters; +} ECC_Parameters_Out; + +TPM_RC +TPM2_ECC_Parameters( + ECC_Parameters_In *in, // IN: input parameter list + ECC_Parameters_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/ECDH_KeyGen_fp.h b/src/tpm2/ECDH_KeyGen_fp.h new file mode 100644 index 0000000..85f16f5 --- /dev/null +++ b/src/tpm2/ECDH_KeyGen_fp.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ECDH_KeyGen_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef ECDH_KEYGEN_FP_H +#define ECDH_KEYGEN_FP_H + +typedef struct { + TPMI_DH_OBJECT keyHandle; +} ECDH_KeyGen_In; + +#define RC_ECDH_KeyGen_keyHandle (TPM_RC_H + TPM_RC_1) + +typedef struct { + TPM2B_ECC_POINT zPoint; + TPM2B_ECC_POINT pubPoint; +} ECDH_KeyGen_Out; + +TPM_RC +TPM2_ECDH_KeyGen( + ECDH_KeyGen_In *in, // IN: input parameter list + ECDH_KeyGen_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/ECDH_ZGen_fp.h b/src/tpm2/ECDH_ZGen_fp.h new file mode 100644 index 0000000..5cc5b71 --- /dev/null +++ b/src/tpm2/ECDH_ZGen_fp.h @@ -0,0 +1,86 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ECDH_ZGen_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef ECDH_ZGEN_FP_H +#define ECDH_ZGEN_FP_H + +typedef struct { + TPMI_DH_OBJECT keyHandle; + TPM2B_ECC_POINT inPoint; +} ECDH_ZGen_In; + +#define RC_ECDH_ZGen_keyHandle (TPM_RC_H + TPM_RC_1) +#define RC_ECDH_ZGen_inPoint (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPM2B_ECC_POINT outPoint; +} ECDH_ZGen_Out; + +TPM_RC +TPM2_ECDH_ZGen( + ECDH_ZGen_In *in, // IN: input parameter list + ECDH_ZGen_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/EC_Ephemeral_fp.h b/src/tpm2/EC_Ephemeral_fp.h new file mode 100644 index 0000000..c004767 --- /dev/null +++ b/src/tpm2/EC_Ephemeral_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EC_Ephemeral_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef EC_EPHEMERAL_FP_H +#define EC_EPHEMERAL_FP_H + +typedef struct { + TPMI_ECC_CURVE curveID; +} EC_Ephemeral_In; + +#define RC_EC_Ephemeral_curveID (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPM2B_ECC_POINT Q; + UINT16 counter; +} EC_Ephemeral_Out; + +TPM_RC +TPM2_EC_Ephemeral( + EC_Ephemeral_In *in, // IN: input parameter list + EC_Ephemeral_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/EccTestData.h b/src/tpm2/EccTestData.h new file mode 100644 index 0000000..44ebaca --- /dev/null +++ b/src/tpm2/EccTestData.h @@ -0,0 +1,155 @@ +/********************************************************************************/ +/* */ +/* Parameter data for ECC testing */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EccTestData.h 1259 2018-07-10 19:11:09Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#ifdef SELF_TEST_DATA +TPM2B_TYPE(EC_TEST, 32); +const TPM_ECC_CURVE c_testCurve = 00003; +// The static key +const TPM2B_EC_TEST c_ecTestKey_ds = {{32, { + 0xdf,0x8d,0xa4,0xa3,0x88,0xf6,0x76,0x96,0x89,0xfc,0x2f,0x2d,0xa1,0xb4,0x39,0x7a, + 0x78,0xc4,0x7f,0x71,0x8c,0xa6,0x91,0x85,0xc0,0xbf,0xf3,0x54,0x20,0x91,0x2f,0x73}}}; +const TPM2B_EC_TEST c_ecTestKey_QsX = {{32, { + 0x17,0xad,0x2f,0xcb,0x18,0xd4,0xdb,0x3f,0x2c,0x53,0x13,0x82,0x42,0x97,0xff,0x8d, + 0x99,0x50,0x16,0x02,0x35,0xa7,0x06,0xae,0x1f,0xda,0xe2,0x9c,0x12,0x77,0xc0,0xf9}}}; +const TPM2B_EC_TEST c_ecTestKey_QsY = {{32, { + 0xa6,0xca,0xf2,0x18,0x45,0x96,0x6e,0x58,0xe6,0x72,0x34,0x12,0x89,0xcd,0xaa,0xad, + 0xcb,0x68,0xb2,0x51,0xdc,0x5e,0xd1,0x6d,0x38,0x20,0x35,0x57,0xb2,0xfd,0xc7,0x52}}}; +// The ephemeral key +const TPM2B_EC_TEST c_ecTestKey_de = {{32, { + 0xb6,0xb5,0x33,0x5c,0xd1,0xee,0x52,0x07,0x99,0xea,0x2e,0x8f,0x8b,0x19,0x18,0x07, + 0xc1,0xf8,0xdf,0xdd,0xb8,0x77,0x00,0xc7,0xd6,0x53,0x21,0xed,0x02,0x53,0xee,0xac}}}; +const TPM2B_EC_TEST c_ecTestKey_QeX = {{32, { + 0xa5,0x1e,0x80,0xd1,0x76,0x3e,0x8b,0x96,0xce,0xcc,0x21,0x82,0xc9,0xa2,0xa2,0xed, + 0x47,0x21,0x89,0x53,0x44,0xe9,0xc7,0x92,0xe7,0x31,0x48,0x38,0xe6,0xea,0x93,0x47}}}; +const TPM2B_EC_TEST c_ecTestKey_QeY = {{32, { + 0x30,0xe6,0x4f,0x97,0x03,0xa1,0xcb,0x3b,0x32,0x2a,0x70,0x39,0x94,0xeb,0x4e,0xea, + 0x55,0x88,0x81,0x3f,0xb5,0x00,0xb8,0x54,0x25,0xab,0xd4,0xda,0xfd,0x53,0x7a,0x18}}}; +// ECDH test results +const TPM2B_EC_TEST c_ecTestEcdh_X = {{32, { + 0x64,0x02,0x68,0x92,0x78,0xdb,0x33,0x52,0xed,0x3b,0xfa,0x3b,0x74,0xa3,0x3d,0x2c, + 0x2f,0x9c,0x59,0x03,0x07,0xf8,0x22,0x90,0xed,0xe3,0x45,0xf8,0x2a,0x0a,0xd8,0x1d}}}; +const TPM2B_EC_TEST c_ecTestEcdh_Y = {{32, { + 0x58,0x94,0x05,0x82,0xbe,0x5f,0x33,0x02,0x25,0x90,0x3a,0x33,0x90,0x89,0xe3,0xe5, + 0x10,0x4a,0xbc,0x78,0xa5,0xc5,0x07,0x64,0xaf,0x91,0xbc,0xe6,0xff,0x85,0x11,0x40}}}; +TPM2B_TYPE(TEST_VALUE, 64); +const TPM2B_TEST_VALUE c_ecTestValue = {{64, { + 0x78,0xd5,0xd4,0x56,0x43,0x61,0xdb,0x97,0xa4,0x32,0xc4,0x0b,0x06,0xa9,0xa8,0xa0, + 0xf4,0x45,0x7f,0x13,0xd8,0x13,0x81,0x0b,0xe5,0x76,0xbe,0xaa,0xb6,0x3f,0x8d,0x4d, + 0x23,0x65,0xcc,0xa7,0xc9,0x19,0x10,0xce,0x69,0xcb,0x0c,0xc7,0x11,0x8d,0xc3,0xff, + 0x62,0x69,0xa2,0xbe,0x46,0x90,0xe7,0x7d,0x81,0x77,0x94,0x65,0x1c,0x3e,0xc1,0x3e}}}; +#if ALG_SHA1_VALUE == DEFAULT_TEST_HASH +const TPM2B_EC_TEST c_TestEcDsa_r = {{32, { + 0x57,0xf3,0x36,0xb7,0xec,0xc2,0xdd,0x76,0x0e,0xe2,0x81,0x21,0x49,0xc5,0x66,0x11, + 0x4b,0x8a,0x4f,0x17,0x62,0x82,0xcc,0x06,0xf6,0x64,0x78,0xef,0x6b,0x7c,0xf2,0x6c}}}; +const TPM2B_EC_TEST c_TestEcDsa_s = {{32, { + 0x1b,0xed,0x23,0x72,0x8f,0x17,0x5f,0x47,0x2e,0xa7,0x97,0x2c,0x51,0x57,0x20,0x70, + 0x6f,0x89,0x74,0x8a,0xa8,0xf4,0x26,0xf4,0x96,0xa1,0xb8,0x3e,0xe5,0x35,0xc5,0x94}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_r = {{32,{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x08,0x9f,0xde, + 0xef,0x62,0xe3,0xf1,0x14,0xcb,0x54,0x28,0x13,0x76,0xfc,0x6d,0x69,0x22,0xb5,0x3e}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_s = {{32,{ + 0xd9,0xd3,0x20,0xfb,0x4d,0x16,0xf2,0xe6,0xe2,0x45,0x07,0x45,0x1c,0x92,0x92,0x92, + 0xa9,0x6b,0x48,0xf8,0xd1,0x98,0x29,0x4d,0xd3,0x8f,0x56,0xf2,0xbb,0x2e,0x22,0x3b}}}; +#endif // SHA1 +#if ALG_SHA256_VALUE == DEFAULT_TEST_HASH +const TPM2B_EC_TEST c_TestEcDsa_r = {{32, { + 0x04,0x7d,0x54,0xeb,0x04,0x6f,0x56,0xec,0xa2,0x6c,0x38,0x8c,0xeb,0x43,0x0b,0x71, + 0xf8,0xf2,0xf4,0xa5,0xe0,0x1d,0x3c,0xa2,0x39,0x31,0xe4,0xe7,0x36,0x3b,0xb5,0x5f}}}; +const TPM2B_EC_TEST c_TestEcDsa_s = {{32, { + 0x8f,0xd0,0x12,0xd9,0x24,0x75,0xf6,0xc4,0x3b,0xb5,0x46,0x75,0x3a,0x41,0x8d,0x80, + 0x23,0x99,0x38,0xd7,0xe2,0x40,0xca,0x9a,0x19,0x2a,0xfc,0x54,0x75,0xd3,0x4a,0x6e}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_r = {{32, { + 0xf7,0xb9,0x15,0x4c,0x34,0xf6,0x41,0x19,0xa3,0xd2,0xf1,0xbd,0xf4,0x13,0x6a,0x4f, + 0x63,0xb8,0x4d,0xb5,0xc8,0xcd,0xde,0x85,0x95,0xa5,0x39,0x0a,0x14,0x49,0x3d,0x2f}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_s = {{32,{ + 0xfe,0xbe,0x17,0xaa,0x31,0x22,0x9f,0xd0,0xd2,0xf5,0x25,0x04,0x92,0xb0,0xaa,0x4e, + 0xcc,0x1c,0xb6,0x79,0xd6,0x42,0xb3,0x4e,0x3f,0xbb,0xfe,0x5f,0xd0,0xd0,0x8b,0xc3}}}; +#endif // SHA256 +#if ALG_SHA384_VALUE == DEFAULT_TEST_HASH +const TPM2B_EC_TEST c_TestEcDsa_r = {{32, { + 0xf5,0x74,0x6d,0xd6,0xc6,0x56,0x86,0xbb,0xba,0x1c,0xba,0x75,0x65,0xee,0x64,0x31, + 0xce,0x04,0xe3,0x9f,0x24,0x3f,0xbd,0xfe,0x04,0xcd,0xab,0x7e,0xfe,0xad,0xcb,0x82}}}; +const TPM2B_EC_TEST c_TestEcDsa_s = {{32, { + 0xc2,0x4f,0x32,0xa1,0x06,0xc0,0x85,0x4f,0xc6,0xd8,0x31,0x66,0x91,0x9f,0x79,0xcd, + 0x5b,0xe5,0x7b,0x94,0xa1,0x91,0x38,0xac,0xd4,0x20,0xa2,0x10,0xf0,0xd5,0x9d,0xbf}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_r = {{32, { + 0x1e,0xb8,0xe1,0xbf,0xa1,0x9e,0x39,0x1e,0x58,0xa2,0xe6,0x59,0xd0,0x1a,0x6a,0x03, + 0x6a,0x1f,0x1c,0x4f,0x36,0x19,0xc1,0xec,0x30,0xa4,0x85,0x1b,0xe9,0x74,0x35,0x66}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_s = {{32,{ + 0xb9,0xe6,0xe3,0x7e,0xcb,0xb9,0xea,0xf1,0xcc,0xf4,0x48,0x44,0x4a,0xda,0xc8,0xd7, + 0x87,0xb4,0xba,0x40,0xfe,0x5b,0x68,0x11,0x14,0xcf,0xa0,0x0e,0x85,0x46,0x99,0x01}}}; +#endif // SHA384 +#if ALG_SHA512_VALUE == DEFAULT_TEST_HASH +const TPM2B_EC_TEST c_TestEcDsa_r = {{32, { + 0xc9,0x71,0xa6,0xb4,0xaf,0x46,0x26,0x8c,0x27,0x00,0x06,0x3b,0x00,0x0f,0xa3,0x17, + 0x72,0x48,0x40,0x49,0x4d,0x51,0x4f,0xa4,0xcb,0x7e,0x86,0xe9,0xe7,0xb4,0x79,0xb2}}}; +const TPM2B_EC_TEST c_TestEcDsa_s = {{32,{ + 0x87,0xbc,0xc0,0xed,0x74,0x60,0x9e,0xfa,0x4e,0xe8,0x16,0xf3,0xf9,0x6b,0x26,0x07, + 0x3c,0x74,0x31,0x7e,0xf0,0x62,0x46,0xdc,0xd6,0x45,0x22,0x47,0x3e,0x0c,0xa0,0x02}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_r = {{32,{ + 0xcc,0x07,0xad,0x65,0x91,0xdd,0xa0,0x10,0x23,0xae,0x53,0xec,0xdf,0xf1,0x50,0x90, + 0x16,0x96,0xf4,0x45,0x09,0x73,0x9c,0x84,0xb5,0x5c,0x5f,0x08,0x51,0xcb,0x60,0x01}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_s = {{32,{ + 0x55,0x20,0x21,0x54,0xe2,0x49,0x07,0x47,0x71,0xf4,0x99,0x15,0x54,0xf3,0xab,0x14, + 0xdb,0x8e,0xda,0x79,0xb6,0x02,0x0e,0xe3,0x5e,0x6f,0x2c,0xb6,0x05,0xbd,0x14,0x10}}}; +#endif // SHA512 +#endif // SELF_TEST_DATA + diff --git a/src/tpm2/EncryptDecrypt2_fp.h b/src/tpm2/EncryptDecrypt2_fp.h new file mode 100644 index 0000000..7696465 --- /dev/null +++ b/src/tpm2/EncryptDecrypt2_fp.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EncryptDecrypt2_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015, 2016 */ +/* */ +/********************************************************************************/ + +/* rev 146 */ + +#ifndef ENCRYPTDECRYPT2_FP_H +#define ENCRYPTDECRYPT2_FP_H + +typedef struct { + TPMI_DH_OBJECT keyHandle; + TPM2B_MAX_BUFFER inData; + TPMI_YES_NO decrypt; + TPMI_ALG_CIPHER_MODE mode; + TPM2B_IV ivIn; +} EncryptDecrypt2_In; + +#define RC_EncryptDecrypt2_keyHandle (TPM_RC_H + TPM_RC_1) +#define RC_EncryptDecrypt2_inData (TPM_RC_P + TPM_RC_1) +#define RC_EncryptDecrypt2_decrypt (TPM_RC_P + TPM_RC_2) +#define RC_EncryptDecrypt2_mode (TPM_RC_P + TPM_RC_3) +#define RC_EncryptDecrypt2_ivIn (TPM_RC_P + TPM_RC_4) + +typedef struct { + TPM2B_MAX_BUFFER outData; + TPM2B_IV ivOut; +} EncryptDecrypt2_Out; + +TPM_RC +TPM2_EncryptDecrypt2( + EncryptDecrypt2_In *in, // IN: input parameter list + EncryptDecrypt2_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/EncryptDecrypt_fp.h b/src/tpm2/EncryptDecrypt_fp.h new file mode 100644 index 0000000..814acce --- /dev/null +++ b/src/tpm2/EncryptDecrypt_fp.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EncryptDecrypt_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef ENCRYPTDECRYPT_FP_H +#define ENCRYPTDECRYPT_FP_H + +typedef struct { + TPMI_DH_OBJECT keyHandle; + TPMI_YES_NO decrypt; + TPMI_ALG_CIPHER_MODE mode; + TPM2B_IV ivIn; + TPM2B_MAX_BUFFER inData; +} EncryptDecrypt_In; + +#define RC_EncryptDecrypt_keyHandle (TPM_RC_H + TPM_RC_1) +#define RC_EncryptDecrypt_decrypt (TPM_RC_P + TPM_RC_1) +#define RC_EncryptDecrypt_mode (TPM_RC_P + TPM_RC_2) +#define RC_EncryptDecrypt_ivIn (TPM_RC_P + TPM_RC_3) +#define RC_EncryptDecrypt_inData (TPM_RC_P + TPM_RC_4) + +typedef struct { + TPM2B_MAX_BUFFER outData; + TPM2B_IV ivOut; +} EncryptDecrypt_Out; + +TPM_RC +TPM2_EncryptDecrypt( + EncryptDecrypt_In *in, // IN: input parameter list + EncryptDecrypt_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/EncryptDecrypt_spt.c b/src/tpm2/EncryptDecrypt_spt.c new file mode 100644 index 0000000..13e8cca --- /dev/null +++ b/src/tpm2/EncryptDecrypt_spt.c @@ -0,0 +1,166 @@ +/********************************************************************************/ +/* */ +/* Encrypt Decrypt Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EncryptDecrypt_spt.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 7.7 Encrypt Decrypt Support (EncryptDecrypt_spt.c) */ +#include "Tpm.h" +#include "EncryptDecrypt_fp.h" +#include "EncryptDecrypt_spt_fp.h" +#if CC_EncryptDecrypt2 +/* Error Returns Meaning */ +/* TPM_RC_KEY is not a symmetric decryption key with both public and private portions loaded */ +/* TPM_RC_SIZE IvIn size is incompatible with the block cipher mode; or inData size is not an even + multiple of the block size for CBC or ECB mode */ +/* TPM_RC_VALUE keyHandle is restricted and the argument mode does not match the key's mode */ +TPM_RC +EncryptDecryptShared( + TPMI_DH_OBJECT keyHandleIn, + TPMI_YES_NO decryptIn, + TPMI_ALG_SYM_MODE modeIn, + TPM2B_IV *ivIn, + TPM2B_MAX_BUFFER *inData, + EncryptDecrypt_Out *out + ) +{ + OBJECT *symKey; + UINT16 keySize; + UINT16 blockSize; + BYTE *key; + TPM_ALG_ID alg; + TPM_ALG_ID mode; + TPM_RC result; + BOOL OK; + // Input Validation + symKey = HandleToObject(keyHandleIn); + mode = symKey->publicArea.parameters.symDetail.sym.mode.sym; + // The input key should be a symmetric key + if(symKey->publicArea.type != TPM_ALG_SYMCIPHER) + return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; + // The key must be unrestricted and allow the selected operation + OK = !IS_ATTRIBUTE(symKey->publicArea.objectAttributes, + TPMA_OBJECT, restricted); + if(YES == decryptIn) + OK = OK && IS_ATTRIBUTE(symKey->publicArea.objectAttributes, + TPMA_OBJECT, decrypt); + else + OK = OK && IS_ATTRIBUTE(symKey->publicArea.objectAttributes, + TPMA_OBJECT, sign); + if(!OK) + return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle; + // Make sure that key is an encrypt/decrypt key and not SMAC + if(!CryptSymModeIsValid(mode, TRUE)) + return TPM_RCS_MODE + RC_EncryptDecrypt_keyHandle; + // If the key mode is not TPM_ALG_NULL... + // or TPM_ALG_NULL + if(mode != TPM_ALG_NULL) + { + // then the input mode has to be TPM_ALG_NULL or the same as the key + if((modeIn != TPM_ALG_NULL) && (modeIn != mode)) + return TPM_RCS_MODE + RC_EncryptDecrypt_mode; + } + else + { + // if the key mode is null, then the input can't be null + if(modeIn == TPM_ALG_NULL) + return TPM_RCS_MODE + RC_EncryptDecrypt_mode; + mode = modeIn; + } + // The input iv for ECB mode should be an Empty Buffer. All the other modes + // should have an iv size same as encryption block size + keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym; + alg = symKey->publicArea.parameters.symDetail.sym.algorithm; + blockSize = CryptGetSymmetricBlockSize(alg, keySize); + // reverify the algorithm. This is mainly to keep static analysis tools happy + if(blockSize == 0) + return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; + if(((mode == TPM_ALG_ECB) && (ivIn->t.size != 0)) + || ((mode != TPM_ALG_ECB) && (ivIn->t.size != blockSize))) + return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn; + // The input data size of CBC mode or ECB mode must be an even multiple of + // the symmetric algorithm's block size + if(((mode == TPM_ALG_CBC) || (mode == TPM_ALG_ECB)) + && ((inData->t.size % blockSize) != 0)) + return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; + // Copy IV + // Note: This is copied here so that the calls to the encrypt/decrypt functions + // will modify the output buffer, not the input buffer + out->ivOut = *ivIn; + // Command Output + key = symKey->sensitive.sensitive.sym.t.buffer; + // For symmetric encryption, the cipher data size is the same as plain data + // size. + out->outData.t.size = inData->t.size; + if(decryptIn == YES) + { + // Decrypt data to output + result = CryptSymmetricDecrypt(out->outData.t.buffer, alg, keySize, key, + &(out->ivOut), mode, inData->t.size, + inData->t.buffer); + } + else + { + // Encrypt data to output + result = CryptSymmetricEncrypt(out->outData.t.buffer, alg, keySize, key, + &(out->ivOut), mode, inData->t.size, + inData->t.buffer); + } + return result; +} +#endif // CC_EncryptDecrypt diff --git a/src/tpm2/EncryptDecrypt_spt_fp.h b/src/tpm2/EncryptDecrypt_spt_fp.h new file mode 100644 index 0000000..563a435 --- /dev/null +++ b/src/tpm2/EncryptDecrypt_spt_fp.h @@ -0,0 +1,75 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EncryptDecrypt_spt_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef ENCRYPTDECRYPT_SPT_FP_H +#define ENCRYPTDECRYPT_SPT_FP_H + +TPM_RC +EncryptDecryptShared( + TPMI_DH_OBJECT keyHandleIn, + TPMI_YES_NO decryptIn, + TPMI_ALG_SYM_MODE modeIn, + TPM2B_IV *ivIn, + TPM2B_MAX_BUFFER *inData, + EncryptDecrypt_Out *out + ); + +#endif diff --git a/src/tpm2/Entity.c b/src/tpm2/Entity.c new file mode 100644 index 0000000..6940262 --- /dev/null +++ b/src/tpm2/Entity.c @@ -0,0 +1,507 @@ +/********************************************************************************/ +/* */ +/* Accessing properties for handles of various types */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Entity.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 9.4 Entity.c */ +/* 9.4.1 Description */ +/* The functions in this file are used for accessing properties for handles of various + types. Functions in other files require handles of a specific type but the functions in this file + allow use of any handle type. */ +/* 9.4.2 Includes */ +#include "Tpm.h" +/* 9.4.3 Functions */ +/* 9.4.3.1 EntityGetLoadStatus() */ +/* This function will check that all the handles access loaded entities. */ +/* Error Returns Meaning */ +/* TPM_RC_HANDLE handle type does not match */ +/* TPM_RC_REFERENCE_Hx() entity is not present */ +/* TPM_RC_HIERARCHY entity belongs to a disabled hierarchy */ +/* TPM_RC_OBJECT_MEMORY handle is an evict object but there is no space to load it to RAM */ +TPM_RC +EntityGetLoadStatus( + COMMAND *command // IN/OUT: command parsing structure + ) +{ + UINT32 i; + TPM_RC result = TPM_RC_SUCCESS; + // + for(i = 0; i < command->handleNum; i++) + { + TPM_HANDLE handle = command->handles[i]; + switch(HandleGetType(handle)) + { + // For handles associated with hierarchies, the entity is present + // only if the associated enable is SET. + case TPM_HT_PERMANENT: + switch(handle) + { + case TPM_RH_OWNER: + if(!gc.shEnable) + result = TPM_RC_HIERARCHY; + break; +#ifdef VENDOR_PERMANENT + case VENDOR_PERMANENT: +#endif + case TPM_RH_ENDORSEMENT: + if(!gc.ehEnable) + result = TPM_RC_HIERARCHY; + break; + case TPM_RH_PLATFORM: + if(!g_phEnable) + result = TPM_RC_HIERARCHY; + break; + // null handle, PW session handle and lockout + // handle are always available + case TPM_RH_NULL: + case TPM_RS_PW: + // Need to be careful for lockout. Lockout is always available + // for policy checks but not always available when authValue + // is being checked. + case TPM_RH_LOCKOUT: + // Rather than have #ifdefs all over the code, + // CASE_ACT_HANDLE is defined in ACT.h. It is 'case TPM_RH_ACT_x:' + // FOR_EACH_ACT(CASE_ACT_HANDLE) creates a simple + // case TPM_RH_ACT_x: // for each of the implemented ACT. + FOR_EACH_ACT(CASE_ACT_HANDLE) + break; + + default: + // If the implementation has a manufacturer-specific value + // then test for it here. Since this implementation does + // not have any, this implementation returns the same failure + // that unmarshaling of a bad handle would produce. + if(((TPM_RH)handle >= TPM_RH_AUTH_00) + && ((TPM_RH)handle <= TPM_RH_AUTH_FF)) + // if the implementation has a manufacturer-specific value + result = TPM_RC_VALUE; + else + // The handle is in the range of reserved handles but is + // not implemented in this TPM. + result = TPM_RC_VALUE; + break; + } + break; + case TPM_HT_TRANSIENT: + // For a transient object, check if the handle is associated + // with a loaded object. + if(!IsObjectPresent(handle)) + result = TPM_RC_REFERENCE_H0; + break; + case TPM_HT_PERSISTENT: + // Persistent object + // Copy the persistent object to RAM and replace the handle with the + // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY, + // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by + // ObjectLoadEvict() + result = ObjectLoadEvict(&command->handles[i], command->index); + break; + case TPM_HT_HMAC_SESSION: + // For an HMAC session, see if the session is loaded + // and if the session in the session slot is actually + // an HMAC session. + if(SessionIsLoaded(handle)) + { + SESSION *session; + session = SessionGet(handle); + // Check if the session is a HMAC session + if(session->attributes.isPolicy == SET) + result = TPM_RC_HANDLE; + } + else + result = TPM_RC_REFERENCE_H0; + break; + case TPM_HT_POLICY_SESSION: + // For a policy session, see if the session is loaded + // and if the session in the session slot is actually + // a policy session. + if(SessionIsLoaded(handle)) + { + SESSION *session; + session = SessionGet(handle); + // Check if the session is a policy session + if(session->attributes.isPolicy == CLEAR) + result = TPM_RC_HANDLE; + } + else + result = TPM_RC_REFERENCE_H0; + break; + case TPM_HT_NV_INDEX: + // For an NV Index, use the TPM-specific routine + // to search the IN Index space. + result = NvIndexIsAccessible(handle); + break; + case TPM_HT_PCR: + // Any PCR handle that is unmarshaled successfully referenced + // a PCR that is defined. + break; +#if CC_AC_Send + case TPM_HT_AC: + // Use the TPM-specific routine to search for the AC + result = AcIsAccessible(handle); + break; +#endif + default: + // Any other handle type is a defect in the unmarshaling code. + FAIL(FATAL_ERROR_INTERNAL); + break; + } + if(result != TPM_RC_SUCCESS) + { + if(result == TPM_RC_REFERENCE_H0) + result = result + i; + else + result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]); + break; + } + } + return result; +} +/* 9.4.3.2 EntityGetAuthValue() */ +/* This function is used to access the authValue associated with a handle. This function assumes + that the handle references an entity that is accessible and the handle is not for a persistent + objects. That is EntityGetLoadStatus() should have been called. Also, the accessibility of the + authValue should have been verified by IsAuthValueAvailable(). */ +/* This function copies the authorization value of the entity to auth. */ +/* Return Values Meaning */ +/* count number of bytes in the authValue with zeros stripped */ +UINT16 +EntityGetAuthValue( + TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_AUTH *auth // OUT: authValue of the entity + ) +{ + TPM2B_AUTH *pAuth = NULL; + auth->t.size = 0; + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + { + switch(handle) + { + case TPM_RH_OWNER: + // ownerAuth for TPM_RH_OWNER + pAuth = &gp.ownerAuth; + break; + case TPM_RH_ENDORSEMENT: + // endorsementAuth for TPM_RH_ENDORSEMENT + pAuth = &gp.endorsementAuth; + break; + // The ACT use platformAuth for auth + FOR_EACH_ACT(CASE_ACT_HANDLE) + case TPM_RH_PLATFORM: + // platformAuth for TPM_RH_PLATFORM + pAuth = &gc.platformAuth; + break; + case TPM_RH_LOCKOUT: + // lockoutAuth for TPM_RH_LOCKOUT + pAuth = &gp.lockoutAuth; + break; + case TPM_RH_NULL: + // nullAuth for TPM_RH_NULL. Return 0 directly here + return 0; + break; +#ifdef VENDOR_PERMANENT + case VENDOR_PERMANENT: + // vendor authorization value + pAuth = &g_platformUniqueDetails; +#endif + default: + // If any other permanent handle is present it is + // a code defect. + FAIL(FATAL_ERROR_INTERNAL); + break; + } + break; + } + case TPM_HT_TRANSIENT: + // authValue for an object + // A persistent object would have been copied into RAM + // and would have an transient object handle here. + { + OBJECT *object; + object = HandleToObject(handle); + // special handling if this is a sequence object + if(ObjectIsSequence(object)) + { + pAuth = &((HASH_OBJECT *)object)->auth; + } + else + { + // Authorization is available only when the private portion of + // the object is loaded. The check should be made before + // this function is called + pAssert(object->attributes.publicOnly == CLEAR); + pAuth = &object->sensitive.authValue; + } + } + break; + case TPM_HT_NV_INDEX: + // authValue for an NV index + { + NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); + pAssert(nvIndex != NULL); + pAuth = &nvIndex->authValue; + } + break; + case TPM_HT_PCR: + // authValue for PCR + pAuth = PCRGetAuthValue(handle); + break; + default: + // If any other handle type is present here, then there is a defect + // in the unmarshaling code. + FAIL(FATAL_ERROR_INTERNAL); + break; + } + // Copy the authValue + MemoryCopy2B((TPM2B *)auth, (TPM2B *)pAuth, sizeof(auth->t.buffer)); + MemoryRemoveTrailingZeros(auth); + return auth->t.size; +} +/* 9.4.3.3 EntityGetAuthPolicy() */ +/* This function is used to access the authPolicy associated with a handle. This function assumes + that the handle references an entity that is accessible and the handle is not for a persistent + objects. That is EntityGetLoadStatus() should have been called. Also, the accessibility of the + authPolicy should have been verified by IsAuthPolicyAvailable(). */ +/* This function copies the authorization policy of the entity to authPolicy. */ +/* The return value is the hash algorithm for the policy. */ +TPMI_ALG_HASH +EntityGetAuthPolicy( + TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity + ) +{ + TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; + authPolicy->t.size = 0; + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + switch(handle) + { + case TPM_RH_OWNER: + // ownerPolicy for TPM_RH_OWNER + *authPolicy = gp.ownerPolicy; + hashAlg = gp.ownerAlg; + break; + case TPM_RH_ENDORSEMENT: + // endorsementPolicy for TPM_RH_ENDORSEMENT + *authPolicy = gp.endorsementPolicy; + hashAlg = gp.endorsementAlg; + break; + case TPM_RH_PLATFORM: + // platformPolicy for TPM_RH_PLATFORM + *authPolicy = gc.platformPolicy; + hashAlg = gc.platformAlg; + break; + case TPM_RH_LOCKOUT: + // lockoutPolicy for TPM_RH_LOCKOUT + *authPolicy = gp.lockoutPolicy; + hashAlg = gp.lockoutAlg; + break; + +#define ACT_GET_POLICY(N) \ + case TPM_RH_ACT_##N: \ + *authPolicy = go.ACT_##N.authPolicy; \ + hashAlg = go.ACT_##N.hashAlg; \ + break; + // Get the policy for each implemented ACT + FOR_EACH_ACT(ACT_GET_POLICY) + default: + hashAlg = TPM_ALG_ERROR; + break; + } + break; + case TPM_HT_TRANSIENT: + // authPolicy for an object + { + OBJECT *object = HandleToObject(handle); + *authPolicy = object->publicArea.authPolicy; + hashAlg = object->publicArea.nameAlg; + } + break; + case TPM_HT_NV_INDEX: + // authPolicy for a NV index + { + NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); + pAssert(nvIndex != 0); + *authPolicy = nvIndex->publicArea.authPolicy; + hashAlg = nvIndex->publicArea.nameAlg; + } + break; + case TPM_HT_PCR: + // authPolicy for a PCR + hashAlg = PCRGetAuthPolicy(handle, authPolicy); + break; + default: + // If any other handle type is present it is a code defect. + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return hashAlg; +} +/* 9.4.3.4 EntityGetName() */ +/* This function returns the Name associated with a handle. */ +TPM2B_NAME * +EntityGetName( + TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_NAME *name // OUT: name of entity + ) +{ + switch(HandleGetType(handle)) + { + case TPM_HT_TRANSIENT: + { + // Name for an object + OBJECT *object = HandleToObject(handle); + // an object with no nameAlg has no name + if(object->publicArea.nameAlg == TPM_ALG_NULL) + name->b.size = 0; + else + *name = object->name; + break; + } + case TPM_HT_NV_INDEX: + // Name for a NV index + NvGetNameByIndexHandle(handle, name); + break; + default: + // For all other types, the handle is the Name + name->t.size = sizeof(TPM_HANDLE); + UINT32_TO_BYTE_ARRAY(handle, name->t.name); + break; + } + return name; +} +/* 9.4.3.5 EntityGetHierarchy() */ +/* This function returns the hierarchy handle associated with an entity. */ +/* a) A handle that is a hierarchy handle is associated with itself. */ +/* b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET, otherwise it belongs + to TPM_RH_OWNER */ +/* c) An object handle belongs to its hierarchy. All other handles belong to the platform + hierarchy. or an NV Index. */ +TPMI_RH_HIERARCHY +EntityGetHierarchy( + TPMI_DH_ENTITY handle // IN :handle of entity + ) +{ + TPMI_RH_HIERARCHY hierarchy = TPM_RH_NULL; + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + // hierarchy for a permanent handle + switch(handle) + { + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + case TPM_RH_NULL: + hierarchy = handle; + break; + // all other permanent handles are associated with the owner + // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT) + default: + hierarchy = TPM_RH_OWNER; + break; + } + break; + case TPM_HT_NV_INDEX: + // hierarchy for NV index + { + NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); + pAssert(nvIndex != NULL); + // If only the platform can delete the index, then it is + // considered to be in the platform hierarchy, otherwise it + // is in the owner hierarchy. + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, + PLATFORMCREATE)) + hierarchy = TPM_RH_PLATFORM; + else + hierarchy = TPM_RH_OWNER; + } + break; + case TPM_HT_TRANSIENT: + // hierarchy for an object + { + OBJECT *object; + object = HandleToObject(handle); + if(object->attributes.ppsHierarchy) + { + hierarchy = TPM_RH_PLATFORM; + } + else if(object->attributes.epsHierarchy) + { + hierarchy = TPM_RH_ENDORSEMENT; + } + else if(object->attributes.spsHierarchy) + { + hierarchy = TPM_RH_OWNER; + } + } + break; + case TPM_HT_PCR: + hierarchy = TPM_RH_OWNER; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + // this is unreachable but it provides a return value for the default + // case which makes the compiler happy + return hierarchy; +} diff --git a/src/tpm2/Entity_fp.h b/src/tpm2/Entity_fp.h new file mode 100644 index 0000000..fd94a87 --- /dev/null +++ b/src/tpm2/Entity_fp.h @@ -0,0 +1,90 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Entity_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef ENTITY_FP_H +#define ENTITY_FP_H + +TPM_RC +EntityGetLoadStatus( + COMMAND *command // IN/OUT: command parsing structure + ); +UINT16 +EntityGetAuthValue( + TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_AUTH *auth // OUT: authValue of the entity + ); +TPMI_ALG_HASH +EntityGetAuthPolicy( + TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity + ); +TPM2B_NAME * +EntityGetName( + TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_NAME *name // OUT: name of entity + ); +TPMI_RH_HIERARCHY +EntityGetHierarchy( + TPMI_DH_ENTITY handle // IN :handle of entity + ); + + +#endif diff --git a/src/tpm2/Entropy.c b/src/tpm2/Entropy.c new file mode 100644 index 0000000..2c2cc18 --- /dev/null +++ b/src/tpm2/Entropy.c @@ -0,0 +1,184 @@ +/********************************************************************************/ +/* */ +/* Entropy */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Entropy.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* C.4 Entropy.c */ +/* C.4.1. Includes and Local values*/ +#define _CRT_RAND_S +#include +#include + +#include /* libtpms added */ + +#include +#include "Platform.h" +#ifdef _MSC_VER +#include +#else +#include +#endif + +/* This is the last 32-bits of hardware entropy produced. We have to check to see that two + consecutive 32-bit values are not the same because (according to FIPS 140-2, annex C */ +/* "If each call to a RNG produces blocks of n bits (where n > 15), the first n-bit block generated + after power-up, initialization, or reset shall not be used, but shall be saved for comparison + with the next n-bit block to be generated. Each subsequent generation of an n-bit block shall be + compared with the previously generated block. The test shall fail if any two compared n-bit + blocks are equal." */ +extern uint32_t lastEntropy; + +/* C.4.2. Functions */ +/* C.4.2.1. rand32() */ +/* Local function to get a 32-bit random number */ + +static uint32_t +rand32( + void + ) +{ + uint32_t rndNum = rand(); +#if RAND_MAX < UINT16_MAX + // If the maximum value of the random number is a 15-bit number, then shift it up + // 15 bits, get 15 more bits, shift that up 2 and then XOR in another value to get + // a full 32 bits. + rndNum = (rndNum << 15) ^ rand(); + rndNum = (rndNum << 2) ^ rand(); +#elif RAND_MAX == UINT16_MAX + // If the maximum size is 16-bits, shift it and add another 16 bits + rndNum = (rndNum << 16) ^ rand(); +#elif RAND_MAX < UINT32_MAX + // If 31 bits, then shift 1 and include another random value to get the extra bit + rndNum = (rndNum << 1) ^ rand(); +#endif + return rndNum; +} + +/* C.4.2.2 _plat__GetEntropy() */ +/* This function is used to get available hardware entropy. In a hardware implementation of this + function, there would be no call to the system to get entropy. */ +/* Return Values Meaning */ +/* < 0 hardware failure of the entropy generator, this is sticky */ +/* >= 0 the returned amount of entropy (bytes) */ +LIB_EXPORT int32_t +_plat__GetEntropy( + unsigned char *entropy, // output buffer + uint32_t amount // amount requested + ) +{ + uint32_t rndNum; + int32_t ret; + // + // libtpms added begin + if (amount > 0 && RAND_bytes(entropy, amount) == 1) + return amount; + // fall back to 'original' method + // libtpms added end + + if(amount == 0) + { + // Seed the platform entropy source if the entropy source is software. There is + // no reason to put a guard macro (#if or #ifdef) around this code because this + // code would not be here if someone was changing it for a system with actual + // hardware. + // + // NOTE 1: The following command does not provide proper cryptographic entropy. + // Its primary purpose to make sure that different instances of the simulator, + // possibly started by a script on the same machine, are seeded differently. + // Vendors of the actual TPMs need to ensure availability of proper entropy + // using their platform specific means. + // + // NOTE 2: In debug builds by default the reference implementation will seed + // its RNG deterministically (without using any platform provided randomness). + // See the USE_DEBUG_RNG macro and DRBG_GetEntropy() function. +#ifdef _MSC_VER + srand((unsigned)_plat__RealTime() ^ _getpid()); +#else + srand((unsigned)_plat__RealTime() ^ getpid()); +#endif + lastEntropy = rand32(); + ret = 0; + } + else + { + rndNum = rand32(); + if(rndNum == lastEntropy) + { + ret = -1; + } + else + { + lastEntropy = rndNum; + // Each process will have its random number generator initialized according + // to the process id and the initialization time. This is not a lot of + // entropy so, to add a bit more, XOR the current time value into the + // returned entropy value. + // NOTE: the reason for including the time here rather than have it in + // in the value assigned to lastEntropy is that rand() could be broken and + // using the time would in the lastEntropy value would hide this. + rndNum ^= (uint32_t)_plat__RealTime(); + // Only provide entropy 32 bits at a time to test the ability + // of the caller to deal with partial results. + ret = MIN(amount, sizeof(rndNum)); + memcpy(entropy, &rndNum, ret); + } + } + return ret; +} + diff --git a/src/tpm2/EphemeralCommands.c b/src/tpm2/EphemeralCommands.c new file mode 100644 index 0000000..0fe0b3a --- /dev/null +++ b/src/tpm2/EphemeralCommands.c @@ -0,0 +1,190 @@ +/********************************************************************************/ +/* */ +/* Ephemeral EC Keys */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EphemeralCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "Commit_fp.h" +#if CC_Commit // Conditional expansion of this file +TPM_RC +TPM2_Commit( + Commit_In *in, // IN: input parameter list + Commit_Out *out // OUT: output parameter list + ) +{ + OBJECT *eccKey; + TPMS_ECC_POINT P2; + TPMS_ECC_POINT *pP2 = NULL; + TPMS_ECC_POINT *pP1 = NULL; + TPM2B_ECC_PARAMETER r; + TPM2B_ECC_PARAMETER p; + TPM_RC result; + TPMS_ECC_PARMS *parms; + // Input Validation + eccKey = HandleToObject(in->signHandle); + parms = &eccKey->publicArea.parameters.eccDetail; + // Input key must be an ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_Commit_signHandle; + // This command may only be used with a sign-only key using an anonymous + // scheme. + // NOTE: a sign + decrypt key has no scheme so it will not be an anonymous one + // and an unrestricted sign key might no have a signing scheme but it can't + // be use in Commit() + if(!CryptIsSchemeAnonymous(parms->scheme.scheme)) + return TPM_RCS_SCHEME + RC_Commit_signHandle; + // Make sure that both parts of P2 are present if either is present + if((in->s2.t.size == 0) != (in->y2.t.size == 0)) + return TPM_RCS_SIZE + RC_Commit_y2; + // Get prime modulus for the curve. This is needed later but getting this now + // allows confirmation that the curve exists. + if(!CryptEccGetParameter(&p, 'p', parms->curveID)) + return TPM_RCS_KEY + RC_Commit_signHandle; + // Get the random value that will be used in the point multiplications + // Note: this does not commit the count. + if(!CryptGenerateR(&r, NULL, parms->curveID, &eccKey->name)) + return TPM_RC_NO_RESULT; + // Set up P2 if s2 and Y2 are provided + if(in->s2.t.size != 0) + { + TPM2B_DIGEST x2; + pP2 = &P2; + // copy y2 for P2 + P2.y = in->y2; + // Compute x2 HnameAlg(s2) mod p + // do the hash operation on s2 with the size of curve 'p' + x2.t.size = CryptHashBlock(eccKey->publicArea.nameAlg, + in->s2.t.size, + in->s2.t.buffer, + sizeof(x2.t.buffer), + x2.t.buffer); + // If there were error returns in the hash routine, indicate a problem + // with the hash algorithm selection + if(x2.t.size == 0) + return TPM_RCS_HASH + RC_Commit_signHandle; + // The size of the remainder will be same as the size of p. DivideB() will + // pad the results (leading zeros) if necessary to make the size the same + P2.x.t.size = p.t.size; + // set p2.x = hash(s2) mod p + if(DivideB(&x2.b, &p.b, NULL, &P2.x.b) != TPM_RC_SUCCESS) + return TPM_RC_NO_RESULT; + if(!CryptEccIsPointOnCurve(parms->curveID, pP2)) + return TPM_RCS_ECC_POINT + RC_Commit_s2; + if(eccKey->attributes.publicOnly == SET) + return TPM_RCS_KEY + RC_Commit_signHandle; + } + // If there is a P1, make sure that it is on the curve + // NOTE: an "empty" point has two UINT16 values which are the size values + // for each of the coordinates. + if(in->P1.size > 4) + { + pP1 = &in->P1.point; + if(!CryptEccIsPointOnCurve(parms->curveID, pP1)) + return TPM_RCS_ECC_POINT + RC_Commit_P1; + } + // Pass the parameters to CryptCommit. + // The work is not done in-line because it does several point multiplies + // with the same curve. It saves work by not having to reload the curve + // parameters multiple times. + result = CryptEccCommitCompute(&out->K.point, + &out->L.point, + &out->E.point, + parms->curveID, + pP1, + pP2, + &eccKey->sensitive.sensitive.ecc, + &r); + if(result != TPM_RC_SUCCESS) + return result; + // The commit computation was successful so complete the commit by setting + // the bit + out->counter = CryptCommit(); + return TPM_RC_SUCCESS; +} +#endif // CC_Commit +#include "Tpm.h" +#include "EC_Ephemeral_fp.h" +#if CC_EC_Ephemeral // Conditional expansion of this file +TPM_RC +TPM2_EC_Ephemeral( + EC_Ephemeral_In *in, // IN: input parameter list + EC_Ephemeral_Out *out // OUT: output parameter list + ) +{ + TPM2B_ECC_PARAMETER r; + TPM_RC result; + // + do + { + // Get the random value that will be used in the point multiplications + // Note: this does not commit the count. + if(!CryptGenerateR(&r, NULL, in->curveID, NULL)) + return TPM_RC_NO_RESULT; + // do a point multiply + result = CryptEccPointMultiply(&out->Q.point, in->curveID, NULL, &r, + NULL, NULL); + // commit the count value if either the r value results in the point at + // infinity or if the value is good. The commit on the r value for infinity + // is so that the r value will be skipped. + if((result == TPM_RC_SUCCESS) || (result == TPM_RC_NO_RESULT)) + out->counter = CryptCommit(); + } while(result == TPM_RC_NO_RESULT); + return TPM_RC_SUCCESS; +} +#endif // CC_EC_Ephemeral diff --git a/src/tpm2/EventSequenceComplete_fp.h b/src/tpm2/EventSequenceComplete_fp.h new file mode 100644 index 0000000..aa75a81 --- /dev/null +++ b/src/tpm2/EventSequenceComplete_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EventSequenceComplete_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef EVENTSEQUENCECOMPLETE_FP_H +#define EVENTSEQUENCECOMPLETE_FP_H + +typedef struct { + TPMI_DH_PCR pcrHandle; + TPMI_DH_OBJECT sequenceHandle; + TPM2B_MAX_BUFFER buffer; +} EventSequenceComplete_In; + +#define RC_EventSequenceComplete_pcrHandle (TPM_RC_H + TPM_RC_1) +#define RC_EventSequenceComplete_sequenceHandle (TPM_RC_H + TPM_RC_2) +#define RC_EventSequenceComplete_buffer (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPML_DIGEST_VALUES results; +} EventSequenceComplete_Out; + +TPM_RC +TPM2_EventSequenceComplete( + EventSequenceComplete_In *in, // IN: input parameter list + EventSequenceComplete_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/EvictControl_fp.h b/src/tpm2/EvictControl_fp.h new file mode 100644 index 0000000..0de7abb --- /dev/null +++ b/src/tpm2/EvictControl_fp.h @@ -0,0 +1,82 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: EvictControl_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef EVICTCONTROL_FP_H +#define EVICTCONTROL_FP_H + +typedef struct { + TPMI_RH_PROVISION auth; + TPMI_DH_OBJECT objectHandle; + TPMI_DH_PERSISTENT persistentHandle; +} EvictControl_In; + +#define RC_EvictControl_auth (TPM_RC_H + TPM_RC_1) +#define RC_EvictControl_objectHandle (TPM_RC_H + TPM_RC_2) +#define RC_EvictControl_persistentHandle (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_EvictControl( + EvictControl_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/ExecCommand.c b/src/tpm2/ExecCommand.c new file mode 100644 index 0000000..f21934b --- /dev/null +++ b/src/tpm2/ExecCommand.c @@ -0,0 +1,317 @@ +/********************************************************************************/ +/* */ +/* ExecCommand */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ExecCommand.c 1600 2020-03-30 22:08:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 6.2 ExecCommand.c */ +/* This file contains the entry function ExecuteCommand() which provides the main control flow for + TPM command execution. */ +#include "Tpm.h" +#include "ExecCommand_fp.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" // libtpms added + +/* Uncomment this next #include if doing static command/response buffer sizing */ +// #include "CommandResponseSizes_fp.h" +// The function performs the following steps. +// a) Parses the command header from input buffer. +// b) Calls ParseHandleBuffer() to parse the handle area of the command. +// c) Validates that each of the handles references a loaded entity. +// d) Calls ParseSessionBuffer() () to: +// 1) unmarshal and parse the session area; +// 2) check the authorizations; and +// 3) when necessary, decrypt a parameter. +// e) Calls CommandDispatcher() to: +// 1) unmarshal the command parameters from the command buffer; +// 2) call the routine that performs the command actions; and +// 3) marshal the responses into the response buffer. +// f) If any error occurs in any of the steps above create the error response and return. +// g) Calls BuildResponseSession() to: +// 1) when necessary, encrypt a parameter +// 2) build the response authorization sessions +// 3) update the audit sessions and nonces +// h) Calls BuildResponseHeader() to complete the construction of the response. + +// responseSize is set by the caller to the maximum number of bytes available in the output +// buffer. ExecuteCommand() will adjust the value and return the number of bytes placed in +// the buffer. +// response is also set by the caller to indicate the buffer into which ExecuteCommand() is +// to place the response. +// request and response may point to the same buffer +// NOTE: As of February, 2016, the failure processing has been moved to the platform-specific +// code. When the TPM code encounters an unrecoverable failure, it will SET g_inFailureMode +// and call _plat__Fail(). That function should not return but may call ExecuteCommand(). +LIB_EXPORT void +ExecuteCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + uint32_t *responseSize, // IN/OUT: response buffer size + unsigned char **response // IN/OUT: response buffer + ) +{ + // Command local variables + UINT32 commandSize; + COMMAND command; + // Response local variables + UINT32 maxResponse = *responseSize; + TPM_RC result; // return code for the command + // This next function call is used in development to size the command and response + // buffers. The values printed are the sizes of the internal structures and + // not the sizes of the canonical forms of he command response structures. Also, + // the sizes do not include the tag, command.code, requestSize, or the authorization + // fields. + //CommandResponseSizes(); + // Set flags for NV access state. This should happen before any other + // operation that may require a NV write. Note, that this needs to be done + // even when in failure mode. Otherwise, g_updateNV would stay SET while in + // Failure mode and the NV would be written on each call. + g_updateNV = UT_NONE; + g_clearOrderly = FALSE; + if(g_inFailureMode) + { + // Do failure mode processing + TpmFailureMode(requestSize, request, responseSize, response); + return; + } + // Query platform to get the NV state. The result state is saved internally + // and will be reported by NvIsAvailable(). The reference code requires that + // accessibility of NV does not change during the execution of a command. + // Specifically, if NV is available when the command execution starts and then + // is not available later when it is necessary to write to NV, then the TPM + // will go into failure mode. + NvCheckState(); + // Due to the limitations of the simulation, TPM clock must be explicitly + // synchronized with the system clock whenever a command is received. + // This function call is not necessary in a hardware TPM. However, taking + // a snapshot of the hardware timer at the beginning of the command allows + // the time value to be consistent for the duration of the command execution. + TimeUpdateToCurrent(); + // Any command through this function will unceremoniously end the + // _TPM_Hash_Data/_TPM_Hash_End sequence. + if(g_DRTMHandle != TPM_RH_UNASSIGNED) + ObjectTerminateEvent(); + // Get command buffer size and command buffer. + command.parameterBuffer = request; + command.parameterSize = requestSize; + // Parse command header: tag, commandSize and command.code. + // First parse the tag. The unmarshaling routine will validate + // that it is either TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS. + result = TPMI_ST_COMMAND_TAG_Unmarshal(&command.tag, + &command.parameterBuffer, + &command.parameterSize); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Unmarshal the commandSize indicator. + result = UINT32_Unmarshal(&commandSize, + &command.parameterBuffer, + &command.parameterSize); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // On a TPM that receives bytes on a port, the number of bytes that were + // received on that port is requestSize it must be identical to commandSize. + // In addition, commandSize must not be larger than MAX_COMMAND_SIZE allowed + // by the implementation. The check against MAX_COMMAND_SIZE may be redundant + // as the input processing (the function that receives the command bytes and + // places them in the input buffer) would likely have the input truncated when + // it reaches MAX_COMMAND_SIZE, and requestSize would not equal commandSize. + if(commandSize != requestSize || commandSize > MAX_COMMAND_SIZE) + { + result = TPM_RC_COMMAND_SIZE; + goto Cleanup; + } + // Unmarshal the command code. + result = TPM_CC_Unmarshal(&command.code, &command.parameterBuffer, + &command.parameterSize); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Check to see if the command is implemented. + command.index = CommandCodeToCommandIndex(command.code); + if(UNIMPLEMENTED_COMMAND_INDEX == command.index) + { + result = TPM_RC_COMMAND_CODE; + goto Cleanup; + } +#if FIELD_UPGRADE_IMPLEMENTED == YES + // If the TPM is in FUM, then the only allowed command is + // TPM_CC_FieldUpgradeData. + if(IsFieldUgradeMode() && (command.code != TPM_CC_FieldUpgradeData)) + { + result = TPM_RC_UPGRADE; + goto Cleanup; + } + else +#endif + // Excepting FUM, the TPM only accepts TPM2_Startup() after + // _TPM_Init. After getting a TPM2_Startup(), TPM2_Startup() + // is no longer allowed. + if((!TPMIsStarted() && command.code != TPM_CC_Startup) + || (TPMIsStarted() && command.code == TPM_CC_Startup)) + { + result = TPM_RC_INITIALIZE; + goto Cleanup; + } + // Start regular command process. + NvIndexCacheInit(); + // Parse Handle buffer. + result = ParseHandleBuffer(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // All handles in the handle area are required to reference TPM-resident + // entities. + result = EntityGetLoadStatus(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Authorization session handling for the command. + ClearCpRpHashes(&command); + if(command.tag == TPM_ST_SESSIONS) + { + // Find out session buffer size. + result = UINT32_Unmarshal((UINT32 *)&command.authSize, + &command.parameterBuffer, + &command.parameterSize); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Perform sanity check on the unmarshaled value. If it is smaller than + // the smallest possible session or larger than the remaining size of + // the command, then it is an error. NOTE: This check could pass but the + // session size could still be wrong. That will be determined after the + // sessions are unmarshaled. + if(command.authSize < 9 + || command.authSize > command.parameterSize) + { + result = TPM_RC_SIZE; + goto Cleanup; + } + command.parameterSize -= command.authSize; + // The actions of ParseSessionBuffer() are described in the introduction. + // As the sessions are parsed command.parameterBuffer is advanced so, on a + // successful return, command.parameterBuffer should be pointing at the + // first byte of the parameters. + result = ParseSessionBuffer(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + } + else + { + command.authSize = 0; + // The command has no authorization sessions. + // If the command requires authorizations, then CheckAuthNoSession() will + // return an error. + result = CheckAuthNoSession(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + } + // Set up the response buffer pointers. CommandDispatch will marshal the + // response parameters starting at the address in command.responseBuffer. + // *response = MemoryGetResponseBuffer(command.index); + // leave space for the command header + command.responseBuffer = *response + STD_RESPONSE_HEADER; + // leave space for the parameter size field if needed + if(command.tag == TPM_ST_SESSIONS) + command.responseBuffer += sizeof(UINT32); + if(IsHandleInResponse(command.index)) + command.responseBuffer += sizeof(TPM_HANDLE); + // CommandDispatcher returns a response handle buffer and a response parameter + // buffer if it succeeds. It will also set the parameterSize field in the + // buffer if the tag is TPM_RC_SESSIONS. + result = CommandDispatcher(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Build the session area at the end of the parameter area. + BuildResponseSession(&command); + Cleanup: + if(g_clearOrderly == TRUE + && NV_IS_ORDERLY) + { +#if USE_DA_USED + gp.orderlyState = g_daUsed ? SU_DA_USED_VALUE : SU_NONE_VALUE; +#else + gp.orderlyState = SU_NONE_VALUE; +#endif + NV_SYNC_PERSISTENT(orderlyState); + } + // This implementation loads an "evict" object to a transient object slot in + // RAM whenever an "evict" object handle is used in a command so that the + // access to any object is the same. These temporary objects need to be + // cleared from RAM whether the command succeeds or fails. + ObjectCleanupEvict(); + // The parameters and sessions have been marshaled. Now tack on the header and + // set the sizes + BuildResponseHeader(&command, *response, result); + // Try to commit all the writes to NV if any NV write happened during this + // command execution. This check should be made for both succeeded and failed + // commands, because a failed one may trigger a NV write in DA logic as well. + // This is the only place in the command execution path that may call the NV + // commit. If the NV commit fails, the TPM should be put in failure mode. + if((g_updateNV != UT_NONE) && !g_inFailureMode) + { + if(g_updateNV == UT_ORDERLY) + NvUpdateIndexOrderlyData(); + if(!NvCommit()) + FAIL(FATAL_ERROR_INTERNAL); + g_updateNV = UT_NONE; + } + pAssert((UINT32)command.parameterSize <= maxResponse); + // Clear unused bits in response buffer. + MemorySet(*response + *responseSize, 0, maxResponse - *responseSize); + // as a final act, and not before, update the response size. + *responseSize = (UINT32)command.parameterSize; + return; +} diff --git a/src/tpm2/ExecCommand_fp.h b/src/tpm2/ExecCommand_fp.h new file mode 100644 index 0000000..43b5dbe --- /dev/null +++ b/src/tpm2/ExecCommand_fp.h @@ -0,0 +1,73 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ExecCommand_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef EXECCOMMAND_FP_H +#define EXECCOMMAND_FP_H + +LIB_EXPORT void +ExecuteCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + uint32_t *responseSize, // IN/OUT: response buffer size + unsigned char **response // IN/OUT: response buffer + ); + +#endif diff --git a/src/tpm2/FlushContext_fp.h b/src/tpm2/FlushContext_fp.h new file mode 100644 index 0000000..6426e9f --- /dev/null +++ b/src/tpm2/FlushContext_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: FlushContext_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef FLUSHCONTEXT_FP_H +#define FLUSHCONTEXT_FP_H + +typedef struct { + TPMI_DH_CONTEXT flushHandle; +} FlushContext_In; + +#define RC_FlushContext_flushHandle (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_FlushContext( + FlushContext_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/GetCapability_fp.h b/src/tpm2/GetCapability_fp.h new file mode 100644 index 0000000..52b81d3 --- /dev/null +++ b/src/tpm2/GetCapability_fp.h @@ -0,0 +1,90 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: GetCapability_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef GETCAPABILITY_FP_H +#define GETCAPABILITY_FP_H + +typedef struct { + TPM_CAP capability; + UINT32 property; + UINT32 propertyCount; +} GetCapability_In; + +#define RC_GetCapability_capability (TPM_RC_P + TPM_RC_1) +#define RC_GetCapability_property (TPM_RC_P + TPM_RC_2) +#define RC_GetCapability_propertyCount (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPMI_YES_NO moreData; + TPMS_CAPABILITY_DATA capabilityData; +} GetCapability_Out; + + +TPM_RC +TPM2_GetCapability( + GetCapability_In *in, // IN: input parameter list + GetCapability_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/GetCommandAuditDigest_fp.h b/src/tpm2/GetCommandAuditDigest_fp.h new file mode 100644 index 0000000..e3467ca --- /dev/null +++ b/src/tpm2/GetCommandAuditDigest_fp.h @@ -0,0 +1,91 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: GetCommandAuditDigest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef GETCOMMANDAUDITDIGEST_FP_H +#define GETCOMMANDAUDITDIGEST_FP_H + +typedef struct { + TPMI_RH_ENDORSEMENT privacyHandle; + TPMI_DH_OBJECT signHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; +} GetCommandAuditDigest_In; + +#define RC_GetCommandAuditDigest_privacyHandle (TPM_RC_H + TPM_RC_1) +#define RC_GetCommandAuditDigest_signHandle (TPM_RC_H + TPM_RC_2) +#define RC_GetCommandAuditDigest_qualifyingData (TPM_RC_P + TPM_RC_1) +#define RC_GetCommandAuditDigest_inScheme (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM2B_ATTEST auditInfo; + TPMT_SIGNATURE signature; +} GetCommandAuditDigest_Out; + +TPM_RC +TPM2_GetCommandAuditDigest( + GetCommandAuditDigest_In *in, // IN: input parameter list + GetCommandAuditDigest_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/GetRandom_fp.h b/src/tpm2/GetRandom_fp.h new file mode 100644 index 0000000..27326d0 --- /dev/null +++ b/src/tpm2/GetRandom_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: GetRandom_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef GETRANDOM_FP_H +#define GETRANDOM_FP_H + +typedef struct { + UINT16 bytesRequested; +} GetRandom_In; + +#define RC_GetRandom_bytesRequested (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPM2B_DIGEST randomBytes; +} GetRandom_Out; + +TPM_RC +TPM2_GetRandom( + GetRandom_In *in, // IN: input parameter list + GetRandom_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/GetSessionAuditDigest_fp.h b/src/tpm2/GetSessionAuditDigest_fp.h new file mode 100644 index 0000000..412ce4b --- /dev/null +++ b/src/tpm2/GetSessionAuditDigest_fp.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: GetSessionAuditDigest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef GETSESSIONAUDITDIGEST_FP_H +#define GETSESSIONAUDITDIGEST_FP_H + +typedef struct { + TPMI_RH_ENDORSEMENT privacyAdminHandle; + TPMI_DH_OBJECT signHandle; + TPMI_SH_HMAC sessionHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; +} GetSessionAuditDigest_In; + +#define RC_GetSessionAuditDigest_privacyAdminHandle (TPM_RC_H + TPM_RC_1) +#define RC_GetSessionAuditDigest_signHandle (TPM_RC_H + TPM_RC_2) +#define RC_GetSessionAuditDigest_sessionHandle (TPM_RC_H + TPM_RC_3) +#define RC_GetSessionAuditDigest_qualifyingData (TPM_RC_P + TPM_RC_1) +#define RC_GetSessionAuditDigest_inScheme (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM2B_ATTEST auditInfo; + TPMT_SIGNATURE signature; +} GetSessionAuditDigest_Out; + +TPM_RC +TPM2_GetSessionAuditDigest( + GetSessionAuditDigest_In *in, // IN: input parameter list + GetSessionAuditDigest_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/GetTestResult_fp.h b/src/tpm2/GetTestResult_fp.h new file mode 100644 index 0000000..21d1e9c --- /dev/null +++ b/src/tpm2/GetTestResult_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: GetTestResult_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2016 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef GETTESTRESULT_FP_H +#define GETTESTRESULT_FP_H + +typedef struct{ + TPM2B_MAX_BUFFER outData; + TPM_RC testResult; +} GetTestResult_Out; + + + TPM_RC +TPM2_GetTestResult( + GetTestResult_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/GetTime_fp.h b/src/tpm2/GetTime_fp.h new file mode 100644 index 0000000..0aeba2a --- /dev/null +++ b/src/tpm2/GetTime_fp.h @@ -0,0 +1,91 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: GetTime_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef GETTIME_FP_H +#define GETTIME_FP_H + +typedef struct { + TPMI_RH_ENDORSEMENT privacyAdminHandle; + TPMI_DH_OBJECT signHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; +} GetTime_In; + +#define RC_GetTime_privacyAdminHandle (TPM_RC_H + TPM_RC_1) +#define RC_GetTime_signHandle (TPM_RC_H + TPM_RC_2) +#define RC_GetTime_qualifyingData (TPM_RC_P + TPM_RC_1) +#define RC_GetTime_inScheme (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM2B_ATTEST timeInfo; + TPMT_SIGNATURE signature; +} GetTime_Out; + +TPM_RC +TPM2_GetTime( + GetTime_In *in, // IN: input parameter list + GetTime_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/Global.c b/src/tpm2/Global.c new file mode 100644 index 0000000..256b721 --- /dev/null +++ b/src/tpm2/Global.c @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* TPM variables that are not stack allocated */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Global.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 9.5 Global.c */ +/* 9.5.1 Description */ +/* This file will instance the TPM variables that are not stack allocated. Descriptions of global + variables are in Global.h. There macro macro definitions that allows a variable to be instanced + or simply defined as an external variable. When global.h is included from this .c file, GLOBAL_C + is defined and values are instanced (and possibly initialized), but when global.h is included by + any other file, they are simply defined as external values. DO NOT DEFINE GLOBAL_C IN ANY OTHER + FILE. */ +/* NOTE: This is a change from previous implementations where Global.h just contained the extern + declaration and values were instanced in this file. This change keeps the definition and + instance in one file making maintenance easier. The instanced data will still be in the + global.obj file. */ +/* The OIDs.h file works in a way that is similar to the Global.h with the definition of the + values in OIDs.h such that they are instanced in global.obj. The macros that are defined in + Global.h are used in OIDs.h in the same way as they are in Global.h. */ + +#define GLOBAL_C +#include "Tpm.h" +#include "OIDs.h" +#if CC_CertifyX509 +# include "X509.h" +#endif // CC_CertifyX509 diff --git a/src/tpm2/Global.h b/src/tpm2/Global.h new file mode 100644 index 0000000..84a0d13 --- /dev/null +++ b/src/tpm2/Global.h @@ -0,0 +1,1350 @@ +/********************************************************************************/ +/* */ +/* Internal Global Type Definitions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Global.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 5.9 Global.h */ +/* 5.9.2 Includes */ + +#if !defined _TPM_H_ +#error "Should only be instanced in TPM.h" +#endif + +#ifndef GLOBAL_H +#define GLOBAL_H +_REDUCE_WARNING_LEVEL_(2) +#include +#include +_NORMAL_WARNING_LEVEL_ +#include "BackwardsCompatibility.h" // libtpms added + +#include "Capabilities.h" +#include "TpmTypes.h" +#include "CommandAttributes.h" +#include "CryptTest.h" +#include "BnValues.h" +#include "CryptHash.h" +#include "CryptSym.h" +#include "CryptRand.h" +#include "CryptEcc.h" +#include "CryptRsa.h" +#include "CryptTest.h" +#include "TpmError.h" +#include "NV.h" +#include "ACT.h" +#include "Utils.h" // libtpms added + +//** Defines and Types + +//*** Size Types +// These types are used to differentiate the two different size values used. +// +// NUMBYTES is used when a size is a number of bytes (usually a TPM2B) +typedef UINT16 NUMBYTES; + +//*** Other Types +// An AUTH_VALUE is a BYTE array containing a digest (TPMU_HA) +typedef BYTE AUTH_VALUE[sizeof(TPMU_HA)]; + +/* A TIME_INFO is a BYTE array that can contain a TPMS_TIME_INFO */ +typedef BYTE TIME_INFO[sizeof(TPMS_TIME_INFO)]; + +/* A NAME is a BYTE array that can contain a TPMU_NAME */ +typedef BYTE NAME[sizeof(TPMU_NAME)]; + +/* Definition for a PROOF value */ +TPM2B_TYPE(PROOF, PROOF_SIZE); + +/* Definition for a Primary Seed value */ +TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE); + +/* A CLOCK_NONCE is used to tag the time value in the authorization session and in the ticket + computation so that the ticket expires when there is a time discontinuity. When the clock stops + during normal operation, the nonce is 64-bit value kept in RAM but it is a 32-bit counter when + the clock only stops during power events. */ +#if CLOCK_STOPS +typedef UINT64 CLOCK_NONCE; +#else +typedef UINT32 CLOCK_NONCE; +#endif + +// 5.9.3 Loaded Object Structures +// 5.9.3.1 Description +// The structures in this section define the object layout as it exists in TPM memory. +// Two types of objects are defined: an ordinary object such as a key, and a sequence object that +// may be a hash, HMAC, or event. + +/* 5.9.3.2 OBJECT_ATTRIBUTES */ +/* An OBJECT_ATTRIBUTES structure contains the variable attributes of an object. These properties + are not part of the public properties but are used by the TPM in managing the object. An + OBJECT_ATTRIBUTES is used in the definition of the OBJECT data type. */ +typedef struct +{ +#if LITTLE_ENDIAN_TPM == YES /* libtpms added */ + unsigned publicOnly : 1; //0) SET if only the public portion of + // an object is loaded + unsigned epsHierarchy : 1; //1) SET if the object belongs to EPS + // Hierarchy + unsigned ppsHierarchy : 1; //2) SET if the object belongs to PPS + // Hierarchy + unsigned spsHierarchy : 1; //3) SET f the object belongs to SPS + // Hierarchy + unsigned evict : 1; //4) SET if the object is a platform or + // owner evict object. Platform- + // evict object belongs to PPS + // hierarchy, owner-evict object + // belongs to SPS or EPS hierarchy. + // This bit is also used to mark a + // completed sequence object so it + // will be flush when the + // SequenceComplete command succeeds. + unsigned primary : 1; //5) SET for a primary object + unsigned temporary : 1; //6) SET for a temporary object + unsigned stClear : 1; //7) SET for an stClear object + unsigned hmacSeq : 1; //8) SET for an HMAC or MAC sequence object + unsigned hashSeq : 1; //9) SET for a hash sequence object + unsigned eventSeq : 1; //10) SET for an event sequence object + unsigned ticketSafe : 1; //11) SET if a ticket is safe to create + // for hash sequence object + unsigned firstBlock : 1; //12) SET if the first block of hash + // data has been received. It + // works with ticketSafe bit + unsigned isParent : 1; //13) SET if the key has the proper + // attributes to be a parent key + unsigned privateExp : 1; //14) SET when the private exponent + // of an RSA key has been validated. + unsigned occupied : 1; //15) SET when the slot is occupied. + unsigned derivation : 1; //16) SET when the key is a derivation + // parent + unsigned external : 1; //17) SET when the object is loaded with + // TPM2_LoadExternal(); + unsigned reserved : 14; //18-31) /* libtpms added */ +#endif /* libtpms added */ +#if BIG_ENDIAN_TPM == YES /* libtpms added begin */ + unsigned reserved : 14; //18-31) + unsigned external : 1; //17) SET when the object is loaded with + unsigned derivation : 1; //16) SET when the key is a derivation + unsigned occupied : 1; //15) SET when the slot is occupied. + unsigned privateExp : 1; //14) SET when the private exponent + unsigned isParent : 1; //13) SET if the key has the proper + unsigned firstBlock : 1; //12) SET if the first block of hash + unsigned ticketSafe : 1; //11) SET if a ticket is safe to create + unsigned eventSeq : 1; //10) SET for an event sequence object + unsigned hashSeq : 1; //9) SET for a hash sequence object + unsigned hmacSeq : 1; //8) SET for an HMAC sequence object + unsigned stClear : 1; //7) SET for an stClear object + unsigned temporary : 1; //6) SET for a temporary object + unsigned primary : 1; //5) SET for a primary object + + unsigned evict : 1; //4) SET if the object is a platform or + unsigned spsHierarchy : 1; //3) SET f the object belongs to SPS + unsigned ppsHierarchy : 1; //2) SET if the object belongs to PPS + unsigned epsHierarchy : 1; //1) SET if the object belongs to EPS + unsigned publicOnly : 1; //0) SET if only the public portion of +#endif /* libtpms added end */ +} OBJECT_ATTRIBUTES; + +#if ALG_RSA +/* There is an overload of the sensitive.rsa.t.size field of a TPMT_SENSITIVE when an RSA key is + loaded. When the sensitive->sensitive contains an RSA key with all of the CRT values, then the + MSB of the size field will be set to indicate that the buffer contains all 5 of the CRT private + key values. */ +#define RSA_prime_flag 0x8000 +#endif + +/* 5.9.3.3 OBJECT Structure */ +/* An OBJECT structure holds the object public, sensitive, and meta-data associated. This structure + is implementation dependent. For this implementation, the structure is not optimized for space + but rather for clarity of the reference implementation. Other implementations may choose to + overlap portions of the structure that are not used simultaneously. These changes would + necessitate changes to the source code but those changes would be compatible with the reference + implementation. */ +typedef struct OBJECT +{ + // The attributes field is required to be first followed by the publicArea. + // This allows the overlay of the object structure and a sequence structure + OBJECT_ATTRIBUTES attributes; // object attributes + TPMT_PUBLIC publicArea; // public area of an object + TPMT_SENSITIVE sensitive; // sensitive area of an object +#if ALG_RSA + privateExponent_t privateExponent; // Additional field for the private +#endif + TPM2B_NAME qualifiedName; // object qualified name + TPMI_DH_OBJECT evictHandle; // if the object is an evict object, + // the original handle is kept here. + // The 'working' handle will be the + // handle of an object slot. + TPM2B_NAME name; // Name of the object name. Kept here + // to avoid repeatedly computing it. + + // libtpms added: SEED_COMPAT_LEVEL to use for deriving child keys + SEED_COMPAT_LEVEL seedCompatLevel; + // libtpms added: OBJECT lies in NVRAM; to avoid that it needs different number + // of bytes on 32 bit and 64 bit architectures, we need to make sure it's the + // same size; simple padding at the end works here + UINT8 _pad[3]; +} OBJECT; + +/* 5.9.3.4 HASH_OBJECT Structure */ +/* This structure holds a hash sequence object or an event sequence object. */ +/* The first four components of this structure are manually set to be the same as the first four + components of the object structure. This prevents the object from being inadvertently misused as + sequence objects occupy the same memory as a regular object. A debug check is present to make + sure that the offsets are what they are supposed to be. */ +/* NOTE: In a future version, this will probably be renamed as SEQUENCE_OBJECT */ +typedef struct HASH_OBJECT +{ + OBJECT_ATTRIBUTES attributes; // The attributes of the HASH object + TPMI_ALG_PUBLIC type; // algorithm + TPMI_ALG_HASH nameAlg; // name algorithm + TPMA_OBJECT objectAttributes; // object attributes + // The data below is unique to a sequence object + TPM2B_AUTH auth; // authorization for use of sequence + union + { + HASH_STATE hashState[HASH_COUNT]; + HMAC_STATE hmacState; + } state; +} HASH_OBJECT; +typedef BYTE HASH_OBJECT_BUFFER[sizeof(HASH_OBJECT)]; + +/* 5.9.3.5 ANY_OBJECT */ +/* This is the union for holding either a sequence object or a regular object. for ContextSave() and + ContextLoad() */ +typedef union ANY_OBJECT +{ + OBJECT entity; + HASH_OBJECT hash; +} ANY_OBJECT; +typedef BYTE ANY_OBJECT_BUFFER[sizeof(ANY_OBJECT)]; + +/* 5.9.4 AUTH_DUP Types */ +/* These values are used in the authorization processing. */ +typedef UINT32 AUTH_ROLE; +#define AUTH_NONE ((AUTH_ROLE)(0)) +#define AUTH_USER ((AUTH_ROLE)(1)) +#define AUTH_ADMIN ((AUTH_ROLE)(2)) +#define AUTH_DUP ((AUTH_ROLE)(3)) + +/* 5.9.5 Active Session Context */ +/* 5.9.5.1 Description */ +/* The structures in this section define the internal structure of a session context. */ +/* 5.9.5.2 SESSION_ATTRIBUTES */ +/* The attributes in the SESSION_ATTRIBUTES structure track the various properties of the + session. It maintains most of the tracking state information for the policy session. It is used + within the SESSION structure. */ +typedef struct SESSION_ATTRIBUTES +{ +#if LITTLE_ENDIAN_TPM == YES /* libtpms added */ + unsigned isPolicy : 1; //1) SET if the session may only be used + // for policy + unsigned isAudit : 1; //2) SET if the session is used for audit + unsigned isBound : 1; //3) SET if the session is bound to with an + // entity. This attribute will be CLEAR + // if either isPolicy or isAudit is SET. + unsigned isCpHashDefined : 1; //4) SET if the cpHash has been defined + // This attribute is not SET unless + // 'isPolicy' is SET. + unsigned isAuthValueNeeded : 1; //5) SET if the authValue is required for + // computing the session HMAC. This + // attribute is not SET unless 'isPolicy' + // is SET. + unsigned isPasswordNeeded : 1; //6) SET if a password authValue is required + // for authorization This attribute is not + // SET unless 'isPolicy' is SET. + unsigned isPPRequired : 1; //7) SET if physical presence is required to + // be asserted when the authorization is + // checked. This attribute is not SET + // unless 'isPolicy' is SET. + unsigned isTrialPolicy : 1; //8) SET if the policy session is created + // for trial of the policy's policyHash + // generation. This attribute is not SET + // unless 'isPolicy' is SET. + unsigned isDaBound : 1; //9) SET if the bind entity had noDA CLEAR. + // If this is SET, then an authorization + // failure using this session will count + // against lockout even if the object + // being authorized is exempt from DA. + unsigned isLockoutBound : 1; //10) SET if the session is bound to + // lockoutAuth. + unsigned includeAuth : 1; //11) This attribute is SET when the + // authValue of an object is to be + // included in the computation of the + // HMAC key for the command and response + // computations. (was 'requestWasBound') + unsigned checkNvWritten : 1; //12) SET if the TPMA_NV_WRITTEN attribute + // needs to be checked when the policy is + // used for authorization for NV access. + // If this is SET for any other type, the + // policy will fail. + unsigned nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is required to + // be SET. Used when 'checkNvWritten' is + // SET + unsigned isTemplateSet : 1; //14) SET if the templateHash needs to be + // checked for Create, CreatePrimary, or + // CreateLoaded. + unsigned _reserved : 18; //15-32 /* libtpms added */ +#endif /* libtpms added */ +#if BIG_ENDIAN_TPM == YES /* libtpms added begin */ + unsigned _reserved : 18; //15-32 + unsigned isTemplateSet : 1; //14) SET if the templateHash needs to be + unsigned nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is required to + unsigned checkNvWritten : 1; //12) SET if the TPMA_NV_WRITTEN attribute + unsigned includeAuth : 1; //11) This attribute is SET when the + unsigned isLockoutBound : 1; //10) SET if the session is bound to + unsigned isDaBound : 1; //9) SET if the bind entity had noDA CLEAR. + unsigned isTrialPolicy : 1; //8) SET if the policy session is created + unsigned isPPRequired : 1; //7) SET if physical presence is required to + unsigned isPasswordNeeded : 1; //6) SET if a password authValue is required + unsigned isAuthValueNeeded : 1; //5) SET if the authValue is required for + unsigned isCpHashDefined : 1; //4) SET if the cpHash has been defined + unsigned isBound : 1; //3) SET if the session is bound to with an + unsigned isAudit : 1; //2) SET if the session is used for audit + unsigned isPolicy : 1; //1) SET if the session may only be used +#endif /* libtpms added end */ +} SESSION_ATTRIBUTES; + +/* 5.9.5.3 SESSION Structure */ +/* The SESSION structure contains all the context of a session except for the associated + contextID. */ +/* NOTE: The contextID of a session is only relevant when the session context is stored off the + TPM. */ +typedef struct SESSION +{ + SESSION_ATTRIBUTES attributes; // session attributes + UINT32 pcrCounter; // PCR counter value when PCR is + // included (policy session) + // If no PCR is included, this + // value is 0. + UINT64 startTime; // The value in g_time + // when the session was started (policy session) + UINT64 timeout; // The timeout relative to g_time + // There is no timeout if this value + // is 0. + CLOCK_NONCE epoch; // The g_clockEpoch value when the + // session was started. If g_clockEpoch + // does not match this value when the + // timeout is used, then + // then the command will fail. + TPM_CC commandCode; // command code (policy session) + TPM_ALG_ID authHashAlg; // session hash algorithm + TPMA_LOCALITY commandLocality; // command locality (policy session) + TPMT_SYM_DEF symmetric; // session symmetric algorithm (if any) + TPM2B_AUTH sessionKey; // session secret value used for + // this session + TPM2B_NONCE nonceTPM; // last TPM-generated nonce for + // generating HMAC and encryption keys + union + { + TPM2B_NAME boundEntity; // value used to track the entity to + // which the session is bound + TPM2B_DIGEST cpHash; // the required cpHash value for the + // command being authorized + TPM2B_DIGEST nameHash; // the required nameHash + TPM2B_DIGEST templateHash; // the required template for creation + } u1; + union + { + TPM2B_DIGEST auditDigest; // audit session digest + TPM2B_DIGEST policyDigest; // policyHash + } u2; // audit log and policyHash may + // share space to save memory +} SESSION; +#define EXPIRES_ON_RESET INT32_MIN +#define TIMEOUT_ON_RESET UINT64_MAX +#define EXPIRES_ON_RESTART (INT32_MIN + 1) +#define TIMEOUT_ON_RESTART (UINT64_MAX - 1) +typedef BYTE SESSION_BUF[sizeof(SESSION)]; + +/* 5.9.7 PCR */ +/* 5.9.7.1 PCR_SAVE Structure */ +/* The PCR_SAVE structure type contains the PCR data that are saved across power cycles. Only the + static PCR are required to be saved across power cycles. The DRTM and resettable PCR are not + saved. The number of static and resettable PCR is determined by the platform-specific + specification to which the TPM is built. */ + +#define PCR_SAVE_SPACE(HASH, Hash) BYTE Hash[NUM_STATIC_PCR][HASH##_DIGEST_SIZE]; + +typedef struct PCR_SAVE +{ + FOR_EACH_HASH(PCR_SAVE_SPACE) + + // This counter increments whenever the PCR are updated. + // NOTE: A platform-specific specification may designate + // certain PCR changes as not causing this counter + // to increment. + UINT32 pcrCounter; +} PCR_SAVE; + +/* 5.9.6.2 PCR_POLICY */ +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 +/* This structure holds the PCR policies, one for each group of PCR controlled by policy. */ +typedef struct PCR_POLICY +{ + TPMI_ALG_HASH hashAlg[NUM_POLICY_PCR_GROUP]; + TPM2B_DIGEST a_unused; /* libtpms: renamed field since not used and not initialized */ + TPM2B_DIGEST policy[NUM_POLICY_PCR_GROUP]; +} PCR_POLICY; +#endif + +/* 5.9.6.3 PCR_AUTHVALUE */ +/* This structure holds the PCR policies, one for each group of PCR controlled by policy. */ +typedef struct PCR_AUTH_VALUE +{ + TPM2B_DIGEST auth[NUM_AUTHVALUE_PCR_GROUP]; +} PCR_AUTHVALUE; + +/* 5.9.7 STARTUP_TYPE */ +/* This enumeration is the possible startup types. The type is determined by the combination of + TPM2_ShutDown() and TPM2_Startup(). */ +typedef enum + { + SU_RESET, + SU_RESTART, + SU_RESUME + } STARTUP_TYPE; + +/* 5.9.8 NV */ +/* 5.9.8.1 NV_INDEX */ +/* The NV_INDEX structure defines the internal format for an NV index. The indexData size varies + according to the type of the index. In this implementation, all of the index is manipulated as a + unit. */ +typedef struct NV_INDEX +{ + TPMS_NV_PUBLIC publicArea; + TPM2B_AUTH authValue; +} NV_INDEX; + +/* 5.9.8.2 NV_REF */ +/* An NV_REF is an opaque value returned by the NV subsystem. It is used to reference and NV Index + in a relatively efficient way. Rather than having to continually search for an Index, its + reference value may be used. In this implementation, an NV_REF is a byte pointer that points to + the copy of the NV memory that is kept in RAM. */ +typedef UINT32 NV_REF; +typedef BYTE *NV_RAM_REF; + +/* 5.9.8.3 NV_PIN */ +/* This structure deals with the possible endianness differences between the canonical form of the + TPMS_NV_PIN_COUNTER_PARAMETERS structure and the internal value. The structures allow the data in + a PIN index to be read as an 8-octet value using NvReadUINT64Data(). That function will byte swap + all the values on a little endian system. This will put the bytes with the 4-octet values in the + correct order but will swap the pinLimit and pinCount values. When written, the PIN index is + simply handled as a normal index with the octets in canonical order. */ +#if BIG_ENDIAN_TPM +typedef struct +{ + UINT32 pinCount; + UINT32 pinLimit; +} PIN_DATA; +#else +typedef struct +{ + UINT32 pinLimit; + UINT32 pinCount; +} PIN_DATA; +#endif +typedef union +{ + UINT64 intVal; + PIN_DATA pin; +} NV_PIN; + +/* 5.9.9 COMMIT_INDEX_MASK */ +/* This is the define for the mask value that is used when manipulating the bits in the commit bit + array. The commit counter is a 64-bit value and the low order bits are used to index the + commitArray. This mask value is applied to the commit counter to extract the bit number in the + array. */ +#if ALG_ECC +#define COMMIT_INDEX_MASK ((UINT16)((sizeof(gr.commitArray)*8)-1)) +#endif + +/* 5.9.10 RAM Global Values */ +/* 5.9.10.1 Description */ +/* The values in this section are only extant in RAM or ROM as constant values. */ +/* 5.9.10.2 Crypto Self-Test Values */ +EXTERN ALGORITHM_VECTOR g_implementedAlgorithms; +EXTERN ALGORITHM_VECTOR g_toTest; + +/* 5.9.10.3 g_rcIndex[] */ +/* This array is used to contain the array of values that are added to a return code when it is a + parameter-, handle-, or session-related error. This is an implementation choice and the same + result can be achieved by using a macro. */ +#define g_rcIndexInitializer { TPM_RC_1, TPM_RC_2, TPM_RC_3, TPM_RC_4, \ + TPM_RC_5, TPM_RC_6, TPM_RC_7, TPM_RC_8, \ + TPM_RC_9, TPM_RC_A, TPM_RC_B, TPM_RC_C, \ + TPM_RC_D, TPM_RC_E, TPM_RC_F } +EXTERN const UINT16 g_rcIndex[15] INITIALIZER(g_rcIndexInitializer); + +/* 5.9.10.4 g_exclusiveAuditSession */ +/* This location holds the session handle for the current exclusive audit session. If there is no + exclusive audit session, the location is set to TPM_RH_UNASSIGNED. */ +EXTERN TPM_HANDLE g_exclusiveAuditSession; + +/* 5.9.10.5 g_time */ +/* This is the value in which we keep the current command time. This is initialized at the start of + each command. The time is the accumulated time since the last time that the TPM's timer was last + powered up. Clock is the accumulated time since the last time that the TPM was cleared. g_time is + in mS. */ +EXTERN UINT64 g_time; + +/* 5.9.10.6 g_timeEpoch */ +/* This value contains the current clock Epoch. It changes when there is a clock discontinuity. It + may be necessary to place this in NV should the timer be able to run across a power down of the + TPM but not in all cases (e.g. dead battery). If the nonce is placed in NV, it should go in gp + because it should be changing slowly. */ +#if CLOCK_STOPS +EXTERN CLOCK_NONCE g_timeEpoch; +#else +#define g_timeEpoch gp.timeEpoch +#endif + +/* 5.9.10.7 g_phEnable */ +/* This is the platform hierarchy control and determines if the platform hierarchy is + available. This value is SET on each TPM2_Startup(). The default value is SET. */ +EXTERN BOOL g_phEnable; + +/* 5.9.10.8 g_pcrReConfig */ +/* This value is SET if a TPM2_PCR_Allocate() command successfully executed since the last + TPM2_Startup(). If so, then the next shutdown is required to be Shutdown(CLEAR). */ +EXTERN BOOL g_pcrReConfig; + +/* 5.9.10.9 g_DRTMHandle */ +/* This location indicates the sequence object handle that holds the DRTM sequence data. When not + used, it is set to TPM_RH_UNASSIGNED. A sequence DRTM sequence is started on either _TPM_Init() + or _TPM_Hash_Start(). */ +EXTERN TPMI_DH_OBJECT g_DRTMHandle; + +/* 5.9.10.10 g_DrtmPreStartup */ +/* This value indicates that an H-CRTM occurred after _TPM_Init() but before TPM2_Startup(). The + define for PRE_STARTUP_FLAG is used to add the g_DrtmPreStartup value to gp_orderlyState at + shutdown. This hack is to avoid adding another NV variable. */ +EXTERN BOOL g_DrtmPreStartup; + +/* 5.9.10.11 g_StartupLocality3 */ +/* This value indicates that a TPM2_Startup() occurred at locality 3. Otherwise, it at locality + 0. The define for STARTUP_LOCALITY_3 is to indicate that the startup was not at locality 0. This + hack is to avoid adding another NV variable. */ +EXTERN BOOL g_StartupLocality3; + +/* 5.9.10.12 TPM_SU_NONE */ +/* Part 2 defines the two shutdown/startup types that may be used in TPM2_Shutdown() and + TPM2_Starup(). This additional define is used by the TPM to indicate that no shutdown was + received. */ +/* NOTE: This is a reserved value. */ +#define SU_NONE_VALUE (0xFFFF) +#define TPM_SU_NONE (TPM_SU)(SU_NONE_VALUE) + +/* 5.9.10.13 TPM_SU_DA_USED */ +/* As with TPM_SU_NONE, this value is added to allow indication that the shutdown was not orderly + and that a DA=protected object was reference during the previous cycle. */ +#define SU_DA_USED_VALUE (SU_NONE_VALUE - 1) +#define TPM_SU_DA_USED (TPM_SU)(SU_DA_USED_VALUE) + +/* 5.9.10.14 Startup Flags */ +/* These flags are included in gp.orderlyState. These are hacks and are being used to avoid having + to change the layout of gp. The PRE_STARTUP_FLAG indicates that a + _TPM_Hash_Start()/_Data()/_End() sequence was received after _TPM_Init() but before + TPM2_StartUp(). STARTUP_LOCALITY_3 indicates that the last TPM2_Startup() was received at + locality 3. These flags are only relevant if after a TPM2_Shutdown(STATE). */ +#define PRE_STARTUP_FLAG 0x8000 +#define STARTUP_LOCALITY_3 0x4000 +#define TPM_SU_STATE_MASK ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3) // libtpms added +#if USE_DA_USED + +/* 5.9.10.15 g_daUsed */ +/* This location indicates if a DA-protected value is accessed during a boot cycle. If none has, + then there is no need to increment failedTries on the next non-orderly startup. This bit is + merged with gp.orderlyState when gp.orderly is set to SU_NONE_VALUE */ + +/* This global is set to FALSE on startup (after a decision has been made on whether to increment + the failedTries or not). On a first attempt to access a DA protected object: this global is set + to 1, the orderlyState is set to SU_DA_USED, committed to NV and the command execution returns + with RC_RETRY (without exposing any information on the DA attempt). */ +EXTERN BOOL g_daUsed; +#endif + +/* 5.9.10.16 g_updateNV */ +/* This flag indicates if NV should be updated at the end of a command. This flag is set to UT_NONE + at the beginning of each command in ExecuteCommand(). This flag is checked in ExecuteCommand() + after the detailed actions of a command complete. If the command execution was successful and + this flag is not UT_NONE, any pending NV writes will be committed to NV. UT_ORDERLY causes any + RAM data to be written to the orderly space for staging the write to NV. */ +typedef BYTE UPDATE_TYPE; +#define UT_NONE (UPDATE_TYPE)0 +#define UT_NV (UPDATE_TYPE)1 +#define UT_ORDERLY (UPDATE_TYPE)(UT_NV + 2) +EXTERN UPDATE_TYPE g_updateNV; +/* 5.9.10.17 g_powerWasLost */ +/* This flag is used to indicate if the power was lost. It is SET in _TPM__Init(). This flag is + cleared by TPM2_Startup() after all power-lost activities are completed. */ +/* NOTE: When power is applied, this value can come up as anything. However, _plat__WasPowerLost() + will provide the proper indication in that case. So, when power is actually lost, we get the + correct answer. When power was not lost, but the power-lost processing has not been completed + before the next _TPM_Init(), then the TPM still does the correct thing. */ +EXTERN BOOL g_powerWasLost; + +/* 5.9.10.18 g_clearOrderly */ +/* This flag indicates if the execution of a command should cause the orderly state to be cleared. + This flag is set to FALSE at the beginning of each command in ExecuteCommand() and is checked in + ExecuteCommand() after the detailed actions of a command complete but before the check of + g_updateNV. If this flag is TRUE, and the orderly state is not SU_NONE_VALUE, then the orderly + state in NV memory will be changed to SU_NONE_VALUE or SU_DA_USED_VALUE. */ +EXTERN BOOL g_clearOrderly; + +/* 5.9.10.19 g_prevOrderlyState */ +/* This location indicates how the TPM was shut down before the most recent TPM2_Startup(). This + value, along with the startup type, determines if the TPM should do a TPM Reset, TPM Restart, or + TPM Resume. */ +EXTERN TPM_SU g_prevOrderlyState; + +/* 5.9.10.20 g_nvOk */ +/* This value indicates if the NV integrity check was successful or not. If not and the failure was + severe, then the TPM would have been put into failure mode after it had been re-manufactured. If + the NV failure was in the area where the state-save data is kept, then this variable will have a + value of FALSE indicating that a TPM2_Startup(CLEAR) is required. */ +EXTERN BOOL g_nvOk; + +/* NV availability is sampled as the start of each command and stored here so that its value remains + consistent during the command execution */ +EXTERN TPM_RC g_NvStatus; + +/* 5.9.10.21 g_platformUnique */ +/* This location contains the unique value(s) used to identify the TPM. It is loaded on every + _TPM2_Startup() The first value is used to seed the RNG. The second value is used as a vendor + authValue. The value used by the RNG would be the value derived from the chip unique value (such + as fused) with a dependency on the authorities of the code in the TPM boot path. The second would + be derived from the chip unique value with a dependency on the details of the code in the boot + path. That is, the first value depends on the various signers of the code and the second depends + on what was signed. The TPM vendor should not be able to know the first value but they are + expected to know the second. */ +EXTERN TPM2B_AUTH g_platformUniqueAuthorities; // Reserved for RNG +EXTERN TPM2B_AUTH g_platformUniqueDetails; // referenced by VENDOR_PERMANENT + +//********************************************************************************* +//********************************************************************************* +//** Persistent Global Values +//********************************************************************************* +//********************************************************************************* +//*** Description +// The values in this section are global values that are persistent across power +// events. The lifetime of the values determines the structure in which the value +// is placed. + +/* 5.9.11.2 PERSISTENT_DATA */ +/* This structure holds the persistent values that only change as a consequence of a specific + Protected Capability and are not affected by TPM power events (TPM2_Startup() or + TPM2_Shutdown(). */ +typedef struct +{ + //********************************************************************************* + // Hierarchy + //********************************************************************************* + // The values in this section are related to the hierarchies. + BOOL disableClear; // TRUE if TPM2_Clear() using + // lockoutAuth is disabled + // Hierarchy authPolicies + TPMI_ALG_HASH ownerAlg; + TPMI_ALG_HASH endorsementAlg; + TPMI_ALG_HASH lockoutAlg; + TPM2B_DIGEST ownerPolicy; + TPM2B_DIGEST endorsementPolicy; + TPM2B_DIGEST lockoutPolicy; + // Hierarchy authValues + TPM2B_AUTH ownerAuth; + TPM2B_AUTH endorsementAuth; + TPM2B_AUTH lockoutAuth; + // Primary Seeds + TPM2B_SEED EPSeed; + TPM2B_SEED SPSeed; + TPM2B_SEED PPSeed; + // SEED_COMPAT_LEVELs related to creation time of seeds + SEED_COMPAT_LEVEL EPSeedCompatLevel; // libtpms added begin + SEED_COMPAT_LEVEL SPSeedCompatLevel; + SEED_COMPAT_LEVEL PPSeedCompatLevel; // libtpms added end + // Note there is a nullSeed in the state_reset memory. + // Hierarchy proofs + TPM2B_PROOF phProof; + TPM2B_PROOF shProof; + TPM2B_PROOF ehProof; + // Note there is a nullProof in the state_reset memory. + //********************************************************************************* + // Reset Events + //********************************************************************************* + // A count that increments at each TPM reset and never get reset during the life + // time of TPM. The value of this counter is initialized to 1 during TPM + // manufacture process. It is used to invalidate all saved contexts after a TPM + // Reset. + UINT64 totalResetCount; + // This counter increments on each TPM Reset. The counter is reset by + // TPM2_Clear(). + UINT32 resetCount; + //********************************************************************************* + // PCR + //********************************************************************************* + // This structure hold the policies for those PCR that have an update policy. + // This implementation only supports a single group of PCR controlled by + // policy. If more are required, then this structure would be changed to + // an array. +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + PCR_POLICY pcrPolicies; +#endif + // This structure indicates the allocation of PCR. The structure contains a + // list of PCR allocations for each implemented algorithm. If no PCR are + // allocated for an algorithm, a list entry still exists but the bit map + // will contain no SET bits. + TPML_PCR_SELECTION pcrAllocated; + //********************************************************************************* + // Physical Presence + //********************************************************************************* + // The PP_LIST type contains a bit map of the commands that require physical + // to be asserted when the authorization is evaluated. Physical presence will be + // checked if the corresponding bit in the array is SET and if the authorization + // handle is TPM_RH_PLATFORM. + // + // These bits may be changed with TPM2_PP_Commands(). + BYTE ppList[(COMMAND_COUNT + 7) / 8]; + //********************************************************************************* + // Dictionary attack values + //********************************************************************************* + // These values are used for dictionary attack tracking and control. + UINT32 failedTries; // the current count of unexpired + // authorization failures + UINT32 maxTries; // number of unexpired authorization + // failures before the TPM is in + // lockout + UINT32 recoveryTime; // time between authorization failures + // before failedTries is decremented + UINT32 lockoutRecovery; // time that must expire between + // authorization failures associated + // with lockoutAuth + BOOL lockOutAuthEnabled; // TRUE if use of lockoutAuth is + // allowed + //***************************************************************************** + // Orderly State + //***************************************************************************** + // The orderly state for current cycle + TPM_SU orderlyState; + //***************************************************************************** + // Command audit values. + //***************************************************************************** + BYTE auditCommands[((COMMAND_COUNT + 1) + 7) / 8]; + TPMI_ALG_HASH auditHashAlg; + UINT64 auditCounter; + //***************************************************************************** + // Algorithm selection + //***************************************************************************** + // + // The 'algorithmSet' value indicates the collection of algorithms that are + // currently in used on the TPM. The interpretation of value is vendor dependent. + UINT32 algorithmSet; + //***************************************************************************** + // Firmware version + //***************************************************************************** + // The firmwareV1 and firmwareV2 values are instanced in TimeStamp.c. This is + // a scheme used in development to allow determination of the linker build time + // of the TPM. An actual implementation would implement these values in a way that + // is consistent with vendor needs. The values are maintained in RAM for simplified + // access with a master version in NV. These values are modified in a + // vendor-specific way. + // g_firmwareV1 contains the more significant 32-bits of the vendor version number. + // In the reference implementation, if this value is printed as a hex + // value, it will have the format of YYYYMMDD + UINT32 firmwareV1; + // g_firmwareV1 contains the less significant 32-bits of the vendor version number. + // In the reference implementation, if this value is printed as a hex + // value, it will have the format of 00 HH MM SS + UINT32 firmwareV2; + //***************************************************************************** + // Timer Epoch + //***************************************************************************** + // timeEpoch contains a nonce that has a vendor=specific size (should not be + // less than 8 bytes. This nonce changes when the clock epoch changes. The clock + // epoch changes when there is a discontinuity in the timing of the TPM. +#if !CLOCK_STOPS + CLOCK_NONCE timeEpoch; +#endif +} PERSISTENT_DATA; +EXTERN PERSISTENT_DATA gp; + +/* 5.9.11.3 ORDERLY_DATA */ +/* The data in this structure is saved to NV on each TPM2_Shutdown(). */ +typedef struct orderly_data +{ + //***************************************************************************** + // TIME + //***************************************************************************** + // Clock has two parts. One is the state save part and one is the NV part. The + // state save version is updated on each command. When the clock rolls over, the + // NV version is updated. When the TPM starts up, if the TPM was shutdown in and + // orderly way, then the sClock value is used to initialize the clock. If the + // TPM shutdown was not orderly, then the persistent value is used and the safe + // attribute is clear. + UINT64 clock; // The orderly version of clock + TPMI_YES_NO clockSafe; // Indicates if the clock value is + // safe. + // In many implementations, the quality of the entropy available is not that + // high. To compensate, the current value of the drbgState can be saved and + // restored on each power cycle. This prevents the internal state from reverting + // to the initial state on each power cycle and starting with a limited amount + // of entropy. By keeping the old state and adding entropy, the entropy will + // accumulate. + DRBG_STATE drbgState; + // These values allow the accumulation of self-healing time across orderly shutdown + // of the TPM. +#if ACCUMULATE_SELF_HEAL_TIMER + UINT64 selfHealTimer; // current value of s_selfHealTimer + UINT64 lockoutTimer; // current value of s_lockoutTimer + UINT64 time; // current value of g_time at shutdown +#endif // ACCUMULATE_SELF_HEAL_TIMER + +#ifndef __ACT_DISABLED // libtpms added +#error ACT not supported in ORDERLY_DATA! + // These are the ACT Timeout values. They are saved with the other timers +#define DefineActData(N) ACT_STATE ACT_##N; + FOR_EACH_ACT(DefineActData) + + // this is the 'signaled' attribute data for all the ACT. It is done this way so + // that they can be manipulated by ACT number rather than having to access a + // structure. + UINT16 signaledACT; + UINT16 preservedSignaled; +#endif // libtpms added +} ORDERLY_DATA; +#if ACCUMULATE_SELF_HEAL_TIMER +#define s_selfHealTimer go.selfHealTimer +#define s_lockoutTimer go.lockoutTimer +#endif // ACCUMULATE_SELF_HEAL_TIMER +# define drbgDefault go.drbgState +EXTERN ORDERLY_DATA go; + +/* 5.9.11.4 STATE_CLEAR_DATA */ +/* This structure contains the data that is saved on Shutdown(STATE). and restored on + Startup(STATE). The values are set to their default settings on any Startup(Clear). In other + words the data is only persistent across TPM Resume. */ +/* If the comments associated with a parameter indicate a default reset value, the value is applied + on each Startup(CLEAR). */ +typedef struct state_clear_data +{ + //***************************************************************************** + // Hierarchy Control + //***************************************************************************** + BOOL shEnable; // default reset is SET + BOOL ehEnable; // default reset is SET + BOOL phEnableNV; // default reset is SET + TPMI_ALG_HASH platformAlg; // default reset is TPM_ALG_NULL + TPM2B_DIGEST platformPolicy; // default reset is an Empty Buffer + TPM2B_AUTH platformAuth; // default reset is an Empty Buffer + //***************************************************************************** + // PCR + //***************************************************************************** + // The set of PCR to be saved on Shutdown(STATE) + PCR_SAVE pcrSave; // default reset is 0...0 + // This structure hold the authorization values for those PCR that have an + // update authorization. + // This implementation only supports a single group of PCR controlled by + // authorization. If more are required, then this structure would be changed to + // an array. + PCR_AUTHVALUE pcrAuthValues; + +#ifndef __ACT_DISABLED // libtpms added + //***************************************************************************** + // ACT + //***************************************************************************** +#define DefineActPolicySpace(N) TPMT_HA act_##N; + FOR_EACH_ACT(DefineActPolicySpace) + +#endif // libtpms added +} STATE_CLEAR_DATA; +EXTERN STATE_CLEAR_DATA gc; + +/* 5.9.11.5 State Reset Data */ +/* This structure contains data is that is saved on Shutdown(STATE) and restored on the subsequent + Startup(ANY). That is, the data is preserved across TPM Resume and TPM Restart. */ +/* If a default value is specified in the comments this value is applied on TPM Reset. */ +typedef struct state_reset_data +{ + //***************************************************************************** + // Hierarchy Control + //***************************************************************************** + TPM2B_PROOF nullProof; // The proof value associated with + // the TPM_RH_NULL hierarchy. The + // default reset value is from the RNG. + TPM2B_SEED nullSeed; // The seed value for the TPM_RN_NULL + SEED_COMPAT_LEVEL nullSeedCompatLevel; // libtpms added + // hierarchy. The default reset value + // is from the RNG. + //***************************************************************************** + // Context + //***************************************************************************** + // The 'clearCount' counter is incremented each time the TPM successfully executes + // a TPM Resume. The counter is included in each saved context that has 'stClear' + // SET (including descendants of keys that have 'stClear' SET). This prevents these + // objects from being loaded after a TPM Resume. + // If 'clearCount' is at its maximum value when the TPM receives a Shutdown(STATE), + // the TPM will return TPM_RC_RANGE and the TPM will only accept Shutdown(CLEAR). + UINT32 clearCount; // The default reset value is 0. + UINT64 objectContextID; // This is the context ID for a saved + // object context. The default reset + // value is 0. + CONTEXT_SLOT contextArray[MAX_ACTIVE_SESSIONS]; // This array contains + // contains the values used to track + // the version numbers of saved + // contexts (see + // Session.c in for details). The + // default reset value is {0}. + CONTEXT_COUNTER contextCounter; // This is the value from which the + // 'contextID' is derived. The + // default reset value is {0}. + //***************************************************************************** + // Command Audit + //***************************************************************************** + // When an audited command completes, ExecuteCommand() checks the return + // value. If it is TPM_RC_SUCCESS, and the command is an audited command, the + // TPM will extend the cpHash and rpHash for the command to this value. If this + // digest was the Zero Digest before the cpHash was extended, the audit counter + // is incremented. + TPM2B_DIGEST commandAuditDigest; // This value is set to an Empty Digest + // by TPM2_GetCommandAuditDigest() or a + // TPM Reset. + //***************************************************************************** + // Boot counter + //***************************************************************************** + UINT32 restartCount; // This counter counts TPM Restarts. + // The default reset value is 0. + //********************************************************************************* + // PCR + //********************************************************************************* + // This counter increments whenever the PCR are updated. This counter is preserved + // across TPM Resume even though the PCR are not preserved. This is because + // sessions remain active across TPM Restart and the count value in the session + // is compared to this counter so this counter must have values that are unique + // as long as the sessions are active. + // NOTE: A platform-specific specification may designate that certain PCR changes + // do not increment this counter to increment. + UINT32 pcrCounter; // The default reset value is 0. +#if ALG_ECC + //***************************************************************************** + // ECDAA + //***************************************************************************** + UINT64 commitCounter; // This counter increments each time + // TPM2_Commit() returns + // TPM_RC_SUCCESS. The default reset + // value is 0. + TPM2B_NONCE commitNonce; // This random value is used to compute + // the commit values. The default reset + // value is from the RNG. + // This implementation relies on the number of bits in g_commitArray being a + // power of 2 (8, 16, 32, 64, etc.) and no greater than 64K. + BYTE commitArray[16]; // The default reset value is {0}. +#endif // ALG_ECC +} STATE_RESET_DATA; +EXTERN STATE_RESET_DATA gr; + + // libtpms added begin +/* The s_ContextSlotMask masks CONTEXT_SLOT values; this variable can have + * only two valid values, 0xff or 0xffff. The former is used to simulate + * a CONTEXT_SLOT defined as UINT8, the latter is used for the CONTEXT_SLOT + * when it is a UINT16. The original TPM 2 code uses a cast to CONTEXT_SLOT + * to truncate larger values and has been modified to use CONTEXT_SLOT_MASKED + * to achieve the same effect with the above two values. + * + * Using CONTEXT_SLOT_MASKED we make sure that when we write values into + * gr.contextArray that these values are properly masked/truncated so that + * when we read values from gr.contextArray that we don't have to mask + * them again. + * + * s_ContextSlotMask may only be initialized to 0xff when resuming an older + * state from the time when CONTEXT_SLOT was UINT8, otherwise it must be set + * to 0xffff. We set it to 0xffff in SessionStartup(SU_CLEAR) and to be + * able to save the TPM state really early (and restore it) also in + * TPM_Manufacture(). + */ +EXTERN CONTEXT_SLOT s_ContextSlotMask; +#define CONTEXT_SLOT_MASKED(val) ((CONTEXT_SLOT)(val) & s_ContextSlotMask) // libtpms added end + +/* 5.9.12 NV Layout */ +/* The NV data organization is */ +/* a) a PERSISTENT_DATA structure */ +/* b) a STATE_RESET_DATA structure */ +/* c) a STATE_CLEAR_DATA structure */ +/* d) an ORDERLY_DATA structure */ +/* e) the user defined NV index space */ + +/* libtpms added: to put certain data structure at fixed offsets + * to give the ones below some room to expand + */ +#define NV_PERSISTENT_DATA (0) +#define NV_STATE_RESET_DATA (NV_PERSISTENT_DATA + sizeof(PERSISTENT_DATA)) +#define NV_STATE_CLEAR_DATA (NV_STATE_RESET_DATA + sizeof(STATE_RESET_DATA)) +#define NV_ORDERLY_DATA (NV_STATE_CLEAR_DATA + sizeof(STATE_CLEAR_DATA)) +#define NV_INDEX_RAM_DATA TPM2_ROUNDUP(NV_ORDERLY_DATA + sizeof(ORDERLY_DATA),\ + 1024) /* libtpms added */ +#define NV_USER_DYNAMIC (NV_INDEX_RAM_DATA + sizeof(s_indexOrderlyRam)) +#define NV_USER_DYNAMIC_END NV_MEMORY_SIZE + +/* 5.9.13 Global Macro Definitions */ +/* The NV_READ_PERSISTENT and NV_WRITE_PERSISTENT macros are used to access members of the + PERSISTENT_DATA structure in NV. */ +#define NV_READ_PERSISTENT(to, from) \ + NvRead(&to, offsetof(PERSISTENT_DATA, from), sizeof(to)) +#define NV_WRITE_PERSISTENT(to, from) \ + NvWrite(offsetof(PERSISTENT_DATA, to), sizeof(gp.to), &from) +#define CLEAR_PERSISTENT(item) \ + NvClearPersistent(offsetof(PERSISTENT_DATA, item), sizeof(gp.item)) +#define NV_SYNC_PERSISTENT(item) NV_WRITE_PERSISTENT(item, gp.item) + +/* At the start of command processing, the index of the command is determined. This index value is + used to access the various data tables that contain per-command information. There are multiple + options for how the per-command tables can be implemented. This is resolved in + GetClosestCommandIndex(). */ +typedef UINT16 COMMAND_INDEX; +#define UNIMPLEMENTED_COMMAND_INDEX ((COMMAND_INDEX)(~0)) +#if 0 /* libtpms added */ +typedef struct _COMMAND_FLAGS_ +{ +#if LITTLE_ENDIAN_TPM == YES /* libtpms added */ + unsigned trialPolicy : 1; //1) If SET, one of the handles references a + // trial policy and authorization may be + // skipped. This is only allowed for a policy + // command. + unsigned reserved : 31; //2-31) /* libtpms added begin */ +#endif +#if BIG_ENDIAN_TPM == YES + unsigned reserved : 31; //2-31) + unsigned trialPolicy : 1; //1) If SET, one of the handles references a +#endif /* libtpms added end */ +} COMMAND_FLAGS; +#endif /* libtpms added */ + +/* This structure is used to avoid having to manage a large number of parameters being passed + through various levels of the command input processing. + + The following macros are used to define the space for the CP and RP hashes. Space is provided + for each implemented hash algorithm because it is not known what the caller may use. +*/ + +#define CP_HASH(HASH, Hash) TPM2B_##HASH##_DIGEST Hash##CpHash; +#define RP_HASH(HASH, Hash) TPM2B_##HASH##_DIGEST Hash##RpHash; + +typedef struct _COMMAND_ +{ + TPM_ST tag; // the parsed command tag + TPM_CC code; // the parsed command code + COMMAND_INDEX index; // the computed command index + UINT32 handleNum; // the number of entity handles in the + // handle area of the command + TPM_HANDLE handles[MAX_HANDLE_NUM]; // the parsed handle values + UINT32 sessionNum; // the number of sessions found + INT32 parameterSize; // starts out with the parsed command size + // and is reduced and values are unmarshaled. Just before calling the command actions, this + // should be zero. After the command actions, this number should grow as values are marshaled + // in to the response buffer. + INT32 authSize; // this is initialized with the parsed size + // of authorizationSize field and should be zero when the authorizations are parsed. + BYTE *parameterBuffer; // input to ExecuteCommand + BYTE *responseBuffer; // input to ExecuteCommand + FOR_EACH_HASH(CP_HASH) // space for the CP hashes + FOR_EACH_HASH(RP_HASH) // space for the RP hashes +} COMMAND; + +// Global string constants for consistency in KDF function calls. These string constants are shared +// across functions to make sure that they are all using consistent string values. +#define STRING_INITIALIZER(value) {{sizeof(value), {value}}} +#define TPM2B_STRING(name, value) \ + typedef union name##_ { \ + struct { \ + UINT16 size; \ + BYTE buffer[sizeof(value)]; \ + } t; \ + TPM2B b; \ + } TPM2B_##name##_; \ + EXTERN const TPM2B_##name##_ name##_ INITIALIZER(STRING_INITIALIZER(value)); \ + EXTERN const TPM2B *name INITIALIZER(&name##_.b) +TPM2B_STRING(PRIMARY_OBJECT_CREATION, "Primary Object Creation"); +TPM2B_STRING(CFB_KEY, "CFB"); +TPM2B_STRING(CONTEXT_KEY, "CONTEXT"); +TPM2B_STRING(INTEGRITY_KEY, "INTEGRITY"); +TPM2B_STRING(SECRET_KEY, "SECRET"); +TPM2B_STRING(SESSION_KEY, "ATH"); +TPM2B_STRING(STORAGE_KEY, "STORAGE"); +TPM2B_STRING(XOR_KEY, "XOR"); +TPM2B_STRING(COMMIT_STRING, "ECDAA Commit"); +TPM2B_STRING(DUPLICATE_STRING, "DUPLICATE"); +TPM2B_STRING(IDENTITY_STRING, "IDENTITY"); +TPM2B_STRING(OBFUSCATE_STRING, "OBFUSCATE"); +#if SELF_TEST +TPM2B_STRING(OAEP_TEST_STRING, "OAEP Test Value"); +#endif // SELF_TEST + +// 5.9.14 From CryptTest.c +// This structure contains the self-test state values for the cryptographic modules. +EXTERN CRYPTO_SELF_TEST_STATE g_cryptoSelfTestState; + +/* 5.9.15 From Manufacture.c */ +EXTERN BOOL g_manufactured; +/* This value indicates if a TPM2_Startup() commands has been receive since the power on event. + This flag is maintained in power simulation module because this is the only place that may + reliably set this flag to FALSE. */ +EXTERN BOOL g_initialized; + +/* 5.9.16 Private data */ +#if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C +/* From SessionProcess.c */ +/* The following arrays are used to save command sessions information so that the command + handle/session buffer does not have to be preserved for the duration of the command. These arrays + are indexed by the session index in accordance with the order of sessions in the session area of + the command. */ + +/* Array of the authorization session handles */ +EXTERN TPM_HANDLE s_sessionHandles[MAX_SESSION_NUM]; + +/* Array of authorization session attributes */ +EXTERN TPMA_SESSION s_attributes[MAX_SESSION_NUM]; + +/* Array of handles authorized by the corresponding authorization sessions; and if none, then + TPM_RH_UNASSIGNED value is used */ + +EXTERN TPM_HANDLE s_associatedHandles[MAX_SESSION_NUM]; + +/* Array of nonces provided by the caller for the corresponding sessions */ +EXTERN TPM2B_NONCE s_nonceCaller[MAX_SESSION_NUM]; + +/* Array of authorization values (HMAC's or passwords) for the corresponding sessions */ +EXTERN TPM2B_AUTH s_inputAuthValues[MAX_SESSION_NUM]; + +/* Array of pointers to the SESSION structures for the sessions in a command */ +EXTERN SESSION *s_usedSessions[MAX_SESSION_NUM]; + +/* Special value to indicate an undefined session index */ +#define UNDEFINED_INDEX (0xFFFF) +/* Index of the session used for encryption of a response parameter */ +EXTERN UINT32 s_encryptSessionIndex; + +/* Index of the session used for decryption of a command parameter */ +EXTERN UINT32 s_decryptSessionIndex; + +/* Index of a session used for audit */ +EXTERN UINT32 s_auditSessionIndex; + +/* The cpHash for command audit */ +#if CC_GetCommandAuditDigest +EXTERN TPM2B_DIGEST s_cpHashForCommandAudit; +#endif + +/* Flag indicating if NV update is pending for the lockOutAuthEnabled or failedTries DA parameter */ +EXTERN BOOL s_DAPendingOnNV; + +#endif // SESSION_PROCESS_C + +/* 5.9.16.2 From DA.c */ +#if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C + +/* From DA.c */ +/* This variable holds the accumulated time since the last time that failedTries was + decremented. This value is in millisecond. */ + +#if !ACCUMULATE_SELF_HEAL_TIMER +EXTERN UINT64 s_selfHealTimer; + +/* This variable holds the accumulated time that the lockoutAuth has been blocked. */ +EXTERN UINT64 s_lockoutTimer; + +#endif // ACCUMULATE_SELF_HEAL_TIMER +#endif // DA_C + +/* 5.9.16.3 From NV.c */ + +#if defined NV_C || defined GLOBAL_C + +/* From NV.c */ +/* This marks the end of the NV area. This is a run-time variable as it might not be compile-time + constant. */ +EXTERN NV_REF s_evictNvEnd; + +/* This space is used to hold the index data for an orderly Index. It also contains the attributes + for the index. */ +EXTERN BYTE s_indexOrderlyRam[RAM_INDEX_SPACE]; // The orderly NV Index data + +/* This value contains the current max counter value. It is written to the end of allocatable NV + space each time an index is deleted or added. This value is initialized on Startup. The indices + are searched and the maximum of all the current counter indices and this value is the initial + value for this. */ +EXTERN UINT64 s_maxCounter; + +/* This is space used for the NV Index cache. As with a persistent object, the contents of a + referenced index are copied into the cache so that the NV Index memory scanning and data copying + can be reduced. Only code that operates on NV Index data should use this cache directly. When + that action code runs, s_lastNvIndex will contain the index header information. It will have been + loaded when the handles were verified. */ +/* NOTE: An NV index handle can appear in many commands that do not operate on the NV data + (e.g. TPM2_StartAuthSession()). However, only one NV Index at a time is ever directly referenced + by any command. If that changes, then the NV Index caching needs to be changed to accommodate + that. Currently, the code will verify that only one NV Index is referenced by the handles of the + command. */ + +EXTERN NV_INDEX s_cachedNvIndex; +EXTERN NV_REF s_cachedNvRef; +EXTERN BYTE *s_cachedNvRamRef; + +/* Initial NV Index/evict object iterator value */ +#define NV_REF_INIT (NV_REF)0xFFFFFFFF +#endif + +/* 5.9.16.4 From Object.c */ +#if defined OBJECT_C || defined GLOBAL_C + +/* This type is the container for an object. */ + +EXTERN OBJECT s_objects[MAX_LOADED_OBJECTS]; +#endif // OBJECT_C + +/* 5.9.17.5 From PCR.c */ + +#if defined PCR_C || defined GLOBAL_C + +/* The following macro is used to define the per-implemented-hash space. This implementation + reserves space for all implemented hashes. */ + +#define PCR_ALL_HASH(HASH, Hash) BYTE Hash##Pcr[HASH##_DIGEST_SIZE]; + +typedef struct +{ + FOR_EACH_HASH(PCR_ALL_HASH) +} PCR; + +typedef struct +{ + unsigned int stateSave : 1; // if the PCR value should be + // saved in state save + unsigned int resetLocality : 5; // The locality that the PCR + // can be reset + unsigned int extendLocality : 5; // The locality that the PCR + // can be extend +} PCR_Attributes; +EXTERN PCR s_pcrs[IMPLEMENTATION_PCR]; +#endif // PCR_C + +/* 5.9.16.6 From Session.c */ + +#if defined SESSION_C || defined GLOBAL_C + +/* Container for HMAC or policy session tracking information */ +typedef struct +{ + BOOL occupied; + SESSION session; // session structure +} SESSION_SLOT; +EXTERN SESSION_SLOT s_sessions[MAX_LOADED_SESSIONS]; +/* The index in contextArray that has the value of the oldest saved session context. When no context + is saved, this will have a value that is greater than or equal to MAX_ACTIVE_SESSIONS. */ + +EXTERN UINT32 s_oldestSavedSession; +/* The number of available session slot openings. When this is 1, a session can't be created or + loaded if the GAP is maxed out. The exception is that the oldest saved session context can always + be loaded (assuming that there is a space in memory to put it) */ +EXTERN int s_freeSessionSlots; + +#endif // SESSION_C + +/* 5.9.16.7 From IoBuffers.c */ + +#if defined IO_BUFFER_C || defined GLOBAL_C + +/* The value of s_actionIoAllocation is the number of UINT64 values allocated. It is used to set the + pointer for the response structure. */ +EXTERN UINT64 s_actionIoBuffer[768]; // action I/O buffer +EXTERN UINT32 s_actionIoAllocation; // number of UIN64 allocated for the action input + // structure +#endif // MEMORY_LIB_C + +/* 5.9.16.8 From TPMFail.c */ + +/* This value holds the address of the string containing the name of the function in which the + failure occurred. This address value isn't useful for anything other than helping the vendor to + know in which file the failure occurred. */ +EXTERN BOOL g_inFailureMode; // Indicates that the TPM is in failure mode +#if SIMULATION +EXTERN BOOL g_forceFailureMode; // flag to force failure mode during test +#endif +typedef void(FailFunction)(const char *function, int line, int code); +#if defined TPM_FAIL_C || defined GLOBAL_C || 1 +EXTERN UINT32 s_failFunction; +EXTERN UINT32 s_failLine; // the line in the file at which +// the error was signaled +EXTERN UINT32 s_failCode; // the error code used +EXTERN FailFunction *LibFailCallback; +#endif // TPM_FAIL_C + +//***************************************************************************** +//*** From ACT_spt.c +//***************************************************************************** +// This value is used to indicate if an ACT has been updated since the last +// TPM2_Startup() (one bit for each ACT). If the ACT is not updated +// (TPM2_ACT_SetTimeout()) after a startup, then on each TPM2_Shutdown() the TPM will +// save 1/2 of the current timer value. This prevents an attack on the ACT by saving +// the counter and then running for a long period of time before doing a TPM Restart. +// A quick TPM2_Shutdown() after each +EXTERN UINT16 s_ActUpdated; + +/* 5.9.16.9 From CommandCodeAttributes.c */ + +extern const TPMA_CC s_ccAttr[]; +extern const COMMAND_ATTRIBUTES s_commandAttributes[]; + +#endif // GLOBAL_H diff --git a/src/tpm2/GpMacros.h b/src/tpm2/GpMacros.h new file mode 100644 index 0000000..d557e02 --- /dev/null +++ b/src/tpm2/GpMacros.h @@ -0,0 +1,354 @@ +/********************************************************************************/ +/* */ +/* This file is a collection of miscellaneous macros. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: GpMacros.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#ifndef GPMACROS_H +#define GPMACROS_H + +/* 5.10.1 Introduction */ +/* This file is a collection of miscellaneous macros. */ +#ifndef NULL +#define NULL 0 +#endif +#include "swap.h" +#include "VendorString.h" +/* 5.10.2 For Self-test */ +/* These macros are used in CryptUtil() to invoke the incremental self test. */ +#if SELF_TEST +# define TEST(alg) if(TEST_BIT(alg, g_toTest)) CryptTestAlgorithm(alg, NULL) +/* Use of TPM_ALG_NULL is reserved for RSAEP/RSADP testing. If someone is wanting to test a hash + with that value, don't do it. */ +# define TEST_HASH(alg) \ + if(TEST_BIT(alg, g_toTest) \ + && (alg != TPM_ALG_NULL)) \ + CryptTestAlgorithm(alg, NULL) +#else +# define TEST(alg) +# define TEST_HASH(alg) +#endif // SELF_TEST +/* 5.10.3 For Failures */ +#if defined _POSIX_ +# define FUNCTION_NAME __func__ /* libtpms changed */ +#else +# define FUNCTION_NAME __FUNCTION__ +#endif +#if !FAIL_TRACE +# define FAIL(errorCode) (TpmFail(errorCode)) +# define LOG_FAILURE(errorCode) (TpmLogFailure(errorCode)) +#else +# define FAIL(errorCode) TpmFail(FUNCTION_NAME, __LINE__, errorCode) +# define LOG_FAILURE(errorCode) TpmLogFailure(FUNCTION_NAME, __LINE__, errorCode) +#endif +/* If implementation is using longjmp, then the call to TpmFail() does not return and the compiler + will complain about unreachable code that comes after. To allow for not having longjmp, TpmFail() + will return and the subsequent code will be executed. This macro accounts for the difference. */ +#ifndef NO_LONGJMP +# define FAIL_RETURN(returnCode) +# define TPM_FAIL_RETURN NORETURN void +#else +# define FAIL_RETURN(returnCode) return (returnCode) +# define TPM_FAIL_RETURN void +#endif +/* This macro tests that a condition is TRUE and puts the TPM into failure mode if it is not. If + longjmp is being used, then the FAIL(FATAL_ERROR_) macro makes a call from which there is no + return. Otherwise, it returns and the function will exit with the appropriate return code. */ +#define REQUIRE(condition, errorCode, returnCode) \ + { \ + if(!!(condition)) \ + { \ + FAIL(FATAL_ERROR_errorCode); \ + FAIL_RETURN(returnCode); \ + } \ + } +#define PARAMETER_CHECK(condition, returnCode) \ + REQUIRE((condition), PARAMETER, returnCode) +#if defined EMPTY_ASSERT && (EMPTY_ASSERT != NO) +# define pAssert(a) ((void)0) +#else +# define pAssert(a) {if(!(a)) FAIL(FATAL_ERROR_PARAMETER);} +#endif +/* 5.10.4 Derived from Vendor-specific values */ +/* Values derived from vendor specific settings in TpmProfile.h */ +#define PCR_SELECT_MIN ((PLATFORM_PCR+7)/8) +#define PCR_SELECT_MAX ((IMPLEMENTATION_PCR+7)/8) +#define MAX_ORDERLY_COUNT ((1 << ORDERLY_BITS) - 1) +#define RSA_MAX_PRIME (MAX_RSA_KEY_BYTES / 2) +#define RSA_PRIVATE_SIZE (RSA_MAX_PRIME * 5) + +/* 5.10.5 Compile-time Checks */ +/* In some cases, the relationship between two values may be dependent on things that change based + on various selections like the chosen cryptographic libraries. It is possible that these + selections will result in incompatible settings. These are often detectable by the compiler but + it isn't always possible to do the check in the preprocessor code. For example, when the check + requires use of sizeof then the preprocessor can't do the comparison. For these cases, we include + a special macro that, depending on the compiler will generate a warning to indicate if the check + always passes or always fails because it involves fixed constants. To run these checks, define + COMPILER_CHECKS in TpmBuildSwitches.h */ +#if COMPILER_CHECKS +# define cAssert pAssert +#else +# define cAssert(value) +#endif +/* This is used commonly in the Crypt code as a way to keep listings from getting too long. This is + not to save paper but to allow one to see more useful stuff on the screen at any given time. */ +#define ERROR_RETURN(returnCode) \ + { \ + retVal = returnCode; \ + goto Exit; \ + } +#ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef IsOdd +# define IsOdd(a) (((a) & 1) != 0) +#endif +#ifndef BITS_TO_BYTES +# define BITS_TO_BYTES(bits) (((bits) + 7) >> 3) +#endif +#ifndef DIV_UP +# define DIV_UP(var, div) ((var + div - 1) / (div)) +#endif +/* These are defined for use when the size of the vector being checked is known at compile time. */ +#define TEST_BIT(bit, vector) TestBit((bit), (BYTE *)&(vector), sizeof(vector)) +#define SET_BIT(bit, vector) SetBit((bit), (BYTE *)&(vector), sizeof(vector)) +#define CLEAR_BIT(bit, vector) ClearBit((bit), (BYTE *)&(vector), sizeof(vector)) +/* The following definitions are used if they have not already been defined. The defaults for these + settings are compatible with ISO/IEC 9899:2011 (E) */ +#ifndef LIB_EXPORT +# define LIB_EXPORT +# define LIB_IMPORT +#endif +#ifndef NORETURN +# define NORETURN _Noreturn +#endif +#ifndef NOT_REFERENCED +# define NOT_REFERENCED(x = x) ((void) (x)) +#endif +#define STD_RESPONSE_HEADER (sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_RC)) +#define JOIN(x,y) x##y +#define JOIN3(x, y, z) x##y##z +#define CONCAT(x,y) JOIN(x, y) +#define CONCAT3(x, y, z) JOIN3(x,y,z) + +/* If CONTEXT_INTEGRITY_HASH_ALG is defined, then the vendor is using the old style + table. Otherwise, pick the strongest implemented hash algorithm as the context hash. */ + +#ifndef CONTEXT_HASH_ALGORITHM +# if defined ALG_SHA3_512 && ALG_SHA3_512 == YES +# define CONTEXT_HASH_ALGORITHM SHA3_512 +# elif defined ALG_SHA512 && ALG_SHA512 == YES +# define CONTEXT_HASH_ALGORITHM SHA512 +# elif defined ALG_SHA3_384 && ALG_SHA3_384 == YES +# define CONTEXT_HASH_ALGORITHM SHA3_384 +# elif defined ALG_SHA384 && ALG_SHA384 == YES +# define CONTEXT_HASH_ALGORITHM SHA384 +# elif defined ALG_SHA3_256 && ALG_SHA3_256 == YES +# define CONTEXT_HASH_ALGORITHM SHA3_256 +# elif defined ALG_SHA256 && ALG_SHA256 == YES +# define CONTEXT_HASH_ALGORITHM SHA256 +# elif defined ALG_SM3_256 && ALG_SM3_256 == YES +# define CONTEXT_HASH_ALGORITHM SM3_256 +# elif defined ALG_SHA1 && ALG_SHA1 == YES +# define CONTEXT_HASH_ALGORITHM SHA1 +# endif +# define CONTEXT_INTEGRITY_HASH_ALG CONCAT(TPM_ALG_, CONTEXT_HASH_ALGORITHM) +#if CONTEXT_HASH_ALGORITHM != SHA512 // libtpms added begin +#error CONTEXT_HASH_ALGORITHM must remain SHA512 +#endif // libtpms added end +#endif + +#ifndef CONTEXT_INTEGRITY_HASH_SIZE +#define CONTEXT_INTEGRITY_HASH_SIZE CONCAT(CONTEXT_HASH_ALGORITHM, _DIGEST_SIZE) +#endif +#if ALG_RSA +#define RSA_SECURITY_STRENGTH (MAX_RSA_KEY_BITS >= 15360 ? 256 : \ + (MAX_RSA_KEY_BITS >= 7680 ? 192 : \ + (MAX_RSA_KEY_BITS >= 3072 ? 128 : \ + (MAX_RSA_KEY_BITS >= 2048 ? 112 : \ + (MAX_RSA_KEY_BITS >= 1024 ? 80 : 0))))) +#else +#define RSA_SECURITY_STRENGTH 0 +#endif // ALG_RSA +#if ALG_ECC +#define ECC_SECURITY_STRENGTH (MAX_ECC_KEY_BITS >= 521 ? 256 : \ + (MAX_ECC_KEY_BITS >= 384 ? 192 : \ + (MAX_ECC_KEY_BITS >= 256 ? 128 : 0))) +#else +#define ECC_SECURITY_STRENGTH 0 +#endif // ALG_ECC +#define MAX_ASYM_SECURITY_STRENGTH \ + MAX(RSA_SECURITY_STRENGTH, ECC_SECURITY_STRENGTH) +#define MAX_HASH_SECURITY_STRENGTH ((CONTEXT_INTEGRITY_HASH_SIZE * 8) / 2) + +/* Unless some algorithm is broken... */ + +#define MAX_SYM_SECURITY_STRENGTH MAX_SYM_KEY_BITS +#define MAX_SECURITY_STRENGTH_BITS \ + MAX(MAX_ASYM_SECURITY_STRENGTH, \ + MAX(MAX_SYM_SECURITY_STRENGTH, \ + MAX_HASH_SECURITY_STRENGTH)) +/* This is the size that was used before the 1.38 errata requiring that P1.14.4 be followed */ +#define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE +/* As required by P1.14.4 */ +#define COMPLIANT_PROOF_SIZE \ + (MAX(CONTEXT_INTEGRITY_HASH_SIZE, (2 * MAX_SYM_KEY_BYTES))) +/* As required by P1.14.3.1 */ +#define COMPLIANT_PRIMARY_SEED_SIZE \ + BITS_TO_BYTES(MAX_SECURITY_STRENGTH_BITS * 2) +/* This is the pre-errata version */ +#ifndef PRIMARY_SEED_SIZE +# define PRIMARY_SEED_SIZE PROOF_SIZE +#endif +#if USE_SPEC_COMPLIANT_PROOFS +# undef PROOF_SIZE +# define PROOF_SIZE COMPLIANT_PROOF_SIZE +# undef PRIMARY_SEED_SIZE +# define PRIMARY_SEED_SIZE COMPLIANT_PRIMARY_SEED_SIZE +#endif // USE_SPEC_COMPLIANT_PROOFS +#if !SKIP_PROOF_ERRORS +# if PROOF_SIZE < COMPLIANT_PROOF_SIZE +# error "PROOF_SIZE is not compliant with TPM specification" +# endif +# if PRIMARY_SEED_SIZE < COMPLIANT_PRIMARY_SEED_SIZE +# error "Non-compliant PRIMARY_SEED_SIZE" +# endif +#endif // !SKIP_PROOF_ERRORS + +/* If CONTEXT_ENCRYPT_ALG is defined, then the vendor is using the old style table */ +#if defined CONTEXT_ENCRYPT_ALG +# undef CONTEXT_ENCRYPT_ALGORITHM +# if CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE +# define CONTEXT_ENCRYPT_ALGORITHM AES +# elif CONTEXT_ENCRYPT_ALG == ALG_SM4_VALUE +# define CONTEXT_ENCRYPT_ALGORITHM SM4 +# elif CONTEXT_ENCRYPT_ALG == ALG_CAMELLIA_VALUE +# define CONTEXT_ENCRYPT_ALGORITHM CAMELLIA +# elif CONTEXT_ENCRYPT_ALG == ALG_TDES_VALUE +# error Are you kidding? +# else +# error Unknown value for CONTEXT_ENCRYPT_ALG +# endif // CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE +#else +# define CONTEXT_ENCRYPT_ALG \ + CONCAT3(ALG_, CONTEXT_ENCRYPT_ALGORITHM, _VALUE) +#endif // CONTEXT_ENCRYPT_ALG +#define CONTEXT_ENCRYPT_KEY_BITS \ + CONCAT(CONTEXT_ENCRYPT_ALGORITHM, _MAX_KEY_SIZE_BITS) +#define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS+7)/8) + +/* This is updated to follow the requirement of P2 that the label not be larger than 32 bytes. */ +#ifndef LABEL_MAX_BUFFER +#define LABEL_MAX_BUFFER MIN(32, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE)) +#endif +/* This bit is used to indicate that an authorization ticket expires on TPM Reset and TPM Restart.It + is added to the timeout value returned by TPM2_PoliySigned() and TPM2_PolicySecret() and used by + TPM2_PolicyTicket(). The timeout value is relative to Time (g_time). Time is reset whenever the + TPM loses power and cannot be moved forward by the user (as can Clock). g_time is a 64-bit value + expressing time in ms. Stealing the MSb() for a flag means that the TPM needs to be reset at least + once every 292,471,208 years rather than once every 584,942,417 years. */ +#define EXPIRATION_BIT ((UINT64)1 << 63) +/* Check for consistency of the bit ordering of bit fields */ +#if BIG_ENDIAN_TPM && MOST_SIGNIFICANT_BIT_0 && USE_BIT_FIELD_STRUCTURES +# error "Settings not consistent" +#endif +/* These macros are used to handle the variation in handling of bit fields. If */ +#if USE_BIT_FIELD_STRUCTURES // The default, old version, with bit fields +# define IS_ATTRIBUTE(a, type, b) ((a.b) != 0) +# define SET_ATTRIBUTE(a, type, b) (a.b = SET) +# define CLEAR_ATTRIBUTE(a, type, b) (a.b = CLEAR) +# define GET_ATTRIBUTE(a, type, b) (a.b) +# define TPMA_ZERO_INITIALIZER() {0} +#else +# define IS_ATTRIBUTE(a, type, b) ((a & type##_##b) != 0) +# define SET_ATTRIBUTE(a, type, b) (a |= type##_##b) +# define CLEAR_ATTRIBUTE(a, type, b) (a &= ~type##_##b) +# define GET_ATTRIBUTE(a, type, b) \ + (type)((a & type##_##b) >> type##_##b##_SHIFT) +# define TPMA_ZERO_INITIALIZER() (0) +#endif +#define VERIFY(_X) if(!(_X)) goto Error +// These macros determine if the values in this file are referenced or instanced. +// Global.c defines GLOBAL_C so all the values in this file will be instanced in +// Global.obj. For all other files that include this file, the values will simply +// be external references. For constants, there can be an initializer. + +#ifdef GLOBAL_C +#define EXTERN +#define INITIALIZER(_value_) = _value_ +#else +#define EXTERN extern +#define INITIALIZER(_value_) +#endif + +// This macro will create an OID. All OIDs are in DER form with a first octet of +// 0x06 indicating an OID fallowed by an octet indicating the number of octets in the +// rest of the OID. This allows a user of this OID to know how much/little to copy. +#define MAKE_OID(NAME) \ + EXTERN const BYTE OID##NAME[] INITIALIZER({OID##NAME##_VALUE}) + +/* This definition is moved from TpmProfile.h because it is not actually vendor- specific. It has to + be the same size as the sequence parameter of a TPMS_CONTEXT and that is a UINT64. So, this is an + invariant value */ +#define CONTEXT_COUNTER UINT64 + +#endif // GP_MACROS_H diff --git a/src/tpm2/HMAC_Start_fp.h b/src/tpm2/HMAC_Start_fp.h new file mode 100644 index 0000000..a05ddf1 --- /dev/null +++ b/src/tpm2/HMAC_Start_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: HMAC_Start_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef HMAC_START_FP_H +#define HMAC_START_FP_H + +typedef struct { + TPMI_DH_OBJECT handle; + TPM2B_AUTH auth; + TPMI_ALG_HASH hashAlg; +} HMAC_Start_In; + +typedef struct { + TPMI_DH_OBJECT sequenceHandle; +} HMAC_Start_Out; + +#define RC_HMAC_Start_handle (TPM_RC_H + TPM_RC_1) +#define RC_HMAC_Start_auth (TPM_RC_P + TPM_RC_1) +#define RC_HMAC_Start_hashAlg (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_HMAC_Start( + HMAC_Start_In *in, // IN: input parameter list + HMAC_Start_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/HMAC_fp.h b/src/tpm2/HMAC_fp.h new file mode 100644 index 0000000..deb4fc2 --- /dev/null +++ b/src/tpm2/HMAC_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: HMAC_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef HMAC_FP_H +#define HMAC_FP_H + +typedef struct { + TPMI_DH_OBJECT handle; + TPM2B_MAX_BUFFER buffer; + TPMI_ALG_HASH hashAlg; +} HMAC_In; + +#define RC_HMAC_handle (TPM_RC_H + TPM_RC_1) +#define RC_HMAC_buffer (TPM_RC_P + TPM_RC_1) +#define RC_HMAC_hashAlg (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM2B_DIGEST outHMAC; +} HMAC_Out; + +TPM_RC +TPM2_HMAC( + HMAC_In *in, // IN: input parameter list + HMAC_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/Handle.c b/src/tpm2/Handle.c new file mode 100644 index 0000000..d762135 --- /dev/null +++ b/src/tpm2/Handle.c @@ -0,0 +1,213 @@ +/********************************************************************************/ +/* */ +/* fUnctions that return the type of a handle. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Handle.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 9.6 Handle.c */ +/* 9.6.1 Description */ +/* This file contains the functions that return the type of a handle. */ +/* 9.6.2 Includes */ +#include "Tpm.h" +/* 9.6.3 Functions */ +/* 9.6.3.1 HandleGetType() */ +/* This function returns the type of a handle which is the MSO of the handle. */ +TPM_HT +HandleGetType( + TPM_HANDLE handle // IN: a handle to be checked + ) +{ + // return the upper bytes of input data + return (TPM_HT)((handle & HR_RANGE_MASK) >> HR_SHIFT); +} +/* 9.6.3.2 NextPermanentHandle() */ +/* This function returns the permanent handle that is equal to the input value or is the next higher + value. If there is no handle with the input value and there is no next higher value, it returns + 0: */ +TPM_HANDLE +NextPermanentHandle( + TPM_HANDLE inHandle // IN: the handle to check + ) +{ + // If inHandle is below the start of the range of permanent handles + // set it to the start and scan from there + if(inHandle < TPM_RH_FIRST) + inHandle = TPM_RH_FIRST; + // scan from input value until we find an implemented permanent handle + // or go out of range + for(; inHandle <= TPM_RH_LAST; inHandle++) + { + switch(inHandle) + { + case TPM_RH_OWNER: + case TPM_RH_NULL: + case TPM_RS_PW: + case TPM_RH_LOCKOUT: + case TPM_RH_ENDORSEMENT: + case TPM_RH_PLATFORM: + case TPM_RH_PLATFORM_NV: +#ifdef VENDOR_PERMANENT + case VENDOR_PERMANENT: +#endif + // Each of the implemented ACT +#define ACT_IMPLEMENTED_CASE(N) \ + case TPM_RH_ACT_##N: + + FOR_EACH_ACT(ACT_IMPLEMENTED_CASE) + + return inHandle; + break; + default: + break; + } + } + // Out of range on the top + return 0; +} +/* 9.6.3.3 PermanentCapGetHandles() */ +/* This function returns a list of the permanent handles of PCR, started from handle. If handle is + larger than the largest permanent handle, an empty list will be returned with more set to NO. */ +/* Return Values Meaning */ +/* YES if there are more handles available */ +/* NO all the available handles has been returned */ +TPMI_YES_NO +PermanentCapGetHandles( + TPM_HANDLE handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ) +{ + TPMI_YES_NO more = NO; + UINT32 i; + pAssert(HandleGetType(handle) == TPM_HT_PERMANENT); + // Initialize output handle list + handleList->count = 0; + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; + // Iterate permanent handle range + for(i = NextPermanentHandle(handle); + i != 0; i = NextPermanentHandle(i + 1)) + { + if(handleList->count < count) + { + // If we have not filled up the return list, add this permanent + // handle to it + handleList->handle[handleList->count] = i; + handleList->count++; + } + else + { + // If the return list is full but we still have permanent handle + // available, report this and stop iterating + more = YES; + break; + } + } + return more; +} +/* 9.6.3.4 PermanentHandleGetPolicy() */ +/* This function returns a list of the permanent handles of PCR, started from handle. If handle is + larger than the largest permanent handle, an empty list will be returned with more set to NO. */ +/* Return Values Meaning */ +/* YES if there are more handles available */ +/* NO all the available handles has been returned */ +TPMI_YES_NO +PermanentHandleGetPolicy( + TPM_HANDLE handle, // IN: start handle + UINT32 count, // IN: max count of returned handles + TPML_TAGGED_POLICY *policyList // OUT: list of handle + ) +{ + TPMI_YES_NO more = NO; + pAssert(HandleGetType(handle) == TPM_HT_PERMANENT); + // Initialize output handle list + policyList->count = 0; + // The maximum count of policies we may return is MAX_TAGGED_POLICIES + if(count > MAX_TAGGED_POLICIES) + count = MAX_TAGGED_POLICIES; + // Iterate permanent handle range + for(handle = NextPermanentHandle(handle); + handle != 0; + handle = NextPermanentHandle(handle + 1)) + { + TPM2B_DIGEST policyDigest; + TPM_ALG_ID policyAlg; + // Check to see if this permanent handle has a policy + policyAlg = EntityGetAuthPolicy(handle, &policyDigest); + if(policyAlg == TPM_ALG_ERROR) + continue; + if(policyList->count < count) + { + // If we have not filled up the return list, add this + // policy to the list; + policyList->policies[policyList->count].handle = handle; + policyList->policies[policyList->count].policyHash.hashAlg = policyAlg; + MemoryCopy(&policyList->policies[policyList->count].policyHash.digest, + policyDigest.t.buffer, policyDigest.t.size); + policyList->count++; + } + else + { + // If the return list is full but we still have permanent handle + // available, report this and stop iterating + more = YES; + break; + } + } + return more; +} diff --git a/src/tpm2/Handle_fp.h b/src/tpm2/Handle_fp.h new file mode 100644 index 0000000..fa6bc83 --- /dev/null +++ b/src/tpm2/Handle_fp.h @@ -0,0 +1,87 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Handle_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef HANDLE_FP_H +#define HANDLE_FP_H + +TPM_HT +HandleGetType( + TPM_HANDLE handle // IN: a handle to be checked + ); +TPM_HANDLE +NextPermanentHandle( + TPM_HANDLE inHandle // IN: the handle to check + ); +TPMI_YES_NO +PermanentCapGetHandles( + TPM_HANDLE handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ); +TPMI_YES_NO +PermanentHandleGetPolicy( + TPM_HANDLE handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_TAGGED_POLICY *policyList // OUT: list of handle + ); + + +#endif diff --git a/src/tpm2/HashCommands.c b/src/tpm2/HashCommands.c new file mode 100644 index 0000000..ba74cc3 --- /dev/null +++ b/src/tpm2/HashCommands.c @@ -0,0 +1,381 @@ +/********************************************************************************/ +/* */ +/* Hash/HMAC/Event Sequences */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: HashCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "HMAC_Start_fp.h" +#if CC_HMAC_Start // Conditional expansion of this file +TPM_RC +TPM2_HMAC_Start( + HMAC_Start_In *in, // IN: input parameter list + HMAC_Start_Out *out // OUT: output parameter list + ) +{ + OBJECT *keyObject; + TPMT_PUBLIC *publicArea; + TPM_ALG_ID hashAlg; + // Input Validation + // Get HMAC key object and public area pointers + keyObject = HandleToObject(in->handle); + publicArea = &keyObject->publicArea; + // Make sure that the key is an HMAC key + if(publicArea->type != TPM_ALG_KEYEDHASH) + return TPM_RCS_TYPE + RC_HMAC_Start_handle; + // and that it is unrestricted + if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_HMAC_Start_handle; + // and that it is a signing key + if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_KEY + RC_HMAC_Start_handle; + // See if the key has a default + if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL) + // it doesn't so use the input value + hashAlg = in->hashAlg; + else + { + // key has a default so use it + hashAlg + = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg; + // and verify that the input was either the TPM_ALG_NULL or the default + if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg) + hashAlg = TPM_ALG_NULL; + } + // if we ended up without a hash algorithm then return an error + if(hashAlg == TPM_ALG_NULL) + return TPM_RCS_VALUE + RC_HMAC_Start_hashAlg; + // Internal Data Update + // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be + // returned at this point + return ObjectCreateHMACSequence(hashAlg, + keyObject, + &in->auth, + &out->sequenceHandle); +} +#endif // CC_HMAC_Start +#include "Tpm.h" +#include "MAC_Start_fp.h" +#if CC_MAC_Start // Conditional expansion of this file +/* Error Returns Meaning */ +/* TPM_RC_ATTRIBUTES key referenced by handle is not a signing key or is restricted */ +/* TPM_RC_OBJECT_MEMORY no space to create an internal object */ +/* TPM_RC_KEY key referenced by handle is not an HMAC key */ +/* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object + referenced by handle */ +TPM_RC +TPM2_MAC_Start( + MAC_Start_In *in, // IN: input parameter list + MAC_Start_Out *out // OUT: output parameter list + ) +{ + OBJECT *keyObject; + TPMT_PUBLIC *publicArea; + TPM_RC result; + // Input Validation + // Get HMAC key object and public area pointers + keyObject = HandleToObject(in->handle); + publicArea = &keyObject->publicArea; + // Make sure that the key can do what is required + result = CryptSelectMac(publicArea, &in->inScheme); + // If the key is not able to do a MAC, indicate that the handle selects an + // object that can't do a MAC + if(result == TPM_RCS_TYPE) + return TPM_RCS_TYPE + RC_MAC_Start_handle; + // If there is another error type, indicate that the scheme and key are not + // compatible + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_MAC_Start_inScheme); + // Make sure that the key is not restricted + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_MAC_Start_handle; + // and that it is a signing key + if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_KEY + RC_MAC_Start_handle; + // Internal Data Update + // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be + // returned at this point + return ObjectCreateHMACSequence(in->inScheme, + keyObject, + &in->auth, + &out->sequenceHandle); +} +#endif // CC_MAC_Start +#include "Tpm.h" +#include "HashSequenceStart_fp.h" +#if CC_HashSequenceStart // Conditional expansion of this file +TPM_RC +TPM2_HashSequenceStart( + HashSequenceStart_In *in, // IN: input parameter list + HashSequenceStart_Out *out // OUT: output parameter list + ) +{ + // Internal Data Update + if(in->hashAlg == TPM_ALG_NULL) + // Start a event sequence. A TPM_RC_OBJECT_MEMORY error may be + // returned at this point + return ObjectCreateEventSequence(&in->auth, &out->sequenceHandle); + // Start a hash sequence. A TPM_RC_OBJECT_MEMORY error may be + // returned at this point + return ObjectCreateHashSequence(in->hashAlg, &in->auth, &out->sequenceHandle); +} +#endif // CC_HashSequenceStart +#include "Tpm.h" +#include "SequenceUpdate_fp.h" +#if CC_SequenceUpdate // Conditional expansion of this file +TPM_RC +TPM2_SequenceUpdate( + SequenceUpdate_In *in // IN: input parameter list + ) +{ + OBJECT *object; + HASH_OBJECT *hashObject; + // Input Validation + // Get sequence object pointer + object = HandleToObject(in->sequenceHandle); + hashObject = (HASH_OBJECT *)object; + // Check that referenced object is a sequence object. + if(!ObjectIsSequence(object)) + return TPM_RCS_MODE + RC_SequenceUpdate_sequenceHandle; + // Internal Data Update + if(object->attributes.eventSeq == SET) + { + // Update event sequence object + UINT32 i; + for(i = 0; i < HASH_COUNT; i++) + { + // Update sequence object + CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b); + } + } + else + { + // Update hash/HMAC sequence object + if(hashObject->attributes.hashSeq == SET) + { + // Is this the first block of the sequence + if(hashObject->attributes.firstBlock == CLEAR) + { + // If so, indicate that first block was received + hashObject->attributes.firstBlock = SET; + // Check the first block to see if the first block can contain + // the TPM_GENERATED_VALUE. If it does, it is not safe for + // a ticket. + if(TicketIsSafe(&in->buffer.b)) + hashObject->attributes.ticketSafe = SET; + } + // Update sequence object hash/HMAC stack + CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b); + } + else if(object->attributes.hmacSeq == SET) + { + // Update sequence object HMAC stack + CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, + &in->buffer.b); + } + } + return TPM_RC_SUCCESS; +} +#endif // CC_SequenceUpdate +#include "Tpm.h" +#include "SequenceComplete_fp.h" +#if CC_SequenceComplete // Conditional expansion of this file +/* Error Returns Meaning */ +/* TPM_RC_MODE sequenceHandle does not reference a hash or HMAC sequence object */ +TPM_RC +TPM2_SequenceComplete( + SequenceComplete_In *in, // IN: input parameter list + SequenceComplete_Out *out // OUT: output parameter list + ) +{ + HASH_OBJECT *hashObject; + // Input validation + // Get hash object pointer + hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle); + // input handle must be a hash or HMAC sequence object. + if(hashObject->attributes.hashSeq == CLEAR + && hashObject->attributes.hmacSeq == CLEAR) + return TPM_RCS_MODE + RC_SequenceComplete_sequenceHandle; + // Command Output + if(hashObject->attributes.hashSeq == SET) // sequence object for hash + { + // Get the hash algorithm before the algorithm is lost in CryptHashEnd + TPM_ALG_ID hashAlg = hashObject->state.hashState[0].hashAlg; + // Update last piece of the data + CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b); + // Complete hash + out->result.t.size = CryptHashEnd(&hashObject->state.hashState[0], + sizeof(out->result.t.buffer), + out->result.t.buffer); + // Check if the first block of the sequence has been received + if(hashObject->attributes.firstBlock == CLEAR) + { + // If not, then this is the first block so see if it is 'safe' + // to sign. + if(TicketIsSafe(&in->buffer.b)) + hashObject->attributes.ticketSafe = SET; + } + // Output ticket + out->validation.tag = TPM_ST_HASHCHECK; + out->validation.hierarchy = in->hierarchy; + if(in->hierarchy == TPM_RH_NULL) + { + // Ticket is not required + out->validation.digest.t.size = 0; + } + else if(hashObject->attributes.ticketSafe == CLEAR) + { + // Ticket is not safe to generate + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + else + { + // Compute ticket + TicketComputeHashCheck(out->validation.hierarchy, hashAlg, + &out->result, &out->validation); + } + } + else + { + // Update last piece of data + CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, &in->buffer.b); +#if !SMAC_IMPLEMENTED + // Complete HMAC + out->result.t.size = CryptHmacEnd(&(hashObject->state.hmacState), + sizeof(out->result.t.buffer), + out->result.t.buffer); +#else + // Complete the MAC + out->result.t.size = CryptMacEnd(&hashObject->state.hmacState, + sizeof(out->result.t.buffer), + out->result.t.buffer); +#endif + // No ticket is generated for HMAC sequence + out->validation.tag = TPM_ST_HASHCHECK; + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + // Internal Data Update + // mark sequence object as evict so it will be flushed on the way out + hashObject->attributes.evict = SET; + return TPM_RC_SUCCESS; +} +#endif // CC_SequenceComplete +#include "Tpm.h" +#include "EventSequenceComplete_fp.h" +#if CC_EventSequenceComplete // Conditional expansion of this file +TPM_RC +TPM2_EventSequenceComplete( + EventSequenceComplete_In *in, // IN: input parameter list + EventSequenceComplete_Out *out // OUT: output parameter list + ) +{ + HASH_OBJECT *hashObject; + UINT32 i; + TPM_ALG_ID hashAlg; + // Input validation + // get the event sequence object pointer + hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle); + // input handle must reference an event sequence object + if(hashObject->attributes.eventSeq != SET) + return TPM_RCS_MODE + RC_EventSequenceComplete_sequenceHandle; + // see if a PCR extend is requested in call + if(in->pcrHandle != TPM_RH_NULL) + { + // see if extend of the PCR is allowed at the locality of the command, + if(!PCRIsExtendAllowed(in->pcrHandle)) + return TPM_RC_LOCALITY; + // if an extend is going to take place, then check to see if there has + // been an orderly shutdown. If so, and the selected PCR is one of the + // state saved PCR, then the orderly state has to change. The orderly state + // does not change for PCR that are not preserved. + // NOTE: This doesn't just check for Shutdown(STATE) because the orderly + // state will have to change if this is a state-saved PCR regardless + // of the current state. This is because a subsequent Shutdown(STATE) will + // check to see if there was an orderly shutdown and not do anything if + // there was. So, this must indicate that a future Shutdown(STATE) has + // something to do. + if(PCRIsStateSaved(in->pcrHandle)) + RETURN_IF_ORDERLY; + } + // Command Output + out->results.count = 0; + for(i = 0; i < HASH_COUNT; i++) + { + hashAlg = CryptHashGetAlgByIndex(i); + // Update last piece of data + CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b); + // Complete hash + out->results.digests[out->results.count].hashAlg = hashAlg; + CryptHashEnd(&hashObject->state.hashState[i], + CryptHashGetDigestSize(hashAlg), + (BYTE *)&out->results.digests[out->results.count].digest); + // Extend PCR + if(in->pcrHandle != TPM_RH_NULL) + PCRExtend(in->pcrHandle, hashAlg, + CryptHashGetDigestSize(hashAlg), + (BYTE *)&out->results.digests[out->results.count].digest); + out->results.count++; + } + // Internal Data Update + // mark sequence object as evict so it will be flushed on the way out + hashObject->attributes.evict = SET; + return TPM_RC_SUCCESS; +} +#endif // CC_EventSequenceComplete diff --git a/src/tpm2/HashSequenceStart_fp.h b/src/tpm2/HashSequenceStart_fp.h new file mode 100644 index 0000000..9f7d9fc --- /dev/null +++ b/src/tpm2/HashSequenceStart_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: HashSequenceStart_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef HASHSEQUENCESTART_FP_H +#define HASHSEQUENCESTART_FP_H + +typedef struct { + TPM2B_AUTH auth; + TPMI_ALG_HASH hashAlg; +} HashSequenceStart_In; + +#define RC_HashSequenceStart_auth (TPM_RC_P + TPM_RC_1) +#define RC_HashSequenceStart_hashAlg (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPMI_DH_OBJECT sequenceHandle; +} HashSequenceStart_Out; + + + +TPM_RC +TPM2_HashSequenceStart( + HashSequenceStart_In *in, // IN: input parameter list + HashSequenceStart_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/HashTestData.h b/src/tpm2/HashTestData.h new file mode 100644 index 0000000..ea0b0af --- /dev/null +++ b/src/tpm2/HashTestData.h @@ -0,0 +1,210 @@ +/********************************************************************************/ +/* */ +/* Hash Test Vectors */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: HashTestData.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#ifndef HASHTESTDATA_H +#define HASHTESTDATA_H + +/* 10.1.8 HashTestData.h */ +/* Hash Test Vectors */ +TPM2B_TYPE(HASH_TEST_KEY, 128); // Twice the largest digest size +TPM2B_HASH_TEST_KEY c_hashTestKey = {{128, { + 0xa0,0xed,0x5c,0x9a,0xd2,0x4a,0x21,0x40,0x1a,0xd0,0x81,0x47,0x39,0x63,0xf9,0x50, + 0xdc,0x59,0x47,0x11,0x40,0x13,0x99,0x92,0xc0,0x72,0xa4,0x0f,0xe2,0x33,0xe4,0x63, + 0x9b,0xb6,0x76,0xc3,0x1e,0x6f,0x13,0xee,0xcc,0x99,0x71,0xa5,0xc0,0xcf,0x9a,0x40, + 0xcf,0xdb,0x66,0x70,0x05,0x63,0x54,0x12,0x25,0xf4,0xe0,0x1b,0x23,0x35,0xe3,0x70, + 0x7d,0x19,0x5f,0x00,0xe4,0xf1,0x61,0x73,0x05,0xd8,0x58,0x7f,0x60,0x61,0x84,0x36, + 0xec,0xbe,0x96,0x1b,0x69,0x00,0xf0,0x9a,0x6e,0xe3,0x26,0x73,0x0d,0x17,0x5b,0x33, + 0x41,0x44,0x9d,0x90,0xab,0xd9,0x6b,0x7d,0x48,0x99,0x25,0x93,0x29,0x14,0x2b,0xce, + 0x93,0x8d,0x8c,0xaf,0x31,0x0e,0x9c,0x57,0xd8,0x5b,0x57,0x20,0x1b,0x9f,0x2d,0xa5 + }}}; + +TPM2B_TYPE(HASH_TEST_DATA, 256); // Twice the largest block size +TPM2B_HASH_TEST_DATA c_hashTestData = {{256, { + 0x88,0xac,0xc3,0xe5,0x5f,0x66,0x9d,0x18,0x80,0xc9,0x7a,0x9c,0xa4,0x08,0x90,0x98, + 0x0f,0x3a,0x53,0x92,0x4c,0x67,0x4e,0xb7,0x37,0xec,0x67,0x87,0xb6,0xbe,0x10,0xca, + 0x11,0x5b,0x4a,0x0b,0x45,0xc3,0x32,0x68,0x48,0x69,0xce,0x25,0x1b,0xc8,0xaf,0x44, + 0x79,0x22,0x83,0xc8,0xfb,0xe2,0x63,0x94,0xa2,0x3c,0x59,0x3e,0x3e,0xc6,0x64,0x2c, + 0x1f,0x8c,0x11,0x93,0x24,0xa3,0x17,0xc5,0x2f,0x37,0xcf,0x95,0x97,0x8e,0x63,0x39, + 0x68,0xd5,0xca,0xba,0x18,0x37,0x69,0x6e,0x4f,0x19,0xfd,0x8a,0xc0,0x8d,0x87,0x3a, + 0xbc,0x31,0x42,0x04,0x05,0xef,0xb5,0x02,0xef,0x1e,0x92,0x4b,0xb7,0x73,0x2c,0x8c, + 0xeb,0x23,0x13,0x81,0x34,0xb9,0xb5,0xc1,0x17,0x37,0x39,0xf8,0x3e,0xe4,0x4c,0x06, + 0xa8,0x81,0x52,0x2f,0xef,0xc9,0x9c,0x69,0x89,0xbc,0x85,0x9c,0x30,0x16,0x02,0xca, + 0xe3,0x61,0xd4,0x0f,0xed,0x34,0x1b,0xca,0xc1,0x1b,0xd1,0xfa,0xc1,0xa2,0xe0,0xdf, + 0x52,0x2f,0x0b,0x4b,0x9f,0x0e,0x45,0x54,0xb9,0x17,0xb6,0xaf,0xd6,0xd5,0xca,0x90, + 0x29,0x57,0x7b,0x70,0x50,0x94,0x5c,0x8e,0xf6,0x4e,0x21,0x8b,0xc6,0x8b,0xa6,0xbc, + 0xb9,0x64,0xd4,0x4d,0xf3,0x68,0xd8,0xac,0xde,0xd8,0xd8,0xb5,0x6d,0xcd,0x93,0xeb, + 0x28,0xa4,0xe2,0x5c,0x44,0xef,0xf0,0xe1,0x6f,0x38,0x1a,0x3c,0xe6,0xef,0xa2,0x9d, + 0xb9,0xa8,0x05,0x2a,0x95,0xec,0x5f,0xdb,0xb0,0x25,0x67,0x9c,0x86,0x7a,0x8e,0xea, + 0x51,0xcc,0xc3,0xd3,0xff,0x6e,0xf0,0xed,0xa3,0xae,0xf9,0x5d,0x33,0x70,0xf2,0x11 + }}}; +#if ALG_SHA1 == YES +TPM2B_TYPE(SHA1, 20); +TPM2B_SHA1 c_SHA1_digest = {{20, { + 0xee,0x2c,0xef,0x93,0x76,0xbd,0xf8,0x91,0xbc,0xe6,0xe5,0x57,0x53,0x77,0x01,0xb5, + 0x70,0x95,0xe5,0x40 + }}}; +#endif +#if ALG_SHA256 == YES +TPM2B_TYPE(SHA256, 32); +TPM2B_SHA256 c_SHA256_digest = {{32, { + 0x64,0xe8,0xe0,0xc3,0xa9,0xa4,0x51,0x49,0x10,0x55,0x8d,0x31,0x71,0xe5,0x2f,0x69, + 0x3a,0xdc,0xc7,0x11,0x32,0x44,0x61,0xbd,0x34,0x39,0x57,0xb0,0xa8,0x75,0x86,0x1b + }}}; +#endif +#if ALG_SHA384 == YES +TPM2B_TYPE(SHA384, 48); +TPM2B_SHA384 c_SHA384_digest = {{48, { + 0x37,0x75,0x29,0xb5,0x20,0x15,0x6e,0xa3,0x7e,0xa3,0x0d,0xcd,0x80,0xa8,0xa3,0x3d, + 0xeb,0xe8,0xad,0x4e,0x1c,0x77,0x94,0x5a,0xaf,0x6c,0xd0,0xc1,0xfa,0x43,0x3f,0xc7, + 0xb8,0xf1,0x01,0xc0,0x60,0xbf,0xf2,0x87,0xe8,0x71,0x9e,0x51,0x97,0xa0,0x09,0x8d + }}}; +#endif +#if ALG_SHA512 == YES +TPM2B_TYPE(SHA512, 64); +TPM2B_SHA512 c_SHA512_digest = {{64, { + 0xe2,0x7b,0x10,0x3d,0x5e,0x48,0x58,0x44,0x67,0xac,0xa3,0x81,0x8c,0x1d,0xc5,0x71, + 0x66,0x92,0x8a,0x89,0xaa,0xd4,0x35,0x51,0x60,0x37,0x31,0xd7,0xba,0xe7,0x93,0x0b, + 0x16,0x4d,0xb3,0xc8,0x34,0x98,0x3c,0xd3,0x53,0xde,0x5e,0xe8,0x0c,0xbc,0xaf,0xc9, + 0x24,0x2c,0xcc,0xed,0xdb,0xde,0xba,0x1f,0x14,0x14,0x5a,0x95,0x80,0xde,0x66,0xbd + }}}; +#endif + +TPM2B_TYPE(EMPTY, 1); + +#if ALG_SM3_256 == YES +TPM2B_EMPTY c_SM3_256_digest = {{0, {0}}}; +#endif + +#if ALG_SHA3_256 == YES +TPM2B_EMPTY c_SHA3_256_digest = {{0, {0}}}; +#endif + +#if ALG_SHA3_384 == YES +TPM2B_EMPTY c_SHA3_384_digest = {{0, {0}}}; +#endif + +#if ALG_SHA3_512 == YES +TPM2B_EMPTY c_SHA3_512_digest = {{0, {0}}}; +#endif + + +// libtpms added begin +#if SMAC_IMPLEMENTED && ALG_CMAC +TPM2B_TYPE(AES128, 16); +static TPM2B_AES128 cmac_aeskey = {{16, { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}}}; +static const struct CMACTest { + TPM2B *key; + const BYTE data[64]; + UINT32 datalen; + const BYTE out[16]; + UINT16 outlen; +} CMACTests[] = { + { + .key = &cmac_aeskey.b, + .data = { }, + .datalen = 0, + .out = { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46}, + .outlen = 16, + }, { + .key = &cmac_aeskey.b, + .data = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}, + .datalen = 16, + .out = { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c}, + .outlen = 16, + }, { + .key = &cmac_aeskey.b, + .data = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11}, + .datalen = 40, + .out = { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27}, + .outlen = 16, + }, { + .key = &cmac_aeskey.b, + .data = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10}, + .datalen = 64, + .out = { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe}, + .outlen = 16, + }, { + .key = NULL, + } +}; +#endif +// libtpms added end + +#endif diff --git a/src/tpm2/Hash_fp.h b/src/tpm2/Hash_fp.h new file mode 100644 index 0000000..710fffc --- /dev/null +++ b/src/tpm2/Hash_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Hash_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef HASH_FP_H +#define HASH_FP_H + +typedef struct { + TPM2B_MAX_BUFFER data; + TPMI_ALG_HASH hashAlg; + TPMI_RH_HIERARCHY hierarchy; +} Hash_In; + +#define RC_Hash_data (TPM_RC_P + TPM_RC_1) +#define RC_Hash_hashAlg (TPM_RC_P + TPM_RC_2) +#define RC_Hash_hierarchy (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPM2B_DIGEST outHash; + TPMT_TK_HASHCHECK validation; +} Hash_Out; + +TPM_RC +TPM2_Hash( + Hash_In *in, // IN: input parameter list + Hash_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/Hierarchy.c b/src/tpm2/Hierarchy.c new file mode 100644 index 0000000..fc522a7 --- /dev/null +++ b/src/tpm2/Hierarchy.c @@ -0,0 +1,273 @@ +/********************************************************************************/ +/* */ +/* Managing and accessing the hierarchy-related values */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Hierarchy.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ +/* 8.3 Hierarchy.c */ +/* 8.3.1 Introduction */ +/* This file contains the functions used for managing and accessing the hierarchy-related values. */ +/* 8.3.2 Includes */ +#include "Tpm.h" +/* 8.3.3 Functions */ +/* 8.3.3.1 HierarchyPreInstall() */ +/* This function performs the initialization functions for the hierarchy when the TPM is + simulated. This function should not be called if the TPM is not in a manufacturing mode at the + manufacturer, or in a simulated environment. */ +void +HierarchyPreInstall_Init( + void + ) +{ + // Allow lockout clear command + gp.disableClear = FALSE; + // Initialize Primary Seeds + gp.EPSeed.t.size = sizeof(gp.EPSeed.t.buffer); + gp.SPSeed.t.size = sizeof(gp.SPSeed.t.buffer); + gp.PPSeed.t.size = sizeof(gp.PPSeed.t.buffer); +#if (defined USE_PLATFORM_EPS) && (USE_PLATFORM_EPS != NO) + _plat__GetEPS(gp.EPSeed.t.size, gp.EPSeed.t.buffer); +#else + CryptRandomGenerate(gp.EPSeed.t.size, gp.EPSeed.t.buffer); +#endif + CryptRandomGenerate(gp.SPSeed.t.size, gp.SPSeed.t.buffer); + CryptRandomGenerate(gp.PPSeed.t.size, gp.PPSeed.t.buffer); + gp.EPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added begin + gp.SPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; + gp.PPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added end + // Initialize owner, endorsement and lockout authorization + gp.ownerAuth.t.size = 0; + gp.endorsementAuth.t.size = 0; + gp.lockoutAuth.t.size = 0; + // Initialize owner, endorsement, and lockout policy + gp.ownerAlg = TPM_ALG_NULL; + gp.ownerPolicy.t.size = 0; + gp.endorsementAlg = TPM_ALG_NULL; + gp.endorsementPolicy.t.size = 0; + gp.lockoutAlg = TPM_ALG_NULL; + gp.lockoutPolicy.t.size = 0; + // Initialize ehProof, shProof and phProof + gp.phProof.t.size = sizeof(gp.phProof.t.buffer); + gp.shProof.t.size = sizeof(gp.shProof.t.buffer); + gp.ehProof.t.size = sizeof(gp.ehProof.t.buffer); + CryptRandomGenerate(gp.phProof.t.size, gp.phProof.t.buffer); + CryptRandomGenerate(gp.shProof.t.size, gp.shProof.t.buffer); + CryptRandomGenerate(gp.ehProof.t.size, gp.ehProof.t.buffer); + // Write hierarchy data to NV + NV_SYNC_PERSISTENT(disableClear); + NV_SYNC_PERSISTENT(EPSeed); + NV_SYNC_PERSISTENT(SPSeed); + NV_SYNC_PERSISTENT(PPSeed); + NV_SYNC_PERSISTENT(EPSeedCompatLevel); // libtpms added begin + NV_SYNC_PERSISTENT(SPSeedCompatLevel); + NV_SYNC_PERSISTENT(PPSeedCompatLevel); // libtpms added end + NV_SYNC_PERSISTENT(ownerAuth); + NV_SYNC_PERSISTENT(endorsementAuth); + NV_SYNC_PERSISTENT(lockoutAuth); + NV_SYNC_PERSISTENT(ownerAlg); + NV_SYNC_PERSISTENT(ownerPolicy); + NV_SYNC_PERSISTENT(endorsementAlg); + NV_SYNC_PERSISTENT(endorsementPolicy); + NV_SYNC_PERSISTENT(lockoutAlg); + NV_SYNC_PERSISTENT(lockoutPolicy); + NV_SYNC_PERSISTENT(phProof); + NV_SYNC_PERSISTENT(shProof); + NV_SYNC_PERSISTENT(ehProof); + return; +} +/* 8.3.3.2 HierarchyStartup() */ +/* This function is called at TPM2_Startup() to initialize the hierarchy related values. */ +BOOL +HierarchyStartup( + STARTUP_TYPE type // IN: start up type + ) +{ + // phEnable is SET on any startup + g_phEnable = TRUE; + // Reset platformAuth, platformPolicy; enable SH and EH at TPM_RESET and + // TPM_RESTART + if(type != SU_RESUME) + { + gc.platformAuth.t.size = 0; + gc.platformPolicy.t.size = 0; + gc.platformAlg = TPM_ALG_NULL; + // enable the storage and endorsement hierarchies and the platformNV + gc.shEnable = gc.ehEnable = gc.phEnableNV = TRUE; + } + // nullProof and nullSeed are updated at every TPM_RESET + if((type != SU_RESTART) && (type != SU_RESUME)) + { + gr.nullProof.t.size = sizeof(gr.nullProof.t.buffer); + CryptRandomGenerate(gr.nullProof.t.size, gr.nullProof.t.buffer); + gr.nullSeed.t.size = sizeof(gr.nullSeed.t.buffer); + CryptRandomGenerate(gr.nullSeed.t.size, gr.nullSeed.t.buffer); + gr.nullSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + } + return TRUE; +} +/* 8.3.3.3 HierarchyGetProof() */ +/* This function finds the proof value associated with a hierarchy.It returns a pointer to the proof + value. */ +TPM2B_PROOF * +HierarchyGetProof( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant + ) +{ + TPM2B_PROOF *proof = NULL; + switch(hierarchy) + { + case TPM_RH_PLATFORM: + // phProof for TPM_RH_PLATFORM + proof = &gp.phProof; + break; + case TPM_RH_ENDORSEMENT: + // ehProof for TPM_RH_ENDORSEMENT + proof = &gp.ehProof; + break; + case TPM_RH_OWNER: + // shProof for TPM_RH_OWNER + proof = &gp.shProof; + break; + default: + // nullProof for TPM_RH_NULL or anything else + proof = &gr.nullProof; + break; + } + return proof; +} +/* 8.3.3.4 HierarchyGetPrimarySeed() */ +/* This function returns the primary seed of a hierarchy. */ +TPM2B_SEED * +HierarchyGetPrimarySeed( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy + ) +{ + TPM2B_SEED *seed = NULL; + switch(hierarchy) + { + case TPM_RH_PLATFORM: + seed = &gp.PPSeed; + break; + case TPM_RH_OWNER: + seed = &gp.SPSeed; + break; + case TPM_RH_ENDORSEMENT: + seed = &gp.EPSeed; + break; + default: + seed = &gr.nullSeed; + break; + } + return seed; +} +// libtpms added begin +SEED_COMPAT_LEVEL +HierarchyGetPrimarySeedCompatLevel( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy + ) +{ + switch(hierarchy) + { + case TPM_RH_PLATFORM: + return gp.PPSeedCompatLevel; + break; + case TPM_RH_OWNER: + return gp.SPSeedCompatLevel; + break; + case TPM_RH_ENDORSEMENT: + return gp.EPSeedCompatLevel; + break; + case TPM_RH_NULL: + return gr.nullSeedCompatLevel; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } +} +// libtpms added end +/* 8.3.3.5 HierarchyIsEnabled() */ +/* This function checks to see if a hierarchy is enabled. */ +/* NOTE: The TPM_RH_NULL hierarchy is always enabled. */ +/* Return Values Meaning */ +/* TRUE hierarchy is enabled */ +/* FALSE hierarchy is disabled */ +BOOL +HierarchyIsEnabled( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy + ) +{ + BOOL enabled = FALSE; + switch(hierarchy) + { + case TPM_RH_PLATFORM: + enabled = g_phEnable; + break; + case TPM_RH_OWNER: + enabled = gc.shEnable; + break; + case TPM_RH_ENDORSEMENT: + enabled = gc.ehEnable; + break; + case TPM_RH_NULL: + enabled = TRUE; + break; + default: + enabled = FALSE; + break; + } + return enabled; +} diff --git a/src/tpm2/HierarchyChangeAuth_fp.h b/src/tpm2/HierarchyChangeAuth_fp.h new file mode 100644 index 0000000..74f0397 --- /dev/null +++ b/src/tpm2/HierarchyChangeAuth_fp.h @@ -0,0 +1,80 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: HierarchyChangeAuth_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef HIERARCHYCHANGEAUTH_FP_H +#define HIERARCHYCHANGEAUTH_FP_H + +typedef struct { + TPMI_RH_HIERARCHY_AUTH authHandle; + TPM2B_AUTH newAuth; +} HierarchyChangeAuth_In; + +#define RC_HierarchyChangeAuth_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_HierarchyChangeAuth_newAuth (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_HierarchyChangeAuth( + HierarchyChangeAuth_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/HierarchyCommands.c b/src/tpm2/HierarchyCommands.c new file mode 100644 index 0000000..cbf777d --- /dev/null +++ b/src/tpm2/HierarchyCommands.c @@ -0,0 +1,514 @@ +/********************************************************************************/ +/* */ +/* Hierarchy Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: HierarchyCommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "CreatePrimary_fp.h" +#if CC_CreatePrimary // Conditional expansion of this file +TPM_RC +TPM2_CreatePrimary( + CreatePrimary_In *in, // IN: input parameter list + CreatePrimary_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + TPMT_PUBLIC *publicArea; + DRBG_STATE rand; + OBJECT *newObject; + TPM2B_NAME name; + // Input Validation + // Will need a place to put the result + newObject = FindEmptyObjectSlot(&out->objectHandle); + if(newObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Get the address of the public area in the new object + // (this is just to save typing) + publicArea = &newObject->publicArea; + *publicArea = in->inPublic.publicArea; + // Check attributes in input public area. CreateChecks() checks the things that + // are unique to creation and then validates the attributes and values that are + // common to create and load. + result = CreateChecks(NULL, publicArea, + in->inSensitive.sensitive.data.t.size); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_CreatePrimary_inPublic); + // Validate the sensitive area values + if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, + publicArea->nameAlg)) + return TPM_RCS_SIZE + RC_CreatePrimary_inSensitive; + // Command output + // Compute the name using out->name as a scratch area (this is not the value + // that ultimately will be returned, then instantiate the state that will be + // used as a random number generator during the object creation. + // The caller does not know the seed values so the actual name does not have + // to be over the input, it can be over the unmarshaled structure. + result = DRBG_InstantiateSeeded(&rand, + &HierarchyGetPrimarySeed(in->primaryHandle)->b, + PRIMARY_OBJECT_CREATION, + (TPM2B *)PublicMarshalAndComputeName(publicArea, &name), + &in->inSensitive.sensitive.data.b, + HierarchyGetPrimarySeedCompatLevel(in->primaryHandle)); // libtpms added + if (result == TPM_RC_SUCCESS) + { + newObject->attributes.primary = SET; + if(in->primaryHandle == TPM_RH_ENDORSEMENT) + newObject->attributes.epsHierarchy = SET; + // Create the primary object. + result = CryptCreateObject(newObject, &in->inSensitive.sensitive, + (RAND_STATE *)&rand); + } + if(result != TPM_RC_SUCCESS) + return result; + // Set the publicArea and name from the computed values + out->outPublic.publicArea = newObject->publicArea; + out->name = newObject->name; + // Fill in creation data + FillInCreationData(in->primaryHandle, publicArea->nameAlg, + &in->creationPCR, &in->outsideInfo, &out->creationData, + &out->creationHash); + // Compute creation ticket + TicketComputeCreation(EntityGetHierarchy(in->primaryHandle), &out->name, + &out->creationHash, &out->creationTicket); + // Set the remaining attributes for a loaded object + ObjectSetLoadedAttributes(newObject, in->primaryHandle, + HierarchyGetPrimarySeedCompatLevel(in->primaryHandle)); // libtpms added + return result; +} +#endif // CC_CreatePrimary +#include "Tpm.h" +#include "HierarchyControl_fp.h" +#if CC_HierarchyControl // Conditional expansion of this file +TPM_RC +TPM2_HierarchyControl( + HierarchyControl_In *in // IN: input parameter list + ) +{ + BOOL select = (in->state == YES); + BOOL *selected = NULL; + // Input Validation + switch(in->enable) + { + // Platform hierarchy has to be disabled by PlatformAuth + // If the platform hierarchy has already been disabled, only a reboot + // can enable it again + case TPM_RH_PLATFORM: + case TPM_RH_PLATFORM_NV: + if(in->authHandle != TPM_RH_PLATFORM) + return TPM_RC_AUTH_TYPE; + break; + // ShEnable may be disabled if PlatformAuth/PlatformPolicy or + // OwnerAuth/OwnerPolicy is provided. If ShEnable is disabled, then it + // may only be enabled if PlatformAuth/PlatformPolicy is provided. + case TPM_RH_OWNER: + if(in->authHandle != TPM_RH_PLATFORM + && in->authHandle != TPM_RH_OWNER) + return TPM_RC_AUTH_TYPE; + if(gc.shEnable == FALSE && in->state == YES + && in->authHandle != TPM_RH_PLATFORM) + return TPM_RC_AUTH_TYPE; + break; + // EhEnable may be disabled if either PlatformAuth/PlatformPolicy or + // EndosementAuth/EndorsementPolicy is provided. If EhEnable is disabled, + // then it may only be enabled if PlatformAuth/PlatformPolicy is + // provided. + case TPM_RH_ENDORSEMENT: + if(in->authHandle != TPM_RH_PLATFORM + && in->authHandle != TPM_RH_ENDORSEMENT) + return TPM_RC_AUTH_TYPE; + if(gc.ehEnable == FALSE && in->state == YES + && in->authHandle != TPM_RH_PLATFORM) + return TPM_RC_AUTH_TYPE; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + // Internal Data Update + // Enable or disable the selected hierarchy + // Note: the authorization processing for this command may keep these + // command actions from being executed. For example, if phEnable is + // CLEAR, then platformAuth cannot be used for authorization. This + // means that would not be possible to use platformAuth to change the + // state of phEnable from CLEAR to SET. + // If it is decided that platformPolicy can still be used when phEnable + // is CLEAR, then this code could SET phEnable when proper platform + // policy is provided. + switch(in->enable) + { + case TPM_RH_OWNER: + selected = &gc.shEnable; + break; + case TPM_RH_ENDORSEMENT: + selected = &gc.ehEnable; + break; + case TPM_RH_PLATFORM: + selected = &g_phEnable; + break; + case TPM_RH_PLATFORM_NV: + selected = &gc.phEnableNV; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + if(selected != NULL && *selected != select) + { + // Before changing the internal state, make sure that NV is available. + // Only need to update NV if changing the orderly state + RETURN_IF_ORDERLY; + // state is changing and NV is available so modify + *selected = select; + // If a hierarchy was just disabled, flush it + if(select == CLEAR && in->enable != TPM_RH_PLATFORM_NV) + // Flush hierarchy + ObjectFlushHierarchy(in->enable); + // orderly state should be cleared because of the update to state clear data + // This gets processed in ExecuteCommand() on the way out. + g_clearOrderly = TRUE; + } + return TPM_RC_SUCCESS; +} +#endif // CC_HierarchyControl +#include "Tpm.h" +#include "SetPrimaryPolicy_fp.h" +#if CC_SetPrimaryPolicy // Conditional expansion of this file +TPM_RC +TPM2_SetPrimaryPolicy( + SetPrimaryPolicy_In *in // IN: input parameter list + ) +{ + // Input Validation + // Check the authPolicy consistent with hash algorithm. If the policy size is + // zero, then the algorithm is required to be TPM_ALG_NULL + if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg)) + return TPM_RCS_SIZE + RC_SetPrimaryPolicy_authPolicy; + // The command need NV update for OWNER and ENDORSEMENT hierarchy, and + // might need orderlyState update for PLATFORM hierarchy. + // Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE + // error may be returned at this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Internal Data Update + // Set hierarchy policy + switch(in->authHandle) + { + case TPM_RH_OWNER: + gp.ownerAlg = in->hashAlg; + gp.ownerPolicy = in->authPolicy; + NV_SYNC_PERSISTENT(ownerAlg); + NV_SYNC_PERSISTENT(ownerPolicy); + break; + case TPM_RH_ENDORSEMENT: + gp.endorsementAlg = in->hashAlg; + gp.endorsementPolicy = in->authPolicy; + NV_SYNC_PERSISTENT(endorsementAlg); + NV_SYNC_PERSISTENT(endorsementPolicy); + break; + case TPM_RH_PLATFORM: + gc.platformAlg = in->hashAlg; + gc.platformPolicy = in->authPolicy; + // need to update orderly state + g_clearOrderly = TRUE; + break; + case TPM_RH_LOCKOUT: + gp.lockoutAlg = in->hashAlg; + gp.lockoutPolicy = in->authPolicy; + NV_SYNC_PERSISTENT(lockoutAlg); + NV_SYNC_PERSISTENT(lockoutPolicy); + break; + +#define SET_ACT_POLICY(N) \ + case TPM_RH_ACT_##N: \ + go.ACT_##N.hashAlg = in->hashAlg; \ + go.ACT_##N.authPolicy = in->authPolicy; \ + g_clearOrderly = TRUE; \ + break; + + FOR_EACH_ACT(SET_ACT_POLICY) + + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return TPM_RC_SUCCESS; +} +#endif // CC_SetPrimaryPolicy +#include "Tpm.h" +#include "ChangePPS_fp.h" +#if CC_ChangePPS // Conditional expansion of this file +TPM_RC +TPM2_ChangePPS( + ChangePPS_In *in // IN: input parameter list + ) +{ + UINT32 i; + // Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE + // error may be returned at this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Input parameter is not reference in command action + NOT_REFERENCED(in); + // Internal Data Update + // Reset platform hierarchy seed from RNG + CryptRandomGenerate(sizeof(gp.PPSeed.t.buffer), gp.PPSeed.t.buffer); + gp.PPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + // Create a new phProof value from RNG to prevent the saved platform + // hierarchy contexts being loaded + CryptRandomGenerate(sizeof(gp.phProof.t.buffer), gp.phProof.t.buffer); + // Set platform authPolicy to null + gc.platformAlg = TPM_ALG_NULL; + gc.platformPolicy.t.size = 0; + // Flush loaded object in platform hierarchy + ObjectFlushHierarchy(TPM_RH_PLATFORM); + // Flush platform evict object and index in NV + NvFlushHierarchy(TPM_RH_PLATFORM); + // Save hierarchy changes to NV + NV_SYNC_PERSISTENT(PPSeed); + NV_SYNC_PERSISTENT(PPSeedCompatLevel); // libtpms added + NV_SYNC_PERSISTENT(phProof); + // Re-initialize PCR policies +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) + { + gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; + gp.pcrPolicies.policy[i].t.size = 0; + } + NV_SYNC_PERSISTENT(pcrPolicies); +#endif + // orderly state should be cleared because of the update to state clear data + g_clearOrderly = TRUE; + return TPM_RC_SUCCESS; +} +#endif // CC_ChangePPS +#include "Tpm.h" +#include "ChangeEPS_fp.h" +#if CC_ChangeEPS // Conditional expansion of this file +TPM_RC +TPM2_ChangeEPS( + ChangeEPS_In *in // IN: input parameter list + ) +{ + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Input parameter is not reference in command action + NOT_REFERENCED(in); + // Internal Data Update + // Reset endorsement hierarchy seed from RNG + CryptRandomGenerate(sizeof(gp.EPSeed.t.buffer), gp.EPSeed.t.buffer); + gp.EPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + // Create new ehProof value from RNG + CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer); + // Enable endorsement hierarchy + gc.ehEnable = TRUE; + // set authValue buffer to zeros + MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size); + // Set endorsement authValue to null + gp.endorsementAuth.t.size = 0; + // Set endorsement authPolicy to null + gp.endorsementAlg = TPM_ALG_NULL; + gp.endorsementPolicy.t.size = 0; + // Flush loaded object in endorsement hierarchy + ObjectFlushHierarchy(TPM_RH_ENDORSEMENT); + // Flush evict object of endorsement hierarchy stored in NV + NvFlushHierarchy(TPM_RH_ENDORSEMENT); + // Save hierarchy changes to NV + NV_SYNC_PERSISTENT(EPSeed); + NV_SYNC_PERSISTENT(EPSeedCompatLevel); // libtpms added + NV_SYNC_PERSISTENT(ehProof); + NV_SYNC_PERSISTENT(endorsementAuth); + NV_SYNC_PERSISTENT(endorsementAlg); + NV_SYNC_PERSISTENT(endorsementPolicy); + // orderly state should be cleared because of the update to state clear data + g_clearOrderly = TRUE; + return TPM_RC_SUCCESS; +} +#endif // CC_ChangeEPS +#include "Tpm.h" +#include "Clear_fp.h" +#if CC_Clear // Conditional expansion of this file +TPM_RC +TPM2_Clear( + Clear_In *in // IN: input parameter list + ) +{ + // Input parameter is not reference in command action + NOT_REFERENCED(in); + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Input Validation + // If Clear command is disabled, return an error + if(gp.disableClear) + return TPM_RC_DISABLED; + // Internal Data Update + // Reset storage hierarchy seed from RNG + CryptRandomGenerate(sizeof(gp.SPSeed.t.buffer), gp.SPSeed.t.buffer); + gp.SPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + // Create new shProof and ehProof value from RNG + CryptRandomGenerate(sizeof(gp.shProof.t.buffer), gp.shProof.t.buffer); + CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer); + // Enable storage and endorsement hierarchy + gc.shEnable = gc.ehEnable = TRUE; + // set the authValue buffers to zero + MemorySet(&gp.ownerAuth, 0, sizeof(gp.ownerAuth)); + MemorySet(&gp.endorsementAuth, 0, sizeof(gp.endorsementAuth)); + MemorySet(&gp.lockoutAuth, 0, sizeof(gp.lockoutAuth)); + // Set storage, endorsement, and lockout authPolicy to null + gp.ownerAlg = gp.endorsementAlg = gp.lockoutAlg = TPM_ALG_NULL; + MemorySet(&gp.ownerPolicy, 0, sizeof(gp.ownerPolicy)); + MemorySet(&gp.endorsementPolicy, 0, sizeof(gp.endorsementPolicy)); + MemorySet(&gp.lockoutPolicy, 0, sizeof(gp.lockoutPolicy)); + // Flush loaded object in storage and endorsement hierarchy + ObjectFlushHierarchy(TPM_RH_OWNER); + ObjectFlushHierarchy(TPM_RH_ENDORSEMENT); + // Flush owner and endorsement object and owner index in NV + NvFlushHierarchy(TPM_RH_OWNER); + NvFlushHierarchy(TPM_RH_ENDORSEMENT); + // Initialize dictionary attack parameters + DAPreInstall_Init(); + // Reset clock + go.clock = 0; + go.clockSafe = YES; + NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); + // Reset counters + gp.resetCount = gr.restartCount = gr.clearCount = 0; + gp.auditCounter = 0; + // Save persistent data changes to NV + // Note: since there are so many changes to the persistent data structure, the + // entire PERSISTENT_DATA structure is written as a unit + NvWrite(NV_PERSISTENT_DATA, sizeof(PERSISTENT_DATA), &gp); + // Reset the PCR authValues (this does not change the PCRs) + PCR_ClearAuth(); + // Bump the PCR counter + PCRChanged(0); + // orderly state should be cleared because of the update to state clear data + g_clearOrderly = TRUE; + return TPM_RC_SUCCESS; +} +#endif // CC_Clear +#include "Tpm.h" +#include "ClearControl_fp.h" +#if CC_ClearControl // Conditional expansion of this file +TPM_RC +TPM2_ClearControl( + ClearControl_In *in // IN: input parameter list + ) +{ + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Input Validation + // LockoutAuth may be used to set disableLockoutClear to TRUE but not to FALSE + if(in->auth == TPM_RH_LOCKOUT && in->disable == NO) + return TPM_RC_AUTH_FAIL; + // Internal Data Update + if(in->disable == YES) + gp.disableClear = TRUE; + else + gp.disableClear = FALSE; + // Record the change to NV + NV_SYNC_PERSISTENT(disableClear); + return TPM_RC_SUCCESS; +} +#endif // CC_ClearControl +#include "Tpm.h" +#include "HierarchyChangeAuth_fp.h" +#if CC_HierarchyChangeAuth // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_HierarchyChangeAuth( + HierarchyChangeAuth_In *in // IN: input parameter list + ) +{ + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Make sure that the authorization value is a reasonable size (not larger than + // the size of the digest produced by the integrity hash. The integrity + // hash is assumed to produce the longest digest of any hash implemented + // on the TPM. This will also remove trailing zeros from the authValue. + if(MemoryRemoveTrailingZeros(&in->newAuth) > CONTEXT_INTEGRITY_HASH_SIZE) + return TPM_RCS_SIZE + RC_HierarchyChangeAuth_newAuth; + // Set hierarchy authValue + switch(in->authHandle) + { + case TPM_RH_OWNER: + gp.ownerAuth = in->newAuth; + NV_SYNC_PERSISTENT(ownerAuth); + break; + case TPM_RH_ENDORSEMENT: + gp.endorsementAuth = in->newAuth; + NV_SYNC_PERSISTENT(endorsementAuth); + break; + case TPM_RH_PLATFORM: + gc.platformAuth = in->newAuth; + // orderly state should be cleared + g_clearOrderly = TRUE; + break; + case TPM_RH_LOCKOUT: + gp.lockoutAuth = in->newAuth; + NV_SYNC_PERSISTENT(lockoutAuth); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return TPM_RC_SUCCESS; +} +#endif // CC_HierarchyChangeAuth diff --git a/src/tpm2/HierarchyControl_fp.h b/src/tpm2/HierarchyControl_fp.h new file mode 100644 index 0000000..ab22a35 --- /dev/null +++ b/src/tpm2/HierarchyControl_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: HierarchyControl_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef HIERARCHYCONTROL_FP_H +#define HIERARCHYCONTROL_FP_H + +typedef struct { + TPMI_RH_HIERARCHY authHandle; + TPMI_RH_ENABLES enable; + TPMI_YES_NO state; +} HierarchyControl_In; + +#define RC_HierarchyControl_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_HierarchyControl_enable (TPM_RC_P + TPM_RC_1) +#define RC_HierarchyControl_state (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_HierarchyControl( + HierarchyControl_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/Hierarchy_fp.h b/src/tpm2/Hierarchy_fp.h new file mode 100644 index 0000000..3cc2a19 --- /dev/null +++ b/src/tpm2/Hierarchy_fp.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Hierarchy_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef HIERARCHY_FP_H +#define HIERARCHY_FP_H + +void +HierarchyPreInstall_Init( + void + ); +BOOL +HierarchyStartup( + STARTUP_TYPE type // IN: start up type + ); +TPM2B_PROOF * +HierarchyGetProof( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant + ); +TPM2B_SEED * +HierarchyGetPrimarySeed( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy + ); +// libtpms added begin +SEED_COMPAT_LEVEL +HierarchyGetPrimarySeedCompatLevel( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy + ); +// libtpms added end +BOOL +HierarchyIsEnabled( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy + ); + + +#endif diff --git a/src/tpm2/Import_fp.h b/src/tpm2/Import_fp.h new file mode 100644 index 0000000..f059b98 --- /dev/null +++ b/src/tpm2/Import_fp.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Import_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef IMPORT_FP_H +#define IMPORT_FP_H + +typedef struct { + TPMI_DH_OBJECT parentHandle; + TPM2B_DATA encryptionKey; + TPM2B_PUBLIC objectPublic; + TPM2B_PRIVATE duplicate; + TPM2B_ENCRYPTED_SECRET inSymSeed; + TPMT_SYM_DEF_OBJECT symmetricAlg; +} Import_In; + +#define RC_Import_parentHandle (TPM_RC_H + TPM_RC_1) +#define RC_Import_encryptionKey (TPM_RC_P + TPM_RC_1) +#define RC_Import_objectPublic (TPM_RC_P + TPM_RC_2) +#define RC_Import_duplicate (TPM_RC_P + TPM_RC_3) +#define RC_Import_inSymSeed (TPM_RC_P + TPM_RC_4) +#define RC_Import_symmetricAlg (TPM_RC_P + TPM_RC_5) + +typedef struct { + TPM2B_PRIVATE outPrivate; +} Import_Out; + +TPM_RC +TPM2_Import( + Import_In *in, // IN: input parameter list + Import_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/IncrementalSelfTest_fp.h b/src/tpm2/IncrementalSelfTest_fp.h new file mode 100644 index 0000000..f817352 --- /dev/null +++ b/src/tpm2/IncrementalSelfTest_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: IncrementalSelfTest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef INCREMENTALSELFTEST_FP_H +#define INCREMENTALSELFTEST_FP_H + +typedef struct{ + TPML_ALG toTest; +} IncrementalSelfTest_In; + +typedef struct{ + TPML_ALG toDoList; +} IncrementalSelfTest_Out; + +#define RC_IncrementalSelfTest_toTest (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_IncrementalSelfTest( + IncrementalSelfTest_In *in, // IN: input parameter list + IncrementalSelfTest_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/IntegrityCommands.c b/src/tpm2/IntegrityCommands.c new file mode 100644 index 0000000..eb9f202 --- /dev/null +++ b/src/tpm2/IntegrityCommands.c @@ -0,0 +1,411 @@ +/********************************************************************************/ +/* */ +/* Integrity Collection (PCR) */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: IntegrityCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "PCR_Extend_fp.h" +#if CC_PCR_Extend // Conditional expansion of this file +TPM_RC +TPM2_PCR_Extend( + PCR_Extend_In *in // IN: input parameter list + ) +{ + UINT32 i; + // Input Validation + // NOTE: This function assumes that the unmarshaling function for 'digests' will + // have validated that all of the indicated hash algorithms are valid. If the + // hash algorithms are correct, the unmarshaling code will unmarshal a digest + // of the size indicated by the hash algorithm. If the overall size is not + // consistent, the unmarshaling code will run out of input data or have input + // data left over. In either case, it will cause an unmarshaling error and this + // function will not be called. + // For NULL handle, do nothing and return success + if(in->pcrHandle == TPM_RH_NULL) + return TPM_RC_SUCCESS; + // Check if the extend operation is allowed by the current command locality + if(!PCRIsExtendAllowed(in->pcrHandle)) + return TPM_RC_LOCALITY; + // If PCR is state saved and we need to update orderlyState, check NV + // availability + if(PCRIsStateSaved(in->pcrHandle)) + RETURN_IF_ORDERLY; + // Internal Data Update + // Iterate input digest list to extend + for(i = 0; i < in->digests.count; i++) + { + PCRExtend(in->pcrHandle, in->digests.digests[i].hashAlg, + CryptHashGetDigestSize(in->digests.digests[i].hashAlg), + (BYTE *)&in->digests.digests[i].digest); + } + return TPM_RC_SUCCESS; +} +#endif // CC_PCR_Extend +#include "Tpm.h" +#include "PCR_Event_fp.h" +#if CC_PCR_Event // Conditional expansion of this file +TPM_RC +TPM2_PCR_Event( + PCR_Event_In *in, // IN: input parameter list + PCR_Event_Out *out // OUT: output parameter list + ) +{ + HASH_STATE hashState; + UINT32 i; + UINT16 size; + // Input Validation + // If a PCR extend is required + if(in->pcrHandle != TPM_RH_NULL) + { + // If the PCR is not allow to extend, return error + if(!PCRIsExtendAllowed(in->pcrHandle)) + return TPM_RC_LOCALITY; + // If PCR is state saved and we need to update orderlyState, check NV + // availability + if(PCRIsStateSaved(in->pcrHandle)) + RETURN_IF_ORDERLY; + } + // Internal Data Update + out->digests.count = HASH_COUNT; + // Iterate supported PCR bank algorithms to extend + for(i = 0; i < HASH_COUNT; i++) + { + TPM_ALG_ID hash = CryptHashGetAlgByIndex(i); + out->digests.digests[i].hashAlg = hash; + size = CryptHashStart(&hashState, hash); + CryptDigestUpdate2B(&hashState, &in->eventData.b); + CryptHashEnd(&hashState, size, + (BYTE *)&out->digests.digests[i].digest); + if(in->pcrHandle != TPM_RH_NULL) + PCRExtend(in->pcrHandle, hash, size, + (BYTE *)&out->digests.digests[i].digest); + } + return TPM_RC_SUCCESS; +} +#endif // CC_PCR_Event +#include "Tpm.h" +#include "PCR_Read_fp.h" +#if CC_PCR_Read // Conditional expansion of this file +TPM_RC +TPM2_PCR_Read( + PCR_Read_In *in, // IN: input parameter list + PCR_Read_Out *out // OUT: output parameter list + ) +{ + // Command Output + // Call PCR read function. input pcrSelectionIn parameter could be changed + // to reflect the actual PCR being returned + PCRRead(&in->pcrSelectionIn, &out->pcrValues, &out->pcrUpdateCounter); + out->pcrSelectionOut = in->pcrSelectionIn; + return TPM_RC_SUCCESS; +} +#endif // CC_PCR_Read +#include "Tpm.h" +#include "PCR_Allocate_fp.h" +#if CC_PCR_Allocate // Conditional expansion of this file +TPM_RC +TPM2_PCR_Allocate( + PCR_Allocate_In *in, // IN: input parameter list + PCR_Allocate_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point. + // Note: These codes are not listed in the return values above because it is + // an implementation choice to check in this routine rather than in a common + // function that is called before these actions are called. These return values + // are described in the Response Code section of Part 3. + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Command Output + // Call PCR Allocation function. + result = PCRAllocate(&in->pcrAllocation, &out->maxPCR, + &out->sizeNeeded, &out->sizeAvailable); + if(result == TPM_RC_PCR) + return result; + // + out->allocationSuccess = (result == TPM_RC_SUCCESS); + // if re-configuration succeeds, set the flag to indicate PCR configuration is + // going to be changed in next boot + if(out->allocationSuccess == YES) + g_pcrReConfig = TRUE; + return TPM_RC_SUCCESS; +} +#endif // CC_PCR_Allocate +#include "Tpm.h" +#include "PCR_SetAuthPolicy_fp.h" +#if CC_PCR_SetAuthPolicy // Conditional expansion of this file +TPM_RC +TPM2_PCR_SetAuthPolicy( + PCR_SetAuthPolicy_In *in // IN: input parameter list + ) +{ + UINT32 groupIndex; + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Input Validation: + // Check the authPolicy consistent with hash algorithm + if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg)) + return TPM_RCS_SIZE + RC_PCR_SetAuthPolicy_authPolicy; + // If PCR does not belong to a policy group, return TPM_RC_VALUE + if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex)) + return TPM_RCS_VALUE + RC_PCR_SetAuthPolicy_pcrNum; + // Internal Data Update + // Set PCR policy + gp.pcrPolicies.hashAlg[groupIndex] = in->hashAlg; + gp.pcrPolicies.policy[groupIndex] = in->authPolicy; + // Save new policy to NV + NV_SYNC_PERSISTENT(pcrPolicies); + return TPM_RC_SUCCESS; +} +#endif // CC_PCR_SetAuthPolicy +#include "Tpm.h" +#include "PCR_SetAuthValue_fp.h" +#if CC_PCR_SetAuthValue // Conditional expansion of this file +// CC_PCR_SetAuthPolicy +TPM_RC +TPM2_PCR_SetAuthValue( + PCR_SetAuthValue_In *in // IN: input parameter list + ) +{ + UINT32 groupIndex; + // Input Validation: + // If PCR does not belong to an auth group, return TPM_RC_VALUE + if(!PCRBelongsAuthGroup(in->pcrHandle, &groupIndex)) + return TPM_RC_VALUE; + // The command may cause the orderlyState to be cleared due to the update of + // state clear data. If this is the case, Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_ORDERLY; + // Internal Data Update + // Set PCR authValue + MemoryRemoveTrailingZeros(&in->auth); + gc.pcrAuthValues.auth[groupIndex] = in->auth; + return TPM_RC_SUCCESS; +} +#endif // CC_PCR_SetAuthValue +#include "Tpm.h" +#include "PCR_Reset_fp.h" +#if CC_PCR_Reset // Conditional expansion of this file +TPM_RC +TPM2_PCR_Reset( + PCR_Reset_In *in // IN: input parameter list + ) +{ + // Input Validation + // Check if the reset operation is allowed by the current command locality + if(!PCRIsResetAllowed(in->pcrHandle)) + return TPM_RC_LOCALITY; + // If PCR is state saved and we need to update orderlyState, check NV + // availability + if(PCRIsStateSaved(in->pcrHandle)) + RETURN_IF_ORDERLY; + // Internal Data Update + // Reset selected PCR in all banks to 0 + PCRSetValue(in->pcrHandle, 0); + // Indicate that the PCR changed so that pcrCounter will be incremented if + // necessary. + PCRChanged(in->pcrHandle); + return TPM_RC_SUCCESS; +} +#endif // CC_PCR_Reset + +#include "Tpm.h" +/* This function is called to process a _TPM_Hash_Start() indication. */ +LIB_EXPORT void +_TPM_Hash_Start( + void + ) +{ + TPM_RC result; + TPMI_DH_OBJECT handle; + // If a DRTM sequence object exists, free it up + if(g_DRTMHandle != TPM_RH_UNASSIGNED) + { + FlushObject(g_DRTMHandle); + g_DRTMHandle = TPM_RH_UNASSIGNED; + } + // Create an event sequence object and store the handle in global + // g_DRTMHandle. A TPM_RC_OBJECT_MEMORY error may be returned at this point + // The NULL value for the first parameter will cause the sequence structure to + // be allocated without being set as present. This keeps the sequence from + // being left behind if the sequence is terminated early. + result = ObjectCreateEventSequence(NULL, &g_DRTMHandle); + // If a free slot was not available, then free up a slot. + if(result != TPM_RC_SUCCESS) + { + // An implementation does not need to have a fixed relationship between + // slot numbers and handle numbers. To handle the general case, scan for + // a handle that is assigned and free it for the DRTM sequence. + // In the reference implementation, the relationship between handles and + // slots is fixed. So, if the call to ObjectCreateEvenSequence() + // failed indicating that all slots are occupied, then the first handle we + // are going to check (TRANSIENT_FIRST) will be occupied. It will be freed + // so that it can be assigned for use as the DRTM sequence object. + for(handle = TRANSIENT_FIRST; handle < TRANSIENT_LAST; handle++) + { + // try to flush the first object + if(IsObjectPresent(handle)) + break; + } + // If the first call to find a slot fails but none of the slots is occupied + // then there's a big problem + pAssert(handle < TRANSIENT_LAST); + // Free the slot + FlushObject(handle); + // Try to create an event sequence object again. This time, we must + // succeed. + result = ObjectCreateEventSequence(NULL, &g_DRTMHandle); + if(result != TPM_RC_SUCCESS) + FAIL(FATAL_ERROR_INTERNAL); + } + return; +} + +#include "Tpm.h" +/* This function is called to process a _TPM_Hash_Data() indication. */ +LIB_EXPORT void +_TPM_Hash_Data( + uint32_t dataSize, // IN: size of data to be extend + unsigned char *data // IN: data buffer + ) +{ + UINT32 i; + HASH_OBJECT *hashObject; + TPMI_DH_PCR pcrHandle = TPMIsStarted() + ? PCR_FIRST + DRTM_PCR : PCR_FIRST + HCRTM_PCR; + // If there is no DRTM sequence object, then _TPM_Hash_Start + // was not called so this function returns without doing + // anything. + if(g_DRTMHandle == TPM_RH_UNASSIGNED) + return; + hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle); + pAssert(hashObject->attributes.eventSeq); + // For each of the implemented hash algorithms, update the digest with the + // data provided. + for(i = 0; i < HASH_COUNT; i++) + { + // make sure that the PCR is implemented for this algorithm + if(PcrIsAllocated(pcrHandle, + hashObject->state.hashState[i].hashAlg)) + // Update sequence object + CryptDigestUpdate(&hashObject->state.hashState[i], dataSize, data); + } + return; +} + +#include "Tpm.h" +/* This function is called to process a _TPM_Hash_End() indication. */ +LIB_EXPORT void +_TPM_Hash_End( + void + ) +{ + UINT32 i; + TPM2B_DIGEST digest; + HASH_OBJECT *hashObject; + TPMI_DH_PCR pcrHandle; + // If the DRTM handle is not being used, then either _TPM_Hash_Start has not + // been called, _TPM_Hash_End was previously called, or some other command + // was executed and the sequence was aborted. + if(g_DRTMHandle == TPM_RH_UNASSIGNED) + return; + // Get DRTM sequence object + hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle); + // Is this _TPM_Hash_End after Startup or before + if(TPMIsStarted()) + { + // After + // Reset the DRTM PCR + PCRResetDynamics(); + // Extend the DRTM_PCR. + pcrHandle = PCR_FIRST + DRTM_PCR; + // DRTM sequence increments restartCount + gr.restartCount++; + } + else + { + pcrHandle = PCR_FIRST + HCRTM_PCR; + g_DrtmPreStartup = TRUE; + } + // Complete hash and extend PCR, or if this is an HCRTM, complete + // the hash, reset the H-CRTM register (PCR[0]) to 0...04, and then + // extend the H-CRTM data + for(i = 0; i < HASH_COUNT; i++) + { + TPMI_ALG_HASH hash = CryptHashGetAlgByIndex(i); + // make sure that the PCR is implemented for this algorithm + if(PcrIsAllocated(pcrHandle, + hashObject->state.hashState[i].hashAlg)) + { + // Complete hash + digest.t.size = CryptHashGetDigestSize(hash); + CryptHashEnd2B(&hashObject->state.hashState[i], &digest.b); + PcrDrtm(pcrHandle, hash, &digest); + } + } + // Flush sequence object. + FlushObject(g_DRTMHandle); + g_DRTMHandle = TPM_RH_UNASSIGNED; + return; +} diff --git a/src/tpm2/InternalRoutines.h b/src/tpm2/InternalRoutines.h new file mode 100644 index 0000000..48a5037 --- /dev/null +++ b/src/tpm2/InternalRoutines.h @@ -0,0 +1,146 @@ +/********************************************************************************/ +/* */ +/* Include Headers for Internal Routines */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: InternalRoutines.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +#ifndef INTERNALROUTINES_H +#define INTERNALROUTINES_H + +#if !defined _LIB_SUPPORT_H_ && !defined _TPM_H_ +#error "Should not be called" +#endif +/* DRTM functions */ +#include "_TPM_Hash_Start_fp.h" +#include "_TPM_Hash_Data_fp.h" +#include "_TPM_Hash_End_fp.h" +/* Internal subsystem functions */ +#include "Object_fp.h" +#include "Context_spt_fp.h" +#include "Object_spt_fp.h" +#include "Entity_fp.h" +#include "Session_fp.h" +#include "Hierarchy_fp.h" +#include "NVReserved_fp.h" +#include "NVDynamic_fp.h" +#include "NV_spt_fp.h" +#include "ACT_spt_fp.h" +#include "PCR_fp.h" +#include "DA_fp.h" +#include "TpmFail_fp.h" +#include "SessionProcess_fp.h" +/* Internal support functions */ +#include "CommandCodeAttributes_fp.h" +#include "Marshal_fp.h" +#include "Unmarshal_fp.h" /* kgold */ +#include "Time_fp.h" +#include "Locality_fp.h" +#include "PP_fp.h" +#include "CommandAudit_fp.h" +#include "Manufacture_fp.h" +#include "Handle_fp.h" +#include "Power_fp.h" +#include "Response_fp.h" +#include "CommandDispatcher_fp.h" +#if CC_AC_Send +# include "AC_spt_fp.h" +#endif // CC_AC_Send +/* Miscellaneous */ +#include "Bits_fp.h" +#include "AlgorithmCap_fp.h" +#include "PropertyCap_fp.h" +#include "IoBuffers_fp.h" +#include "Memory_fp.h" +#include "ResponseCodeProcessing_fp.h" +/* Internal cryptographic functions */ +#include "BnConvert_fp.h" +#include "BnMath_fp.h" +#include "BnMemory_fp.h" +#include "Ticket_fp.h" +#include "CryptUtil_fp.h" +#include "CryptHash_fp.h" +#include "CryptSym_fp.h" +#include "CryptDes_fp.h" +#include "CryptPrime_fp.h" +#include "CryptRand_fp.h" +#include "CryptSelfTest_fp.h" +#include "MathOnByteBuffers_fp.h" +#include "CryptSym_fp.h" +#include "AlgorithmTests_fp.h" +#if ALG_RSA +#include "CryptRsa_fp.h" +#include "CryptPrimeSieve_fp.h" +#endif +#if ALG_ECC +#include "CryptEccMain_fp.h" +#include "CryptEccSignature_fp.h" +#include "CryptEccKeyExchange_fp.h" +#include "CryptEccCrypt_fp.h" +#endif +#if CC_MAC || CC_MAC_Start +# include "CryptSmac_fp.h" +# if ALG_CMAC +# include "CryptCmac_fp.h" +# endif +#endif +/* Support library */ +#include "SupportLibraryFunctionPrototypes_fp.h" +/* Linkage to platform functions */ +#include "Platform_fp.h" + +#endif diff --git a/src/tpm2/IoBuffers.c b/src/tpm2/IoBuffers.c new file mode 100644 index 0000000..03739ed --- /dev/null +++ b/src/tpm2/IoBuffers.c @@ -0,0 +1,145 @@ +/********************************************************************************/ +/* */ +/* I/O Buffers */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: IoBuffers.c 1311 2018-08-23 21:39:29Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +/* 9.7 IoBuffers.c */ +/* 9.7.1 Includes and Data Definitions */ +/* This definition allows this module to see the values that are private to this module but kept in + Global.c for ease of state migration. */ +#define IO_BUFFER_C +#include "Tpm.h" +#include "IoBuffers_fp.h" +/* 9.7.2 Buffers and Functions */ +/* These buffers are set aside to hold command and response values. In this implementation, it is + not guaranteed that the code will stop accessing the s_actionInputBuffer before starting to put + values in the s_actionOutputBuffer so different buffers are required. */ +/* 9.7.2.1 MemoryIoBufferAllocationReset() */ +/* This function is used to reset the allocation of buffers. */ +void +MemoryIoBufferAllocationReset( + void + ) +{ + s_actionIoAllocation = 0; +} +/* 9.7.2.2 MemoryIoBufferZero() */ +/* Function zeros the action I/O buffer at the end of a command. Calling this is not mandatory for + proper functionality. */ +void +MemoryIoBufferZero( + void + ) +{ + memset(s_actionIoBuffer, 0, s_actionIoAllocation); +} +/* 9.7.2.3 MemoryGetInBuffer() */ +/* This function returns the address of the buffer into which the command parameters will be + unmarshaled in preparation for calling the command actions. */ +BYTE * +MemoryGetInBuffer( + UINT32 size // Size, in bytes, required for the input + // unmarshaling + ) +{ + pAssert(size <= sizeof(s_actionIoBuffer)); + // In this implementation, a static buffer is set aside for the command action + // buffers. The buffer is shared between input and output. This is because + // there is no need to allocate for the worst case input and worst case output + // at the same time. + // Round size up +#define UoM (sizeof(s_actionIoBuffer[0])) + size = (size + (UoM - 1)) & (UINT32_MAX - (UoM - 1)); + memset(s_actionIoBuffer, 0, size); + s_actionIoAllocation = size; + return (BYTE *)&s_actionIoBuffer[0]; +} +/* 9.7.2.4 MemoryGetOutBuffer() */ +/* This function returns the address of the buffer into which the command action code places its + output values. */ +BYTE * +MemoryGetOutBuffer( + UINT32 size // required size of the buffer + ) +{ + BYTE *retVal = (BYTE *)(&s_actionIoBuffer[s_actionIoAllocation / UoM]); + pAssert((size + s_actionIoAllocation) < (sizeof(s_actionIoBuffer))); + // In this implementation, a static buffer is set aside for the command action + // output buffer. + memset(retVal, 0, size); + s_actionIoAllocation += size; + return retVal; +} +/* 9.7.2.5 IsLabelProperlyFormatted() */ +/* This function checks that a label is a null-terminated string. */ +/* NOTE: this function is here because there was no better place for it. */ +/* Return Value Meaning */ +/* FALSE string is not null terminated */ +/* TRUE string is null terminated */ + +BOOL +IsLabelProperlyFormatted( + TPM2B *x + ) +{ + return (((x)->size == 0) || ((x)->buffer[(x)->size - 1] == 0)); +} + + + diff --git a/src/tpm2/IoBuffers_fp.h b/src/tpm2/IoBuffers_fp.h new file mode 100644 index 0000000..91113e1 --- /dev/null +++ b/src/tpm2/IoBuffers_fp.h @@ -0,0 +1,87 @@ +/********************************************************************************/ +/* */ +/* I/O Buffers */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: IoBuffers_fp.h 1259 2018-07-10 19:11:09Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#ifndef IOBUFFERS_FP_H +#define IOBUFFERS_FP_H + +void +MemoryIoBufferAllocationReset( + void + ); +void +MemoryIoBufferZero( + void + ); +BYTE * +MemoryGetInBuffer( + UINT32 size // Size, in bytes, required for the input + // unmarshaling + ); +BYTE * +MemoryGetOutBuffer( + UINT32 size // required size of the buffer + ); +BOOL +IsLabelProperlyFormatted( + TPM2B *x + ); + +#endif diff --git a/src/tpm2/KdfTestData.h b/src/tpm2/KdfTestData.h new file mode 100644 index 0000000..aa6c9ce --- /dev/null +++ b/src/tpm2/KdfTestData.h @@ -0,0 +1,100 @@ +/********************************************************************************/ +/* */ +/* Hash Test Vectors */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: KdfTestData.h 1311 2018-08-23 21:39:29Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +// +// Hash Test Vectors +// + +#define TEST_KDF_KEY_SIZE 20 +TPM2B_TYPE(KDF_TEST_KEY, TEST_KDF_KEY_SIZE); +TPM2B_KDF_TEST_KEY c_kdfTestKeyIn = {{TEST_KDF_KEY_SIZE, { + 0x27, 0x1F, 0xA0, 0x8B, 0xBD, 0xC5, 0x06, 0x0E, 0xC3, 0xDF, + 0xA9, 0x28, 0xFF, 0x9B, 0x73, 0x12, 0x3A, 0x12, 0xDA, 0x0C }}}; +TPM2B_TYPE(KDF_TEST_LABEL, 17); +TPM2B_KDF_TEST_LABEL c_kdfTestLabel = {{17, { + 0x4B, 0x44, 0x46, 0x53, 0x45, 0x4C, 0x46, 0x54, + 0x45, 0x53, 0x54, 0x4C, 0x41, 0x42, 0x45, 0x4C, 0x00 }}}; +TPM2B_TYPE(KDF_TEST_CONTEXT, 8); +TPM2B_KDF_TEST_CONTEXT c_kdfTestContextU = {{8, { + 0xCE, 0x24, 0x4F, 0x39, 0x5D, 0xCA, 0x73, 0x91 }}}; +TPM2B_KDF_TEST_CONTEXT c_kdfTestContextV = {{8, { + 0xDA, 0x50, 0x40, 0x31, 0xDD, 0xF1, 0x2E, 0x83 }}}; +#if ALG_SHA512 == ALG_YES +TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, { + 0x8b, 0xe2, 0xc1, 0xb8, 0x5b, 0x78, 0x56, 0x9b, 0x9f, 0xa7, + 0x59, 0xf5, 0x85, 0x7c, 0x56, 0xd6, 0x84, 0x81, 0x0f, 0xd3 }}}; +#define KDF_TEST_ALG TPM_ALG_SHA512 +#elif ALG_SHA384 == ALG_YES +TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, { + 0x1d, 0xce, 0x70, 0xc9, 0x11, 0x3e, 0xb2, 0xdb, 0xa4, 0x7b, + 0xd9, 0xcf, 0xc7, 0x2b, 0xf4, 0x6f, 0x45, 0xb0, 0x93, 0x12 }}}; +#define KDF_TEST_ALG TPM_ALG_SHA384 +#elif ALG_SHA256 == ALG_YES +TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, { + 0xbb, 0x02, 0x59, 0xe1, 0xc8, 0xba, 0x60, 0x7e, 0x6a, 0x2c, + 0xd7, 0x04, 0xb6, 0x9a, 0x90, 0x2e, 0x9a, 0xde, 0x84, 0xc4 }}}; +#define KDF_TEST_ALG TPM_ALG_SHA256 +#elif ALG_SHA1 == ALG_YES +TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, { + 0x55, 0xb5, 0xa7, 0x18, 0x4a, 0xa0, 0x74, 0x23, 0xc4, 0x7d, + 0xae, 0x76, 0x6c, 0x26, 0xa2, 0x37, 0x7d, 0x7c, 0xf8, 0x51 }}}; +#define KDF_TEST_ALG TPM_ALG_SHA1 +#endif diff --git a/src/tpm2/LibtpmsCallbacks.c b/src/tpm2/LibtpmsCallbacks.c new file mode 100644 index 0000000..5d22147 --- /dev/null +++ b/src/tpm2/LibtpmsCallbacks.c @@ -0,0 +1,178 @@ +/********************************************************************************/ +/* */ +/* Libtpms Callbacks */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "Platform.h" +#include "LibtpmsCallbacks.h" +#include "NVMarshal.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" +#include "tpm_error.h" +#include "tpm_nvfilename.h" + +int +libtpms_plat__NVEnable(void) +{ + unsigned char *data = NULL; + uint32_t length = 0; + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + TPM_RC rc; + bool is_empty_state; + + /* try to get state blob set via TPMLIB_SetState() */ + GetCachedState(TPMLIB_STATE_PERMANENT, &data, &length, &is_empty_state); + if (is_empty_state) { + memset(s_NV, 0, NV_MEMORY_SIZE); + return 0; + } + + if (data == NULL && cbs->tpm_nvram_loaddata) { + uint32_t tpm_number = 0; + const char *name = TPM_PERMANENT_ALL_NAME; + TPM_RESULT ret; + + ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name); + switch (ret) { + case TPM_RETRY: + if (!cbs->tpm_nvram_storedata) { + return -1; + } + memset(s_NV, 0, NV_MEMORY_SIZE); + return 0; + + case TPM_SUCCESS: + /* got the data -- unmarshal them... */ + break; + + case TPM_FAIL: + default: + return -1; + } + } + + if (data) { + unsigned char *buffer = data; + INT32 size = length; + + rc = PERSISTENT_ALL_Unmarshal(&buffer, &size); + free(data); + if (rc != TPM_RC_SUCCESS) + return -1; + return 0; + } + return LIBTPMS_CALLBACK_FALLTHROUGH; /* -2 */ +} + +int +libtpms_plat__NVDisable( + void + ) +{ + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + if (cbs->tpm_nvram_loaddata) + return 0; + return LIBTPMS_CALLBACK_FALLTHROUGH; /* -2 */ +} + +int +libtpms_plat__IsNvAvailable( + void + ) +{ + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + if (cbs->tpm_nvram_loaddata && + cbs->tpm_nvram_storedata) { + return 1; + } + return LIBTPMS_CALLBACK_FALLTHROUGH; /* -2 */ +} + +int +libtpms_plat__NvCommit( + void + ) +{ + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + if (cbs->tpm_nvram_storedata) { + uint32_t tpm_number = 0; + const char *name = TPM_PERMANENT_ALL_NAME; + TPM_RESULT ret; + BYTE *buf; + uint32_t buflen; + + ret = TPM2_PersistentAllStore(&buf, &buflen); + if (ret != TPM_SUCCESS) + return ret; + + ret = cbs->tpm_nvram_storedata(buf, buflen, + tpm_number, name); + free(buf); + if (ret == TPM_SUCCESS) + return 0; + + return -1; + } + return LIBTPMS_CALLBACK_FALLTHROUGH; /* -2 */ +} + +int +libtpms_plat__PhysicalPresenceAsserted( + BOOL *pp + ) +{ + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + if (cbs->tpm_io_getphysicalpresence) { + uint32_t tpm_number = 0; + TPM_RESULT res; + unsigned char mypp; + + res = cbs->tpm_io_getphysicalpresence(&mypp, tpm_number); + if (res == TPM_SUCCESS) { + *pp = mypp; + return 0; + } + } + return LIBTPMS_CALLBACK_FALLTHROUGH; +} diff --git a/src/tpm2/LibtpmsCallbacks.h b/src/tpm2/LibtpmsCallbacks.h new file mode 100644 index 0000000..e262b9d --- /dev/null +++ b/src/tpm2/LibtpmsCallbacks.h @@ -0,0 +1,50 @@ +/********************************************************************************/ +/* */ +/* Libtpms Callbacks */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef LIBTPMS_CALLBACKS_H +#define LIBTPMS_CALLBACKS_H + +#define LIBTPMS_CALLBACK_FALLTHROUGH -2 + +int libtpms_plat__NVEnable(void); +int libtpms_plat__NVDisable(void); +int libtpms_plat__IsNvAvailable(void); +int libtpms_plat__NvCommit(void); +int libtpms_plat__PhysicalPresenceAsserted(BOOL *pp); + +#endif /* LIBTPMS_CALLBACKS_H */ diff --git a/src/tpm2/LoadExternal_fp.h b/src/tpm2/LoadExternal_fp.h new file mode 100644 index 0000000..f57f942 --- /dev/null +++ b/src/tpm2/LoadExternal_fp.h @@ -0,0 +1,87 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: LoadExternal_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef LOADEXTERNAL_FP_H +#define LOADEXTERNAL_FP_H + +typedef struct { + TPM2B_SENSITIVE inPrivate; + TPM2B_PUBLIC inPublic; + TPMI_RH_HIERARCHY hierarchy; +} LoadExternal_In; + +#define RC_LoadExternal_inPrivate (TPM_RC_P + TPM_RC_1) +#define RC_LoadExternal_inPublic (TPM_RC_P + TPM_RC_2) +#define RC_LoadExternal_hierarchy (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPM_HANDLE objectHandle; + TPM2B_NAME name; +} LoadExternal_Out; + +TPM_RC +TPM2_LoadExternal( + LoadExternal_In *in, // IN: input parameter list + LoadExternal_Out *out // OUT: output parameter list + ); +#endif diff --git a/src/tpm2/Load_fp.h b/src/tpm2/Load_fp.h new file mode 100644 index 0000000..7d5c2a5 --- /dev/null +++ b/src/tpm2/Load_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Load_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef LOAD_FP_H +#define LOAD_FP_H + +typedef struct { + TPMI_DH_OBJECT parentHandle; + TPM2B_PRIVATE inPrivate; + TPM2B_PUBLIC inPublic; +} Load_In; + +#define RC_Load_parentHandle (TPM_RC_H + TPM_RC_1) +#define RC_Load_inPrivate (TPM_RC_P + TPM_RC_1) +#define RC_Load_inPublic (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM_HANDLE objectHandle; + TPM2B_NAME name; +} Load_Out; + +TPM_RC +TPM2_Load( + Load_In *in, // IN: input parameter list + Load_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/Locality.c b/src/tpm2/Locality.c new file mode 100644 index 0000000..d3f08c9 --- /dev/null +++ b/src/tpm2/Locality.c @@ -0,0 +1,99 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Locality.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016, 2017 */ +/* */ +/********************************************************************************/ + +/* 9.8 Locality.c */ +/* 9.8.1 Includes */ +#include "Tpm.h" +/* 9.8.2 LocalityGetAttributes() */ +/* This function will convert a locality expressed as an integer into TPMA_LOCALITY form. */ +/* The function returns the locality attribute. */ +TPMA_LOCALITY +LocalityGetAttributes( + UINT8 locality // IN: locality value + ) +{ + TPMA_LOCALITY locality_attributes; + BYTE *localityAsByte = (BYTE *)&locality_attributes; + MemorySet(&locality_attributes, 0, sizeof(TPMA_LOCALITY)); + switch(locality) + { + case 0: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ZERO); + break; + case 1: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ONE); + break; + case 2: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_TWO); + break; + case 3: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_THREE); + break; + case 4: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_FOUR); + break; + default: + pAssert(locality > 31); + *localityAsByte = locality; + break; + } + return locality_attributes; +} diff --git a/src/tpm2/LocalityPlat.c b/src/tpm2/LocalityPlat.c new file mode 100644 index 0000000..c3dc7de --- /dev/null +++ b/src/tpm2/LocalityPlat.c @@ -0,0 +1,87 @@ +/********************************************************************************/ +/* */ +/* Platform Locality Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: LocalityPlat.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* C.5 LocalityPlat.c */ +/* C.5.1. Includes */ +#include "Platform.h" +/* C.5.2. Functions */ +/* C.5.2.1. _plat__LocalityGet() */ +/* Get the most recent command locality in locality value form. This is an integer value for + locality and not a locality structure The locality can be 0-4 or 32-255. 5-31 is not allowed. */ +LIB_EXPORT unsigned char +_plat__LocalityGet( + void + ) +{ + return s_locality; +} +/* C.5.2.2. _plat__LocalitySet() */ +/* Set the most recent command locality in locality value form */ +LIB_EXPORT void +_plat__LocalitySet( + unsigned char locality + ) +{ + if(locality > 4 && locality < 32) + locality = 0; + s_locality = locality; + return; +} diff --git a/src/tpm2/Locality_fp.h b/src/tpm2/Locality_fp.h new file mode 100644 index 0000000..3592126 --- /dev/null +++ b/src/tpm2/Locality_fp.h @@ -0,0 +1,71 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Locality_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef LOCALITY_FP_H +#define LOCALITY_FP_H + +TPMA_LOCALITY +LocalityGetAttributes( + UINT8 locality // IN: locality value + ); + + +#endif diff --git a/src/tpm2/MAC_Start_fp.h b/src/tpm2/MAC_Start_fp.h new file mode 100644 index 0000000..6d73ad1 --- /dev/null +++ b/src/tpm2/MAC_Start_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: MAC_Start_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2017 */ +/* */ +/********************************************************************************/ + +/* rev 146 */ + +#ifndef MAC_START_FP_H +#define MAC_START_FP_H + +typedef struct { + TPMI_DH_OBJECT handle; + TPM2B_AUTH auth; + TPMI_ALG_MAC_SCHEME inScheme; +} MAC_Start_In; + +typedef struct { + TPMI_DH_OBJECT sequenceHandle; +} MAC_Start_Out; + +#define RC_MAC_Start_handle (TPM_RC_H + TPM_RC_1) +#define RC_MAC_Start_auth (TPM_RC_P + TPM_RC_1) +#define RC_MAC_Start_inScheme (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_MAC_Start( + MAC_Start_In *in, // IN: input parameter list + MAC_Start_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/MAC_fp.h b/src/tpm2/MAC_fp.h new file mode 100644 index 0000000..0dc9679 --- /dev/null +++ b/src/tpm2/MAC_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: MAC_fp.h 1259 2018-07-10 19:11:09Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2018 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef MAC_FP_H +#define MAC_FP_H + +typedef struct { + TPMI_DH_OBJECT handle; + TPM2B_MAX_BUFFER buffer; + TPMI_ALG_MAC_SCHEME inScheme; +} MAC_In; + +#define RC_MAC_handle (TPM_RC_H + TPM_RC_1) +#define RC_MAC_buffer (TPM_RC_P + TPM_RC_1) +#define RC_MAC_inScheme (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM2B_MAX_BUFFER outMAC; +} MAC_Out; + +TPM_RC +TPM2_MAC( + MAC_In *in, // IN: input parameter list + MAC_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/MakeCredential_fp.h b/src/tpm2/MakeCredential_fp.h new file mode 100644 index 0000000..e824a51 --- /dev/null +++ b/src/tpm2/MakeCredential_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: MakeCredential_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef MAKECREDENTIAL_FP_H +#define MAKECREDENTIAL_FP_H + +typedef struct { + TPMI_DH_OBJECT handle; + TPM2B_DIGEST credential; + TPM2B_NAME objectName; +} MakeCredential_In; + +#define RC_MakeCredential_handle (TPM_RC_H + TPM_RC_1) +#define RC_MakeCredential_credential (TPM_RC_P + TPM_RC_1) +#define RC_MakeCredential_objectName (TPM_RC_P + TPM_RC_2) + + +typedef struct { + TPM2B_ID_OBJECT credentialBlob; + TPM2B_ENCRYPTED_SECRET secret; +} MakeCredential_Out; + +TPM_RC +TPM2_MakeCredential( + MakeCredential_In *in, // IN: input parameter list + MakeCredential_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/ManagementCommands.c b/src/tpm2/ManagementCommands.c new file mode 100644 index 0000000..4ba70df --- /dev/null +++ b/src/tpm2/ManagementCommands.c @@ -0,0 +1,113 @@ +/********************************************************************************/ +/* */ +/* Miscellaneous Management Functions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ManagementCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "PP_Commands_fp.h" +#if CC_PP_Commands // Conditional expansion of this file +TPM_RC +TPM2_PP_Commands( + PP_Commands_In *in // IN: input parameter list + ) +{ + UINT32 i; + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Internal Data Update + // Process set list + for(i = 0; i < in->setList.count; i++) + // If command is implemented, set it as PP required. If the input + // command is not a PP command, it will be ignored at + // PhysicalPresenceCommandSet(). + // Note: PhysicalPresenceCommandSet() checks if the command is implemented. + PhysicalPresenceCommandSet(in->setList.commandCodes[i]); + // Process clear list + for(i = 0; i < in->clearList.count; i++) + // If command is implemented, clear it as PP required. If the input + // command is not a PP command, it will be ignored at + // PhysicalPresenceCommandClear(). If the input command is + // TPM2_PP_Commands, it will be ignored as well + PhysicalPresenceCommandClear(in->clearList.commandCodes[i]); + // Save the change of PP list + NV_SYNC_PERSISTENT(ppList); + return TPM_RC_SUCCESS; +} +#endif // CC_PP_Commands +#include "Tpm.h" +#include "SetAlgorithmSet_fp.h" +#if CC_SetAlgorithmSet // Conditional expansion of this file +TPM_RC +TPM2_SetAlgorithmSet( + SetAlgorithmSet_In *in // IN: input parameter list + ) +{ + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Internal Data Update + gp.algorithmSet = in->algorithmSet; + // Write the algorithm set changes to NV + NV_SYNC_PERSISTENT(algorithmSet); + return TPM_RC_SUCCESS; +} +#endif // CC_SetAlgorithmSet diff --git a/src/tpm2/Manufacture.c b/src/tpm2/Manufacture.c new file mode 100644 index 0000000..032bc76 --- /dev/null +++ b/src/tpm2/Manufacture.c @@ -0,0 +1,206 @@ +/********************************************************************************/ +/* */ +/* Performs the manufacturing of the TPM */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Manufacture.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 9.9 Manufacture.c */ +/* 9.9.1 Description */ +/* This file contains the function that performs the manufacturing of the TPM in a simulated + environment. These functions should not be used outside of a manufacturing or simulation + environment. */ +/* 9.9.2 Includes and Data Definitions */ +#define MANUFACTURE_C +#include "Tpm.h" +#include "TpmSizeChecks_fp.h" +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" // libtpms added +/* 9.9.3 Functions */ +/* 9.9.3.1 TPM_Manufacture() */ +/* This function initializes the TPM values in preparation for the TPMs first use. This function + will fail if previously called. The TPM can be re-manufactured by calling TPM_Teardown() first + and then calling this function again. */ +/* Return Values Meaning */ +/* -1 failure */ +/* 0 success */ +/* 1 manufacturing process previously performed */ +LIB_EXPORT int +TPM_Manufacture( + int firstTime // IN: indicates if this is the first call from + // main() + ) +{ + TPM_SU orderlyShutdown; + + // Initialize the context slot mask for UINT16 + s_ContextSlotMask = 0xffff; // libtpms added +#if RUNTIME_SIZE_CHECKS + // Call the function to verify the sizes of values that result from different + // compile options. + if(!TpmSizeChecks()) + return -1; +#endif +#if LIBRARY_COMPATIBILITY_CHECK + // Make sure that the attached library performs as expected. + if(!MathLibraryCompatibilityCheck()) + return -1; +#endif + // If TPM has been manufactured, return indication. + if(!firstTime && g_manufactured) + return 1; + // Do power on initializations of the cryptographic libraries. + CryptInit(); + s_DAPendingOnNV = FALSE; + // initialize NV + NvManufacture(); + // Clear the magic value in the DRBG state + go.drbgState.magic = 0; + if (CryptStartup(SU_RESET) == FALSE) { // libtpms added begin + TPMLIB_LogTPM2Error( + "CryptStartup failed:\n" + "IsEntropyBad : %d\n" + "IsTestStateSet(TESTING) : %d\n" + "IsTestStateSet(TESTED) : %d\n" + "IsTestStateSet(ENTROPY) : %d\n" + "IsDrbgTested : %d\n", + IsEntropyBad(), + IsTestStateSet(TESTING), + IsTestStateSet(TESTED), + IsTestStateSet(ENTROPY), + IsDrbgTested()); + return -1; + } // libtpms added end + // default configuration for PCR + PCRSimStart(); + // initialize pre-installed hierarchy data + // This should happen after NV is initialized because hierarchy data is + // stored in NV. + HierarchyPreInstall_Init(); + // initialize dictionary attack parameters + DAPreInstall_Init(); + // initialize PP list + PhysicalPresencePreInstall_Init(); + // initialize command audit list + CommandAuditPreInstall_Init(); + // first start up is required to be Startup(CLEAR) + orderlyShutdown = TPM_SU_CLEAR; + NV_WRITE_PERSISTENT(orderlyState, orderlyShutdown); + // initialize the firmware version + gp.firmwareV1 = FIRMWARE_V1; +#ifdef FIRMWARE_V2 + gp.firmwareV2 = FIRMWARE_V2; +#else + gp.firmwareV2 = 0; +#endif + NV_SYNC_PERSISTENT(firmwareV1); + NV_SYNC_PERSISTENT(firmwareV2); + // initialize the total reset counter to 0 + gp.totalResetCount = 0; + NV_SYNC_PERSISTENT(totalResetCount); + // initialize the clock stuff + go.clock = 0; + go.clockSafe = YES; + NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); + // Commit NV writes. Manufacture process is an artificial process existing + // only in simulator environment and it is not defined in the specification + // that what should be the expected behavior if the NV write fails at this + // point. Therefore, it is assumed the NV write here is always success and + // no return code of this function is checked. + NvCommit(); + g_manufactured = TRUE; + return 0; +} +/* 9.9.3.2 TPM_TearDown() */ +/* This function prepares the TPM for re-manufacture. It should not be implemented in anything other + than a simulated TPM. */ +/* In this implementation, all that is needs is to stop the cryptographic units and set a flag to + indicate that the TPM can be re-manufactured. This should be all that is necessary to start the + manufacturing process again. */ +/* Return Values Meaning */ +/* 0 success */ +/* 1 TPM not previously manufactured */ +LIB_EXPORT int +TPM_TearDown( + void + ) +{ + g_manufactured = FALSE; + return 0; +} +#if 0 /* libtpms added */ +/* 9.9.3.3 TpmEndSimulation() */ +/* This function is called at the end of the simulation run. It is used to provoke printing of any + statistics that might be needed. */ +LIB_EXPORT void +TpmEndSimulation( + void + ) +{ +#if SIMULATION + HashLibSimulationEnd(); + SymLibSimulationEnd(); + MathLibSimulationEnd(); +#if ALG_RSA + RsaSimulationEnd(); +#endif +#if ALG_ECC + EccSimulationEnd(); +#endif +#endif // SIMULATION +} +#endif /* libtpms added */ diff --git a/src/tpm2/Manufacture_fp.h b/src/tpm2/Manufacture_fp.h new file mode 100644 index 0000000..2ba2e36 --- /dev/null +++ b/src/tpm2/Manufacture_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* Performs the manufacturing of the TPM */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Manufacture_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef MANUFACTURE_FP_H +#define MANUFACTURE_FP_H + +#include "CompilerDependencies.h" /* kgold */ + +LIB_EXPORT int +TPM_Manufacture( + int firstTime + ); +LIB_EXPORT int +TPM_TearDown( + void + ); +LIB_EXPORT void +TpmEndSimulation( + void + ); + + +#endif diff --git a/src/tpm2/Marshal.c b/src/tpm2/Marshal.c new file mode 100644 index 0000000..a3fa08a --- /dev/null +++ b/src/tpm2/Marshal.c @@ -0,0 +1,2313 @@ +/********************************************************************************/ +/* */ +/* Parameter Marshaling */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Marshal.c 1642 2020-08-18 19:42:24Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +#include // libtpms added +#include + +#include "Tpm.h" +#include "Marshal_fp.h" + +UINT16 +UINT8_Marshal(UINT8 *source, BYTE **buffer, INT32 *size) +{ + if (buffer != NULL) { + if ((size == NULL) || ((UINT32)*size >= sizeof(UINT8))) { + + (*buffer)[0] = *source; + *buffer += sizeof(UINT8); + + if (size != NULL) { + *size -= sizeof(UINT8); + } + } + else { + pAssert(FALSE); + } + } + return sizeof(UINT8); +} + +UINT16 +UINT16_Marshal(UINT16 *source, BYTE **buffer, INT32 *size) +{ + if (buffer != NULL) { + if ((size == NULL) || ((UINT32)*size >= sizeof(UINT16))) { + + (*buffer)[0] = (BYTE)((*source >> 8) & 0xff); + (*buffer)[1] = (BYTE)((*source >> 0) & 0xff); + *buffer += sizeof(UINT16); + + if (size != NULL) { + *size -= sizeof(UINT16); + } + } + else { + pAssert(FALSE); + } + } + return sizeof(UINT16); +} + +UINT16 +UINT32_Marshal(UINT32 *source, BYTE **buffer, INT32 *size) +{ + if (buffer != NULL) { + if ((size == NULL) || ((UINT32)*size >= sizeof(UINT32))) { + + (*buffer)[0] = (BYTE)((*source >> 24) & 0xff); + (*buffer)[1] = (BYTE)((*source >> 16) & 0xff); + (*buffer)[2] = (BYTE)((*source >> 8) & 0xff); + (*buffer)[3] = (BYTE)((*source >> 0) & 0xff); + *buffer += sizeof(UINT32); + + if (size != NULL) { + *size -= sizeof(UINT32); + } + } + else { + pAssert(FALSE); + } + } + return sizeof(UINT32); +} + +UINT16 +UINT64_Marshal(UINT64 *source, BYTE **buffer, INT32 *size) +{ + if (buffer != NULL) { + if ((size == NULL) || ((UINT32)*size >= sizeof(UINT64))) { + + (*buffer)[0] = (BYTE)((*source >> 56) & 0xff); + (*buffer)[1] = (BYTE)((*source >> 48) & 0xff); + (*buffer)[2] = (BYTE)((*source >> 40) & 0xff); + (*buffer)[3] = (BYTE)((*source >> 32) & 0xff); + (*buffer)[4] = (BYTE)((*source >> 24) & 0xff); + (*buffer)[5] = (BYTE)((*source >> 16) & 0xff); + (*buffer)[6] = (BYTE)((*source >> 8) & 0xff); + (*buffer)[7] = (BYTE)((*source >> 0) & 0xff); + *buffer += sizeof(UINT64); + + if (size != NULL) { + *size -= sizeof(UINT64); + } + } + else { + pAssert(FALSE); + } + } + return sizeof(UINT64); +} + +UINT16 +Array_Marshal(BYTE *sourceBuffer, UINT16 sourceSize, BYTE **buffer, INT32 *size) +{ + if (buffer != NULL) { + if ((size == NULL) || (*size >= sourceSize)) { + memcpy(*buffer, sourceBuffer, sourceSize); + + *buffer += sourceSize; + + if (size != NULL) { + *size -= sourceSize; + } + } + else { + pAssert(FALSE); + } + } + return sourceSize; +} + +UINT16 +TPM2B_Marshal(TPM2B *source, UINT32 maxSize, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + assert(source->size <= maxSize); // libtpms added + written += UINT16_Marshal(&(source->size), buffer, size); + written += Array_Marshal(source->buffer, source->size, buffer, size); + return written; +} + +/* Table 2:5 - Definition of Types for Documentation Clarity (TypedefTable()) */ + +UINT16 +TPM_KEY_BITS_Marshal(TPM_KEY_BITS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT16_Marshal(source, buffer, size); + return written; +} + +/* Table 2:7 - Definition of TPM_CONSTANTS32 Constants (EnumTable()) */ +UINT16 +TPM_CONSTANTS32_Marshal(TPM_CONSTANTS32 *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal(source, buffer, size); + return written; +} + +/* Table 9 - Definition of (UINT16) TPM_ALG_ID Constants */ + +UINT16 +TPM_ALG_ID_Marshal(TPM_ALG_ID *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT16_Marshal(source, buffer, size); + return written; +} + +/* Table 10 - Definition of (UINT16) {ECC} TPM_ECC_CURVE Constants */ + +#if ALG_ECC +UINT16 +TPM_ECC_CURVE_Marshal(TPM_ECC_CURVE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT16_Marshal(source, buffer, size); + return written; +} +#endif + +/* Table 12 - Definition of TPM_CC Constants */ + +UINT16 +TPM_CC_Marshal(TPM_CC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal(source, buffer, size); + return written; +} + +/* Table 2:16 - Definition of TPM_RC Constants (EnumTable()) */ + +UINT16 +TPM_RC_Marshal(TPM_RC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal(source, buffer, size); + return written; +} + +/* Table 2:19 - Definition of TPM_ST Constants (EnumTable()) */ + +UINT16 +TPM_ST_Marshal(TPM_ST *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT16_Marshal(source, buffer, size); + return written; +} + +/* Table 2:22 - Definition of TPM_CAP Constants (EnumTable()) */ + +INT16 +TPM_CAP_Marshal(TPM_CAP *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal(source, buffer, size); + return written; +} + +/* Table 2:23 - Definition of TPM_PT Constants (EnumTable()) */ + +UINT16 +TPM_PT_Marshal(TPM_PT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal(source, buffer, size); + return written; +} + +/* Table 2:24 - Definition of TPM_PT_PCR Constants (EnumTable()) */ + +UINT16 +TPM_PT_PCR_Marshal(TPM_PT_PCR *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal(source, buffer, size); + return written; +} + +/* Table 2:26 - Definition of Types for Handles (TypedefTable()) */ + +UINT16 +TPM_HANDLE_Marshal(TPM_HANDLE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal(source, buffer, size); + return written; +} + +/* Table 2:30 - Definition of TPMA_ALGORITHM Bits (BitsTable()) */ + +UINT16 +TPMA_ALGORITHM_Marshal(TPMA_ALGORITHM *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal((UINT32 *)source, buffer, size); + return written; +} + +/* Table 2:31 - Definition of TPMA_OBJECT Bits (BitsTable()) */ + +UINT16 +TPMA_OBJECT_Marshal(TPMA_OBJECT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal((UINT32 *)source, buffer, size); + return written; +} + +/* Table 2:32 - Definition of TPMA_SESSION Bits (BitsTable()) */ + +UINT16 +TPMA_SESSION_Marshal(TPMA_SESSION *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT8_Marshal((UINT8 *)source, buffer, size); /* libtpms changed */ + return written; +} + +/* Table 2:33 - Definition of TPMA_LOCALITY Bits (BitsTable()) */ + +UINT16 +TPMA_LOCALITY_Marshal(TPMA_LOCALITY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT8_Marshal((UINT8 *)source, buffer, size); /* libtpms changed */ + return written; +} + +/* Table 2:37 - Definition of TPMA_CC Bits (BitsTable()) */ + +UINT16 +TPMA_CC_Marshal(TPMA_CC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal((UINT32 *)source, buffer, size); + return written; +} + +/* Table 2:39 - Definition of TPMI_YES_NO Type (InterfaceTable()) */ + +UINT16 +TPMI_YES_NO_Marshal(TPMI_YES_NO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT8_Marshal(source, buffer, size); + return written; +} + +/* Table 40 - Definition of (UINT32) TPMA_ACT Bits */ + +UINT16 +TPMA_ACT_Marshal(TPMA_ACT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal((UINT32 *)source, buffer, size); + return written; +} + +/* Table 2:49 - Definition of TPMI_DH_SAVED Type (InterfaceTable()) */ + +UINT16 +TPMI_DH_SAVED_Marshal(TPMI_DH_CONTEXT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_HANDLE_Marshal(source, buffer, size); + return written; +} + +//* Table 2:49 - Definition of TPMI_RH_HIERARCHY Type (InterfaceTable()) */ + +UINT16 +TPMI_RH_HIERARCHY_Marshal(TPMI_RH_HIERARCHY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_HANDLE_Marshal(source, buffer, size); + return written; +} + +/* Table 2:59 - Definition of TPMI_RH_NV_INDEX Type (InterfaceTable()) */ + +UINT16 +TPMI_RH_NV_INDEX_Marshal(TPMI_RH_NV_INDEX *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_HANDLE_Marshal(source, buffer, size); + return written; +} + +/* Table 2:60 - Definition of TPMI_ALG_HASH Type (InterfaceTable()) */ + +UINT16 +TPMI_ALG_HASH_Marshal(TPMI_ALG_HASH *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:63 - Definition of TPMI_ALG_SYM_OBJECT Type (InterfaceTable()) */ + +UINT16 +TPMI_ALG_SYM_OBJECT_Marshal(TPMI_ALG_SYM_OBJECT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:64 - Definition of TPMI_ALG_SYM_MODE Type (InterfaceTable()) */ + +UINT16 +TPMI_ALG_SYM_MODE_Marshal(TPMI_ALG_SYM_MODE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:65 - Definition of TPMI_ALG_KDF Type (InterfaceTable()) */ + +UINT16 +TPMI_ALG_KDF_Marshal(TPMI_ALG_KDF *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:66 - Definition of TPMI_ALG_SIG_SCHEME Type (InterfaceTable()) */ + +UINT16 +TPMI_ALG_SIG_SCHEME_Marshal(TPMI_ALG_SIG_SCHEME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:71 - Definition of TPMU_HA Union (StructuresTable()) */ + +UINT16 +TPMU_HA_Marshal(TPMU_HA *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { +#if ALG_SHA1 + case TPM_ALG_SHA1: + written += Array_Marshal(&source->sha1[0], SHA1_DIGEST_SIZE, buffer, size); + break; +#endif +#if ALG_SHA256 + case TPM_ALG_SHA256: + written += Array_Marshal(&source->sha256[0], SHA256_DIGEST_SIZE, buffer, size); + break; +#endif +#if ALG_SHA384 + case TPM_ALG_SHA384: + written += Array_Marshal(&source->sha384[0], SHA384_DIGEST_SIZE, buffer, size); + break; +#endif +#if ALG_SHA512 + case TPM_ALG_SHA512: + written += Array_Marshal(&source->sha512[0], SHA512_DIGEST_SIZE, buffer, size); + break; +#endif +#if ALG_SM3_256 + case TPM_ALG_SM3_256: + written += Array_Marshal(&source->sm3_256[0], SM3_256_DIGEST_SIZE, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:72 - Definition of TPMT_HA Structure (StructuresTable()) */ + +UINT16 +TPMT_HA_Marshal(TPMT_HA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMI_ALG_HASH_Marshal(&source->hashAlg, buffer, size); + written += TPMU_HA_Marshal(&source->digest, buffer, size, source->hashAlg); + return written; +} + +/* Table 2:73 - Definition of TPM2B_DIGEST Structure (StructuresTable()) */ + +UINT16 +TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size) +{ +UINT16 written = 0; +written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed +return written; +} + +/* Table 2:74 - Definition of TPM2B_DATA Structure (StructuresTable()) */ + +UINT16 +TPM2B_DATA_Marshal(TPM2B_DATA *source, BYTE **buffer, INT32 *size) +{ +UINT16 written = 0; +written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed +return written; +} + +/* Table 2:75 - Definition of Types for TPM2B_NONCE (TypedefTable()) */ + +UINT16 +TPM2B_NONCE_Marshal(TPM2B_NONCE *source, BYTE **buffer, INT32 *size) +{ +UINT16 written = 0; +written += TPM2B_DIGEST_Marshal(source, buffer, size); +return written; +} + +/* Table 2:76 - Definition of Types for TPM2B_AUTH (TypedefTable()) */ + +UINT16 +TPM2B_AUTH_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_DIGEST_Marshal(source, buffer, size); + return written; +} + +/* Table 2:79 - Definition of TPM2B_MAX_BUFFER Structure (StructuresTable()) */ + +UINT16 +TPM2B_MAX_BUFFER_Marshal(TPM2B_MAX_BUFFER *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:80 - Definition of TPM2B_MAX_NV_BUFFER Structure (StructuresTable()) */ + +UINT16 +TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 80 - Definition of TPM2B_TIMEOUT Structure */ +UINT16 +TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:82 - Definition of TPM2B_IV Structure (StructuresTable()) */ + +UINT16 +TPM2B_IV_Marshal(TPM2B_IV *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:84 - Definition of TPM2B_NAME Structure (StructuresTable()) */ + +UINT16 +TPM2B_NAME_Marshal(TPM2B_NAME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.name), buffer, size); // libtpms changed + return written; +} + +/* Table 2:86 - Definition of TPMS_PCR_SELECTION Structure (StructuresTable()) */ + +UINT16 +TPMS_PCR_SELECTION_Marshal(TPMS_PCR_SELECTION *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_HASH_Marshal(&source->hash, buffer, size); + written += UINT8_Marshal(&source->sizeofSelect, buffer, size); + written += Array_Marshal(&source->pcrSelect[0], source->sizeofSelect, buffer, size); + return written; +} + +/* Table 2:89 - Definition of TPMT_TK_CREATION Structure (StructuresTable()) */ + +UINT16 +TPMT_TK_CREATION_Marshal(TPMT_TK_CREATION *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_ST_Marshal(&source->tag, buffer, size); + written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->digest, buffer, size); + return written; +} + +/* Table 2:90 - Definition of TPMT_TK_VERIFIED Structure (StructuresTable()) */ + +UINT16 +TPMT_TK_VERIFIED_Marshal(TPMT_TK_VERIFIED *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_ST_Marshal(&source->tag, buffer, size); + written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->digest, buffer, size); + return written; +} + +/* Table 2:91 - Definition of TPMT_TK_AUTH Structure (StructuresTable()) */ + +UINT16 +TPMT_TK_AUTH_Marshal(TPMT_TK_AUTH *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_ST_Marshal(&source->tag, buffer, size); + written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->digest, buffer, size); + return written; +} + +/* Table 2:92 - Definition of TPMT_TK_HASHCHECK Structure (StructuresTable()) */ + +UINT16 +TPMT_TK_HASHCHECK_Marshal(TPMT_TK_HASHCHECK *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_ST_Marshal(&source->tag, buffer, size); + written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->digest, buffer, size); + return written; +} + +/* Table 2:93 - Definition of TPMS_ALG_PROPERTY Structure (StructuresTable()) */ + +UINT16 +TPMS_ALG_PROPERTY_Marshal(TPMS_ALG_PROPERTY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_ALG_ID_Marshal(&source->alg, buffer, size); + written += TPMA_ALGORITHM_Marshal(&source->algProperties, buffer, size); + return written; +} + +/* Table 2:95 - Definition of TPMS_TAGGED_PCR_SELECT Structure (StructuresTable()) */ + +UINT16 +TPMS_TAGGED_PCR_SELECT_Marshal(TPMS_TAGGED_PCR_SELECT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_PT_PCR_Marshal(&source->tag, buffer, size); + written += UINT8_Marshal(&source->sizeofSelect, buffer, size); + written += Array_Marshal(&source->pcrSelect[0], source->sizeofSelect, buffer, size); + return written; +} + +/* Table 2:96 - Definition of TPMS_TAGGED_POLICY Structure (StructuresTable()) */ + +UINT16 +TPMS_TAGGED_POLICY_Marshal(TPMS_TAGGED_POLICY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_HANDLE_Marshal(&source->handle, buffer, size); + written += TPMT_HA_Marshal(&source->policyHash, buffer, size); + return written; +} + +/* Table 105 - Definition of TPMS_ACT_DATA Structure */ + +UINT16 +TPMS_ACT_DATA_Marshal(TPMS_ACT_DATA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_HANDLE_Marshal(&source->handle, buffer, size); + written += UINT32_Marshal(&source->timeout, buffer, size); + written += TPMA_ACT_Marshal(&source->attributes, buffer, size); + return written; +} + +/* Table 2:94 - Definition of TPMS_TAGGED_PROPERTY Structure (StructuresTable()) */ + +UINT16 +TPMS_TAGGED_PROPERTY_Marshal(TPMS_TAGGED_PROPERTY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_PT_Marshal(&source->property, buffer, size); + written += UINT32_Marshal(&source->value, buffer, size); + return written; +} + +/* Table 2:97 - Definition of TPML_CC Structure (StructuresTable()) */ + +UINT16 +TPML_CC_Marshal(TPML_CC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPM_CC_Marshal(&source->commandCodes[i], buffer, size); + } + return written; +} + +/* Table 2:98 - Definition of TPML_CCA Structure (StructuresTable()) */ + +UINT16 +TPML_CCA_Marshal(TPML_CCA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMA_CC_Marshal(&source->commandAttributes[i], buffer, size); + } + return written; +} + +/* Table 2:99 - Definition of TPML_ALG Structure (StructuresTable()) */ + +UINT16 +TPML_ALG_Marshal(TPML_ALG *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPM_ALG_ID_Marshal(&source->algorithms[i], buffer, size); + } + return written; +} + +/* Table 2:100 - Definition of TPML_HANDLE Structure (StructuresTable()) */ + +UINT16 +TPML_HANDLE_Marshal(TPML_HANDLE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPM_HANDLE_Marshal(&source->handle[i], buffer, size); + } + return written; +} + +/* Table 2:101 - Definition of TPML_DIGEST Structure (StructuresTable()) */ + +UINT16 +TPML_DIGEST_Marshal(TPML_DIGEST *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPM2B_DIGEST_Marshal(&source->digests[i], buffer, size); + } + return written; +} + +/* Table 2:102 - Definition of TPML_DIGEST_VALUES Structure (StructuresTable()) */ + +UINT16 +TPML_DIGEST_VALUES_Marshal(TPML_DIGEST_VALUES *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMT_HA_Marshal(&source->digests[i], buffer, size); + } + return written; +} + +/* Table 2:104 - Definition of TPML_PCR_SELECTION Structure (StructuresTable()) */ + +UINT16 +TPML_PCR_SELECTION_Marshal(TPML_PCR_SELECTION *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMS_PCR_SELECTION_Marshal(&source->pcrSelections[i], buffer, size); + } + return written; +} + +/* Table 2:105 - Definition of TPML_ALG_PROPERTY Structure (StructuresTable()) */ + + +UINT16 +TPML_ALG_PROPERTY_Marshal(TPML_ALG_PROPERTY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMS_ALG_PROPERTY_Marshal(&source->algProperties[i], buffer, size); + } + return written; +} + +//* Table 2:106 - Definition of TPML_TAGGED_TPM_PROPERTY Structure (StructuresTable()) */ + +UINT16 +TPML_TAGGED_TPM_PROPERTY_Marshal(TPML_TAGGED_TPM_PROPERTY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMS_TAGGED_PROPERTY_Marshal(&source->tpmProperty[i], buffer, size); + } + return written; +} + +/* Table 2:107 - Definition of TPML_TAGGED_PCR_PROPERTY Structure (StructuresTable()) */ + +UINT16 +TPML_TAGGED_PCR_PROPERTY_Marshal(TPML_TAGGED_PCR_PROPERTY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMS_TAGGED_PCR_SELECT_Marshal(&source->pcrProperty[i], buffer, size); + } + return written; +} + +/* Table 2:108 - Definition of TPML_ECC_CURVE Structure (StructuresTable()) */ + +UINT16 +TPML_ECC_CURVE_Marshal(TPML_ECC_CURVE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPM_ECC_CURVE_Marshal(&source->eccCurves[i], buffer, size); + } + return written; +} + +/* Table 2:109 - Definition of TPML_TAGGED_POLICY Structure (StructuresTable()) */ + +UINT16 +TPML_TAGGED_POLICY_Marshal(TPML_TAGGED_POLICY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMS_TAGGED_POLICY_Marshal(&source->policies[i], buffer, size); + } + return written; +} + +/* Table 2:118 - Definition of TPML_ACT_DATA Structure (StructuresTable()) */ + +UINT16 +TPML_ACT_DATA_Marshal(TPML_ACT_DATA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMS_ACT_DATA_Marshal(&source->actData[i], buffer, size); + } + return written; +} + +/* Table 2:110 - Definition of TPMU_CAPABILITIES Union (StructuresTable()) */ + +UINT16 +TPMU_CAPABILITIES_Marshal(TPMU_CAPABILITIES *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { + case TPM_CAP_ALGS: + written += TPML_ALG_PROPERTY_Marshal(&source->algorithms, buffer, size); + break; + case TPM_CAP_HANDLES: + written += TPML_HANDLE_Marshal(&source->handles, buffer, size); + break; + case TPM_CAP_COMMANDS: + written += TPML_CCA_Marshal(&source->command, buffer, size); + break; + case TPM_CAP_PP_COMMANDS: + written += TPML_CC_Marshal(&source->ppCommands, buffer, size); + break; + case TPM_CAP_AUDIT_COMMANDS: + written += TPML_CC_Marshal(&source->auditCommands, buffer, size); + break; + case TPM_CAP_PCRS: + written += TPML_PCR_SELECTION_Marshal(&source->assignedPCR, buffer, size); + break; + case TPM_CAP_TPM_PROPERTIES: + written += TPML_TAGGED_TPM_PROPERTY_Marshal(&source->tpmProperties, buffer, size); + break; + case TPM_CAP_PCR_PROPERTIES: + written += TPML_TAGGED_PCR_PROPERTY_Marshal(&source->pcrProperties, buffer, size); + break; + case TPM_CAP_ECC_CURVES: + written += TPML_ECC_CURVE_Marshal(&source->eccCurves, buffer, size); + break; + case TPM_CAP_AUTH_POLICIES: + written += TPML_TAGGED_POLICY_Marshal(&source->authPolicies, buffer, size); + break; + case TPM_CAP_ACT: + written += TPML_ACT_DATA_Marshal(&source->actData, buffer, size); + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:111 - Definition of TPMS_CAPABILITY_DATA Structure (StructuresTable()) */ + +UINT16 +TPMS_CAPABILITY_DATA_Marshal(TPMS_CAPABILITY_DATA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_CAP_Marshal(&source->capability, buffer, size); + written += TPMU_CAPABILITIES_Marshal(&source->data, buffer, size, source->capability); + return written; +} + +/* Table 2:112 - Definition of TPMS_CLOCK_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_CLOCK_INFO_Marshal(TPMS_CLOCK_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += UINT64_Marshal(&source->clock, buffer, size); + written += UINT32_Marshal(&source->resetCount, buffer, size); + written += UINT32_Marshal(&source->restartCount, buffer, size); + written += TPMI_YES_NO_Marshal(&source->safe, buffer, size); + return written; +} + +/* Table 2:113 - Definition of TPMS_TIME_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_TIME_INFO_Marshal(TPMS_TIME_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += UINT64_Marshal(&source->time, buffer, size); + written += TPMS_CLOCK_INFO_Marshal(&source->clockInfo, buffer, size); + return written; +} + +/* Table 2:114 - Definition of TPMS_TIME_ATTEST_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_TIME_ATTEST_INFO_Marshal(TPMS_TIME_ATTEST_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMS_TIME_INFO_Marshal(&source->time, buffer, size); + written += UINT64_Marshal(&source->firmwareVersion, buffer, size); + return written; +} + +/* Table 2:115 - Definition of TPMS_CERTIFY_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_CERTIFY_INFO_Marshal(TPMS_CERTIFY_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM2B_NAME_Marshal(&source->name, buffer, size); + written += TPM2B_NAME_Marshal(&source->qualifiedName, buffer, size); + return written; +} + +/* Table 2:116 - Definition of TPMS_QUOTE_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_QUOTE_INFO_Marshal(TPMS_QUOTE_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPML_PCR_SELECTION_Marshal(&source->pcrSelect, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->pcrDigest, buffer, size); + return written; +} + +/* Table 2:117 - Definition of TPMS_COMMAND_AUDIT_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_COMMAND_AUDIT_INFO_Marshal(TPMS_COMMAND_AUDIT_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += UINT64_Marshal(&source->auditCounter, buffer, size); + written += TPM_ALG_ID_Marshal(&source->digestAlg, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->auditDigest, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->commandDigest, buffer, size); + return written; +} + +/* Table 2:118 - Definition of TPMS_SESSION_AUDIT_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_SESSION_AUDIT_INFO_Marshal(TPMS_SESSION_AUDIT_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_YES_NO_Marshal(&source->exclusiveSession, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->sessionDigest, buffer, size); + return written; +} + +/* Table 2:119 - Definition of TPMS_CREATION_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_CREATION_INFO_Marshal(TPMS_CREATION_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM2B_NAME_Marshal(&source->objectName, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->creationHash, buffer, size); + return written; +} + +/* Table 2:120 - Definition of TPMS_NV_CERTIFY_INFO Structure (StructuresTable()) */ + +UINT16 +TPMS_NV_CERTIFY_INFO_Marshal(TPMS_NV_CERTIFY_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM2B_NAME_Marshal(&source->indexName, buffer, size); + written += UINT16_Marshal(&source->offset, buffer, size); + written += TPM2B_MAX_NV_BUFFER_Marshal(&source->nvContents, buffer, size); + return written; +} + +/* Table 125 - Definition of TPMS_NV_DIGEST_CERTIFY_INFO Structure */ +UINT16 +TPMS_NV_DIGEST_CERTIFY_INFO_Marshal(TPMS_NV_DIGEST_CERTIFY_INFO *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_NAME_Marshal(&source->indexName, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->nvDigest, buffer, size); + return written; +} + +/* Table 2:121 - Definition of TPMI_ST_ATTEST Type (InterfaceTable()) */ + +UINT16 +TPMI_ST_ATTEST_Marshal(TPMI_ST_ATTEST *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ST_Marshal(source, buffer, size); + return written; +} + +/* Table 2:122 - Definition of TPMU_ATTEST Union (StructuresTable()) */ + +UINT16 +TPMU_ATTEST_Marshal(TPMU_ATTEST *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { + case TPM_ST_ATTEST_CERTIFY: + written += TPMS_CERTIFY_INFO_Marshal(&source->certify, buffer, size); + break; + case TPM_ST_ATTEST_CREATION: + written += TPMS_CREATION_INFO_Marshal(&source->creation, buffer, size); + break; + case TPM_ST_ATTEST_QUOTE: + written += TPMS_QUOTE_INFO_Marshal(&source->quote, buffer, size); + break; + case TPM_ST_ATTEST_COMMAND_AUDIT: + written += TPMS_COMMAND_AUDIT_INFO_Marshal(&source->commandAudit, buffer, size); + break; + case TPM_ST_ATTEST_SESSION_AUDIT: + written += TPMS_SESSION_AUDIT_INFO_Marshal(&source->sessionAudit, buffer, size); + break; + case TPM_ST_ATTEST_TIME: + written += TPMS_TIME_ATTEST_INFO_Marshal(&source->time, buffer, size); + break; + case TPM_ST_ATTEST_NV: + written += TPMS_NV_CERTIFY_INFO_Marshal(&source->nv, buffer, size); + break; + case TPM_ST_ATTEST_NV_DIGEST: + written += TPMS_NV_DIGEST_CERTIFY_INFO_Marshal(&source->nvDigest, buffer, size); + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:123 - Definition of TPMS_ATTEST Structure (StructuresTable()) */ + +UINT16 +TPMS_ATTEST_Marshal(TPMS_ATTEST *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_CONSTANTS32_Marshal(&source->magic, buffer, size); + written += TPMI_ST_ATTEST_Marshal(&source->type, buffer, size); + written += TPM2B_NAME_Marshal(&source->qualifiedSigner, buffer, size); + written += TPM2B_DATA_Marshal(&source->extraData, buffer, size); + written += TPMS_CLOCK_INFO_Marshal(&source->clockInfo, buffer, size); + written += UINT64_Marshal(&source->firmwareVersion, buffer, size); + written += TPMU_ATTEST_Marshal(&source->attested, buffer, size,source->type); + return written; +} + +/* Table 2:124 - Definition of TPM2B_ATTEST Structure (StructuresTable()) */ + +UINT16 +TPM2B_ATTEST_Marshal(TPM2B_ATTEST *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.attestationData), buffer, size); // libtpms changed + return written; +} + +/* Table 2:127 - Definition of TPMI_AES_KEY_BITS Type (InterfaceTable()) */ + +UINT16 +TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_KEY_BITS_Marshal(source, buffer, size); + return written; +} + +UINT16 // libtpms added begin +TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_KEY_BITS_Marshal(source, buffer, size); + return written; +} + +#if ALG_CAMELLIA +UINT16 +TPMI_CAMELLIA_KEY_BITS_Marshal(TPMI_CAMELLIA_KEY_BITS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_KEY_BITS_Marshal(source, buffer, size); + return written; +} +#endif // libtpms added end + +/* Table 2:128 - Definition of TPMU_SYM_KEY_BITS Union (StructuresTable()) */ + +UINT16 +TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch(selector) { +#if ALG_AES + case TPM_ALG_AES: + written += TPMI_AES_KEY_BITS_Marshal(&source->aes, buffer, size); + break; +#endif +#if ALG_SM4 + case TPM_ALG_SM4: + written += TPMI_SM4_KEY_BITS_Marshal(&source->sm4, buffer, size); + break; +#endif +#if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + written += TPMI_CAMELLIA_KEY_BITS_Marshal(&source->camellia, buffer, size); + break; +#endif +#if ALG_TDES // libtpms added begin + case TPM_ALG_TDES: + written += TPMI_TDES_KEY_BITS_Marshal(&source->tdes, buffer, size); + break; +#endif // libtpms added end +#if ALG_XOR + case TPM_ALG_XOR: + written += TPMI_ALG_HASH_Marshal(&source->xorr, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:129 - Definition of TPMU_SYM_MODE Union (StructuresTable()) */ + +UINT16 +TPMU_SYM_MODE_Marshal(TPMU_SYM_MODE *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { +#if ALG_AES + case TPM_ALG_AES: + written += TPMI_ALG_SYM_MODE_Marshal(&source->aes, buffer, size); + break; +#endif +#if ALG_SM4 + case TPM_ALG_SM4: + written += TPMI_ALG_SYM_MODE_Marshal(&source->sm4, buffer, size); + break; +#endif +#if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + written += TPMI_ALG_SYM_MODE_Marshal(&source->camellia, buffer, size); + break; +#endif +#if ALG_TDES // libtpms added begin + case TPM_ALG_TDES: + written += TPMI_ALG_SYM_MODE_Marshal(&source->tdes, buffer, size); + break; +#endif // libtpms added end +#if ALG_XOR + case TPM_ALG_XOR: +#endif + case TPM_ALG_NULL: + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:132 - Definition of TPMT_SYM_DEF_OBJECT Structure (StructuresTable()) */ + +UINT16 +TPMT_SYM_DEF_OBJECT_Marshal(TPMT_SYM_DEF_OBJECT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_SYM_OBJECT_Marshal(&source->algorithm, buffer, size); + written += TPMU_SYM_KEY_BITS_Marshal(&source->keyBits, buffer, size, source->algorithm); + written += TPMU_SYM_MODE_Marshal(&source->mode, buffer, size, source->algorithm); + return written; +} + +/* Table 2:133 - Definition of TPM2B_SYM_KEY Structure (StructuresTable()) */ + +UINT16 +TPM2B_SYM_KEY_Marshal(TPM2B_SYM_KEY *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:134 - Definition of TPMS_SYMCIPHER_PARMS Structure (StructuresTable()) */ + +UINT16 +TPMS_SYMCIPHER_PARMS_Marshal(TPMS_SYMCIPHER_PARMS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMT_SYM_DEF_OBJECT_Marshal(&source->sym, buffer, size); + return written; +} + +/* Table 2:139 - Definition of TPM2B_SENSITIVE_DATA Structure (StructuresTable()) */ + +UINT16 +TPM2B_SENSITIVE_DATA_Marshal(TPM2B_SENSITIVE_DATA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:142 - Definition of TPMS_SCHEME_HASH Structure (StructuresTable()) */ + +UINT16 +TPMS_SCHEME_HASH_Marshal(TPMS_SCHEME_HASH *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_HASH_Marshal(&source->hashAlg, buffer, size); + return written; +} + +/* Table 2:143 - Definition of TPMS_SCHEME_ECDAA Structure (StructuresTable()) */ + +UINT16 +TPMS_SCHEME_ECDAA_Marshal(TPMS_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_HASH_Marshal(&source->hashAlg, buffer, size); + written += UINT16_Marshal(&source->count, buffer, size); + return written; +} + +/* Table 2:144 - Definition of TPMI_ALG_KEYEDHASH_SCHEME Type (InterfaceTable()) */ + +UINT16 +TPMI_ALG_KEYEDHASH_SCHEME_Marshal(TPMI_ALG_KEYEDHASH_SCHEME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:145 - Definition of Types for HMAC_SIG_SCHEME (TypedefTable()) */ + +UINT16 +TPMS_SCHEME_HMAC_Marshal(TPMS_SCHEME_HMAC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} + +/* Table 2:146 - Definition of TPMS_SCHEME_XOR Structure (StructuresTable()) */ + +UINT16 +TPMS_SCHEME_XOR_Marshal(TPMS_SCHEME_XOR *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_HASH_Marshal(&source->hashAlg, buffer, size); + written += TPMI_ALG_KDF_Marshal(&source->kdf, buffer, size); + return written; +} + +/* Table 2:148 - Definition of TPMT_KEYEDHASH_SCHEME Structure (StructuresTable()) */ + +UINT16 +TPMT_KEYEDHASH_SCHEME_Marshal(TPMT_KEYEDHASH_SCHEME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_KEYEDHASH_SCHEME_Marshal(&source->scheme, buffer, size); + written += TPMU_SCHEME_KEYEDHASH_Marshal(&source->details, buffer, size, source->scheme); + return written; +} + +/* Table 2:149 - Definition of Types for RSA Signature Schemes (TypedefTable()) */ + +UINT16 +TPMS_SIG_SCHEME_RSASSA_Marshal(TPMS_SIG_SCHEME_RSASSA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} + +UINT16 +TPMS_SIG_SCHEME_RSAPSS_Marshal(TPMS_SIG_SCHEME_RSAPSS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} + +/* Table 2:150 - Definition of Types for ECC Signature Schemes (TypedefTable()) */ + +UINT16 +TPMS_SIG_SCHEME_ECDSA_Marshal(TPMS_SIG_SCHEME_ECDSA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} +UINT16 +TPMS_SIG_SCHEME_SM2_Marshal(TPMS_SIG_SCHEME_SM2 *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} +UINT16 +TPMS_SIG_SCHEME_ECSCHNORR_Marshal(TPMS_SIG_SCHEME_ECSCHNORR *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} +UINT16 +TPMS_SIG_SCHEME_ECDAA_Marshal(TPMS_SIG_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_ECDAA_Marshal(source, buffer, size); + return written; +} + +/* Table 2:153 - Definition of Types for Encryption Schemes (TypedefTable()) */ + +UINT16 +TPMS_ENC_SCHEME_OAEP_Marshal(TPMS_ENC_SCHEME_OAEP *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} + +/* Table 146 - Definition of Types for {RSA} Encryption Schemes */ + +UINT16 +TPMS_ENC_SCHEME_RSAES_Marshal(TPMS_ENC_SCHEME_RSAES *source, BYTE **buffer, INT32 *size) +{ + source = source; + buffer = buffer; + size = size; + return 0; +} + +/* Table 2:147 - Definition of TPMU_SCHEME_KEYEDHASH Union (StructuresTable()) */ + +UINT16 +TPMU_SCHEME_KEYEDHASH_Marshal(TPMU_SCHEME_KEYEDHASH *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { +#if ALG_HMAC + case TPM_ALG_HMAC: + written += TPMS_SCHEME_HMAC_Marshal(&source->hmac, buffer, size); + break; +#endif +#if ALG_XOR + case TPM_ALG_XOR: + written += TPMS_SCHEME_XOR_Marshal(&source->xorr, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:154 - Definition of Types for ECC Key Exchange (TypedefTable()) */ + +UINT16 +TPMS_KEY_SCHEME_ECDH_Marshal(TPMS_KEY_SCHEME_ECDH *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} + +UINT16 +TPMS_KEY_SCHEME_ECMQV_Marshal(TPMS_KEY_SCHEME_ECMQV*source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} + +/* Table 2:155 - Definition of Types for KDF Schemes (TypedefTable()) */ +UINT16 +TPMS_KDF_SCHEME_MGF1_Marshal(TPMS_KDF_SCHEME_MGF1 *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} +UINT16 +TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(TPMS_KDF_SCHEME_KDF1_SP800_56A *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} +UINT16 +TPMS_KDF_SCHEME_KDF2_Marshal(TPMS_KDF_SCHEME_KDF2 *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} +UINT16 +TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(TPMS_KDF_SCHEME_KDF1_SP800_108 *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); + return written; +} + +/* Table 2:156 - Definition of TPMU_KDF_SCHEME Union (StructuresTable()) */ + +UINT16 +TPMU_KDF_SCHEME_Marshal(TPMU_KDF_SCHEME *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + + switch (selector) { +#if ALG_MGF1 + case TPM_ALG_MGF1: + written += TPMS_KDF_SCHEME_MGF1_Marshal(&source->mgf1, buffer, size); + break; +#endif +#if ALG_KDF1_SP800_56A + case TPM_ALG_KDF1_SP800_56A: + written += TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(&source->kdf1_sp800_56a, buffer, size); + break; +#endif +#if ALG_KDF2 + case TPM_ALG_KDF2: + written += TPMS_KDF_SCHEME_KDF2_Marshal(&source->kdf2, buffer, size); + break; +#endif +#if ALG_KDF1_SP800_108 + case TPM_ALG_KDF1_SP800_108: + written += TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(&source->kdf1_sp800_108, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:157 - Definition of TPMT_KDF_SCHEME Structure (StructuresTable()) */ + +UINT16 +TPMT_KDF_SCHEME_Marshal(TPMT_KDF_SCHEME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_KDF_Marshal(&source->scheme, buffer, size); + written += TPMU_KDF_SCHEME_Marshal(&source->details, buffer, size, source->scheme); + return written; +} + +/* Table 2:159 - Definition of TPMU_ASYM_SCHEME Union (StructuresTable()) */ + +UINT16 +TPMU_ASYM_SCHEME_Marshal(TPMU_ASYM_SCHEME *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { +#if ALG_ECDH + case TPM_ALG_ECDH: + written += TPMS_KEY_SCHEME_ECDH_Marshal(&source->ecdh, buffer, size); + break; +#endif +#if ALG_ECMQV + case TPM_ALG_ECMQV: + written += TPMS_KEY_SCHEME_ECMQV_Marshal(&source->ecmqv, buffer, size); + break; +#endif +#if ALG_RSASSA + case TPM_ALG_RSASSA: + written += TPMS_SIG_SCHEME_RSASSA_Marshal(&source->rsassa, buffer, size); + break; +#endif +#if ALG_RSAPSS + case TPM_ALG_RSAPSS: + written += TPMS_SIG_SCHEME_RSAPSS_Marshal(&source->rsapss, buffer, size); + break; +#endif +#if ALG_ECDSA + case TPM_ALG_ECDSA: + written += TPMS_SIG_SCHEME_ECDSA_Marshal(&source->ecdsa, buffer, size); + break; +#endif +#if ALG_ECDAA + case TPM_ALG_ECDAA: + written += TPMS_SIG_SCHEME_ECDAA_Marshal(&source->ecdaa, buffer, size); + break; +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + written += TPMS_SIG_SCHEME_SM2_Marshal(&source->sm2, buffer, size); + break; +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + written += TPMS_SIG_SCHEME_ECSCHNORR_Marshal(&source->ecschnorr, buffer, size); + break; +#endif +#if ALG_RSAES + case TPM_ALG_RSAES: + written += TPMS_ENC_SCHEME_RSAES_Marshal(&source->rsaes, buffer, size); + break; +#endif +#if ALG_OAEP + case TPM_ALG_OAEP: + written += TPMS_ENC_SCHEME_OAEP_Marshal(&source->oaep, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:161 - Definition of TPMI_ALG_RSA_SCHEME Type (InterfaceTable()) */ + +UINT16 +TPMI_ALG_RSA_SCHEME_Marshal(TPMI_ALG_RSA_SCHEME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:162 - Definition of TPMT_RSA_SCHEME Structure (StructuresTable()) */ + +UINT16 +TPMT_RSA_SCHEME_Marshal(TPMT_RSA_SCHEME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_RSA_SCHEME_Marshal(&source->scheme, buffer, size); + written += TPMU_ASYM_SCHEME_Marshal(&source->details, buffer, size, source->scheme); + return written; +} + +/* Table 2:165 - Definition of TPM2B_PUBLIC_KEY_RSA Structure (StructuresTable()) */ + +UINT16 +TPM2B_PUBLIC_KEY_RSA_Marshal(TPM2B_PUBLIC_KEY_RSA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:166 - Definition of TPMI_RSA_KEY_BITS Type (InterfaceTable()) */ + +UINT16 +TPMI_RSA_KEY_BITS_Marshal(TPMI_RSA_KEY_BITS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_KEY_BITS_Marshal(source, buffer, size); + return written; +} + +/* Table 2:167 - Definition of TPM2B_PRIVATE_KEY_RSA Structure (StructuresTable()) */ + +UINT16 +TPM2B_PRIVATE_KEY_RSA_Marshal(TPM2B_PRIVATE_KEY_RSA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:168 - Definition of TPM2B_ECC_PARAMETER Structure (StructuresTable()) */ + +UINT16 +TPM2B_ECC_PARAMETER_Marshal(TPM2B_ECC_PARAMETER *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:169 - Definition of TPMS_ECC_POINT Structure (StructuresTable()) */ + +UINT16 +TPMS_ECC_POINT_Marshal(TPMS_ECC_POINT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM2B_ECC_PARAMETER_Marshal(&source->x, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->y, buffer, size); + return written; +} + +/* Table 2:170 - Definition of TPM2B_ECC_POINT Structure (StructuresTable()) */ + +UINT16 +TPM2B_ECC_POINT_Marshal(TPM2B_ECC_POINT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + BYTE *sizePtr; + + if (buffer != NULL) { + sizePtr = *buffer; + *buffer += sizeof(UINT16); + } + written += TPMS_ECC_POINT_Marshal(&source->point, buffer, size); + if (buffer != NULL) { + written += UINT16_Marshal(&written, &sizePtr, size); + } + else { + written += sizeof(UINT16); + } + return written; +} + +/* Table 2:171 - Definition of TPMI_ALG_ECC_SCHEME Type (InterfaceTable()) */ + +UINT16 +TPMI_ALG_ECC_SCHEME_Marshal(TPMI_ALG_ECC_SCHEME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:172 - Definition of TPMI_ECC_CURVE Type (InterfaceTable()) */ + +UINT16 +TPMI_ECC_CURVE_Marshal(TPMI_ECC_CURVE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ECC_CURVE_Marshal(source, buffer, size); + return written; +} + +/* Table 2:173 - Definition of TPMT_ECC_SCHEME Structure (StructuresTable()) */ + +UINT16 +TPMT_ECC_SCHEME_Marshal(TPMT_ECC_SCHEME *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_ECC_SCHEME_Marshal(&source->scheme, buffer, size); + written += TPMU_ASYM_SCHEME_Marshal(&source->details, buffer, size, source->scheme); + return written; +} + +/* Table 2:174 - Definition of TPMS_ALGORITHM_DETAIL_ECC Structure (StructuresTable()) */ + +UINT16 +TPMS_ALGORITHM_DETAIL_ECC_Marshal(TPMS_ALGORITHM_DETAIL_ECC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_ECC_CURVE_Marshal(&source->curveID, buffer, size); + written += UINT16_Marshal(&source->keySize, buffer, size); + written += TPMT_KDF_SCHEME_Marshal(&source->kdf, buffer, size); + written += TPMT_ECC_SCHEME_Marshal(&source->sign, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->p, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->a, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->b, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->gX, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->gY, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->n, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->h, buffer, size); + return written; +} + +/* Table 2:175 - Definition of TPMS_SIGNATURE_RSA Structure (StructuresTable()) */ + +UINT16 +TPMS_SIGNATURE_RSA_Marshal(TPMS_SIGNATURE_RSA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_HASH_Marshal(&source->hash, buffer, size); + written += TPM2B_PUBLIC_KEY_RSA_Marshal(&source->sig, buffer, size); + return written; +} + +/* Table 2:176 - Definition of Types for Signature (TypedefTable()) */ +UINT16 +TPMS_SIGNATURE_RSASSA_Marshal(TPMS_SIGNATURE_RSASSA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SIGNATURE_RSA_Marshal(source, buffer, size); + return written; +} +UINT16 +TPMS_SIGNATURE_RSAPSS_Marshal(TPMS_SIGNATURE_RSAPSS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SIGNATURE_RSA_Marshal(source, buffer, size); + return written; +} + +/* Table 2:177 - Definition of TPMS_SIGNATURE_ECC Structure (StructuresTable()) */ + +UINT16 +TPMS_SIGNATURE_ECC_Marshal(TPMS_SIGNATURE_ECC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_HASH_Marshal(&source->hash, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->signatureR, buffer, size); + written += TPM2B_ECC_PARAMETER_Marshal(&source->signatureS, buffer, size); + return written; +} + +/* Table 2:178 - Definition of Types for TPMS_SIGNATURE_ECC (TypedefTable()) */ + +UINT16 +TPMS_SIGNATURE_ECDSA_Marshal(TPMS_SIGNATURE_ECDSA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SIGNATURE_ECC_Marshal(source, buffer, size); + return written; +} + +UINT16 +TPMS_SIGNATURE_ECDAA_Marshal(TPMS_SIGNATURE_ECDAA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SIGNATURE_ECC_Marshal(source, buffer, size); + return written; +} + +UINT16 +TPMS_SIGNATURE_SM2_Marshal(TPMS_SIGNATURE_SM2 *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SIGNATURE_ECC_Marshal(source, buffer, size); + return written; +} + +UINT16 +TPMS_SIGNATURE_ECSCHNORR_Marshal(TPMS_SIGNATURE_ECSCHNORR *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMS_SIGNATURE_ECC_Marshal(source, buffer, size); + return written; +} + +/* Table 2:179 - Definition of TPMU_SIGNATURE Union (StructuresTable()) */ +UINT16 +TPMU_SIGNATURE_Marshal(TPMU_SIGNATURE *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { +#if ALG_RSASSA + case TPM_ALG_RSASSA: + written += TPMS_SIGNATURE_RSASSA_Marshal(&source->rsassa, buffer, size); + break; +#endif +#if ALG_RSAPSS + case TPM_ALG_RSAPSS: + written += TPMS_SIGNATURE_RSAPSS_Marshal(&source->rsapss, buffer, size); + break; +#endif +#if ALG_ECDSA + case TPM_ALG_ECDSA: + written += TPMS_SIGNATURE_ECDSA_Marshal(&source->ecdsa, buffer, size); + break; +#endif +#if ALG_ECDAA + case TPM_ALG_ECDAA: + written += TPMS_SIGNATURE_ECDAA_Marshal(&source->ecdaa, buffer, size); + break; +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + written += TPMS_SIGNATURE_SM2_Marshal(&source->sm2, buffer, size); + break; +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + written += TPMS_SIGNATURE_ECSCHNORR_Marshal(&source->ecschnorr, buffer, size); + break; +#endif +#if ALG_HMAC + case TPM_ALG_HMAC: + written += TPMT_HA_Marshal(&source->hmac, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:180 - Definition of TPMT_SIGNATURE Structure (StructuresTable()) */ + +UINT16 +TPMT_SIGNATURE_Marshal(TPMT_SIGNATURE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_SIG_SCHEME_Marshal(&source->sigAlg, buffer, size); + written += TPMU_SIGNATURE_Marshal(&source->signature, buffer, size, source->sigAlg); + return written; +} + +/* Table 2:182 - Definition of TPM2B_ENCRYPTED_SECRET Structure (StructuresTable()) */ + +UINT16 +TPM2B_ENCRYPTED_SECRET_Marshal(TPM2B_ENCRYPTED_SECRET *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.secret), buffer, size); // libtpms changed + return written; +} + +/* Table 2:183 - Definition of TPMI_ALG_PUBLIC Type (InterfaceTable()) */ + + +UINT16 +TPMI_ALG_PUBLIC_Marshal(TPMI_ALG_PUBLIC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM_ALG_ID_Marshal(source, buffer, size); + return written; +} + +/* Table 2:184 - Definition of TPMU_PUBLIC_ID Union (StructuresTable()) */ +UINT16 +TPMU_PUBLIC_ID_Marshal(TPMU_PUBLIC_ID *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { +#if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + written += TPM2B_DIGEST_Marshal(&source->keyedHash, buffer, size); + break; +#endif +#if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + written += TPM2B_DIGEST_Marshal(&source->sym, buffer, size); + break; +#endif +#if ALG_RSA + case TPM_ALG_RSA: + written += TPM2B_PUBLIC_KEY_RSA_Marshal(&source->rsa, buffer, size); + break; +#endif +#if ALG_ECC + case TPM_ALG_ECC: + written += TPMS_ECC_POINT_Marshal(&source->ecc, buffer, size); + break; +#endif + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:185 - Definition of TPMS_KEYEDHASH_PARMS Structure (StructuresTable()) */ + +UINT16 +TPMS_KEYEDHASH_PARMS_Marshal(TPMS_KEYEDHASH_PARMS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMT_KEYEDHASH_SCHEME_Marshal(&source->scheme, buffer, size); + return written; +} + +/* Table 2:187 - Definition of TPMS_RSA_PARMS Structure (StructuresTable()) */ + +UINT16 +TPMS_RSA_PARMS_Marshal(TPMS_RSA_PARMS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMT_SYM_DEF_OBJECT_Marshal(&source->symmetric, buffer, size); + written += TPMT_RSA_SCHEME_Marshal(&source->scheme, buffer, size); + written += TPMI_RSA_KEY_BITS_Marshal(&source->keyBits, buffer, size); + written += UINT32_Marshal(&source->exponent, buffer, size); + return written; +} + +/* Table 2:188 - Definition of TPMS_ECC_PARMS Structure (StructuresTable()) */ + +UINT16 +TPMS_ECC_PARMS_Marshal(TPMS_ECC_PARMS *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMT_SYM_DEF_OBJECT_Marshal(&source->symmetric, buffer, size); + written += TPMT_ECC_SCHEME_Marshal(&source->scheme, buffer, size); + written += TPMI_ECC_CURVE_Marshal(&source->curveID, buffer, size); + written += TPMT_KDF_SCHEME_Marshal(&source->kdf, buffer, size); + return written; +} + +/* Table 2:189 - Definition of TPMU_PUBLIC_PARMS Union (StructuresTable()) */ + +UINT16 +TPMU_PUBLIC_PARMS_Marshal(TPMU_PUBLIC_PARMS *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { +#if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + written += TPMS_KEYEDHASH_PARMS_Marshal(&source->keyedHashDetail, buffer, size); + break; +#endif +#if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + written += TPMS_SYMCIPHER_PARMS_Marshal(&source->symDetail, buffer, size); + break; +#endif +#if ALG_RSA + case TPM_ALG_RSA: + written += TPMS_RSA_PARMS_Marshal(&source->rsaDetail, buffer, size); + break; +#endif +#if ALG_ECC + case TPM_ALG_ECC: + written += TPMS_ECC_PARMS_Marshal(&source->eccDetail, buffer, size); + break; +#endif + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:191 - Definition of TPMT_PUBLIC Structure (StructuresTable()) */ + +UINT16 +TPMT_PUBLIC_Marshal(TPMT_PUBLIC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPMI_ALG_PUBLIC_Marshal(&source->type, buffer, size); + written += TPMI_ALG_HASH_Marshal(&source->nameAlg, buffer, size); + written += TPMA_OBJECT_Marshal(&source->objectAttributes, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->authPolicy, buffer, size); + written += TPMU_PUBLIC_PARMS_Marshal(&source->parameters, buffer, size, source->type); + written += TPMU_PUBLIC_ID_Marshal(&source->unique, buffer, size, source->type); + return written; +} + +/* Table 2:192 - Definition of TPM2B_PUBLIC Structure (StructuresTable()) */ + +UINT16 +TPM2B_PUBLIC_Marshal(TPM2B_PUBLIC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + BYTE *sizePtr = NULL; // libtpms changes for ppc64el gcc-5 -O3 + + if (buffer != NULL) { + sizePtr = *buffer; + *buffer += sizeof(UINT16); + } + written += TPMT_PUBLIC_Marshal(&source->publicArea, buffer, size); + if (buffer != NULL) { + written += UINT16_Marshal(&written, &sizePtr, size); + } + else { + written += sizeof(UINT16); + } + return written; +} + +/* Table 2:195 - Definition of TPMU_SENSITIVE_COMPOSITE Union (StructuresTable()) */ + +UINT16 +TPMU_SENSITIVE_COMPOSITE_Marshal(TPMU_SENSITIVE_COMPOSITE *source, BYTE **buffer, INT32 *size, UINT32 selector) +{ + UINT16 written = 0; + + switch (selector) { +#if ALG_RSA + case TPM_ALG_RSA: + written += TPM2B_PRIVATE_KEY_RSA_Marshal(&source->rsa, buffer, size); + break; +#endif +#if ALG_ECC + case TPM_ALG_ECC: + written += TPM2B_ECC_PARAMETER_Marshal(&source->ecc, buffer, size); + break; +#endif +#if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + written += TPM2B_SENSITIVE_DATA_Marshal(&source->bits, buffer, size); + break; +#endif +#if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + written += TPM2B_SYM_KEY_Marshal(&source->sym, buffer, size); + break; +#endif + default: + pAssert(FALSE); + } + return written; +} + +/* Table 2:196 - Definition of TPMT_SENSITIVE Structure (StructuresTable()) */ + +UINT16 +TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_ALG_PUBLIC_Marshal(&source->sensitiveType, buffer, size); + written += TPM2B_AUTH_Marshal(&source->authValue, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->seedValue, buffer, size); + written += TPMU_SENSITIVE_COMPOSITE_Marshal(&source->sensitive, buffer, size, source->sensitiveType); + return written; +} + +/* Table 2:199 - Definition of TPM2B_PRIVATE Structure (StructuresTable()) */ + +UINT16 +TPM2B_PRIVATE_Marshal(TPM2B_PRIVATE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:201 - Definition of TPM2B_ID_OBJECT Structure (StructuresTable()) */ + +UINT16 +TPM2B_ID_OBJECT_Marshal(TPM2B_ID_OBJECT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.credential), buffer, size); // libtpms changed + return written; +} + +/* Table 2:205 - Definition of TPMA_NV Bits (BitsTable()) */ + +UINT16 +TPMA_NV_Marshal(TPMA_NV *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal((UINT32 *)source, buffer, size); /* libtpms changed */ + return written; +} + +/* Table 2:206 - Definition of TPMS_NV_PUBLIC Structure (StructuresTable()) */ + +UINT16 +TPMS_NV_PUBLIC_Marshal(TPMS_NV_PUBLIC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPMI_RH_NV_INDEX_Marshal(&source->nvIndex, buffer, size); + written += TPMI_ALG_HASH_Marshal(&source->nameAlg, buffer, size); + written += TPMA_NV_Marshal(&source->attributes, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->authPolicy, buffer, size); + written += UINT16_Marshal(&source->dataSize, buffer, size); + return written; +} + +/* Table 2:207 - Definition of TPM2B_NV_PUBLIC Structure (StructuresTable()) */ + +UINT16 +TPM2B_NV_PUBLIC_Marshal(TPM2B_NV_PUBLIC *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + BYTE *sizePtr; + + if (buffer != NULL) { + sizePtr = *buffer; + *buffer += sizeof(UINT16); + } + written += TPMS_NV_PUBLIC_Marshal(&source->nvPublic, buffer, size); + if (buffer != NULL) { + written += UINT16_Marshal(&written, &sizePtr, size); + } + else { + written += sizeof(UINT16); + } + return written; +} + +/* Table 2:210 - Definition of TPM2B_CONTEXT_DATA Structure (StructuresTable()) */ + +UINT16 +TPM2B_CONTEXT_DATA_Marshal(TPM2B_CONTEXT_DATA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; +} + +/* Table 2:211 - Definition of TPMS_CONTEXT Structure (StructuresTable()) */ + +UINT16 +TPMS_CONTEXT_Marshal(TPMS_CONTEXT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += UINT64_Marshal(&source->sequence, buffer, size); + written += TPMI_DH_SAVED_Marshal(&source->savedHandle, buffer, size); + written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); + written += TPM2B_CONTEXT_DATA_Marshal(&source->contextBlob, buffer, size); + return written; +} + +/* Table 2:213 - Definition of TPMS_CREATION_DATA Structure (StructuresTable()) */ + +UINT16 +TPMS_CREATION_DATA_Marshal(TPMS_CREATION_DATA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPML_PCR_SELECTION_Marshal(&source->pcrSelect, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->pcrDigest, buffer, size); + written += TPMA_LOCALITY_Marshal(&source->locality, buffer, size); + written += TPM_ALG_ID_Marshal(&source->parentNameAlg, buffer, size); + written += TPM2B_NAME_Marshal(&source->parentName, buffer, size); + written += TPM2B_NAME_Marshal(&source->parentQualifiedName, buffer, size); + written += TPM2B_DATA_Marshal(&source->outsideInfo, buffer, size); + return written; +} + +/* Table 2:214 - Definition of TPM2B_CREATION_DATA Structure (StructuresTable()) */ + +UINT16 +TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + BYTE *sizePtr = NULL; // libtpms added for s390x on Fedora 32 + + if (buffer != NULL) { + sizePtr = *buffer; + *buffer += sizeof(UINT16); + } + written += TPMS_CREATION_DATA_Marshal(&source->creationData, buffer, size); + if (buffer != NULL) { + written += UINT16_Marshal(&written, &sizePtr, size); + } + else { + written += sizeof(UINT16); + } + return written; +} + +/* Table 225 - Definition of (UINT32) TPM_AT Constants */ + +UINT16 +TPM_AT_Marshal(TPM_AT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += UINT32_Marshal(source, buffer, size); + return written; +} + +/* Table 227 - Definition of TPMS_AC_OUTPUT Structure */ + +UINT16 +TPMS_AC_OUTPUT_Marshal(TPMS_AC_OUTPUT *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_AT_Marshal(&source->tag, buffer, size); + written += UINT32_Marshal(&source->data, buffer, size); + return written; +} + +/* Table 228 - Definition of TPML_AC_CAPABILITIES Structure */ + +UINT16 +TPML_AC_CAPABILITIES_Marshal(TPML_AC_CAPABILITIES *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT32 i; + + written += UINT32_Marshal(&source->count, buffer, size); + for (i = 0 ; i < source->count ; i++) { + written += TPMS_AC_OUTPUT_Marshal(&source->acCapabilities[i], buffer, size); + } + return written; +} + diff --git a/src/tpm2/Marshal_fp.h b/src/tpm2/Marshal_fp.h new file mode 100644 index 0000000..d52f497 --- /dev/null +++ b/src/tpm2/Marshal_fp.h @@ -0,0 +1,400 @@ +/********************************************************************************/ +/* */ +/* Parameter Marshaling */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Marshal_fp.h 1635 2020-06-12 21:48:27Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +#ifndef MARSHAL_FP_H +#define MARSHAL_FP_H + +#include "TpmTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + + UINT16 + UINT8_Marshal(UINT8 *source, BYTE **buffer, INT32 *size); + UINT16 + UINT16_Marshal(UINT16 *source, BYTE **buffer, INT32 *size); + UINT16 + UINT32_Marshal(UINT32 *source, BYTE **buffer, INT32 *size); + UINT16 + UINT64_Marshal(UINT64 *source, BYTE **buffer, INT32 *size); + UINT16 + Array_Marshal(BYTE *sourceBuffer, UINT16 sourceSize, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_Marshal(TPM2B *source, UINT32 maxSize, BYTE **buffer, INT32 *size); // libtpms changed + UINT16 + TPM_KEY_BITS_Marshal(TPM_KEY_BITS *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_CONSTANTS32_Marshal(TPM_CONSTANTS32 *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_ALG_ID_Marshal(TPM_ALG_ID *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_ECC_CURVE_Marshal(TPM_ECC_CURVE *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_CC_Marshal(TPM_CC *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_RC_Marshal(TPM_RC *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_ST_Marshal(TPM_ST *source, BYTE **buffer, INT32 *size); + INT16 + TPM_CAP_Marshal(TPM_CAP *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_PT_Marshal(TPM_PT *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_PT_PCR_Marshal(TPM_PT_PCR *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_HANDLE_Marshal(TPM_HANDLE *source, BYTE **buffer, INT32 *size); + UINT16 + TPMA_ALGORITHM_Marshal(TPMA_ALGORITHM *source, BYTE **buffer, INT32 *size); + UINT16 + TPMA_OBJECT_Marshal(TPMA_OBJECT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMA_SESSION_Marshal(TPMA_SESSION *source, BYTE **buffer, INT32 *size); + UINT16 + TPMA_LOCALITY_Marshal(TPMA_LOCALITY *source, BYTE **buffer, INT32 *size); + UINT16 + TPMA_CC_Marshal(TPMA_CC *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_YES_NO_Marshal(TPMI_YES_NO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMA_ACT_Marshal(TPMA_ACT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_DH_SAVED_Marshal(TPMI_DH_CONTEXT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_RH_HIERARCHY_Marshal(TPMI_RH_HIERARCHY *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_RH_NV_INDEX_Marshal(TPMI_RH_NV_INDEX *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ALG_HASH_Marshal(TPMI_ALG_HASH *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ALG_SYM_OBJECT_Marshal(TPMI_ALG_SYM_OBJECT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMI_ALG_SYM_MODE_Marshal(TPMI_ALG_SYM_MODE *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ALG_KDF_Marshal(TPMI_ALG_KDF *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ALG_SIG_SCHEME_Marshal(TPMI_ALG_SIG_SCHEME *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_HA_Marshal(TPMU_HA *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMT_HA_Marshal(TPMT_HA *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_DATA_Marshal(TPM2B_DATA *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_NONCE_Marshal(TPM2B_NONCE *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_AUTH_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_MAX_BUFFER_Marshal(TPM2B_MAX_BUFFER *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_IV_Marshal(TPM2B_IV *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_NAME_Marshal(TPM2B_NAME *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_PCR_SELECTION_Marshal(TPMS_PCR_SELECTION *source, BYTE **buffer, INT32 *size); + UINT16 + TPMT_TK_CREATION_Marshal(TPMT_TK_CREATION *source, BYTE **buffer, INT32 *size); + UINT16 + TPMT_TK_VERIFIED_Marshal(TPMT_TK_VERIFIED *source, BYTE **buffer, INT32 *size); + UINT16 + TPMT_TK_AUTH_Marshal(TPMT_TK_AUTH *source, BYTE **buffer, INT32 *size); + UINT16 + TPMT_TK_HASHCHECK_Marshal(TPMT_TK_HASHCHECK *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_ALG_PROPERTY_Marshal(TPMS_ALG_PROPERTY *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_TAGGED_PCR_SELECT_Marshal(TPMS_TAGGED_PCR_SELECT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_TAGGED_POLICY_Marshal(TPMS_TAGGED_POLICY *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_ACT_DATA_Marshal(TPMS_ACT_DATA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_TAGGED_PROPERTY_Marshal(TPMS_TAGGED_PROPERTY *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_CC_Marshal(TPML_CC *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_CCA_Marshal(TPML_CCA *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_ALG_Marshal(TPML_ALG *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_DIGEST_Marshal(TPML_DIGEST *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_HANDLE_Marshal(TPML_HANDLE *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_DIGEST_VALUES_Marshal(TPML_DIGEST_VALUES *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_PCR_SELECTION_Marshal(TPML_PCR_SELECTION *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_ALG_PROPERTY_Marshal(TPML_ALG_PROPERTY *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_TAGGED_TPM_PROPERTY_Marshal(TPML_TAGGED_TPM_PROPERTY *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_TAGGED_PCR_PROPERTY_Marshal(TPML_TAGGED_PCR_PROPERTY *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_ECC_CURVE_Marshal(TPML_ECC_CURVE *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_TAGGED_POLICY_Marshal(TPML_TAGGED_POLICY *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_ACT_DATA_Marshal(TPML_ACT_DATA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_CAPABILITIES_Marshal(TPMU_CAPABILITIES *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMS_CAPABILITY_DATA_Marshal(TPMS_CAPABILITY_DATA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_CLOCK_INFO_Marshal(TPMS_CLOCK_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_TIME_INFO_Marshal(TPMS_TIME_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_TIME_ATTEST_INFO_Marshal(TPMS_TIME_ATTEST_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_CERTIFY_INFO_Marshal(TPMS_CERTIFY_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_QUOTE_INFO_Marshal(TPMS_QUOTE_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_COMMAND_AUDIT_INFO_Marshal(TPMS_COMMAND_AUDIT_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SESSION_AUDIT_INFO_Marshal(TPMS_SESSION_AUDIT_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_CREATION_INFO_Marshal(TPMS_CREATION_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_NV_CERTIFY_INFO_Marshal(TPMS_NV_CERTIFY_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_NV_DIGEST_CERTIFY_INFO_Marshal(TPMS_NV_DIGEST_CERTIFY_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_ST_ATTEST_NV_DIGEST_Marshal(TPMS_NV_DIGEST_CERTIFY_INFO *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ST_ATTEST_Marshal(TPMI_ST_ATTEST *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_ATTEST_Marshal(TPMU_ATTEST *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMS_ATTEST_Marshal(TPMS_ATTEST *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_ATTEST_Marshal(TPM2B_ATTEST *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size); + UINT16 // libtpms added + TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_CAMELLIA_KEY_BITS_Marshal(TPMI_CAMELLIA_KEY_BITS *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMU_SYM_MODE_Marshal(TPMU_SYM_MODE *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMT_SYM_DEF_OBJECT_Marshal(TPMT_SYM_DEF_OBJECT *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_SYM_KEY_Marshal(TPM2B_SYM_KEY *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SYMCIPHER_PARMS_Marshal(TPMS_SYMCIPHER_PARMS *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_SENSITIVE_DATA_Marshal(TPM2B_SENSITIVE_DATA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SCHEME_HASH_Marshal(TPMS_SCHEME_HASH *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SCHEME_ECDAA_Marshal(TPMS_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ALG_KEYEDHASH_SCHEME_Marshal(TPMI_ALG_KEYEDHASH_SCHEME *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SCHEME_HMAC_Marshal(TPMS_SCHEME_HMAC *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SCHEME_XOR_Marshal(TPMS_SCHEME_XOR *source, BYTE **buffer, INT32 *size); + UINT16 + TPMT_KEYEDHASH_SCHEME_Marshal(TPMT_KEYEDHASH_SCHEME *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIG_SCHEME_RSASSA_Marshal(TPMS_SIG_SCHEME_RSASSA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIG_SCHEME_RSAPSS_Marshal(TPMS_SIG_SCHEME_RSAPSS *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIG_SCHEME_ECDSA_Marshal(TPMS_SIG_SCHEME_ECDSA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIG_SCHEME_SM2_Marshal(TPMS_SIG_SCHEME_SM2 *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIG_SCHEME_ECSCHNORR_Marshal(TPMS_SIG_SCHEME_ECSCHNORR *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIG_SCHEME_ECDAA_Marshal(TPMS_SIG_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_ENC_SCHEME_OAEP_Marshal(TPMS_ENC_SCHEME_OAEP *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_ENC_SCHEME_RSAES_Marshal(TPMS_ENC_SCHEME_RSAES *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_SCHEME_KEYEDHASH_Marshal(TPMU_SCHEME_KEYEDHASH *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMS_KEY_SCHEME_ECDH_Marshal(TPMS_KEY_SCHEME_ECDH *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_KEY_SCHEME_ECMQV_Marshal(TPMS_KEY_SCHEME_ECMQV*source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_KDF_SCHEME_MGF1_Marshal(TPMS_KDF_SCHEME_MGF1 *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(TPMS_KDF_SCHEME_KDF1_SP800_56A *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_KDF_SCHEME_KDF2_Marshal(TPMS_KDF_SCHEME_KDF2 *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(TPMS_KDF_SCHEME_KDF1_SP800_108 *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_KDF_SCHEME_Marshal(TPMU_KDF_SCHEME *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMT_KDF_SCHEME_Marshal(TPMT_KDF_SCHEME *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_ASYM_SCHEME_Marshal(TPMU_ASYM_SCHEME *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMI_ALG_RSA_SCHEME_Marshal(TPMI_ALG_RSA_SCHEME *source, BYTE **buffer, INT32 *size); + UINT16 + TPMT_RSA_SCHEME_Marshal(TPMT_RSA_SCHEME *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_PUBLIC_KEY_RSA_Marshal(TPM2B_PUBLIC_KEY_RSA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_RSA_KEY_BITS_Marshal(TPMI_RSA_KEY_BITS *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_PRIVATE_KEY_RSA_Marshal(TPM2B_PRIVATE_KEY_RSA *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_ECC_PARAMETER_Marshal(TPM2B_ECC_PARAMETER *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_ECC_POINT_Marshal(TPMS_ECC_POINT *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_ECC_POINT_Marshal(TPM2B_ECC_POINT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ALG_ECC_SCHEME_Marshal(TPMI_ALG_ECC_SCHEME *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ECC_CURVE_Marshal(TPMI_ECC_CURVE *source, BYTE **buffer, INT32 *size); + UINT16 + TPMT_ECC_SCHEME_Marshal(TPMT_ECC_SCHEME *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_ALGORITHM_DETAIL_ECC_Marshal(TPMS_ALGORITHM_DETAIL_ECC *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIGNATURE_RSA_Marshal(TPMS_SIGNATURE_RSA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIGNATURE_RSASSA_Marshal(TPMS_SIGNATURE_RSASSA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIGNATURE_RSAPSS_Marshal(TPMS_SIGNATURE_RSAPSS *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIGNATURE_ECC_Marshal(TPMS_SIGNATURE_ECC *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIGNATURE_ECDSA_Marshal(TPMS_SIGNATURE_ECDSA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIGNATURE_ECDAA_Marshal(TPMS_SIGNATURE_ECDAA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIGNATURE_SM2_Marshal(TPMS_SIGNATURE_SM2 *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_SIGNATURE_ECSCHNORR_Marshal(TPMS_SIGNATURE_ECSCHNORR *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_SIGNATURE_Marshal(TPMU_SIGNATURE *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMT_SIGNATURE_Marshal(TPMT_SIGNATURE *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_ENCRYPTED_SECRET_Marshal(TPM2B_ENCRYPTED_SECRET *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_ALG_PUBLIC_Marshal(TPMI_ALG_PUBLIC *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_PUBLIC_ID_Marshal(TPMU_PUBLIC_ID *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMS_KEYEDHASH_PARMS_Marshal(TPMS_KEYEDHASH_PARMS *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_RSA_PARMS_Marshal(TPMS_RSA_PARMS *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_ECC_PARMS_Marshal(TPMS_ECC_PARMS *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_PUBLIC_PARMS_Marshal(TPMU_PUBLIC_PARMS *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMT_PUBLIC_Marshal(TPMT_PUBLIC *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_PUBLIC_Marshal(TPM2B_PUBLIC *source, BYTE **buffer, INT32 *size); + UINT16 + TPMU_SENSITIVE_COMPOSITE_Marshal(TPMU_SENSITIVE_COMPOSITE *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 + TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_PRIVATE_Marshal(TPM2B_PRIVATE *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_ID_OBJECT_Marshal(TPM2B_ID_OBJECT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMA_NV_Marshal(TPMA_NV *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_NV_PUBLIC_Marshal(TPMS_NV_PUBLIC *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_NV_PUBLIC_Marshal(TPM2B_NV_PUBLIC *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_CONTEXT_DATA_Marshal(TPM2B_CONTEXT_DATA *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_CONTEXT_Marshal(TPMS_CONTEXT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_CREATION_DATA_Marshal(TPMS_CREATION_DATA *source, BYTE **buffer, INT32 *size); + UINT16 + TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA *source, BYTE **buffer, INT32 *size); + UINT16 + TPM_AT_Marshal(TPM_AT *source, BYTE **buffer, INT32 *size); + UINT16 + TPMS_AC_OUTPUT_Marshal(TPMS_AC_OUTPUT *source, BYTE **buffer, INT32 *size); + UINT16 + TPML_AC_CAPABILITIES_Marshal(TPML_AC_CAPABILITIES *source, BYTE **buffer, INT32 *size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/tpm2/MathOnByteBuffers.c b/src/tpm2/MathOnByteBuffers.c new file mode 100644 index 0000000..7a0b9da --- /dev/null +++ b/src/tpm2/MathOnByteBuffers.c @@ -0,0 +1,266 @@ +/********************************************************************************/ +/* */ +/* Math functions performed with canonical integers in byte buffers */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: MathOnByteBuffers.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 9.11 MathOnByteBuffers.c */ +/* 9.11.1 Introduction */ +/* This file contains implementation of the math functions that are performed with canonical + integers in byte buffers. The canonical integer is big-endian bytes. */ +#include "Tpm.h" +/* 9.11.2.1 UnsignedCmpB */ +/* This function compare two unsigned values. The values are byte-aligned, big-endian numbers (e.g, + a hash). */ +/* Return Values Meaning */ +/* 1 if (a > b) */ +/* 0 if (a = b) */ +/* -1 if (a < b) */ +LIB_EXPORT int +UnsignedCompareB( + UINT32 aSize, // IN: size of a + const BYTE *a, // IN: a + UINT32 bSize, // IN: size of b + const BYTE *b // IN: b + ) +{ + UINT32 i; + if(aSize > bSize) + return 1; + else if(aSize < bSize) + return -1; + else + { + for(i = 0; i < aSize; i++) + { + if(a[i] != b[i]) + return (a[i] > b[i]) ? 1 : -1; + } + } + return 0; +} +/* 9.11.2.2 SignedCompareB() */ +/* Compare two signed integers: */ +/* Return Values Meaning */ +/* 1 if a > b */ +/* 0 if a = b */ +/* -1 if a < b */ +int +SignedCompareB( + const UINT32 aSize, // IN: size of a + const BYTE *a, // IN: a buffer + const UINT32 bSize, // IN: size of b + const BYTE *b // IN: b buffer + ) +{ + int signA, signB; // sign of a and b + // For positive or 0, sign_a is 1 + // for negative, sign_a is 0 + signA = ((a[0] & 0x80) == 0) ? 1 : 0; + // For positive or 0, sign_b is 1 + // for negative, sign_b is 0 + signB = ((b[0] & 0x80) == 0) ? 1 : 0; + if(signA != signB) + { + return signA - signB; + } + if(signA == 1) + // do unsigned compare function + return UnsignedCompareB(aSize, a, bSize, b); + else + // do unsigned compare the other way + return 0 - UnsignedCompareB(aSize, a, bSize, b); +} +/* 9.11.3.3 ModExpB */ +/* This function is used to do modular exponentiation in support of RSA. The most typical uses are: + c = m^e mod n (RSA encrypt) and m = c^d mod n (RSA decrypt). When doing decryption, the e + parameter of the function will contain the private exponent d instead of the public exponent + e. */ +/* If the results will not fit in the provided buffer, an error is returned + (CRYPT_ERROR_UNDERFLOW). If the results is smaller than the buffer, the results is + de-normalized. */ +/* This version is intended for use with RSA and requires that m be less than n. */ +/* Error Returns Meaning */ +/* TPM_RC_SIZE number to exponentiate is larger than the modulus */ +/* TPM_RC_NO_RESULT result will not fit into the provided buffer */ +TPM_RC +ModExpB( + UINT32 cSize, // IN: the size of the output buffer. It will + // need to be the same size as the modulus + BYTE *c, // OUT: the buffer to receive the results + // (c->size must be set to the maximum size + // for the returned value) + const UINT32 mSize, + const BYTE *m, // IN: number to exponentiate + const UINT32 eSize, + const BYTE *e, // IN: power + const UINT32 nSize, + const BYTE *n // IN: modulus + ) +{ + BN_MAX(bnC); + BN_MAX(bnM); + BN_MAX(bnE); + BN_MAX(bnN); + NUMBYTES tSize = (NUMBYTES)nSize; + TPM_RC retVal = TPM_RC_SUCCESS; + // Convert input parameters + BnFromBytes(bnM, m, (NUMBYTES)mSize); + BnFromBytes(bnE, e, (NUMBYTES)eSize); + BnFromBytes(bnN, n, (NUMBYTES)nSize); + // Make sure that the output is big enough to hold the result + // and that 'm' is less than 'n' (the modulus) + if(cSize < nSize) + ERROR_RETURN(TPM_RC_NO_RESULT); + if(BnUnsignedCmp(bnM, bnN) >= 0) + ERROR_RETURN(TPM_RC_SIZE); + BnModExp(bnC, bnM, bnE, bnN); + BnToBytes(bnC, c, &tSize); + Exit: + return retVal; +} +/* 9.11.2.4 DivideB() */ +/* Divide an integer (n) by an integer (d) producing a quotient (q) and a remainder (r). If q or r + is not needed, then the pointer to them may be set to NULL. */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT q or r is too small to receive the result */ +LIB_EXPORT TPM_RC +DivideB( + const TPM2B *n, // IN: numerator + const TPM2B *d, // IN: denominator + TPM2B *q, // OUT: quotient + TPM2B *r // OUT: remainder + ) +{ + BN_MAX_INITIALIZED(bnN, n); + BN_MAX_INITIALIZED(bnD, d); + BN_MAX(bnQ); + BN_MAX(bnR); + // + // Do divide with converted values + BnDiv(bnQ, bnR, bnN, bnD); + // Convert the BIGNUM result back to 2B format using the size of the original + // number + if(q != NULL) + if(!BnTo2B(bnQ, q, q->size)) + return TPM_RC_NO_RESULT; + if(r != NULL) + if(!BnTo2B(bnR, r, r->size)) + return TPM_RC_NO_RESULT; + return TPM_RC_SUCCESS; +} +/* 9.11.2.5 AdjustNumberB() */ +/* Remove/add leading zeros from a number in a TPM2B. Will try to make the number by adding or + removing leading zeros. If the number is larger than the requested size, it will make the number + as small as possible. Setting requestedSize to zero is equivalent to requesting that the number + be normalized. */ +UINT16 +AdjustNumberB( + TPM2B *num, + UINT16 requestedSize + ) +{ + BYTE *from; + UINT16 i; + // See if number is already the requested size + if(num->size == requestedSize) + return requestedSize; + from = num->buffer; + if (num->size > requestedSize) + { + // This is a request to shift the number to the left (remove leading zeros) + // Find the first non-zero byte. Don't look past the point where removing + // more zeros would make the number smaller than requested, and don't throw + // away any significant digits. + for(i = num->size; *from == 0 && i > requestedSize; from++, i--); + if(i < num->size) + { + num->size = i; + MemoryCopy(num->buffer, from, i); + } + } + // This is a request to shift the number to the right (add leading zeros) + else + { + MemoryCopy(&num->buffer[requestedSize - num->size], num->buffer, num->size); + MemorySet(num->buffer, 0, requestedSize- num->size); + num->size = requestedSize; + } + return num->size; +} + +/* 9.11.2.6 ShiftLeft() */ +/* This function shifts a byte buffer (a TPM2B) one byte to the left. That is, the most significant + bit of the most significant byte is lost. */ +TPM2B * +ShiftLeft( + TPM2B *value // IN/OUT: value to shift and shifted value out + ) +{ + UINT16 count = value->size; + BYTE *buffer = value->buffer; + if(count > 0) + { + for(count -= 1; count > 0; buffer++, count--) + { + buffer[0] = (buffer[0] << 1) + ((buffer[1] & 0x80) ? 1 : 0); + } + *buffer <<= 1; + } + return value; +} diff --git a/src/tpm2/MathOnByteBuffers_fp.h b/src/tpm2/MathOnByteBuffers_fp.h new file mode 100644 index 0000000..42f6112 --- /dev/null +++ b/src/tpm2/MathOnByteBuffers_fp.h @@ -0,0 +1,110 @@ +/********************************************************************************/ +/* */ +/* Math functions performed with canonical integers in byte buffers */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: MathOnByteBuffers_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef MATHONBYTEBUFFERS_FP_H +#define MATHONBYTEBUFFERS_FP_H + +LIB_EXPORT int +UnsignedCompareB( + UINT32 aSize, // IN: size of a + const BYTE *a, // IN: a + UINT32 bSize, // IN: size of b + const BYTE *b // IN: b + ); +int +SignedCompareB( + const UINT32 aSize, // IN: size of a + const BYTE *a, // IN: a buffer + const UINT32 bSize, // IN: size of b + const BYTE *b // IN: b buffer + ); +TPM_RC +ModExpB( + UINT32 cSize, // IN: the size of the output buffer. It will + // need to be the same size as the modulus + BYTE *c, // OUT: the buffer to receive the results + // (c->size must be set to the maximum size + // for the returned value) + const UINT32 mSize, + const BYTE *m, // IN: number to exponentiate + const UINT32 eSize, + const BYTE *e, // IN: power + const UINT32 nSize, + const BYTE *n // IN: modulus + ); +LIB_EXPORT TPM_RC +DivideB( + const TPM2B *n, // IN: numerator + const TPM2B *d, // IN: denominator + TPM2B *q, // OUT: quotient + TPM2B *r // OUT: remainder + ); +UINT16 +AdjustNumberB( + TPM2B *num, + UINT16 requestedSize + ); +TPM2B * +ShiftLeft( + TPM2B *value // IN/OUT: value to shift and shifted value out + ); + +#endif diff --git a/src/tpm2/Memory.c b/src/tpm2/Memory.c new file mode 100644 index 0000000..e9472dd --- /dev/null +++ b/src/tpm2/Memory.c @@ -0,0 +1,287 @@ +/********************************************************************************/ +/* */ +/* Miscellaneous Memory Manipulation Routines */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Memory.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 9.12 Memory.c */ +/* 9.12.1 Description */ +/* This file contains a set of miscellaneous memory manipulation routines. Many of the functions + have the same semantics as functions defined in string.h. Those functions are not used directly + in the TPM because they are not safe */ +/* This version uses string.h after adding guards. This is because the math libraries invariably + use those functions so it is not practical to prevent those library functions from being pulled + into the build. */ +/* 9.12.2 Includes and Data Definitions */ +#include "Tpm.h" +#include "Memory_fp.h" +/* 9.12.3 Functions */ +/* 9.12.3.1 MemoryCopy() */ +/* This is an alias for memmove. This is used in place of memcpy because some of the moves may + overlap and rather than try to make sure that memmove is used when necessary, it is always + used. */ + +void +MemoryCopy( + void *dest, + const void *src, + int sSize + ) +{ + if (dest != src) + memmove(dest, src, sSize); +} + +/* 9.12.3.2 MemoryEqual() */ +/* This function indicates if two buffers have the same values in the indicated number of bytes. */ +/* Return Values Meaning */ +/* TRUE all octets are the same */ +/* FALSE all octets are not the same */ +BOOL +MemoryEqual( + const void *buffer1, // IN: compare buffer1 + const void *buffer2, // IN: compare buffer2 + unsigned int size // IN: size of bytes being compared + ) +{ + BYTE equal = 0; + const BYTE *b1 = (BYTE *)buffer1; + const BYTE *b2 = (BYTE *)buffer2; + // + // Compare all bytes so that there is no leakage of information + // due to timing differences. + for(; size > 0; size--) + equal |= (*b1++ ^ *b2++); + return (equal == 0); +} +/* 9.12.3.3 MemoryCopy2B() */ +/* This function copies a TPM2B. This can be used when the TPM2B types are the same or different. */ +/* This function returns the number of octets in the data buffer of the TPM2B. */ +LIB_EXPORT INT16 +MemoryCopy2B( + TPM2B *dest, // OUT: receiving TPM2B + const TPM2B *source, // IN: source TPM2B + unsigned int dSize // IN: size of the receiving buffer + ) +{ + pAssert(dest != NULL); + if(source == NULL) + dest->size = 0; + else + { + pAssert(source->size <= dSize); + MemoryCopy(dest->buffer, source->buffer, source->size); + dest->size = source->size; + } + return dest->size; +} +/* 9.12.3.4 MemoryConcat2B() */ +/* This function will concatenate the buffer contents of a TPM2B to the buffer contents of + another TPM2B and adjust the size accordingly (a := (a | b)). */ +void +MemoryConcat2B( + TPM2B *aInOut, // IN/OUT: destination 2B + TPM2B *bIn, // IN: second 2B + unsigned int aMaxSize // IN: The size of aInOut.buffer (max values for + // aInOut.size) + ) +{ + pAssert(bIn->size <= aMaxSize - aInOut->size); + MemoryCopy(&aInOut->buffer[aInOut->size], &bIn->buffer, bIn->size); + aInOut->size = aInOut->size + bIn->size; + return; +} +/* 9.12.3.5 MemoryEqual2B() */ +/* This function will compare two TPM2B structures. To be equal, they need to be the same size and + the buffer contexts need to be the same in all octets. */ +/* Return Values Meaning */ +/* TRUE size and buffer contents are the same */ +/* FALSE size or buffer contents are not the same */ +BOOL +MemoryEqual2B( + const TPM2B *aIn, // IN: compare value + const TPM2B *bIn // IN: compare value + ) +{ + if(aIn->size != bIn->size) + return FALSE; + return MemoryEqual(aIn->buffer, bIn->buffer, aIn->size); +} +/* 9.12.3.6 MemorySet() */ +/* This function will set all the octets in the specified memory range to the specified octet + value. */ +/* NOTE: A previous version had an additional parameter (dSize) that was intended to make sure that + the destination would not be overrun. The problem is that, in use, all that was happening was + that the value of size was used for dSize so there was no benefit in the extra parameter. */ + +void +MemorySet( + void *dest, + int value, + size_t size + ) +{ + memset(dest, value, size); +} + +/* 9.12.3.7 MemoryPad2B() */ +/* Function to pad a TPM2B with zeros and adjust the size. */ + +void +MemoryPad2B( + TPM2B *b, + UINT16 newSize + ) +{ + MemorySet(&b->buffer[b->size], 0, newSize - b->size); + b->size = newSize; +} + +/* 9.12.3.8 Uint16ToByteArray() */ +/* Function to write an integer to a byte array */ + +void +Uint16ToByteArray( + UINT16 i, + BYTE *a + ) +{ + a[1] = (BYTE)(i); i >>= 8; + a[0] = (BYTE)(i); +} + +/* 9.12.3.9 Uint32ToByteArray() */ +/* Function to write an integer to a byte array */ + +void +Uint32ToByteArray( + UINT32 i, + BYTE *a + ) +{ + a[3] = (BYTE)(i); i >>= 8; + a[2] = (BYTE)(i); i >>= 8; + a[1] = (BYTE)(i); i >>= 8; + a[0] = (BYTE)(i); +} + +/* 9.12.3.10 Uint64ToByteArray() */ +/* Function to write an integer to a byte array */ + +void +Uint64ToByteArray( + UINT64 i, + BYTE *a + ) +{ + a[7] = (BYTE)(i); i >>= 8; + a[6] = (BYTE)(i); i >>= 8; + a[5] = (BYTE)(i); i >>= 8; + a[4] = (BYTE)(i); i >>= 8; + a[3] = (BYTE)(i); i >>= 8; + a[2] = (BYTE)(i); i >>= 8; + a[1] = (BYTE)(i); i >>= 8; + a[0] = (BYTE)(i); +} + +/* 9.12.3.11 ByteArrayToUint8() */ +/* Function to write a UINT8 to a byte array. This is included for completeness and to allow certain + macro expansions */ +#if 0 // libtpms added +UINT8 +ByteArrayToUint8( + BYTE *a + ) +{ + return *a; +} +#endif // libtpms added + +/* 9.12.3.12 ByteArrayToUint16() */ +/* Function to write an integer to a byte array */ + +UINT16 +ByteArrayToUint16( + BYTE *a + ) +{ + return ((UINT16)a[0] << 8) + a[1]; +} + +/* 9.12.3.13 ByteArrayToUint32() */ +/* Function to write an integer to a byte array */ + +UINT32 +ByteArrayToUint32( + BYTE *a + ) +{ + return (UINT32)((((((UINT32)a[0] << 8) + a[1]) << 8) + (UINT32)a[2]) << 8) + a[3]; +} + +/* 9.12.3.14 ByteArrayToUint64() */ +/* Function to write an integer to a byte array */ + +UINT64 +ByteArrayToUint64( + BYTE *a + ) +{ + return (((UINT64)BYTE_ARRAY_TO_UINT32(a)) << 32) + BYTE_ARRAY_TO_UINT32(&a[4]); +} + diff --git a/src/tpm2/Memory_fp.h b/src/tpm2/Memory_fp.h new file mode 100644 index 0000000..082e8db --- /dev/null +++ b/src/tpm2/Memory_fp.h @@ -0,0 +1,139 @@ +/********************************************************************************/ +/* */ +/* Miscellaneous Memory Manipulation Routines */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Memory_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef MEMORY_FP_H +#define MEMORY_FP_H + +void +MemoryCopy( + void *dest, + const void *src, + int sSize + ); +BOOL +MemoryEqual( + const void *buffer1, // IN: compare buffer1 + const void *buffer2, // IN: compare buffer2 + unsigned int size // IN: size of bytes being compared + ); +LIB_EXPORT INT16 +MemoryCopy2B( + TPM2B *dest, // OUT: receiving TPM2B + const TPM2B *source, // IN: source TPM2B + unsigned int dSize // IN: size of the receiving buffer + ); +void +MemoryConcat2B( + TPM2B *aInOut, // IN/OUT: destination 2B + TPM2B *bIn, // IN: second 2B + unsigned int aMaxSize // IN: The size of aInOut.buffer (max values for + // aInOut.size) + ); +BOOL +MemoryEqual2B( + const TPM2B *aIn, // IN: compare value + const TPM2B *bIn // IN: compare value + ); +void +MemorySet( + void *dest, + int value, + size_t size + ); +void +MemoryPad2B( + TPM2B *b, + UINT16 newSize + ); +void +Uint16ToByteArray( + UINT16 i, + BYTE *a + ); +void +Uint32ToByteArray( + UINT32 i, + BYTE *a + ); +void +Uint64ToByteArray( + UINT64 i, + BYTE *a + ); +UINT8 +ByteArrayToUint8( + BYTE *a + ); +UINT16 +ByteArrayToUint16( + BYTE *a + ); +UINT32 +ByteArrayToUint32( + BYTE *a + ); +UINT64 +ByteArrayToUint64( + BYTE *a + ); + + +#endif diff --git a/src/tpm2/MinMax.h b/src/tpm2/MinMax.h new file mode 100644 index 0000000..db008a8 --- /dev/null +++ b/src/tpm2/MinMax.h @@ -0,0 +1,73 @@ +/********************************************************************************/ +/* */ +/* Min Max Macros */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: MinMax.h 1529 2019-11-21 23:29:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +// 5.13 MinMax.h + +#ifndef _MIN_MAX_H_ +#define _MIN_MAX_H_ +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#endif // _MIN_MAX_H_ + diff --git a/src/tpm2/NV.h b/src/tpm2/NV.h new file mode 100644 index 0000000..26218c0 --- /dev/null +++ b/src/tpm2/NV.h @@ -0,0 +1,162 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef NV_H +#define NV_H + +/* 5.14.1 Index Type Definitions */ +/* These definitions allow the same code to be used pre and post 1.21. The main action is to + redefine the index type values from the bit values. Use TPM_NT_ORDINARY to indicate if the TPM_NT + type is defined */ +#ifdef TPM_NT_ORDINARY +/* If TPM_NT_ORDINARY is defined, then the TPM_NT field is present in a TPMA_NV */ +# define GET_TPM_NT(attributes) GET_ATTRIBUTE(attributes, TPMA_NV, TPM_NT) +#else +/* If TPM_NT_ORDINARY is not defined, then need to synthesize it from the attributes */ +# define GetNv_TPM_NV(attributes) \ + ( IS_ATTRIBUTE(attributes, TPMA_NV, COUNTER) \ + + (IS_ATTRIBUTE(attributes, TPMA_NV, BITS) << 1) \ + + (IS_ATTRIBUTE(attributes, TPMA_NV, EXTEND) << 2) \ + ) +# define TPM_NT_ORDINARY (0) +# define TPM_NT_COUNTER (1) +# define TPM_NT_BITS (2) +# define TPM_NT_EXTEND (4) +#endif +/* 5.14.2 Attribute Macros */ +/* These macros are used to isolate the differences in the way that the index type changed in + version 1.21 of the specification */ +# define IsNvOrdinaryIndex(attributes) \ + (GET_TPM_NT(attributes) == TPM_NT_ORDINARY) +# define IsNvCounterIndex(attributes) \ + (GET_TPM_NT(attributes) == TPM_NT_COUNTER) +# define IsNvBitsIndex(attributes) \ + (GET_TPM_NT(attributes) == TPM_NT_BITS) +# define IsNvExtendIndex(attributes) \ + (GET_TPM_NT(attributes) == TPM_NT_EXTEND) +#ifdef TPM_NT_PIN_PASS +# define IsNvPinPassIndex(attributes) \ + (GET_TPM_NT(attributes) == TPM_NT_PIN_PASS) +#endif +#ifdef TPM_NT_PIN_FAIL +# define IsNvPinFailIndex(attributes) \ + (GET_TPM_NT(attributes) == TPM_NT_PIN_FAIL) +#endif +typedef struct { + UINT32 size; + TPM_HANDLE handle; +} NV_ENTRY_HEADER; +#define NV_EVICT_OBJECT_SIZE \ + (sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(OBJECT)) +#define NV_INDEX_COUNTER_SIZE \ + (sizeof(UINT32) + sizeof(NV_INDEX) + sizeof(UINT64)) +#define NV_RAM_INDEX_COUNTER_SIZE \ + (sizeof(NV_RAM_HEADER) + sizeof(UINT64)) +typedef struct { + UINT32 size; + TPM_HANDLE handle; + TPMA_NV attributes; +} NV_RAM_HEADER; +/* Defines the end-of-list marker for NV. The list terminator is a UINT32 of zero, followed by the + current value of s_maxCounter which is a 64-bit value. The structure is defined as an array of 3 + UINT32 values so that there is no padding between the UINT32 list end marker and the UINT64 + maxCounter value. */ +typedef UINT32 NV_LIST_TERMINATOR[3]; +/* 5.14.3 Orderly RAM Values */ +/* The following defines are for accessing orderly RAM values. This is the initialize for the RAM + reference iterator. */ +#define NV_RAM_REF_INIT 0 +/* This is the starting address of the RAM space used for orderly data */ +#define RAM_ORDERLY_START \ + (&s_indexOrderlyRam[0]) +/* This is the offset within NV that is used to save the orderly data on an orderly shutdown. */ +#define NV_ORDERLY_START \ + (NV_INDEX_RAM_DATA) +/* This is the end of the orderly RAM space. It is actually the first byte after the last byte of + orderly RAM data */ +#define RAM_ORDERLY_END \ + (RAM_ORDERLY_START + sizeof(s_indexOrderlyRam)) +/* This is the end of the orderly space in NV memory. As with RAM_ORDERLY_END, it is actually the + offset of the first byte after the end of the NV orderly data. */ +#define NV_ORDERLY_END \ + (NV_ORDERLY_START + sizeof(s_indexOrderlyRam)) +/* Macro to check that an orderly RAM address is with range. */ +#define ORDERLY_RAM_ADDRESS_OK(start, offset) \ + ((start >= RAM_ORDERLY_START) && ((start + offset - 1) < RAM_ORDERLY_END)) +#define RETURN_IF_NV_IS_NOT_AVAILABLE \ + { \ + if(g_NvStatus != TPM_RC_SUCCESS) \ + return g_NvStatus; \ + } +/* Routinely have to clear the orderly flag and fail if the NV is not available so that it can be + cleared. */ +#define RETURN_IF_ORDERLY \ + { \ + if(NvClearOrderly() != TPM_RC_SUCCESS) \ + return g_NvStatus; \ + } +#define NV_IS_AVAILABLE (g_NvStatus == TPM_RC_SUCCESS) +#define IS_ORDERLY(value) (value < SU_DA_USED_VALUE) +#define NV_IS_ORDERLY (IS_ORDERLY(gp.orderlyState)) +/* Macro to set the NV UPDATE_TYPE. This deals with the fact that the update is possibly a + combination of UT_NV and UT_ORDERLY. */ +#define SET_NV_UPDATE(type) g_updateNV |= (type) +#endif // _NV_H_ diff --git a/src/tpm2/NVCommands.c b/src/tpm2/NVCommands.c new file mode 100644 index 0000000..6908a14 --- /dev/null +++ b/src/tpm2/NVCommands.c @@ -0,0 +1,707 @@ +/********************************************************************************/ +/* */ +/* Non-Volatile Storage */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NVCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "NV_DefineSpace_fp.h" +#if CC_NV_DefineSpace // Conditional expansion of this file +TPM_RC +TPM2_NV_DefineSpace( + NV_DefineSpace_In *in // IN: input parameter list + ) +{ + TPMA_NV attributes = in->publicInfo.nvPublic.attributes; + UINT16 nameSize; + nameSize = CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg); + // Input Validation + // Checks not specific to type + // If the UndefineSpaceSpecial command is not implemented, then can't have + // an index that can only be deleted with policy +#if CC_NV_UndefineSpaceSpecial == NO + if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; +#endif + // check that the authPolicy consistent with hash algorithm + if(in->publicInfo.nvPublic.authPolicy.t.size != 0 + && in->publicInfo.nvPublic.authPolicy.t.size != nameSize) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + // make sure that the authValue is not too large + if(MemoryRemoveTrailingZeros(&in->auth) + > CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg)) + return TPM_RCS_SIZE + RC_NV_DefineSpace_auth; + // If an index is being created by the owner and shEnable is + // clear, then we would not reach this point because ownerAuth + // can't be given when shEnable is CLEAR. However, if phEnable + // is SET but phEnableNV is CLEAR, we have to check here + if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR) + return TPM_RCS_HIERARCHY + RC_NV_DefineSpace_authHandle; + // Attribute checks + // Eliminate the unsupported types + switch(GET_TPM_NT(attributes)) + { +#if CC_NV_Increment == YES + case TPM_NT_COUNTER: +#endif +#if CC_NV_SetBits == YES + case TPM_NT_BITS: +#endif +#if CC_NV_Extend == YES + case TPM_NT_EXTEND: +#endif +#if CC_PolicySecret == YES && defined TPM_NT_PIN_PASS + case TPM_NT_PIN_PASS: + case TPM_NT_PIN_FAIL: +#endif + case TPM_NT_ORDINARY: + break; + default: + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + break; + } + // Check that the sizes are OK based on the type + switch(GET_TPM_NT(attributes)) + { + case TPM_NT_ORDINARY: + // Can't exceed the allowed size for the implementation + if(in->publicInfo.nvPublic.dataSize > MAX_NV_INDEX_SIZE) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + break; + case TPM_NT_EXTEND: + if(in->publicInfo.nvPublic.dataSize != nameSize) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + break; + default: + // Everything else needs a size of 8 + if(in->publicInfo.nvPublic.dataSize != 8) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + break; + } + // Handle other specifics + switch(GET_TPM_NT(attributes)) + { + case TPM_NT_COUNTER: + // Counter can't have TPMA_NV_CLEAR_STCLEAR SET (don't clear counters) + if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + break; +#ifdef TPM_NT_PIN_FAIL + case TPM_NT_PIN_FAIL: + // NV_NO_DA must be SET and AUTHWRITE must be CLEAR + // NOTE: As with a PIN_PASS index, the authValue of the index is not + // available until the index is written. If AUTHWRITE is the only way to + // write then index, it could never be written. Rather than go through + // all of the other possible ways to write the Index, it is simply + // prohibited to write the index with the authValue. Other checks + // below will insure that there seems to be a way to write the index + // (i.e., with platform authorization , owner authorization, + // or with policyAuth.) + // It is not allowed to create a PIN Index that can't be modified. + if(!IS_ATTRIBUTE(attributes, TPMA_NV, NO_DA)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + /* fall through */ +#endif +#ifdef TPM_NT_PIN_PASS + case TPM_NT_PIN_PASS: + // AUTHWRITE must be CLEAR (see note above to TPM_NT_PIN_FAIL) + if(IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE) + || IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK) + || IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; +#endif // this comes before break because PIN_FAIL falls through + break; + default: + break; + } + // Locks may not be SET and written cannot be SET + if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN) + || IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED) + || IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + // There must be a way to read the index. + if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD) + && !IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD) + && !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHREAD) + && !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYREAD)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + // There must be a way to write the index + if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE) + && !IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE) + && !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE) + && !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYWRITE)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + // An index with TPMA_NV_CLEAR_STCLEAR can't have TPMA_NV_WRITEDEFINE SET + if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR) + && IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + // Make sure that the creator of the index can delete the index + if((IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE) + && in->authHandle == TPM_RH_OWNER) + || (!IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE) + && in->authHandle == TPM_RH_PLATFORM)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_authHandle; + // If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by + // the platform + if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE) + && TPM_RH_PLATFORM != in->authHandle) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + // Make sure that the TPMA_NV_WRITEALL is not set if the index size is larger + // than the allowed NV buffer size. + if(in->publicInfo.nvPublic.dataSize > MAX_NV_BUFFER_SIZE + && IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL)) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + // And finally, see if the index is already defined. + if(NvIndexIsDefined(in->publicInfo.nvPublic.nvIndex)) + return TPM_RC_NV_DEFINED; + // Internal Data Update + // define the space. A TPM_RC_NV_SPACE error may be returned at this point + return NvDefineIndex(&in->publicInfo.nvPublic, &in->auth); +} +#endif // CC_NV_DefineSpace +#include "Tpm.h" +#include "NV_UndefineSpace_fp.h" +#if CC_NV_UndefineSpace // Conditional expansion of this file +TPM_RC +TPM2_NV_UndefineSpace( + NV_UndefineSpace_In *in // IN: input parameter list + ) +{ + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + // Input Validation + // This command can't be used to delete an index with TPMA_NV_POLICY_DELETE SET + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE)) + return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex; + // The owner may only delete an index that was defined with ownerAuth. The + // platform may delete an index that was created with either authorization. + if(in->authHandle == TPM_RH_OWNER + && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) + return TPM_RC_NV_AUTHORIZATION; + // Internal Data Update + // Call implementation dependent internal routine to delete NV index + return NvDeleteIndex(nvIndex, locator); +} +#endif // CC_NV_UndefineSpace +#include "Tpm.h" +#include "NV_UndefineSpaceSpecial_fp.h" +#include "SessionProcess_fp.h" +#if CC_NV_UndefineSpaceSpecial // Conditional expansion of this file +TPM_RC +TPM2_NV_UndefineSpaceSpecial( + NV_UndefineSpaceSpecial_In *in // IN: input parameter list + ) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + // Input Validation + // This operation only applies when the TPMA_NV_POLICY_DELETE attribute is SET + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE)) + return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpaceSpecial_nvIndex; + // Internal Data Update + // Call implementation dependent internal routine to delete NV index + result = NvDeleteIndex(nvIndex, locator); + // If we just removed the index providing the authorization, make sure that the + // authorization session computation is modified so that it doesn't try to + // access the authValue of the just deleted index + if(result == TPM_RC_SUCCESS) + SessionRemoveAssociationToHandle(in->nvIndex); + return result; +} +#endif // CC_NV_UndefineSpaceSpecial +#include "Tpm.h" +#include "NV_ReadPublic_fp.h" +#if CC_NV_ReadPublic // Conditional expansion of this file +TPM_RC +TPM2_NV_ReadPublic( + NV_ReadPublic_In *in, // IN: input parameter list + NV_ReadPublic_Out *out // OUT: output parameter list + ) +{ + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, NULL); + // Command Output + // Copy index public data to output + out->nvPublic.nvPublic = nvIndex->publicArea; + // Compute NV name + NvGetIndexName(nvIndex, &out->nvName); + return TPM_RC_SUCCESS; +} +#endif // CC_NV_ReadPublic +#include "Tpm.h" +#include "NV_Write_fp.h" +#if CC_NV_Write // Conditional expansion of this file +TPM_RC +TPM2_NV_Write( + NV_Write_In *in // IN: input parameter list + ) +{ + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, NULL); + TPMA_NV attributes = nvIndex->publicArea.attributes; + TPM_RC result; + // Input Validation + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks(in->authHandle, + in->nvIndex, + attributes); + if(result != TPM_RC_SUCCESS) + return result; + // Bits index, extend index or counter index may not be updated by + // TPM2_NV_Write + if(IsNvCounterIndex(attributes) + || IsNvBitsIndex(attributes) + || IsNvExtendIndex(attributes)) + return TPM_RC_ATTRIBUTES; + // Make sure that the offset is not too large + if(in->offset > nvIndex->publicArea.dataSize) + return TPM_RCS_VALUE + RC_NV_Write_offset; + // Make sure that the selection is within the range of the Index + if(in->data.t.size > (nvIndex->publicArea.dataSize - in->offset)) + return TPM_RC_NV_RANGE; + // If this index requires a full sized write, make sure that input range is + // full sized. + // Note: if the requested size is the same as the Index data size, then offset + // will have to be zero. Otherwise, the range check above would have failed. + if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL) + && in->data.t.size < nvIndex->publicArea.dataSize) + return TPM_RC_NV_RANGE; + // Internal Data Update + // Perform the write. This called routine will SET the TPMA_NV_WRITTEN + // attribute if it has not already been SET. If NV isn't available, an error + // will be returned. + return NvWriteIndexData(nvIndex, in->offset, in->data.t.size, + in->data.t.buffer); +} +#endif // CC_NV_Write +#include "Tpm.h" +#include "NV_Increment_fp.h" +#if CC_NV_Increment // Conditional expansion of this file +TPM_RC +TPM2_NV_Increment( + NV_Increment_In *in // IN: input parameter list + ) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + UINT64 countValue; + // Input Validation + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks(in->authHandle, + in->nvIndex, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // Make sure that this is a counter + if(!IsNvCounterIndex(nvIndex->publicArea.attributes)) + return TPM_RCS_ATTRIBUTES + RC_NV_Increment_nvIndex; + // Internal Data Update + // If counter index is not been written, initialize it + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + countValue = NvReadMaxCount(); + else + // Read NV data in native format for TPM CPU. + countValue = NvGetUINT64Data(nvIndex, locator); + // Do the increment + countValue++; + // Write NV data back. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may + // be returned at this point. If necessary, this function will set the + // TPMA_NV_WRITTEN attribute + result = NvWriteUINT64Data(nvIndex, countValue); + if(result == TPM_RC_SUCCESS) + { + // If a counter just rolled over, then force the NV update. + // Note, if this is an orderly counter, then the write-back needs to be + // forced, for other counters, the write-back will happen anyway + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY) + && (countValue & MAX_ORDERLY_COUNT) == 0 ) + { + // Need to force an NV update of orderly data + SET_NV_UPDATE(UT_ORDERLY); + } + } + return result; +} +#endif // CC_NV_Increment +#include "Tpm.h" +#include "NV_Extend_fp.h" +#if CC_NV_Extend // Conditional expansion of this file +TPM_RC +TPM2_NV_Extend( + NV_Extend_In *in // IN: input parameter list + ) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPM2B_DIGEST oldDigest; + TPM2B_DIGEST newDigest; + HASH_STATE hashState; + // Input Validation + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks(in->authHandle, + in->nvIndex, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // Make sure that this is an extend index + if(!IsNvExtendIndex(nvIndex->publicArea.attributes)) + return TPM_RCS_ATTRIBUTES + RC_NV_Extend_nvIndex; + // Internal Data Update + // Perform the write. + oldDigest.t.size = CryptHashGetDigestSize(nvIndex->publicArea.nameAlg); + pAssert(oldDigest.t.size <= sizeof(oldDigest.t.buffer)); + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + { + NvGetIndexData(nvIndex, locator, 0, oldDigest.t.size, oldDigest.t.buffer); + } + else + { + MemorySet(oldDigest.t.buffer, 0, oldDigest.t.size); + } + // Start hash + newDigest.t.size = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg); + // Adding old digest + CryptDigestUpdate2B(&hashState, &oldDigest.b); + // Adding new data + CryptDigestUpdate2B(&hashState, &in->data.b); + // Complete hash + CryptHashEnd2B(&hashState, &newDigest.b); + // Write extended hash back. + // Note, this routine will SET the TPMA_NV_WRITTEN attribute if necessary + return NvWriteIndexData(nvIndex, 0, newDigest.t.size, newDigest.t.buffer); +} +#endif // CC_NV_Extend +#include "Tpm.h" +#include "NV_SetBits_fp.h" +#if CC_NV_SetBits // Conditional expansion of this file +TPM_RC +TPM2_NV_SetBits( + NV_SetBits_In *in // IN: input parameter list + ) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + UINT64 oldValue; + UINT64 newValue; + // Input Validation + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks(in->authHandle, + in->nvIndex, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // Make sure that this is a bit field + if(!IsNvBitsIndex(nvIndex->publicArea.attributes)) + return TPM_RCS_ATTRIBUTES + RC_NV_SetBits_nvIndex; + // If index is not been written, initialize it + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + oldValue = 0; + else + // Read index data + oldValue = NvGetUINT64Data(nvIndex, locator); + // Figure out what the new value is going to be + newValue = oldValue | in->bits; + // Internal Data Update + return NvWriteUINT64Data(nvIndex, newValue); +} +#endif // CC_NV_SetBits +#include "Tpm.h" +#include "NV_WriteLock_fp.h" +#if CC_NV_WriteLock // Conditional expansion of this file +TPM_RC +TPM2_NV_WriteLock( + NV_WriteLock_In *in // IN: input parameter list + ) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPMA_NV nvAttributes = nvIndex->publicArea.attributes; + // Input Validation: + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvAttributes); + if(result != TPM_RC_SUCCESS) + { + if(result == TPM_RC_NV_AUTHORIZATION) + return result; + // If write access failed because the index is already locked, then it is + // no error. + return TPM_RC_SUCCESS; + } + // if neither TPMA_NV_WRITEDEFINE nor TPMA_NV_WRITE_STCLEAR is set, the index + // can not be write-locked + if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITEDEFINE) + && !IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITE_STCLEAR)) + return TPM_RCS_ATTRIBUTES + RC_NV_WriteLock_nvIndex; + // Internal Data Update + // Set the WRITELOCK attribute. + // Note: if TPMA_NV_WRITELOCKED were already SET, then the write access check + // above would have failed and this code isn't executed. + SET_ATTRIBUTE(nvAttributes, TPMA_NV, WRITELOCKED); + // Write index info back + return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator, + nvAttributes); +} +#endif // CC_NV_WriteLock +#include "Tpm.h" +#include "NV_GlobalWriteLock_fp.h" +#if CC_NV_GlobalWriteLock // Conditional expansion of this file +TPM_RC +TPM2_NV_GlobalWriteLock( + NV_GlobalWriteLock_In *in // IN: input parameter list + ) +{ + // Input parameter (the authorization handle) is not reference in command action. + NOT_REFERENCED(in); + // Internal Data Update + // Implementation dependent method of setting the global lock + return NvSetGlobalLock(); +} +#endif // CC_NV_GlobalWriteLock +#include "Tpm.h" +#include "NV_Read_fp.h" +#if CC_NV_Read // Conditional expansion of this file +/* TPM_RC_NV_AUTHORIZATION the authorization was valid but the authorizing entity (authHandle) is + not allowed to read from the Index referenced by nvIndex */ +/* TPM_RC_NV_LOCKED the Index referenced by nvIndex is read locked */ +/* TPM_RC_NV_RANGE read range defined by size and offset is outside the range of the Index + referenced by nvIndex */ +/* TPM_RC_NV_UNINITIALIZED the Index referenced by nvIndex has not been initialized (written) */ +/* TPM_RC_VALUE the read size is larger than the MAX_NV_BUFFER_SIZE */ +TPM_RC +TPM2_NV_Read( + NV_Read_In *in, // IN: input parameter list + NV_Read_Out *out // OUT: output parameter list + ) +{ + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPM_RC result; + // Input Validation + // Common read access checks. NvReadAccessChecks() may return + // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED + result = NvReadAccessChecks(in->authHandle, in->nvIndex, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // Make sure the data will fit the return buffer + if(in->size > MAX_NV_BUFFER_SIZE) + return TPM_RCS_VALUE + RC_NV_Read_size; + // Verify that the offset is not too large + if(in->offset > nvIndex->publicArea.dataSize) + return TPM_RCS_VALUE + RC_NV_Read_offset; + // Make sure that the selection is within the range of the Index + if(in->size > (nvIndex->publicArea.dataSize - in->offset)) + return TPM_RC_NV_RANGE; + // Command Output + // Set the return size + out->data.t.size = in->size; + // Perform the read + NvGetIndexData(nvIndex, locator, in->offset, in->size, out->data.t.buffer); + return TPM_RC_SUCCESS; +} +#endif // CC_NV_Read +#include "Tpm.h" +#include "NV_ReadLock_fp.h" +#if CC_NV_ReadLock // Conditional expansion of this file +TPM_RC +TPM2_NV_ReadLock( + NV_ReadLock_In *in // IN: input parameter list + ) +{ + TPM_RC result; + NV_REF locator; + // The referenced index has been checked multiple times before this is called + // so it must be present and will be loaded into cache + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPMA_NV nvAttributes = nvIndex->publicArea.attributes; + // Input Validation + // Common read access checks. NvReadAccessChecks() may return + // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED + result = NvReadAccessChecks(in->authHandle, + in->nvIndex, + nvAttributes); + if(result == TPM_RC_NV_AUTHORIZATION) + return TPM_RC_NV_AUTHORIZATION; + // Index is already locked for write + else if(result == TPM_RC_NV_LOCKED) + return TPM_RC_SUCCESS; + // If NvReadAccessChecks return TPM_RC_NV_UNINITALIZED, then continue. + // It is not an error to read lock an uninitialized Index. + // if TPMA_NV_READ_STCLEAR is not set, the index can not be read-locked + if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, READ_STCLEAR)) + return TPM_RCS_ATTRIBUTES + RC_NV_ReadLock_nvIndex; + // Internal Data Update + // Set the READLOCK attribute + SET_ATTRIBUTE(nvAttributes, TPMA_NV, READLOCKED); + // Write NV info back + return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, + locator, + nvAttributes); +} +#endif // CC_NV_ReadLock +#include "Tpm.h" +#include "NV_ChangeAuth_fp.h" +#if CC_NV_ChangeAuth // Conditional expansion of this file +TPM_RC +TPM2_NV_ChangeAuth( + NV_ChangeAuth_In *in // IN: input parameter list + ) +{ + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + // Input Validation + // Remove trailing zeros and make sure that the result is not larger than the + // digest of the nameAlg. + if(MemoryRemoveTrailingZeros(&in->newAuth) + > CryptHashGetDigestSize(nvIndex->publicArea.nameAlg)) + return TPM_RCS_SIZE + RC_NV_ChangeAuth_newAuth; + // Internal Data Update + // Change authValue + return NvWriteIndexAuth(locator, &in->newAuth); +} +#endif // CC_NV_ChangeAuth +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "NV_Certify_fp.h" +#if CC_NV_Certify // Conditional expansion of this file +TPM_RC +TPM2_NV_Certify( + NV_Certify_In *in, // IN: input parameter list + NV_Certify_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPMS_ATTEST certifyInfo; + OBJECT *signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_NV_Certify_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_NV_Certify_inScheme; + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvReadAccessChecks(in->authHandle, in->nvIndex, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // make sure that the selection is within the range of the Index (cast to avoid + // any wrap issues with addition) + if((UINT32)in->size + (UINT32)in->offset > (UINT32)nvIndex->publicArea.dataSize) + return TPM_RC_NV_RANGE; + // Make sure the data will fit the return buffer + // NOTE: This check may be modified if the output buffer will not hold the + // maximum sized NV buffer as part of the certified data. The difference in + // size could be substantial if the signature scheme was produced a large + // signature (e.g., RSA 4096). + if(in->size > MAX_NV_BUFFER_SIZE) + return TPM_RCS_VALUE + RC_NV_Certify_size; + // Command Output + + // Fill in attest information common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, + &certifyInfo); + + // Get the name of the index + NvGetIndexName(nvIndex, &certifyInfo.attested.nv.indexName); + + // See if this is old format or new format + if ((in->size != 0) || (in->offset != 0)) + { + // NV certify specific fields + // Attestation type + certifyInfo.type = TPM_ST_ATTEST_NV; + + // Set the return size + certifyInfo.attested.nv.nvContents.t.size = in->size; + + // Set the offset + certifyInfo.attested.nv.offset = in->offset; + + // Perform the read + NvGetIndexData(nvIndex, locator, in->offset, in->size, + certifyInfo.attested.nv.nvContents.t.buffer); + } + else + { + HASH_STATE hashState; + // This is to sign a digest of the data + certifyInfo.type = TPM_ST_ATTEST_NV_DIGEST; + // Initialize the hash before calling the function to add the Index data to + // the hash. + certifyInfo.attested.nvDigest.nvDigest.t.size = + CryptHashStart(&hashState, in->inScheme.details.any.hashAlg); + NvHashIndexData(&hashState, nvIndex, locator, 0, + nvIndex->publicArea.dataSize); + CryptHashEnd2B(&hashState, &certifyInfo.attested.nvDigest.nvDigest.b); + } + // Sign attestation structure. A NULL signature will be returned if + // signObject is NULL. + return SignAttestInfo(signObject, &in->inScheme, &certifyInfo, + &in->qualifyingData, &out->certifyInfo, &out->signature); +} +#endif // CC_NV_Certify diff --git a/src/tpm2/NVDynamic.c b/src/tpm2/NVDynamic.c new file mode 100644 index 0000000..c7c6a3b --- /dev/null +++ b/src/tpm2/NVDynamic.c @@ -0,0 +1,1679 @@ +/********************************************************************************/ +/* */ +/* Dynamic space for user defined NV */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NVDynamic.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 8.4 NVDynamic.c */ +/* 8.4.2 Includes, Defines and Data Definitions */ +#define NV_C +#include "Tpm.h" + +/* 8.4.3 Local Functions */ +/* 8.4.3.1 NvNext() */ +/* This function provides a method to traverse every data entry in NV dynamic area. */ +/* To begin with, parameter iter should be initialized to NV_REF_INIT indicating the first element. + Every time this function is called, the value in iter would be adjusted pointing to the next + element in traversal. If there is no next element, iter value would be 0. This function returns + the address of the 'data entry' pointed by the iter. If there is no more elements in the set, a 0 + value is returned indicating the end of traversal. */ +static NV_REF +NvNext( + NV_REF *iter, // IN/OUT: the list iterator + TPM_HANDLE *handle // OUT: the handle of the next item. + ) +{ + NV_REF currentAddr; + NV_ENTRY_HEADER header; + // + // If iterator is at the beginning of list + if(*iter == NV_REF_INIT) + { + // Initialize iterator + *iter = NV_USER_DYNAMIC; + } + // Step over the size field and point to the handle + currentAddr = *iter + sizeof(UINT32); + // read the header of the next entry + NvRead(&header, *iter, sizeof(NV_ENTRY_HEADER)); + // if the size field is zero, then we have hit the end of the list + if(header.size == 0) + // leave the *iter pointing at the end of the list + return 0; + // advance the header by the size of the entry + *iter += header.size; + if(handle != NULL) + *handle = header.handle; + return currentAddr; +} +/* 8.4.3.2 NvNextByType() */ +/* This function returns a reference to the next NV entry of the desired type */ +/* Return Values Meaning */ +/* 0 end of list */ +/* != 0 the next entry of the indicated type */ +static NV_REF +NvNextByType( + TPM_HANDLE *handle, // OUT: the handle of the found type or 0 + NV_REF *iter, // IN: the iterator + TPM_HT type // IN: the handle type to look for + ) +{ + NV_REF addr; + TPM_HANDLE nvHandle = 0; + while((addr = NvNext(iter, &nvHandle)) != 0) + { + // addr: the address of the location containing the handle of the value + // iter: the next location. + if(HandleGetType(nvHandle) == type) + break; + } + if(handle != NULL) + *handle = nvHandle; + return addr; +} +/* 8.4.3.3 NvNextIndex() */ +/* This function returns the reference to the next NV Index entry. A value of 0 indicates the end + of the list. */ +/* Return Values Meaning */ +/* 0 end of list */ +/* != 0 the next */ +#define NvNextIndex(handle, iter) \ + NvNextByType(handle, iter, TPM_HT_NV_INDEX) +/* 8.4.3.4 NvNextEvict() */ +/* This function returns the offset in NV of the next evict object entry. A value of 0 indicates + the end of the list. */ +#define NvNextEvict(handle, iter) \ + NvNextByType(handle, iter, TPM_HT_PERSISTENT) +/* 8.4.3.5 NvGetEnd() */ +/* Function to find the end of the NV dynamic data list */ +static NV_REF +NvGetEnd( + void + ) +{ + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + // Scan until the next address is 0 + while((currentAddr = NvNext(&iter, NULL)) != 0); + return iter; +} +/* 8.4.3.6 NvGetFreeBytes */ +/* This function returns the number of free octets in NV space. */ +static UINT32 +NvGetFreeBytes( + void + ) +{ + // This does not have an overflow issue because NvGetEnd() cannot return a value + // that is larger than s_evictNvEnd. This is because there is always a 'stop' + // word in the NV memory that terminates the search for the end before the + // value can go past s_evictNvEnd. + return s_evictNvEnd - NvGetEnd(); +} +/* 8.4.3.7 NvTestSpace() */ +/* This function will test if there is enough space to add a new entity. */ +/* Return Values Meaning */ +/* TRUE space available */ +/* FALSE no enough space */ +static BOOL +NvTestSpace( + UINT32 size, // IN: size of the entity to be added + BOOL isIndex, // IN: TRUE if the entity is an index + BOOL isCounter // IN: TRUE if the index is a counter + ) +{ + UINT32 remainBytes = NvGetFreeBytes(); + UINT32 reserved = sizeof(UINT32) // size of the forward pointer + + sizeof(NV_LIST_TERMINATOR); + // Do a compile time sanity check on the setting for NV_MEMORY_SIZE +#if NV_MEMORY_SIZE < 1024 +#error "NV_MEMORY_SIZE probably isn't large enough" +#endif + // For NV Index, need to make sure that we do not allocate an Index if this + // would mean that the TPM cannot allocate the minimum number of evict + // objects. + if(isIndex) + { + // Get the number of persistent objects allocated + UINT32 persistentNum = NvCapGetPersistentNumber(); + // If we have not allocated the requisite number of evict objects, then we + // need to reserve space for them. + // NOTE: some of this is not written as simply as it might seem because + // the values are all unsigned and subtracting needs to be done carefully + // so that an underflow doesn't cause problems. + if(persistentNum < MIN_EVICT_OBJECTS) + reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE; + } + // If this is not an index or is not a counter, reserve space for the + // required number of counter indexes + if(!isIndex || !isCounter) + { + // Get the number of counters + UINT32 counterNum = NvCapGetCounterNumber(); + // If the required number of counters have not been allocated, reserved + // space for the extra needed counters + if(counterNum < MIN_COUNTER_INDICES) + reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE; + } + // Check that the requested allocation will fit after making sure that there + // will be no chance of overflow + return ((reserved < remainBytes) + && (size <= remainBytes) + && (size + reserved <= remainBytes)); +} +/* 8.4.3.8 NvWriteNvListEnd() */ +/* Function to write the list terminator. */ +NV_REF +NvWriteNvListEnd( + NV_REF end + ) +{ + // Marker is initialized with zeros + BYTE listEndMarker[sizeof(NV_LIST_TERMINATOR)] = {0}; + UINT64 maxCount = NvReadMaxCount(); + // + // This is a constant check that can be resolved at compile time. + cAssert(sizeof(UINT64) <= sizeof(NV_LIST_TERMINATOR) - sizeof(UINT32)); + // Copy the maxCount value to the marker buffer + MemoryCopy(&listEndMarker[sizeof(UINT32)], &maxCount, sizeof(UINT64)); + pAssert(end + sizeof(NV_LIST_TERMINATOR) <= s_evictNvEnd); + // Write it to memory + NvWrite(end, sizeof(NV_LIST_TERMINATOR), &listEndMarker); + return end + sizeof(NV_LIST_TERMINATOR); +} +/* 8.4.3.9 NvAdd() */ +/* This function adds a new entity to NV. */ +/* This function requires that there is enough space to add a new entity (i.e., that NvTestSpace() + has been called and the available space is at least as large as the required space). */ +/* The totalSize will be the size of entity. If a handle is added, this function will increase the + size accordingly. */ +static TPM_RC +NvAdd( + UINT32 totalSize, // IN: total size needed for this entity For + // evict object, totalSize is the same as + // bufferSize. For NV Index, totalSize is + // bufferSize plus index data size + UINT32 bufferSize, // IN: size of initial buffer + TPM_HANDLE handle, // IN: optional handle + BYTE *entity // IN: initial buffer + ) +{ + NV_REF newAddr; // IN: where the new entity will start + NV_REF nextAddr; + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Get the end of data list + newAddr = NvGetEnd(); + // Step over the forward pointer + nextAddr = newAddr + sizeof(UINT32); + // Optionally write the handle. For indexes, the handle is TPM_RH_UNASSIGNED + // so that the handle in the nvIndex is used instead of writing this value + if(handle != TPM_RH_UNASSIGNED) + { + NvWrite((UINT32)nextAddr, sizeof(TPM_HANDLE), &handle); + nextAddr += sizeof(TPM_HANDLE); + } + // Write entity data + NvWrite((UINT32)nextAddr, bufferSize, entity); + // Advance the pointer by the amount of the total + nextAddr += totalSize; + // Finish by writing the link value + // Write the next offset (relative addressing) + totalSize = nextAddr - newAddr; + // Write link value + NvWrite((UINT32)newAddr, sizeof(UINT32), &totalSize); + // Write the list terminator + NvWriteNvListEnd(nextAddr); + return TPM_RC_SUCCESS; +} +/* 8.4.3.10 NvDelete() */ +/* This function is used to delete an NV Index or persistent object from NV memory. */ +static TPM_RC +NvDelete( + NV_REF entityRef // IN: reference to entity to be deleted + ) +{ + UINT32 entrySize; + // adjust entityAddr to back up and point to the forward pointer + NV_REF entryRef = entityRef - sizeof(UINT32); + NV_REF endRef = NvGetEnd(); + NV_REF nextAddr; // address of the next entry + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Get the offset of the next entry. That is, back up and point to the size + // field of the entry + NvRead(&entrySize, entryRef, sizeof(UINT32)); + // The next entry after the one being deleted is at a relative offset + // from the current entry + nextAddr = entryRef + entrySize; + // If this is not the last entry, move everything up + if(nextAddr < endRef) + { + pAssert(nextAddr > entryRef); + _plat__NvMemoryMove(nextAddr, + entryRef, + (endRef - nextAddr)); + } + // The end of the used space is now moved up by the amount of space we just + // reclaimed + endRef -= entrySize; + // Write the end marker, and make the new end equal to the first byte after + // the just added end value. This will automatically update the NV value for + // maxCounter + // NOTE: This is the call that sets flag to cause NV to be updated + endRef = NvWriteNvListEnd(endRef); + // Clear the reclaimed memory + _plat__NvMemoryClear(endRef, entrySize); + return TPM_RC_SUCCESS; +} +/* 8.4.4 RAM-based NV Index Data Access Functions */ +/* 8.4.4.1 Introduction */ +/* The data layout in ram buffer is {size of(NV_handle() + attributes + data NV_handle(), + attributes, data} for each NV Index data stored in RAM. */ +/* NV storage associated with orderly data is updated when a NV Index is added but NOT when the data + or attributes are changed. Orderly data is only updated to NV on an orderly shutdown + (TPM2_Shutdown()) */ +/* 8.4.4.2 NvRamNext() */ +/* This function is used to iterate trough the list of Ram Index values. *iter needs to be + initialized by calling */ +static NV_RAM_REF +NvRamNext( + NV_RAM_REF *iter, // IN/OUT: the list iterator + TPM_HANDLE *handle // OUT: the handle of the next item. + ) +{ + NV_RAM_REF currentAddr; + NV_RAM_HEADER header; + // + // If iterator is at the beginning of list + if(*iter == NV_RAM_REF_INIT) + { + // Initialize iterator + *iter = &s_indexOrderlyRam[0]; + } + // if we are going to return what the iter is currently pointing to... + currentAddr = *iter; + // If iterator reaches the end of NV space, then don't advance and return + // that we are at the end of the list. The end of the list occurs when + // we don't have space for a size and a handle + if(currentAddr + sizeof(NV_RAM_HEADER) > RAM_ORDERLY_END) + return NULL; + // read the header of the next entry + memcpy(&header, currentAddr, sizeof(NV_RAM_HEADER)); // libtpms: do not use MemoryCopy to avoid gcc warning + // if the size field is zero, then we have hit the end of the list + if(header.size == 0) + // leave the *iter pointing at the end of the list + return NULL; + // advance the header by the size of the entry + *iter = currentAddr + header.size; + // pAssert(*iter <= RAM_ORDERLY_END); + if(handle != NULL) + *handle = header.handle; + return currentAddr; +} +/* 8.4.4.2 NvRamGetEnd() */ +/* This routine performs the same function as NvGetEnd() but for the RAM data. */ +static NV_RAM_REF +NvRamGetEnd( + void + ) +{ + NV_RAM_REF iter = NV_RAM_REF_INIT; + NV_RAM_REF currentAddr; + // Scan until the next address is 0 + while((currentAddr = NvRamNext(&iter, NULL)) != 0); + return iter; +} +/* 8.4.4.3 NvRamTestSpaceIndex() */ +/* This function indicates if there is enough RAM space to add a data for a new NV Index. */ +/* Return Values Meaning */ +/* TRUE space available */ +/* FALSE no enough space */ +static BOOL +NvRamTestSpaceIndex( + UINT32 size // IN: size of the data to be added to RAM + ) +{ + UINT32 remaining = (UINT32)(RAM_ORDERLY_END - NvRamGetEnd()); + UINT32 needed = sizeof(NV_RAM_HEADER) + size; + // NvRamGetEnd points to the next available byte. + return remaining >= needed; +} +/* 8.4.4.4 NvRamGetIndex() */ +/* This function returns the offset of NV data in the RAM buffer */ +/* This function requires that NV Index is in RAM. That is, the index must be known to exist. */ +static NV_RAM_REF +NvRamGetIndex( + TPMI_RH_NV_INDEX handle // IN: NV handle + ) +{ + NV_RAM_REF iter = NV_RAM_REF_INIT; + NV_RAM_REF currentAddr; + TPM_HANDLE foundHandle; + while((currentAddr = NvRamNext(&iter, &foundHandle)) != 0) + { + if(handle == foundHandle) + break; + } + return currentAddr; +} +/* 8.4.4.5 NvUpdateIndexOrderlyData() */ +/* This function is used to cause an update of the orderly data to the NV backing store. */ +void +NvUpdateIndexOrderlyData( + void + ) +{ + // Write reserved RAM space to NV + NvWrite(NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam), s_indexOrderlyRam); +} +/* 8.4.4.6 NvAddRAM() */ +/* This function adds a new data area to RAM. */ +/* This function requires that enough free RAM space is available to add the new data. */ +/* This function should be called after the NV Index space has been updated and the index + removed. This insures that NV is available so that checking for NV availability is not required + during this function. */ +static void +NvAddRAM( + TPMS_NV_PUBLIC *index // IN: the index descriptor + ) +{ + NV_RAM_HEADER header; + NV_RAM_REF end = NvRamGetEnd(); + header.size = sizeof(NV_RAM_HEADER) + index->dataSize; + header.handle = index->nvIndex; + MemoryCopy(&header.attributes, &index->attributes, sizeof(TPMA_NV)); + pAssert(ORDERLY_RAM_ADDRESS_OK(end, header.size)); + // Copy the header to the memory + MemoryCopy(end, &header, sizeof(NV_RAM_HEADER)); + // Clear the data area (just in case) + MemorySet(end + sizeof(NV_RAM_HEADER), 0, index->dataSize); + // Step over this new entry + end += header.size; + // If the end marker will fit, add it + if(end + sizeof(UINT32) < RAM_ORDERLY_END) + MemorySet(end, 0, sizeof(UINT32)); + // Write reserved RAM space to NV to reflect the newly added NV Index + SET_NV_UPDATE(UT_ORDERLY); + return; +} +/* 8.4.4.7 NvDeleteRAM() */ +/* This function is used to delete a RAM-backed NV Index data area. The space used by the entry are + overwritten by the contents of the Index data that comes after (the data is moved up to fill the + hole left by removing this index. The reclaimed space is cleared to zeros. This function assumes + the data of NV Index exists in RAM. */ +/* This function should be called after the NV Index space has been updated and the index + removed. This insures that NV is available so that checking for NV availability is not required + during this function. */ +static void +NvDeleteRAM( + TPMI_RH_NV_INDEX handle // IN: NV handle + ) +{ + NV_RAM_REF nodeAddress; + NV_RAM_REF nextNode; + UINT32 size; + NV_RAM_REF lastUsed = NvRamGetEnd(); + nodeAddress = NvRamGetIndex(handle); + pAssert(nodeAddress != 0); + // Get node size + MemoryCopy(&size, nodeAddress, sizeof(size)); + // Get the offset of next node + nextNode = nodeAddress + size; + // Copy the data + MemoryCopy(nodeAddress, nextNode, (int)(lastUsed - nextNode)); + // Clear out the reclaimed space + MemorySet(lastUsed - size, 0, size); + // Write reserved RAM space to NV to reflect the newly delete NV Index + SET_NV_UPDATE(UT_ORDERLY); + return; +} +/* 8.4.4.9 NvReadIndex() */ +/* This function is used to read the NV Index NV_INDEX. This is used so that the index information + can be compressed and only this function would be needed to decompress it. Mostly, compression + would only be able to save the space needed by the policy. */ +void +NvReadNvIndexInfo( + NV_REF ref, // IN: points to NV where index is located + NV_INDEX *nvIndex // OUT: place to receive index data + ) +{ + pAssert(nvIndex != NULL); + NvRead(nvIndex, ref, sizeof(NV_INDEX)); + return; +} +/* 8.4.4.9 NvReadObject() */ +/* This function is used to read a persistent object. This is used so that the object information + can be compressed and only this function would be needed to uncompress it. */ +void +NvReadObject( + NV_REF ref, // IN: points to NV where index is located + OBJECT *object // OUT: place to receive the object data + ) +{ + NvRead(object, (ref + sizeof(TPM_HANDLE)), sizeof(OBJECT)); + return; +} +/* 8.4.4.10 NvFindEvict() */ +/* This function will return the NV offset of an evict object */ +/* Return Values Meaning */ +/* 0 evict object not found */ +/* != 0 offset of evict object */ +static NV_REF +NvFindEvict( + TPM_HANDLE nvHandle, + OBJECT *object + ) +{ + NV_REF found = NvFindHandle(nvHandle); + // If we found the handle and the request included an object pointer, fill it in + if(found != 0 && object != NULL) + NvReadObject(found, object); + return found; +} +/* 8.4.4.11 NvIndexIsDefined() */ +/* See if an index is already defined */ +BOOL +NvIndexIsDefined( + TPM_HANDLE nvHandle // IN: Index to look for + ) +{ + return (NvFindHandle(nvHandle) != 0); +} +/* 8.4.4.12 NvConditionallyWrite() */ +/* Function to check if the data to be written has changed and write it if it has */ +/* Error Returns Meaning */ +/* TPM_RC_NV_RATE NV is unavailable because of rate limit */ +/* TPM_RC_NV_UNAVAILABLE NV is inaccessible */ +static TPM_RC +NvConditionallyWrite( + NV_REF entryAddr, // IN: stating address + UINT32 size, // IN: size of the data to write + void *data // IN: the data to write + ) +{ + // If the index data is actually changed, then a write to NV is required + if(_plat__NvIsDifferent(entryAddr, size, data)) + { + // Write the data if NV is available + if(g_NvStatus == TPM_RC_SUCCESS) + { + NvWrite(entryAddr, size, data); + } + return g_NvStatus; + } + return TPM_RC_SUCCESS; +} +/* 8.4.4.13 NvReadNvIndexAttributes() */ +/* This function returns the attributes of an NV Index. */ +static TPMA_NV +NvReadNvIndexAttributes( + NV_REF locator // IN: reference to an NV index + ) +{ + TPMA_NV attributes; + NvRead(&attributes, + locator + offsetof(NV_INDEX, publicArea.attributes), + sizeof(TPMA_NV)); + return attributes; +} +/* 8.4.4.14 NvReadRamIndexAttributes() */ +/* This function returns the attributes from the RAM header structure. This function is used to deal + with the fact that the header structure is only byte aligned. */ +static TPMA_NV +NvReadRamIndexAttributes( + NV_RAM_REF ref // IN: pointer to a NV_RAM_HEADER + ) +{ + TPMA_NV attributes; + MemoryCopy(&attributes, ref + offsetof(NV_RAM_HEADER, attributes), + sizeof(TPMA_NV)); + return attributes; +} +/* 8.4.4.15 NvWriteNvIndexAttributes() */ +/* This function is used to write just the attributes of an index to NV. */ +/* Error Returns Meaning */ +/* TPM_RC_NV_RATE NV is rate limiting so retry */ +/* TPM_RC_NV_UNAVAILABLE NV is not available */ +static TPM_RC +NvWriteNvIndexAttributes( + NV_REF locator, // IN: location of the index + TPMA_NV attributes // IN: attributes to write + ) +{ + return NvConditionallyWrite( + locator + offsetof(NV_INDEX, publicArea.attributes), + sizeof(TPMA_NV), + &attributes); +} +/* 8.4.4.16 NvWriteRamIndexAttributes() */ +/* This function is used to write the index attributes into an unaligned structure */ +static void +NvWriteRamIndexAttributes( + NV_RAM_REF ref, // IN: address of the header + TPMA_NV attributes // IN: the attributes to write + ) +{ + MemoryCopy(ref + offsetof(NV_RAM_HEADER, attributes), &attributes, + sizeof(TPMA_NV)); + return; +} +/* 8.4.5 Externally Accessible Functions */ +/* 8.4.5.1 NvIsPlatformPersistentHandle() */ +/* This function indicates if a handle references a persistent object in the range belonging to the + platform. */ +/* Return Values Meaning */ +/* TRUE handle references a platform persistent object */ +/* FALSE handle does not reference platform persistent object */ +BOOL +NvIsPlatformPersistentHandle( + TPM_HANDLE handle // IN: handle + ) +{ + return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST); +} +/* 8.4.5.2 NvIsOwnerPersistentHandle() */ +/* This function indicates if a handle references a persistent object in the range belonging to the + owner. */ +/* Return Values Meaning */ +/* TRUE handle is owner persistent handle */ +/* FALSE handle is not owner persistent handle and may not be a persistent handle at all */ +BOOL +NvIsOwnerPersistentHandle( + TPM_HANDLE handle // IN: handle + ) +{ + return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT); +} +/* 8.4.5.3 NvIndexIsAccessible() */ +/* This function validates that a handle references a defined NV Index and that the Index is + currently accessible. */ +/* Error Returns Meaning */ +/* TPM_RC_HANDLE the handle points to an undefined NV Index If shEnable is CLEAR, this would include + an index created using ownerAuth. If phEnableNV is CLEAR, this would include and index created + using platformAuth */ +/* TPM_RC_NV_READLOCKED Index is present but locked for reading and command does not write to the + index */ +/* TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command writes to the index */ +TPM_RC +NvIndexIsAccessible( + TPMI_RH_NV_INDEX handle // IN: handle + ) +{ + NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); + // + if(nvIndex == NULL) + // If index is not found, return TPM_RC_HANDLE + return TPM_RC_HANDLE; + if(gc.shEnable == FALSE || gc.phEnableNV == FALSE) + { + // if shEnable is CLEAR, an ownerCreate NV Index should not be + // indicated as present + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) + { + if(gc.shEnable == FALSE) + return TPM_RC_HANDLE; + } + // if phEnableNV is CLEAR, a platform created Index should not + // be visible + else if(gc.phEnableNV == FALSE) + return TPM_RC_HANDLE; + } +#if 0 // Writelock test for debug + // If the Index is write locked and this is an NV Write operation... + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITELOCKED) + && IsWriteOperation(commandIndex)) + { + // then return a locked indication unless the command is TPM2_NV_WriteLock + if(GetCommandCode(commandIndex) != TPM_CC_NV_WriteLock) + return TPM_RC_NV_LOCKED; + return TPM_RC_SUCCESS; + } +#endif +#if 0 // Readlock Test for debug + // If the Index is read locked and this is an NV Read operation... + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, READLOCKED) + && IsReadOperation(commandIndex)) + { + // then return a locked indication unless the command is TPM2_NV_ReadLock + if(GetCommandCode(commandIndex) != TPM_CC_NV_ReadLock) + return TPM_RC_NV_LOCKED; + } +#endif + // NV Index is accessible + return TPM_RC_SUCCESS; +} +/* 8.4.5.4 NvGetEvictObject() */ +/* This function is used to dereference an evict object handle and get a pointer to the object. */ +/* Error Returns Meaning */ +/* TPM_RC_HANDLE the handle does not point to an existing persistent object */ +TPM_RC +NvGetEvictObject( + TPM_HANDLE handle, // IN: handle + OBJECT *object // OUT: object data + ) +{ + NV_REF entityAddr; // offset points to the entity + // Find the address of evict object and copy to object + entityAddr = NvFindEvict(handle, object); + // whether there is an error or not, make sure that the evict + // status of the object is set so that the slot will get freed on exit + // Must do this after NvFindEvict loads the object + object->attributes.evict = SET; + // If handle is not found, return an error + if(entityAddr == 0) + return TPM_RC_HANDLE; + return TPM_RC_SUCCESS; +} +/* 8.4.5.5 NvIndexCacheInit() */ +/* Function to initialize the Index cache */ +void +NvIndexCacheInit( + void + ) +{ + s_cachedNvRef = NV_REF_INIT; + s_cachedNvRamRef = NV_RAM_REF_INIT; + s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED; + return; +} +/* 8.4.5.6 NvGetIndexData() */ +/* This function is used to access the data in an NV Index. The data is returned as a byte + sequence. */ +/* This function requires that the NV Index be defined, and that the required data is within the + data range. It also requires that TPMA_NV_WRITTEN of the Index is SET. */ +void +NvGetIndexData( + NV_INDEX *nvIndex, // IN: the in RAM index descriptor + NV_REF locator, // IN: where the data is located + UINT32 offset, // IN: offset of NV data + UINT16 size, // IN: size of NV data + void *data // OUT: data buffer + ) +{ + TPMA_NV nvAttributes; + // + pAssert(nvIndex != NULL); + nvAttributes = nvIndex->publicArea.attributes; + pAssert(IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)); + if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, ORDERLY)) + { + // Get data from RAM buffer + NV_RAM_REF ramAddr = NvRamGetIndex(nvIndex->publicArea.nvIndex); + pAssert(ramAddr != 0 && (size <= + ((NV_RAM_HEADER *)ramAddr)->size - + sizeof(NV_RAM_HEADER) - offset)); + MemoryCopy(data, ramAddr + sizeof(NV_RAM_HEADER) + offset, size); + } + else + { + // Validate that read falls within range of the index + pAssert(offset <= nvIndex->publicArea.dataSize + && size <= (nvIndex->publicArea.dataSize - offset)); + NvRead(data, locator + sizeof(NV_INDEX) + offset, size); + } + return; +} +/* 8.4.5.7 NvHashIndexData() */ +/* This function adds Index data to a hash. It does this in parts to avoid large stack buffers. */ +void +NvHashIndexData( + HASH_STATE *hashState, // IN: Initialized hash state + NV_INDEX *nvIndex, // IN: Index + NV_REF locator, // IN: where the data is located + UINT32 offset, // IN: starting offset + UINT16 size // IN: amount to hash + ) +{ +#define BUFFER_SIZE 64 + BYTE buffer[BUFFER_SIZE]; + if (offset > nvIndex->publicArea.dataSize) + return; + // Make sure that we don't try to read off the end. + if ((offset + size) > nvIndex->publicArea.dataSize) + size = nvIndex->publicArea.dataSize - (UINT16)offset; +#if BUFFER_SIZE >= MAX_NV_INDEX_SIZE + NvGetIndexData(nvIndex, locator, offset, size, buffer); + CryptDigestUpdate(hashState, size, buffer); +#else + { + INT16 i; + UINT16 readSize; + // + for (i = size; i > 0; offset += readSize, i -= readSize) + { + readSize = (i < BUFFER_SIZE) ? i : BUFFER_SIZE; + NvGetIndexData(nvIndex, locator, offset, readSize, buffer); + CryptDigestUpdate(hashState, readSize, buffer); + } + } +#endif // BUFFER_SIZE >= MAX_NV_INDEX_SIZE +#undef BUFFER_SIZE +} +/* 8.4.5.7 NvGetUINT64Data() */ +/* Get data in integer format of a bit or counter NV Index. */ +/* This function requires that the NV Index is defined and that the NV Index previously has been + written. */ +UINT64 +NvGetUINT64Data( + NV_INDEX *nvIndex, // IN: the in RAM index descriptor + NV_REF locator // IN: where index exists in NV + ) +{ + UINT64 intVal; + // Read the value and convert it to internal format + NvGetIndexData(nvIndex, locator, 0, 8, &intVal); + return BYTE_ARRAY_TO_UINT64(((BYTE *)&intVal)); +} +/* 8.4.5.8 NvWriteIndexAttributes() */ +/* This function is used to write just the attributes of an index. */ +/* Error Returns Meaning */ +/* TPM_RC_NV_RATE NV is rate limiting so retry */ +/* TPM_RC_NV_UNAVAILABLE NV is not available */ +TPM_RC +NvWriteIndexAttributes( + TPM_HANDLE handle, + NV_REF locator, // IN: location of the index + TPMA_NV attributes // IN: attributes to write + ) +{ + TPM_RC result; + // + if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)) + { + NV_RAM_REF ram = NvRamGetIndex(handle); + NvWriteRamIndexAttributes(ram, attributes); + result = TPM_RC_SUCCESS; + } + else + { + result = NvWriteNvIndexAttributes(locator, attributes); + } + return result; +} +/* 8.4.5.9 NvWriteIndexAuth() */ +/* This function is used to write the authValue of an index. It is used by TPM2_NV_ChangeAuth() */ +/* Error Returns Meaning */ +/* TPM_RC_NV_RATE NV is rate limiting so retry */ +/* TPM_RC_NV_UNAVAILABLE NV is not available */ +TPM_RC +NvWriteIndexAuth( + NV_REF locator, // IN: location of the index + TPM2B_AUTH *authValue // IN: the authValue to write + ) +{ + { + TPM_RC result; + // + // If the locator is pointing to the cached index value... + if(locator == s_cachedNvRef) + { + // copy the authValue to the cached index so it will be there if we + // look for it. This is a safety thing. + MemoryCopy2B(&s_cachedNvIndex.authValue.b, &authValue->b, + sizeof(s_cachedNvIndex.authValue.t.buffer)); + } + result = NvConditionallyWrite( + locator + offsetof(NV_INDEX, authValue), + sizeof(UINT16) + authValue->t.size, + authValue); + return result; + } +} +/* 8.4.5.10 NvGetIndexInfo() */ +/* This function loads the nvIndex Info into the NV cache and returns a pointer to the NV_INDEX. If + the returned value is zero, the index was not found. The locator parameter, if not NULL, will be + set to the offset in NV of the Index (the location of the handle of the Index). */ +/* This function will set the index cache. If the index is orderly, the attributes from RAM are + substituted for the attributes in the cached index */ +NV_INDEX * +NvGetIndexInfo( + TPM_HANDLE nvHandle, // IN: the index handle + NV_REF *locator // OUT: location of the index + ) +{ + if(s_cachedNvIndex.publicArea.nvIndex != nvHandle) + { + s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED; + s_cachedNvRamRef = 0; + s_cachedNvRef = NvFindHandle(nvHandle); + if(s_cachedNvRef == 0) + return NULL; + NvReadNvIndexInfo(s_cachedNvRef, &s_cachedNvIndex); + if(IS_ATTRIBUTE(s_cachedNvIndex.publicArea.attributes, TPMA_NV, ORDERLY)) + { + s_cachedNvRamRef = NvRamGetIndex(nvHandle); + s_cachedNvIndex.publicArea.attributes = + NvReadRamIndexAttributes(s_cachedNvRamRef); + } + } + if(locator != NULL) + *locator = s_cachedNvRef; + return &s_cachedNvIndex; +} +/* 8.4.5.11 NvWriteIndexData() */ +/* This function is used to write NV index data. It is intended to be used to update the data + associated with the default index. */ +/* This function requires that the NV Index is defined, and the data is within the defined data + range for the index. */ +/* Index data is only written due to a command that modifies the data in a single index. There is no + case where changes are made to multiple indexes data at the same time. Multiple attributes may be + change but not multiple index data. This is important because we will normally be handling the + index for which we have the cached pointer values. */ +/* Error Returns Meaning */ +/* TPM_RC_NV_RATE NV is rate limiting so retry */ +/* TPM_RC_NV_UNAVAILABLE NV is not available */ +TPM_RC +NvWriteIndexData( + NV_INDEX *nvIndex, // IN: the description of the index + UINT32 offset, // IN: offset of NV data + UINT32 size, // IN: size of NV data + void *data // IN: data buffer + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + // + pAssert(nvIndex != NULL); + // Make sure that this is dealing with the 'default' index. + // Note: it is tempting to change the calling sequence so that the 'default' is + // presumed. + pAssert(nvIndex->publicArea.nvIndex == s_cachedNvIndex.publicArea.nvIndex); + // Validate that write falls within range of the index + pAssert(offset <= nvIndex->publicArea.dataSize + && size <= (nvIndex->publicArea.dataSize - offset)); + // Update TPMA_NV_WRITTEN bit if necessary + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + { + // Update the in memory version of the attributes + SET_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN); + // If this is not orderly, then update the NV version of + // the attributes + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) + { + result = NvWriteNvIndexAttributes(s_cachedNvRef, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // If this is a partial write of an ordinary index, clear the whole + // index. + if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes) + && (nvIndex->publicArea.dataSize > size)) + _plat__NvMemoryClear(s_cachedNvRef + sizeof(NV_INDEX), + nvIndex->publicArea.dataSize); + } + else + { + // This is orderly so update the RAM version + MemoryCopy(s_cachedNvRamRef + offsetof(NV_RAM_HEADER, attributes), + &nvIndex->publicArea.attributes, sizeof(TPMA_NV)); + // If setting WRITTEN for an orderly counter, make sure that the + // state saved version of the counter is saved + if(IsNvCounterIndex(nvIndex->publicArea.attributes)) + SET_NV_UPDATE(UT_ORDERLY); + // If setting the written attribute on an ordinary index, make sure that + // the data is all cleared out in case there is a partial write. This + // is only necessary for ordinary indexes because all of the other types + // are always written in total. + else if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes)) + MemorySet(s_cachedNvRamRef + sizeof(NV_RAM_HEADER), + 0, nvIndex->publicArea.dataSize); + } + } + // If this is orderly data, write it to RAM + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) + { + // Note: if this is the first write to a counter, the code above will queue + // the write to NV of the RAM data in order to update TPMA_NV_WRITTEN. In + // process of doing that write, it will also write the initial counter value + // Update RAM + MemoryCopy(s_cachedNvRamRef + sizeof(NV_RAM_HEADER) + offset, data, size); + // And indicate that the TPM is no longer orderly + g_clearOrderly = TRUE; + } + else + { + // Offset into the index to the first byte of the data to be written to NV + result = NvConditionallyWrite(s_cachedNvRef + sizeof(NV_INDEX) + offset, + size, data); + } + return result; +} +/* 8.4.5.12 NvWriteUINT64Data() */ +/* This function to write back a UINT64 value. The various UINT64 values (bits, counters, and + PINs()) are kept in canonical format but manipulate in native format. This takes a native format + value converts it and saves it back as in canonical format. */ +/* This function will return the value from NV or RAM depending on the type of the index (orderly or + not) */ +TPM_RC +NvWriteUINT64Data( + NV_INDEX *nvIndex, // IN: the description of the index + UINT64 intValue // IN: the value to write + ) +{ + BYTE bytes[8]; + UINT64_TO_BYTE_ARRAY(intValue, bytes); + return NvWriteIndexData(nvIndex, 0, 8, &bytes); +} +/* 8.4.5.13 NvGetIndexName() */ +/* This function computes the Name of an index The name buffer receives the bytes of the Name and + the return value is the number of octets in the Name. */ +/* This function requires that the NV Index is defined. */ +TPM2B_NAME * +NvGetIndexName( + NV_INDEX *nvIndex, // IN: the index over which the name is to be + // computed + TPM2B_NAME *name // OUT: name of the index + ) +{ + UINT16 dataSize, digestSize; + BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)]; + BYTE *buffer; + HASH_STATE hashState; + // Marshal public area + buffer = marshalBuffer; + dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex->publicArea, &buffer, NULL); + // hash public area + digestSize = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg); + CryptDigestUpdate(&hashState, dataSize, marshalBuffer); + // Complete digest leaving room for the nameAlg + CryptHashEnd(&hashState, digestSize, &name->b.buffer[2]); + // Include the nameAlg + UINT16_TO_BYTE_ARRAY(nvIndex->publicArea.nameAlg, name->b.buffer); + name->t.size = digestSize + 2; + return name; +} +/* 8.4.5.14 NvGetNameByIndexHandle() */ +/* This function is used to compute the Name of an NV Index referenced by handle. */ +/* The name buffer receives the bytes of the Name and the return value is the number of octets in + the Name. */ +/* This function requires that the NV Index is defined. */ +TPM2B_NAME * +NvGetNameByIndexHandle( + TPMI_RH_NV_INDEX handle, // IN: handle of the index + TPM2B_NAME *name // OUT: name of the index + ) +{ + NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); + return NvGetIndexName(nvIndex, name); +} +/* 8.4.5.15 NvDefineIndex() */ +/* This function is used to assign NV memory to an NV Index. */ +/* Error Returns Meaning */ +/* TPM_RC_NV_SPACE insufficient NV space */ +TPM_RC +NvDefineIndex( + TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create. + TPM2B_AUTH *authValue // IN: The initial authorization value + ) +{ + + // The buffer to be written to NV memory + NV_INDEX nvIndex; // the index data + UINT16 entrySize; // size of entry + TPM_RC result; + // + entrySize = sizeof(NV_INDEX); + // only allocate data space for indexes that are going to be written to NV. + // Orderly indexes don't need space. + if(!IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)) + entrySize += publicArea->dataSize; + // Check if we have enough space to create the NV Index + // In this implementation, the only resource limitation is the available NV + // space (and possibly RAM space.) Other implementation may have other + // limitation on counter or on NV slots + if(!NvTestSpace(entrySize, TRUE, IsNvCounterIndex(publicArea->attributes))) + return TPM_RC_NV_SPACE; + // if the index to be defined is RAM backed, check RAM space availability + // as well + if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY) + && !NvRamTestSpaceIndex(publicArea->dataSize)) + return TPM_RC_NV_SPACE; + // Copy input value to nvBuffer + nvIndex.publicArea = *publicArea; + // Copy the authValue + nvIndex.authValue = *authValue; + // Add index to NV memory + result = NvAdd(entrySize, sizeof(NV_INDEX), TPM_RH_UNASSIGNED, + (BYTE *)&nvIndex); + if(result == TPM_RC_SUCCESS) + { + // If the data of NV Index is RAM backed, add the data area in RAM as well + if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)) + NvAddRAM(publicArea); + } + return result; +} +/* 8.4.5.16 NvAddEvictObject() */ +/* This function is used to assign NV memory to a persistent object. */ +/* Error Returns Meaning */ +/* TPM_RC_NV_HANDLE the requested handle is already in use */ +/* TPM_RC_NV_SPACE insufficient NV space */ +TPM_RC +NvAddEvictObject( + TPMI_DH_OBJECT evictHandle, // IN: new evict handle + OBJECT *object // IN: object to be added + ) +{ + TPM_HANDLE temp = object->evictHandle; + TPM_RC result; + // Check if we have enough space to add the evict object + // An evict object needs 8 bytes in index table + sizeof OBJECT + // In this implementation, the only resource limitation is the available NV + // space. Other implementation may have other limitation on evict object + // handle space + if(!NvTestSpace(sizeof(OBJECT) + sizeof(TPM_HANDLE), FALSE, FALSE)) + return TPM_RC_NV_SPACE; + // Set evict attribute and handle + object->attributes.evict = SET; + object->evictHandle = evictHandle; + // Now put this in NV + result = NvAdd(sizeof(OBJECT), sizeof(OBJECT), evictHandle, (BYTE *)object); + // Put things back the way they were + object->attributes.evict = CLEAR; + object->evictHandle = temp; + return result; +} +/* 8.4.5.17 NvDeleteIndex() */ +/* This function is used to delete an NV Index. */ +/* Error Returns Meaning */ +/* TPM_RC_NV_UNAVAILABLE NV is not accessible */ +/* TPM_RC_NV_RATE NV is rate limiting */ +TPM_RC +NvDeleteIndex( + NV_INDEX *nvIndex, // IN: an in RAM index descriptor + NV_REF entityAddr // IN: location in NV + ) +{ + TPM_RC result; + // + if(nvIndex != NULL) + { + // Whenever a counter is deleted, make sure that the MaxCounter value is + // updated to reflect the value + if(IsNvCounterIndex(nvIndex->publicArea.attributes) + && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + NvUpdateMaxCount(NvGetUINT64Data(nvIndex, entityAddr)); + result = NvDelete(entityAddr); + if(result != TPM_RC_SUCCESS) + return result; + // If the NV Index is RAM backed, delete the RAM data as well + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) + NvDeleteRAM(nvIndex->publicArea.nvIndex); + NvIndexCacheInit(); + } + return TPM_RC_SUCCESS; +} +/* 8.4.5.18 NvDeleteEvict() */ +/* This function will delete a NV evict object. Will return success if object deleted or if it does + not exist */ +TPM_RC +NvDeleteEvict( + TPM_HANDLE handle // IN: handle of entity to be deleted + ) +{ + NV_REF entityAddr = NvFindEvict(handle, NULL); // pointer to entity + TPM_RC result = TPM_RC_SUCCESS; + if(entityAddr != 0) + result = NvDelete(entityAddr); + return result; +} +/* 8.4.5.19 NvFlushHierarchy() */ +/* This function will delete persistent objects belonging to the indicated hierarchy. If the + storage hierarchy is selected, the function will also delete any NV Index defined using + ownerAuth. */ +/* Error Returns Meaning */ +/* TPM_RC_NV_RATE NV is unavailable because of rate limit */ +/* TPM_RC_NV_UNAVAILABLE NV is inaccessible */ +TPM_RC +NvFlushHierarchy( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. + ) +{ + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + TPM_HANDLE entityHandle; + TPM_RC result = TPM_RC_SUCCESS; + // + while((currentAddr = NvNext(&iter, &entityHandle)) != 0) + { + if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX) + { + NV_INDEX nvIndex; + // + // If flush endorsement or platform hierarchy, no NV Index would be + // flushed + if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM) + continue; + // Get the index information + NvReadNvIndexInfo(currentAddr, &nvIndex); + // For storage hierarchy, flush OwnerCreated index + if(!IS_ATTRIBUTE(nvIndex.publicArea.attributes, TPMA_NV, + PLATFORMCREATE)) + { + // Delete the index (including RAM for orderly) + result = NvDeleteIndex(&nvIndex, currentAddr); + if(result != TPM_RC_SUCCESS) + break; + // Re-iterate from beginning after a delete + iter = NV_REF_INIT; + } + } + else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT) + { + OBJECT_ATTRIBUTES attributes; + // + NvRead(&attributes, + (UINT32)(currentAddr + + sizeof(TPM_HANDLE) + + offsetof(OBJECT, attributes)), + sizeof(OBJECT_ATTRIBUTES)); + // If the evict object belongs to the hierarchy to be flushed... + if((hierarchy == TPM_RH_PLATFORM && attributes.ppsHierarchy == SET) + || (hierarchy == TPM_RH_OWNER && attributes.spsHierarchy == SET) + || (hierarchy == TPM_RH_ENDORSEMENT + && attributes.epsHierarchy == SET)) + { + // ...then delete the evict object + result = NvDelete(currentAddr); + if(result != TPM_RC_SUCCESS) + break; + // Re-iterate from beginning after a delete + iter = NV_REF_INIT; + } + } + else + { + FAIL(FATAL_ERROR_INTERNAL); + } + } + return result; +} +/* 8.4.5.20 NvSetGlobalLock() */ +/* This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indexes that have + TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock(). */ +/* Error Returns Meaning */ +/* TPM_RC_NV_RATE NV is unavailable because of rate limit */ +/* TPM_RC_NV_UNAVAILABLE NV is inaccessible */ +TPM_RC +NvSetGlobalLock( + void + ) +{ + NV_REF iter = NV_REF_INIT; + NV_RAM_REF ramIter = NV_RAM_REF_INIT; + NV_REF currentAddr; + NV_RAM_REF currentRamAddr; + TPM_RC result = TPM_RC_SUCCESS; + // + // Check all normal indexes + while((currentAddr = NvNextIndex(NULL, &iter)) != 0) + { + TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr); + // + // See if it should be locked + if(!IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY) + && IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)) + { + SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); + result = NvWriteNvIndexAttributes(currentAddr, attributes); + if(result != TPM_RC_SUCCESS) + return result; + } + } + // Now search all the orderly attributes + while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0) + { + // See if it should be locked + TPMA_NV attributes = NvReadRamIndexAttributes(currentRamAddr); + if(IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)) + { + SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); + NvWriteRamIndexAttributes(currentRamAddr, attributes); + } + } + return result; +} +/* 8.4.5.21 InsertSort() */ +/* Sort a handle into handle list in ascending order. The total handle number in the list should + not exceed MAX_CAP_HANDLES */ +static void +InsertSort( + TPML_HANDLE *handleList, // IN/OUT: sorted handle list + UINT32 count, // IN: maximum count in the handle list + TPM_HANDLE entityHandle // IN: handle to be inserted + ) +{ + UINT32 i, j; + UINT32 originalCount; + // For a corner case that the maximum count is 0, do nothing + if(count == 0) + return; + // For empty list, add the handle at the beginning and return + if(handleList->count == 0) + { + handleList->handle[0] = entityHandle; + handleList->count++; + return; + } + // Check if the maximum of the list has been reached + originalCount = handleList->count; + if(originalCount < count) + handleList->count++; + // Insert the handle to the list + for(i = 0; i < originalCount; i++) + { + if(handleList->handle[i] > entityHandle) + { + for(j = handleList->count - 1; j > i; j--) + { + handleList->handle[j] = handleList->handle[j - 1]; + } + break; + } + } + // If a slot was found, insert the handle in this position + if(i < originalCount || handleList->count > originalCount) + handleList->handle[i] = entityHandle; + return; +} +/* 8.4.5.22 NvCapGetPersistent() */ +/* This function is used to get a list of handles of the persistent objects, starting at handle. */ +/* Handle must be in valid persistent object handle range, but does not have to reference an + existing persistent object. */ +/* Return Values Meaning */ +/* YES if there are more handles available */ +/* NO all the available handles has been returned */ +TPMI_YES_NO +NvCapGetPersistent( + TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: maximum number of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ) +{ + TPMI_YES_NO more = NO; + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + TPM_HANDLE entityHandle; + pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); + // Initialize output handle list + handleList->count = 0; + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; + while((currentAddr = NvNextEvict(&entityHandle, &iter)) != 0) + { + // Ignore persistent handles that have values less than the input handle + if(entityHandle < handle) + continue; + // if the handles in the list have reached the requested count, and there + // are still handles need to be inserted, indicate that there are more. + if(handleList->count == count) + more = YES; + // A handle with a value larger than start handle is a candidate + // for return. Insert sort it to the return list. Insert sort algorithm + // is chosen here for simplicity based on the assumption that the total + // number of NV Indexes is small. For an implementation that may allow + // large number of NV Indexes, a more efficient sorting algorithm may be + // used here. + InsertSort(handleList, count, entityHandle); + } + return more; +} +/* 8.4.5.23 NvCapGetIndex() */ +/* This function returns a list of handles of NV Indexes, starting from handle. Handle must be in + the range of NV Indexes, but does not have to reference an existing NV Index. */ +/* Return Values Meaning */ +/* YES if there are more handles to report */ +/* NO all the available handles has been reported */ +TPMI_YES_NO +NvCapGetIndex( + TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: max number of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ) +{ + TPMI_YES_NO more = NO; + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + TPM_HANDLE nvHandle; + pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); + // Initialize output handle list + handleList->count = 0; + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; + while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0) + { + // Ignore index handles that have values less than the 'handle' + if(nvHandle < handle) + continue; + // if the count of handles in the list has reached the requested count, + // and there are still handles to report, set more. + if(handleList->count == count) + more = YES; + // A handle with a value larger than start handle is a candidate + // for return. Insert sort it to the return list. Insert sort algorithm + // is chosen here for simplicity based on the assumption that the total + // number of NV Indexes is small. For an implementation that may allow + // large number of NV Indexes, a more efficient sorting algorithm may be + // used here. + InsertSort(handleList, count, nvHandle); + } + return more; +} +/* 8.4.5.24 NvCapGetIndexNumber() */ +/* This function returns the count of NV Indexes currently defined. */ +UINT32 +NvCapGetIndexNumber( + void + ) +{ + UINT32 num = 0; + NV_REF iter = NV_REF_INIT; + while(NvNextIndex(NULL, &iter) != 0) + num++; + return num; +} +/* 8.4.5.25 NvCapGetPersistentNumber() */ +/* Function returns the count of persistent objects currently in NV memory. */ +UINT32 +NvCapGetPersistentNumber( + void + ) +{ + UINT32 num = 0; + NV_REF iter = NV_REF_INIT; + TPM_HANDLE handle; + while(NvNextEvict(&handle, &iter) != 0) + num++; + return num; +} +/* 8.4.5.26 NvCapGetPersistentAvail() */ +/* This function returns an estimate of the number of additional persistent objects that could be + loaded into NV memory. */ +UINT32 +NvCapGetPersistentAvail( + void + ) +{ + UINT32 availNVSpace; + UINT32 counterNum = NvCapGetCounterNumber(); + UINT32 reserved = sizeof(NV_LIST_TERMINATOR); + // Get the available space in NV storage + availNVSpace = NvGetFreeBytes(); + if(counterNum < MIN_COUNTER_INDICES) + { + // Some space has to be reserved for counter objects. + reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE; + if(reserved > availNVSpace) + availNVSpace = 0; + else + availNVSpace -= reserved; + } + return availNVSpace / NV_EVICT_OBJECT_SIZE; +} +/* 8.4.5.27 NvCapGetCounterNumber() */ +/* Get the number of defined NV Indexes that are counter indexes. */ +UINT32 +NvCapGetCounterNumber( + void + ) +{ + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + UINT32 num = 0; + while((currentAddr = NvNextIndex(NULL, &iter)) != 0) + { + TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr); + if(IsNvCounterIndex(attributes)) + num++; + } + return num; +} +/* 8.4.5.28 NvSetStartupAttributes() */ +/* Local function to set the attributes of an Index at TPM Reset and TPM Restart. */ +static TPMA_NV +NvSetStartupAttributes( + TPMA_NV attributes, // IN: attributes to change + STARTUP_TYPE type // IN: start up type + ) +{ + // Clear read lock + CLEAR_ATTRIBUTE(attributes, TPMA_NV, READLOCKED); + // Will change a non counter index to the unwritten state if: + // a) TPMA_NV_CLEAR_STCLEAR is SET + // b) orderly and TPM Reset + if(!IsNvCounterIndex(attributes)) + { + if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR) + || (IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY) + && (type == SU_RESET))) + CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITTEN); + } + // Unlock any index that is not written or that does not have + // TPMA_NV_WRITEDEFINE SET. + if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN) + || !IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) + CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); + return attributes; +} +/* 8.4.5.29 NvEntityStartup() */ +/* This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action + is taken. If the startup is a TPM Reset or a TPM Restart, then this function will: */ +/* a) clear read/write lock; */ +/* b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and */ +/* c) set the lower bits in orderly counters to 1 for a non-orderly startup */ +/* It is a prerequisite that NV be available for writing before this function is called. */ +BOOL +NvEntityStartup( + STARTUP_TYPE type // IN: start up type + ) +{ + NV_REF iter = NV_REF_INIT; + NV_RAM_REF ramIter = NV_RAM_REF_INIT; + NV_REF currentAddr; // offset points to the current entity + NV_RAM_REF currentRamAddr; + TPM_HANDLE nvHandle; + TPMA_NV attributes; + // Restore RAM index data + NvRead(s_indexOrderlyRam, NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam)); + // Initialize the max NV counter value + NvSetMaxCount(NvGetMaxCount()); + // If recovering from state save, do nothing else + if(type == SU_RESUME) + return TRUE; + // Iterate all the NV Index to clear the locks + while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0) + { + attributes = NvReadNvIndexAttributes(currentAddr); + // If this is an orderly index, defer processing until loop below + if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)) + continue; + // Set the attributes appropriate for this startup type + attributes = NvSetStartupAttributes(attributes, type); + NvWriteNvIndexAttributes(currentAddr, attributes); + } + // Iterate all the orderly indexes to clear the locks and initialize counters + while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0) + { + attributes = NvReadRamIndexAttributes(currentRamAddr); + attributes = NvSetStartupAttributes(attributes, type); + // update attributes in RAM + NvWriteRamIndexAttributes(currentRamAddr, attributes); + // Set the lower bits in an orderly counter to 1 for a non-orderly startup + if(IsNvCounterIndex(attributes) + && (g_prevOrderlyState == SU_NONE_VALUE)) + { + UINT64 counter; + // Read the counter value last saved to NV. + counter = BYTE_ARRAY_TO_UINT64(currentRamAddr + sizeof(NV_RAM_HEADER)); + // Set the lower bits of counter to 1's + counter |= MAX_ORDERLY_COUNT; + // Write back to RAM + // NOTE: Do not want to force a write to NV here. The counter value will + // stay in RAM until the next shutdown or rollover. + UINT64_TO_BYTE_ARRAY(counter, currentRamAddr + sizeof(NV_RAM_HEADER)); + } + } + return TRUE; +} +/* 8.4.5.30 NvCapGetCounterAvail() */ +/* This function returns an estimate of the number of additional counter type NV Indexes that can be + defined. */ +UINT32 +NvCapGetCounterAvail( + void + ) +{ + UINT32 availNVSpace; + UINT32 availRAMSpace; + UINT32 persistentNum = NvCapGetPersistentNumber(); + UINT32 reserved = sizeof(NV_LIST_TERMINATOR); + // Get the available space in NV storage + availNVSpace = NvGetFreeBytes(); + if(persistentNum < MIN_EVICT_OBJECTS) + { + // Some space has to be reserved for evict object. Adjust availNVSpace. + reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE; + if(reserved > availNVSpace) + availNVSpace = 0; + else + availNVSpace -= reserved; + } + // Compute the available space in RAM + availRAMSpace = (RAM_ORDERLY_END - NvRamGetEnd()); /* kgold - removed cast */ + // Return the min of counter number in NV and in RAM + if(availNVSpace / NV_INDEX_COUNTER_SIZE + > availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE) + return availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE; + else + return availNVSpace / NV_INDEX_COUNTER_SIZE; +} +/* 8.4.5.31 NvFindHandle() */ +/* this function returns the offset in NV memory of the entity associated with the input handle. A + value of zero indicates that handle does not exist reference an existing persistent object or + defined NV Index. */ +NV_REF +NvFindHandle( + TPM_HANDLE handle + ) +{ + NV_REF addr; + NV_REF iter = NV_REF_INIT; + TPM_HANDLE nextHandle; + while((addr = NvNext(&iter, &nextHandle)) != 0) + { + if(nextHandle == handle) + break; + } + return addr; +} +/* 8.4.6 NV Max Counter */ +/* 8.4.6.1 Introduction */ +/* The TPM keeps track of the highest value of a deleted counter index. When an index is deleted, + this value is updated if the deleted counter index is greater than the previous value. When a new + index is created and first incremented, it will get a value that is at least one greater than any + other index than any previously deleted index. This ensures that it is not possible to roll back + an index. */ +/* The highest counter value is kept in NV in a special end-of-list marker. This marker is only + updated when an index is deleted. Otherwise it just moves. */ +/* When the TPM starts up, it searches NV for the end of list marker and initializes an in memory + value (s_maxCounter). */ +/* 8.4.6.2 NvReadMaxCount() */ +/* This function returns the max NV counter value. */ +UINT64 +NvReadMaxCount( + void + ) +{ + return s_maxCounter; +} +/* 8.4.6.3 NvUpdateMaxCount() */ +/* This function updates the max counter value to NV memory. This is just staging for the actual + write that will occur when the NV index memory is modified. */ +void +NvUpdateMaxCount( + UINT64 count + ) +{ + if(count > s_maxCounter) + s_maxCounter = count; +} +/* 8.4.6.4 NvSetMaxCount() */ +/* This function is used at NV initialization time to set the initial value of the maximum + counter. */ +void +NvSetMaxCount( + UINT64 value + ) +{ + s_maxCounter = value; +} +/* 8.4.6.5 NvGetMaxCount() */ +/* Function to get the NV max counter value from the end-of-list marker */ +UINT64 +NvGetMaxCount( + void + ) +{ + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + UINT64 maxCount; + // Find the end of list marker and initialize the NV Max Counter value. + while((currentAddr = NvNext(&iter, NULL )) != 0); + // 'iter' should be pointing at the end of list marker so read in the current + // value of the s_maxCounter. + NvRead(&maxCount, iter + sizeof(UINT32), sizeof(maxCount)); + return maxCount; +} diff --git a/src/tpm2/NVDynamic_fp.h b/src/tpm2/NVDynamic_fp.h new file mode 100644 index 0000000..376f1aa --- /dev/null +++ b/src/tpm2/NVDynamic_fp.h @@ -0,0 +1,253 @@ +/********************************************************************************/ +/* */ +/* Dynamic space for user defined NV */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NVDynamic_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef NVDYNAMIC_FP_H +#define NVDYNAMIC_FP_H + +NV_REF +NvWriteNvListEnd( + NV_REF end + ); +void +NvUpdateIndexOrderlyData( + void + ); +void +NvReadNvIndexInfo( + NV_REF ref, // IN: points to NV where index is located + NV_INDEX *nvIndex // OUT: place to receive index data + ); +void +NvReadObject( + NV_REF ref, // IN: points to NV where index is located + OBJECT *object // OUT: place to receive the object data + ); +BOOL +NvIndexIsDefined( + TPM_HANDLE nvHandle // IN: Index to look for + ); +BOOL +NvIsPlatformPersistentHandle( + TPM_HANDLE handle // IN: handle + ); +BOOL +NvIsOwnerPersistentHandle( + TPM_HANDLE handle // IN: handle + ); +TPM_RC +NvIndexIsAccessible( + TPMI_RH_NV_INDEX handle // IN: handle + ); +TPM_RC +NvGetEvictObject( + TPM_HANDLE handle, // IN: handle + OBJECT *object // OUT: object data + ); +void +NvIndexCacheInit( + void + ); +void +NvGetIndexData( + NV_INDEX *nvIndex, // IN: the in RAM index descriptor + NV_REF locator, // IN: where the data is located + UINT32 offset, // IN: offset of NV data + UINT16 size, // IN: size of NV data + void *data // OUT: data buffer + ); +void +NvHashIndexData( + HASH_STATE *hashState, // IN: Initialized hash state + NV_INDEX *nvIndex, // IN: Index + NV_REF locator, // IN: where the data is located + UINT32 offset, // IN: starting offset + UINT16 size // IN: amount to hash + ); +UINT64 +NvGetUINT64Data( + NV_INDEX *nvIndex, // IN: the in RAM index descriptor + NV_REF locator // IN: where index exists in NV + ); +TPM_RC +NvWriteIndexAttributes( + TPM_HANDLE handle, + NV_REF locator, // IN: location of the index + TPMA_NV attributes // IN: attributes to write + ); +TPM_RC +NvWriteIndexAuth( + NV_REF locator, // IN: location of the index + TPM2B_AUTH *authValue // IN: the authValue to write + ); +NV_INDEX * +NvGetIndexInfo( + TPM_HANDLE nvHandle, // IN: the index handle + NV_REF *locator // OUT: location of the index + ); +TPM_RC +NvWriteIndexData( + NV_INDEX *nvIndex, // IN: the description of the index + UINT32 offset, // IN: offset of NV data + UINT32 size, // IN: size of NV data + void *data // IN: data buffer + ); +TPM_RC +NvWriteUINT64Data( + NV_INDEX *nvIndex, // IN: the description of the index + UINT64 intValue // IN: the value to write + ); +TPM2B_NAME * +NvGetIndexName( + NV_INDEX *nvIndex, // IN: the index over which the name is to be + // computed + TPM2B_NAME *name // OUT: name of the index + ); +TPM2B_NAME * +NvGetNameByIndexHandle( + TPMI_RH_NV_INDEX handle, // IN: handle of the index + TPM2B_NAME *name // OUT: name of the index + ); +TPM_RC +NvDefineIndex( + TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create. + TPM2B_AUTH *authValue // IN: The initial authorization value + ); +TPM_RC +NvAddEvictObject( + TPMI_DH_OBJECT evictHandle, // IN: new evict handle + OBJECT *object // IN: object to be added + ); +TPM_RC +NvDeleteIndex( + NV_INDEX *nvIndex, // IN: an in RAM index descriptor + NV_REF entityAddr // IN: location in NV + ); +TPM_RC +NvDeleteEvict( + TPM_HANDLE handle // IN: handle of entity to be deleted + ); +TPM_RC +NvFlushHierarchy( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. + ); +TPM_RC +NvSetGlobalLock( + void + ); +TPMI_YES_NO +NvCapGetPersistent( + TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: maximum number of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ); +TPMI_YES_NO +NvCapGetIndex( + TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: max number of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ); +UINT32 +NvCapGetIndexNumber( + void + ); +UINT32 +NvCapGetPersistentNumber( + void + ); +UINT32 +NvCapGetPersistentAvail( + void + ); +UINT32 +NvCapGetCounterNumber( + void + ); +BOOL +NvEntityStartup( + STARTUP_TYPE type // IN: start up type + ); +UINT32 +NvCapGetCounterAvail( + void + ); +NV_REF +NvFindHandle( + TPM_HANDLE handle + ); +UINT64 +NvReadMaxCount( + void + ); +void +NvUpdateMaxCount( + UINT64 count + ); +void +NvSetMaxCount( + UINT64 value + ); +UINT64 +NvGetMaxCount( + void + ); + + +#endif diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c new file mode 100644 index 0000000..c7cd1e0 --- /dev/null +++ b/src/tpm2/NVMarshal.c @@ -0,0 +1,4916 @@ +/********************************************************************************/ +/* */ +/* Marshalling and unmarshalling of state */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "assert.h" + +#define _CRYPT_HASH_C_ +#define SESSION_PROCESS_C +#define NV_C +#define OBJECT_C +#define PCR_C +#define SESSION_C +#include "Platform.h" +#include "NVMarshal.h" +#include "Marshal_fp.h" +#include "Unmarshal_fp.h" +#include "Global.h" +#include "TpmTcpProtocol.h" +#include "Simulator_fp.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" + +/* + * The TPM2 maintains a pcrAllocated shadow variable; the current active one is + * in gp.pcrAllocated and the one to be active after reboot is in NVRAM. So, + * this means we have to restore two of these variables when we resume. The + * tricky part is that the global gp will be restored by reading from NVRAM. + * Once that has been done the gp.pcrAllocated needs to be restored with the + * one that is supposed to be active. All of this is only supposed to happen + * when we resume a VM's volatile state. + */ +static struct shadow { + TPML_PCR_SELECTION pcrAllocated; + BOOL pcrAllocatedIsNew; +} shadow; + +/* prevent misconfiguration: */ +typedef char assertion_failed_nvram[ + (NV_USER_DYNAMIC_END < NV_USER_DYNAMIC) ? -1 : 0]; + +typedef struct +{ + UINT16 version; + UINT32 magic; + UINT16 min_version; /* min. implementation version to accept the blob */ +} NV_HEADER; + +static UINT8 BOOL_Marshal(BOOL *boolean, BYTE **buffer, INT32 *size); +static TPM_RC BOOL_Unmarshal(BOOL *boolean, BYTE **buffer, INT32 *size); + +/* + * There are compile-time optional variables that we marshal. To allow + * for some flexibility, we marshal them in such a way that these + * variables can be skipped if they are in the byte stream but are not + * needed by the implementation. The following block_skip data structure + * and related functions address this issue. + */ +typedef struct { + size_t idx; + size_t sz; + struct position { + BYTE *buffer; + INT32 size; + } pos[5]; /* more only needed for nested compile-time #ifdef's */ +} block_skip; + +/* + * This function is to be called when an optional block follows. It inserts + * a BOOL into the byte stream indicating whether the block is there or not. + * Then it leaves a 16bit zero in the byt stream and remembers the location + * of that zero. We will update the location with the number of optional + * bytes written when block_skip_write_pop() is called. + */ +static UINT16 +block_skip_write_push(block_skip *bs, BOOL has_block, + BYTE **buffer, INT32 *size) { + UINT16 written , w; + UINT16 zero = 0; + written = BOOL_Marshal(&has_block, buffer, size); + bs->pos[bs->idx].buffer = *buffer; + bs->pos[bs->idx].size = *size; + w = UINT16_Marshal(&zero, buffer, size); + if (w) { + bs->idx++; + pAssert(bs->idx < bs->sz); + written += w; + } + return written; +} + +/* + * This function must be called for every block_skip_write_push() call. + * It has to be called once a compile-time optional block has been + * processed. It must be called after the #endif. + * In this function we updated the previously remembered location with + * the numbers of bytes to skip in case a block is there but it is not + * needed. + */ +static void +block_skip_write_pop(block_skip *bs, INT32 *size) { + UINT16 skip; + unsigned i = --bs->idx; + pAssert((int)bs->idx >= 0); + skip = bs->pos[i].size - *size - sizeof(UINT16); + UINT16_Marshal(&skip, &bs->pos[i].buffer, &bs->pos[i].size); +} + +/* + * This function must be called when unmarshalling a byte stream and + * a compile-time optional block follows. In case the compile-time + * optional block is there but not in the byte stream, we log an error. + * In case the bytes stream contains the block, but we don't need it + * we skip it. In the other cases we don't need to do anything since + * the code is 'in sync' with the byte stream. + */ +static TPM_RC +block_skip_read(BOOL needs_block, BYTE **buffer, INT32 *size, + const char *name, const char *field, + BOOL *skip_code) +{ + TPM_RC rc = TPM_RC_SUCCESS; + BOOL has_block; + UINT16 blocksize; + + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&has_block, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&blocksize, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (!has_block && needs_block) { + TPMLIB_LogTPM2Error("%s needs missing %s\n", name, field); + rc = TPM_RC_BAD_PARAMETER; + } else if (has_block && !needs_block) { + /* byte stream has the data but we don't need them */ + *buffer += blocksize; + *size -= blocksize; + *skip_code = TRUE; + } + } + return rc; +} + +#define BLOCK_SKIP_INIT \ + block_skip block_skip = { \ + .idx = 0, \ + .sz = ARRAY_SIZE(block_skip.pos), \ + } + +#define BLOCK_SKIP_WRITE_PUSH(HAS_BLOCK, BUFFER, POS) \ + block_skip_write_push(&block_skip, HAS_BLOCK, BUFFER, POS) + +#define BLOCK_SKIP_WRITE_POP(SIZE) \ + block_skip_write_pop(&block_skip, SIZE) + +#define BLOCK_SKIP_WRITE_CHECK \ + pAssert(block_skip.idx == 0) + +#define BLOCK_SKIP_READ(SKIP_MARK, NEEDS_BLOCK, BUFFER, SIZE, NAME, FIELD) \ + { \ + BOOL skip_code = FALSE; \ + rc = block_skip_read(NEEDS_BLOCK, buffer, size, \ + NAME, FIELD, &skip_code); \ + if (rc == TPM_RC_SUCCESS && skip_code) \ + goto SKIP_MARK; \ + } + +static unsigned int _ffsll(long long bits) +{ + size_t i = 0; + + for (i = 0; i < 8 * sizeof(bits); i++) { + if (bits & (1ULL << i)) + return i + 1; + } + return 0; +} + +/* BOOL is 'int' but we store a single byte */ +static UINT8 +BOOL_Marshal(BOOL *boolean, BYTE **buffer, INT32 *size) +{ + UINT8 _bool = (*boolean != 0); + UINT16 written = 0; + written += UINT8_Marshal(&_bool, buffer, size); + return written; +} + +static TPM_RC +BOOL_Unmarshal(BOOL *boolean, BYTE **buffer, INT32 *size) +{ + UINT8 _bool; + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(&_bool, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + *boolean = (_bool != 0); + } + + return rc; +} + +static UINT16 +SEED_COMPAT_LEVEL_Marshal(SEED_COMPAT_LEVEL *source, + BYTE **buffer, INT32 *size) +{ + return UINT8_Marshal((UINT8 *)source, buffer, size); +} + +static TPM_RC +SEED_COMPAT_LEVEL_Unmarshal(SEED_COMPAT_LEVEL *source, + BYTE **buffer, INT32 *size, + const char *name) +{ + TPM_RC rc; + + rc = UINT8_Unmarshal((UINT8 *)source, buffer, size); + if (rc == TPM_RC_SUCCESS && *source > SEED_COMPAT_LEVEL_LAST) { + TPMLIB_LogTPM2Error("%s compatLevel '%u' higher than supported '%u'\n", + name, *source, SEED_COMPAT_LEVEL_LAST); + rc = TPM_RC_BAD_VERSION; + } + return rc; +} + +static int +TPM2B_Cmp(const TPM2B *t1, const TPM2B *t2) +{ + if (t1->size != t2->size) + return 1; + + return memcmp(t1->buffer, t2->buffer, t1->size); +} + +static UINT16 +TPM2B_PROOF_Marshal(TPM2B_PROOF *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); + return written; +} + +static TPM_RC +TPM2B_PROOF_Unmarshal(TPM2B_PROOF *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(target->t.buffer), buffer, size); + } + return rc; +} + +static TPM_RC +UINT32_Unmarshal_Check(UINT32 *data, UINT32 exp, BYTE **buffer, INT32 *size, + const char *msg) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(data, buffer, size); + } + if (rc == TPM_RC_SUCCESS && exp != *data) { + TPMLIB_LogTPM2Error("%s: Expected value: 0x%08x, found: 0x%08x\n", + __func__, exp, *data); + rc = TPM_RC_BAD_TAG; + } + return rc; +} + +static void +NV_HEADER_INIT(NV_HEADER *t, UINT16 version, UINT32 magic, UINT16 min_version) +{ + t->version = version; + t->magic = magic; + t->min_version = min_version; +} + +static UINT16 +NV_HEADER_Marshal(BYTE **buffer, INT32 *size, UINT16 version, UINT32 magic, + UINT16 min_version) +{ + UINT16 written; + NV_HEADER hdr; + + NV_HEADER_INIT(&hdr, version, magic, min_version); + + written = UINT16_Marshal(&hdr.version, buffer, size); + written += UINT32_Marshal(&hdr.magic, buffer, size); + if (version >= 2) + written += UINT16_Marshal(&hdr.min_version, buffer, size); + + return written; +} + +static TPM_RC +NV_HEADER_UnmarshalVerbose(NV_HEADER *data, BYTE **buffer, INT32 *size, + UINT16 cur_version, UINT32 exp_magic, BOOL verbose) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&data->version, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->magic, buffer, size); + } + if (rc == TPM_RC_SUCCESS && exp_magic != data->magic) { + if (verbose) + TPMLIB_LogTPM2Error("%s: Invalid magic. Expected 0x%08x, got 0x%08x\n", + __func__, exp_magic, data->magic); + rc = TPM_RC_BAD_TAG; + } + + data->min_version = 0; + if (rc == TPM_RC_SUCCESS && data->version >= 2) { + + rc = UINT16_Unmarshal(&data->min_version, buffer, size); + + if (rc == TPM_RC_SUCCESS && data->min_version > cur_version) { + if (verbose) + TPMLIB_LogTPM2Error("%s: Minimum version %u higher than " + "implementation version %u for type 0x%08x\n", + __func__, data->min_version, cur_version, + exp_magic); + rc = TPM_RC_BAD_VERSION; + } + } + + return rc; +} + +static TPM_RC +NV_HEADER_Unmarshal(NV_HEADER *data, BYTE **buffer, INT32 *size, + UINT16 cur_version, UINT32 exp_magic) +{ + return NV_HEADER_UnmarshalVerbose(data, buffer, size, cur_version, + exp_magic, true); +} + +#define NV_INDEX_MAGIC 0x2547265a +#define NV_INDEX_VERSION 2 +static UINT16 +NV_INDEX_Marshal(NV_INDEX *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + NV_INDEX_VERSION, + NV_INDEX_MAGIC, 1); + + written += TPMS_NV_PUBLIC_Marshal(&data->publicArea, buffer, size); + written += TPM2B_AUTH_Marshal(&data->authValue, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +NV_INDEX_Unmarshal(NV_INDEX *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + NV_INDEX_VERSION, NV_INDEX_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_NV_PUBLIC_Unmarshal(&data->publicArea, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&data->authValue, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "NV_INDEX", "version 3 or later"); + /* future versions nest-append here */ + } +skip_future_versions: + return rc; +} + +#define DRBG_STATE_MAGIC 0x6fe83ea1 +#define DRBG_STATE_VERSION 2 +static UINT16 +DRBG_STATE_Marshal(DRBG_STATE *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + size_t i; + UINT16 array_size; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + DRBG_STATE_VERSION, DRBG_STATE_MAGIC, 1); + written += UINT64_Marshal(&data->reseedCounter, buffer, size); + written += UINT32_Marshal(&data->magic, buffer, size); + + array_size = sizeof(data->seed.bytes); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal(&data->seed.bytes[0], array_size, buffer, size); + + array_size = ARRAY_SIZE(data->lastValue); + written += UINT16_Marshal(&array_size, buffer, size); + for (i = 0; i < array_size; i++) { + written += UINT32_Marshal(&data->lastValue[i], buffer, size); + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +DRBG_STATE_Unmarshal(DRBG_STATE *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc= TPM_RC_SUCCESS; + size_t i; + NV_HEADER hdr; + UINT16 array_size = 0; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + DRBG_STATE_VERSION, DRBG_STATE_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->reseedCounter, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->magic, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (array_size != ARRAY_SIZE(data->seed.bytes)) { + TPMLIB_LogTPM2Error("Non-matching DRBG_STATE seed array size. " + "Expected %zu, got %u\n", + ARRAY_SIZE(data->seed.bytes), array_size); + rc = TPM_RC_SIZE; + } + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal(&data->seed.bytes[0], array_size, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (array_size != ARRAY_SIZE(data->lastValue)) { + TPMLIB_LogTPM2Error("Non-matching DRBG_STATE lastValue array size. " + "Expected %zu, got %u\n", + ARRAY_SIZE(data->lastValue), array_size); + rc = TPM_RC_SIZE; + } + } + if (rc == TPM_RC_SUCCESS) { + for (i = 0; i < ARRAY_SIZE(data->lastValue) && rc == TPM_RC_SUCCESS; i++) { + rc = UINT32_Unmarshal(&data->lastValue[i], buffer, size); + } + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "DRBG_STATE", "version 3 or later"); + /* future versions nest-append here */ + } +skip_future_versions: + + return rc; +} + +#define PCR_POLICY_MAGIC 0x176be626 +#define PCR_POLICY_VERSION 2 +static UINT16 +PCR_POLICY_Marshal(PCR_POLICY *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + unsigned i; + UINT16 array_size = ARRAY_SIZE(data->hashAlg); + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + PCR_POLICY_VERSION, + PCR_POLICY_MAGIC, 1); + + written += UINT16_Marshal(&array_size, buffer, size); + + for (i = 0; i < array_size; i++) { + /* TPMI_ALG_HASH_Unmarshal errors on algid 0 */ + written += TPM_ALG_ID_Marshal(&data->hashAlg[i], buffer, size); + written += TPM2B_DIGEST_Marshal(&data->policy[i], buffer, size); + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +PCR_POLICY_Unmarshal(PCR_POLICY *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc= TPM_RC_SUCCESS; + unsigned i; + UINT16 array_size; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + PCR_POLICY_VERSION, PCR_POLICY_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + if (array_size != ARRAY_SIZE(data->hashAlg)) { + TPMLIB_LogTPM2Error("Non-matching PCR_POLICY array size. " + "Expected %zu, got %u\n", + ARRAY_SIZE(data->hashAlg), array_size); + rc = TPM_RC_SIZE; + } + } + + for (i = 0; + rc == TPM_RC_SUCCESS && + i < ARRAY_SIZE(data->hashAlg); + i++) { + /* TPMI_ALG_HASH_Unmarshal errors on algid 0 */ + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&data->hashAlg[i], buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&data->policy[i], buffer, size); + } + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "PCR_POLICY", "version 3 or later"); + /* future versions nest-append here */ + } +skip_future_versions: + return rc; +} + +#define ORDERLY_DATA_MAGIC 0x56657887 +#define ORDERLY_DATA_VERSION 2 + +static UINT16 +ORDERLY_DATA_Marshal(ORDERLY_DATA *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + BOOL has_block; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + ORDERLY_DATA_VERSION, ORDERLY_DATA_MAGIC, 1); + written += UINT64_Marshal(&data->clock, buffer, size); + written += UINT8_Marshal(&data->clockSafe, buffer, size); + + written += DRBG_STATE_Marshal(&data->drbgState, buffer, size); + +#if ACCUMULATE_SELF_HEAL_TIMER + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if ACCUMULATE_SELF_HEAL_TIMER + written += UINT64_Marshal(&data->selfHealTimer, buffer, size); + written += UINT64_Marshal(&data->lockoutTimer, buffer, size); + written += UINT64_Marshal(&data->time, buffer, size); +#endif // ACCUMULATE_SELF_HEAL_TIMER + + BLOCK_SKIP_WRITE_POP(size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +ORDERLY_DATA_Unmarshal(ORDERLY_DATA *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + BOOL needs_block; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + ORDERLY_DATA_VERSION, ORDERLY_DATA_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->clock, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(&data->clockSafe, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = DRBG_STATE_Unmarshal(&data->drbgState, buffer, size); + } + +#if ACCUMULATE_SELF_HEAL_TIMER + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_self_heal_timer, needs_block, buffer, size, + "ORDERLY_DATA", "selfHealTimer"); + } +#if ACCUMULATE_SELF_HEAL_TIMER + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->selfHealTimer, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->lockoutTimer, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->time, buffer, size); + } +#endif // ACCUMULATE_SELF_HEAL_TIMER +skip_self_heal_timer: + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "ORDERLY_DATA", "version 3 or later"); + /* future versions nest-append here */ + } +skip_future_versions: + + return rc; +} + +#define PCR_SAVE_MAGIC 0x7372eabc +#define PCR_SAVE_VERSION 2 +static UINT16 +PCR_SAVE_Marshal(PCR_SAVE *data, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + TPM_ALG_ID algid; + UINT16 array_size; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + PCR_SAVE_VERSION, PCR_SAVE_MAGIC, 1); + + array_size = NUM_STATIC_PCR; + written += UINT16_Marshal(&array_size, buffer, size); + +#if ALG_SHA1 + algid = TPM_ALG_SHA1; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sha1); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sha1, array_size, + buffer, size); +#endif +#if ALG_SHA256 + algid = TPM_ALG_SHA256; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sha256); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sha256, array_size, + buffer, size); +#endif +#if ALG_SHA384 + algid = TPM_ALG_SHA384; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sha384); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sha384, array_size, + buffer, size); +#endif +#if ALG_SHA512 + algid = TPM_ALG_SHA512; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sha512); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sha512, array_size, + buffer, size); +#endif +#if ALG_SM3_256 + algid = TPM_ALG_SM3_256; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sm3_256); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sm3_256, array_size, + buffer, size); +#endif +#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256 +#error SHA3 and SM3 are not supported +#endif + + /* end marker */ + algid = TPM_ALG_NULL; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +/* + * Get the PCR banks that are active so that we know what PCRs need to be + * restored. Only data for active PCR banks needs to restored, inactive PCR + * banks need no data restored. + */ +static UINT64 +pcrbanks_algs_active(const TPML_PCR_SELECTION *pcrAllocated) +{ + UINT64 algs_active = 0; + unsigned i, j; + + for(i = 0; i < pcrAllocated->count; i++) { + for (j = 0; j < pcrAllocated->pcrSelections[i].sizeofSelect; j++) { + if (pcrAllocated->pcrSelections[i].pcrSelect[j]) { + algs_active |= 1 << pcrAllocated->pcrSelections[i].hash; + break; + } + } + } + + return algs_active; +} + +static TPM_RC +PCR_SAVE_Unmarshal(PCR_SAVE *data, BYTE **buffer, INT32 *size, + const TPML_PCR_SELECTION *pcrAllocated) +{ + TPM_RC rc = TPM_RC_SUCCESS; + UINT16 array_size, needed_size = 0; + NV_HEADER hdr; + TPM_ALG_ID algid; + BOOL end = FALSE; + BYTE *t = NULL; + UINT64 algs_needed = pcrbanks_algs_active(pcrAllocated); + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + PCR_SAVE_VERSION, PCR_SAVE_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != NUM_STATIC_PCR) { + TPMLIB_LogTPM2Error("Non-matching PCR_SAVE NUM_STATIC_PCR. " + "Expected %zu, got %u\n", + sizeof(NUM_STATIC_PCR), array_size); + rc = TPM_RC_SIZE; + } + + while (rc == TPM_RC_SUCCESS && !end) { + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&algid, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (algid) { +#if ALG_SHA1 + case TPM_ALG_SHA1: + needed_size = sizeof(data->Sha1); + t = (BYTE *)&data->Sha1; + break; +#endif +#if ALG_SHA256 + case TPM_ALG_SHA256: + needed_size = sizeof(data->Sha256); + t = (BYTE *)&data->Sha256; + break; +#endif +#if ALG_SHA384 + case TPM_ALG_SHA384: + needed_size = sizeof(data->Sha384); + t = (BYTE *)&data->Sha384; + break; +#endif +#if ALG_SHA512 + case TPM_ALG_SHA512: + needed_size = sizeof(data->Sha512); + t = (BYTE *)&data->Sha512; + break; +#endif +#if ALG_SM3_256 + case TPM_ALG_SM3_256: + needed_size = sizeof(data->Sm3_256); + t = (BYTE *)&data->Sm3_256; + break; +#endif +#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256 +#error SHA3 and SM3 are not supported +#endif + case TPM_ALG_NULL: + /* end marker */ + end = TRUE; + t = NULL; + break; + default: + TPMLIB_LogTPM2Error("PCR_SAVE: Unsupported algid %d.", + algid); + rc = TPM_RC_BAD_PARAMETER; + t = NULL; + } + } + if (t) { + if (rc == TPM_RC_SUCCESS) { + algs_needed &= ~(1 << algid); + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && array_size != needed_size) { + TPMLIB_LogTPM2Error("PCR_SAVE: Bad size for PCRs for hash 0x%x; " + "Expected %u, got %d\n", + algid, needed_size, array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal(t, array_size, buffer, size); + } + } + } + + if (rc == TPM_RC_SUCCESS && algs_needed) { + TPMLIB_LogTPM2Error("PCR_SAVE: Missing data for hash algorithm %d.\n", + _ffsll(algs_needed) - 1); + rc = TPM_RC_BAD_PARAMETER; + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "PCR_SAVE", "version 3 or later"); + /* future versions nest-append here */ + } +skip_future_versions: + + return rc; +} + + +#ifdef PCR_C + +#define PCR_MAGIC 0xe95f0387 +#define PCR_VERSION 2 +static UINT16 +PCR_Marshal(PCR *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + TPM_ALG_ID algid; + UINT16 array_size; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + PCR_VERSION, PCR_MAGIC, 1); + +#if ALG_SHA1 + algid = TPM_ALG_SHA1; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sha1Pcr); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sha1Pcr, array_size, + buffer, size); +#endif +#if ALG_SHA256 + algid = TPM_ALG_SHA256; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sha256Pcr); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sha256Pcr, array_size, + buffer, size); +#endif +#if ALG_SHA384 + algid = TPM_ALG_SHA384; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sha384Pcr); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sha384Pcr, array_size, + buffer, size); +#endif +#if ALG_SHA512 + algid = TPM_ALG_SHA512; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sha512Pcr); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sha512Pcr, array_size, + buffer, size); +#endif +#if ALG_SM3_256 + algid = TPM_ALG_SM3_256; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + array_size = sizeof(data->Sm3_256Pcr); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->Sm3_256Pcr, array_size, + buffer, size); +#endif +#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256 +#error SHA3 and SM3 are not supported +#endif + + /* end marker */ + algid = TPM_ALG_NULL; + written += TPM_ALG_ID_Marshal(&algid, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +PCR_Unmarshal(PCR *data, BYTE **buffer, INT32 *size, + const TPML_PCR_SELECTION *pcrAllocated) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + BOOL end = FALSE; + BYTE *t = NULL; + UINT16 needed_size = 0, array_size; + TPM_ALG_ID algid; + UINT64 algs_needed = pcrbanks_algs_active(pcrAllocated); + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + PCR_VERSION, PCR_MAGIC); + } + + while (rc == TPM_RC_SUCCESS && !end) { + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&algid, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (algid) { +#if ALG_SHA1 + case TPM_ALG_SHA1: + needed_size = sizeof(data->Sha1Pcr); + t = (BYTE *)&data->Sha1Pcr; + break; +#endif +#if ALG_SHA256 + case TPM_ALG_SHA256: + needed_size = sizeof(data->Sha256Pcr); + t = (BYTE *)&data->Sha256Pcr; + break; +#endif +#if ALG_SHA384 + case TPM_ALG_SHA384: + needed_size = sizeof(data->Sha384Pcr); + t = (BYTE *)&data->Sha384Pcr; + break; +#endif +#if ALG_SHA512 + case TPM_ALG_SHA512: + needed_size = sizeof(data->Sha512Pcr); + t = (BYTE *)&data->Sha512Pcr; + break; +#endif +#if ALG_SM3_256 + case TPM_ALG_SM3_256: + needed_size = sizeof(data->Sm3_256Pcr); + t = (BYTE *)&data->Sm3_256Pcr; + break; +#endif +#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256 +#error SHA3 and SM3 are not supported +#endif + case TPM_ALG_NULL: + /* end marker */ + end = TRUE; + t = NULL; + break; + default: + TPMLIB_LogTPM2Error("PCR: Unsupported algid %d.", + algid); + rc = TPM_RC_BAD_PARAMETER; + t = NULL; + } + } + if (t) { + if (rc == TPM_RC_SUCCESS) { + algs_needed &= ~(1 << algid); + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && array_size != needed_size) { + TPMLIB_LogTPM2Error("PCR: Bad size for PCR for hash 0x%x; " + "Expected %u, got %d\n", + algid, needed_size, array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal(t, array_size, buffer, size); + } + } + } + + if (rc == TPM_RC_SUCCESS && algs_needed) { + TPMLIB_LogTPM2Error("PCR: Missing data for hash algorithm %d.\n", + _ffsll(algs_needed) - 1); + rc = TPM_RC_BAD_PARAMETER; + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "PCR", "version 3 or later"); + /* future versions nest-append here */ + } +skip_future_versions: + + return rc; +} +#endif + +#define PCR_AUTHVALUE_MAGIC 0x6be82eaf +#define PCR_AUTHVALUE_VERSION 2 +static UINT16 +PCR_AUTHVALUE_Marshal(PCR_AUTHVALUE *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + size_t i; + UINT16 array_size; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + PCR_AUTHVALUE_VERSION, PCR_AUTHVALUE_MAGIC, 1); + + array_size = ARRAY_SIZE(data->auth); + written += UINT16_Marshal(&array_size, buffer, size); + for (i = 0; i < array_size; i++) { + written += TPM2B_DIGEST_Marshal(&data->auth[i], buffer, size); + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +PCR_AUTHVALUE_Unmarshal(PCR_AUTHVALUE *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + size_t i; + NV_HEADER hdr; + UINT16 array_size = 0; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + PCR_AUTHVALUE_VERSION, PCR_AUTHVALUE_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(data->auth)) { + TPMLIB_LogTPM2Error("PCR_AUTHVALUE: Bad array size for auth; " + "expected %zu, got %u\n", + ARRAY_SIZE(data->auth), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + for (i = 0; i < ARRAY_SIZE(data->auth) && rc == TPM_RC_SUCCESS; i++) { + rc = TPM2B_DIGEST_Unmarshal(&data->auth[i], buffer, size); + } + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "PCR_AUTHVALUE", "version 3 or later"); + /* future versions nest-append here */ + } +skip_future_versions: + + return rc; +} + +#define STATE_CLEAR_DATA_MAGIC 0x98897667 +#define STATE_CLEAR_DATA_VERSION 2 + +static UINT16 +STATE_CLEAR_DATA_Marshal(STATE_CLEAR_DATA *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + STATE_CLEAR_DATA_VERSION, + STATE_CLEAR_DATA_MAGIC, 1); + written += BOOL_Marshal(&data->shEnable, buffer, size); + written += BOOL_Marshal(&data->ehEnable, buffer, size); + written += BOOL_Marshal(&data->phEnableNV, buffer, size); + written += UINT16_Marshal(&data->platformAlg, buffer, size); + written += TPM2B_DIGEST_Marshal(&data->platformPolicy, buffer, size); + written += TPM2B_AUTH_Marshal(&data->platformAuth, buffer, size); + written += PCR_SAVE_Marshal(&data->pcrSave, buffer, size); + written += PCR_AUTHVALUE_Marshal(&data->pcrAuthValues, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +STATE_CLEAR_DATA_Unmarshal(STATE_CLEAR_DATA *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + STATE_CLEAR_DATA_VERSION, + STATE_CLEAR_DATA_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&data->shEnable, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&data->ehEnable, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&data->phEnableNV, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&data->platformAlg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&data->platformPolicy, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&data->platformAuth, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = PCR_SAVE_Unmarshal(&data->pcrSave, buffer, size, &shadow.pcrAllocated); + } + if (rc == TPM_RC_SUCCESS) { + rc = PCR_AUTHVALUE_Unmarshal(&data->pcrAuthValues, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "STATE_CLEAR_DATA", "version 3 or later"); + /* future versions nest-append here */ + } +skip_future_versions: + + return rc; +} + +#define STATE_RESET_DATA_MAGIC 0x01102332 +#define STATE_RESET_DATA_VERSION 4 + +static TPM_RC +STATE_RESET_DATA_Unmarshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + BOOL needs_block; + UINT16 array_size; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + STATE_RESET_DATA_VERSION, + STATE_RESET_DATA_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_PROOF_Unmarshal(&data->nullProof, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&data->nullSeed.b, PRIMARY_SEED_SIZE, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->clearCount, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->objectContextID, buffer, size); + } + + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(data->contextArray)) { + TPMLIB_LogTPM2Error("STATE_RESET_DATA: Bad array size for contextArray; " + "expected %zu, got %u\n", + ARRAY_SIZE(data->contextArray), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + size_t i; + if (hdr.version <= 3) { + /* version <= 3 was writing an array of UINT8 */ + UINT8 element; + for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { + rc = UINT8_Unmarshal(&element, buffer, size); + data->contextArray[i] = element; + } + s_ContextSlotMask = 0xff; + } else { + /* version 4 and later an array of UINT16 */ + for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { + rc = UINT16_Unmarshal(&data->contextArray[i], buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&s_ContextSlotMask, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (s_ContextSlotMask != 0xffff && s_ContextSlotMask != 0x00ff) { + TPMLIB_LogTPM2Error("STATE_RESET_DATA: s_ContextSlotMask has bad value: 0x%04x\n", + s_ContextSlotMask); + rc = TPM_RC_BAD_PARAMETER; + } + } + } + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->contextCounter, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&data->commandAuditDigest, + buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->restartCount, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->pcrCounter, buffer, size); + } + +#if ALG_ECC + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_alg_ecc, needs_block, buffer, size, + "STATE_RESET_DATA", "commitCounter"); + } +#if ALG_ECC + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->commitCounter, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&data->commitNonce, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != sizeof(data->commitArray)) { + TPMLIB_LogTPM2Error("STATE_RESET_DATA: Bad array size for commitArray; " + "expected %zu, got %u\n", + sizeof(data->commitArray), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal((BYTE *)&data->commitArray, array_size, + buffer, size); + } +#endif +skip_alg_ecc: + + /* default values before conditional block */ + data->nullSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, + "STATE_RESET_DATA", "version 3 or later"); + if (rc == TPM_RC_SUCCESS) { + rc = SEED_COMPAT_LEVEL_Unmarshal(&gr.nullSeedCompatLevel, + buffer, size, "nullSeed"); + } + + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "STATE_RESET_DATA", "version 4 or later"); + } + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} + +static UINT16 +STATE_RESET_DATA_Marshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + BOOL has_block; + UINT16 array_size; + BLOCK_SKIP_INIT; + size_t i; + + written = NV_HEADER_Marshal(buffer, size, + STATE_RESET_DATA_VERSION, + STATE_RESET_DATA_MAGIC, 4); + written += TPM2B_PROOF_Marshal(&data->nullProof, buffer, size); + written += TPM2B_Marshal(&data->nullSeed.b, sizeof(data->nullSeed.t.buffer), buffer, size); + written += UINT32_Marshal(&data->clearCount, buffer, size); + written += UINT64_Marshal(&data->objectContextID, buffer, size); + + array_size = ARRAY_SIZE(data->contextArray); + written += UINT16_Marshal(&array_size, buffer, size); + for (i = 0; i < array_size; i++) + written += UINT16_Marshal(&data->contextArray[i], buffer, size); + + if (s_ContextSlotMask != 0x00ff && s_ContextSlotMask != 0xffff) { + /* TPM wasn't initialized, so s_ContextSlotMask wasn't set */ + s_ContextSlotMask = 0xffff; + } + written += UINT16_Marshal(&s_ContextSlotMask, buffer, size); + + written += UINT64_Marshal(&data->contextCounter, buffer, size); + written += TPM2B_DIGEST_Marshal(&data->commandAuditDigest, + buffer, size); + written += UINT32_Marshal(&data->restartCount, buffer, size); + written += UINT32_Marshal(&data->pcrCounter, buffer, size); +#if ALG_ECC + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if ALG_ECC + written += UINT64_Marshal(&data->commitCounter, buffer, size); + written += TPM2B_AUTH_Marshal(&data->commitNonce, buffer, size); + + array_size = sizeof(data->commitArray); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->commitArray, array_size, + buffer, size); +#endif + BLOCK_SKIP_WRITE_POP(size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + written += SEED_COMPAT_LEVEL_Marshal(&data->nullSeedCompatLevel, + buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +#define BN_PRIME_T_MAGIC 0x2fe736ab +#define BN_PRIME_T_VERSION 2 +static UINT16 +bn_prime_t_Marshal(bn_prime_t *data, BYTE **buffer, INT32 *size) +{ + UINT16 written, numbytes; + size_t i, idx; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + BN_PRIME_T_VERSION, BN_PRIME_T_MAGIC, 1); + + /* we do not write 'allocated' */ + numbytes = data->size * sizeof(crypt_uword_t); + written += UINT16_Marshal(&numbytes, buffer, size); + + for (i = 0, idx = 0; + i < numbytes; + i += sizeof(crypt_uword_t), idx += 1) { +#if RADIX_BITS == 64 + written += UINT64_Marshal(&data->d[idx], buffer, size); +#elif RADIX_BITS == 32 + written += UINT32_Marshal(&data->d[idx], buffer, size); +#else +#error RADIX_BYTES it no defined +#endif + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +bn_prime_t_Unmarshal(bn_prime_t *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + size_t i, idx; + UINT16 numbytes = 0; + UINT32 word; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + BN_PRIME_T_VERSION, + BN_PRIME_T_MAGIC); + } + + data->allocated = ARRAY_SIZE(data->d); + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&numbytes, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + /* coverity: num_bytes is sanitized here! */ + data->size = (numbytes + sizeof(crypt_uword_t) - 1) / sizeof(crypt_word_t); + if (data->size > data->allocated) { + TPMLIB_LogTPM2Error("bn_prime_t: Require size larger %zu than " + "allocated %zu\n", + (size_t)data->size, (size_t)data->allocated); + rc = TPM_RC_SIZE; + data->size = 0; + } + } + + if (rc == TPM_RC_SUCCESS) { + for (i = 0, idx = 0; + i < numbytes && rc == TPM_RC_SUCCESS; + i += sizeof(UINT32), idx += 1) { + rc = UINT32_Unmarshal(&word, buffer, size); +#if RADIX_BITS == 64 + data->d[idx / 2] <<= 32; + data->d[idx / 2] |= word; +#elif RADIX_BITS == 32 + data->d[idx] = word; +#endif + } + } + +#if RADIX_BITS == 64 + if (rc == TPM_RC_SUCCESS) { + if (idx & 1) + data->d[idx / 2] <<= 32; + } +#endif + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "BN_PRIME_T", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} + +#define PRIVATE_EXPONENT_T_MAGIC 0x854eab2 +#define PRIVATE_EXPONENT_T_VERSION 2 +static UINT16 +privateExponent_t_Marshal(privateExponent_t *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + PRIVATE_EXPONENT_T_VERSION, + PRIVATE_EXPONENT_T_MAGIC, 1); +#if CRT_FORMAT_RSA == NO +#error Missing code +#else + written += bn_prime_t_Marshal(&data->Q, buffer, size); + written += bn_prime_t_Marshal(&data->dP, buffer, size); + written += bn_prime_t_Marshal(&data->dQ, buffer, size); + written += bn_prime_t_Marshal(&data->qInv, buffer, size); +#endif + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +privateExponent_t_Unmarshal(privateExponent_t *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + PRIVATE_EXPONENT_T_VERSION, + PRIVATE_EXPONENT_T_MAGIC); + } + +#if CRT_FORMAT_RSA == NO +#error Missing code +#else + if (rc == TPM_RC_SUCCESS) { + rc = bn_prime_t_Unmarshal(&data->Q, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = bn_prime_t_Unmarshal(&data->dP, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = bn_prime_t_Unmarshal(&data->dQ, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = bn_prime_t_Unmarshal(&data->qInv, buffer, size); + } +#endif + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "PRIVATE_EXPONENT_T", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} + +static UINT16 +HASH_STATE_TYPE_Marshal(HASH_STATE_TYPE *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + + written = UINT8_Marshal(data, buffer, size); + + return written; +} + +static UINT16 +HASH_STATE_TYPE_Unmarshal(HASH_STATE_TYPE *data, BYTE **buffer, INT32 *size) +{ + return UINT8_Unmarshal(data, buffer, size); +} + +static inline UINT16 +SHA_LONG_Marshal(SHA_LONG *data, BYTE **buffer, INT32 *size) +{ + return UINT32_Marshal(data, buffer, size); +} + +static inline UINT16 +SHA_LONG_Unmarshal(SHA_LONG *data, BYTE **buffer, INT32 *size) +{ + return UINT32_Unmarshal(data, buffer, size); +} + +static inline UINT16 +SHA_LONG64_Marshal(SHA_LONG64 *data, BYTE **buffer, INT32 *size) +{ + assert(sizeof(*data) == 8); + return UINT64_Marshal((UINT64 *)data, buffer, size); +} + +static inline UINT16 +SHA_LONG64_Unmarshal(SHA_LONG64 *data, BYTE **buffer, INT32 *size) +{ + assert(sizeof(*data) == 8); + return UINT64_Unmarshal((UINT64 *)data, buffer, size); +} + +#if ALG_SHA1 + +#define HASH_STATE_SHA1_MAGIC 0x19d46f50 +#define HASH_STATE_SHA1_VERSION 2 + +static UINT16 +tpmHashStateSHA1_Marshal(tpmHashStateSHA1_t *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + UINT16 array_size; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + HASH_STATE_SHA1_VERSION, + HASH_STATE_SHA1_MAGIC,1); + written += SHA_LONG_Marshal(&data->h0, buffer, size); + written += SHA_LONG_Marshal(&data->h1, buffer, size); + written += SHA_LONG_Marshal(&data->h2, buffer, size); + written += SHA_LONG_Marshal(&data->h3, buffer, size); + written += SHA_LONG_Marshal(&data->h4, buffer, size); + written += SHA_LONG_Marshal(&data->Nl, buffer, size); + written += SHA_LONG_Marshal(&data->Nh, buffer, size); + + /* data must be written as array */ + array_size = sizeof(data->data); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->data[0], array_size, + buffer, size); + + written += UINT32_Marshal(&data->num, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static UINT16 +tpmHashStateSHA1_Unmarshal(tpmHashStateSHA1_t *data, BYTE **buffer, INT32 *size) +{ + UINT16 rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + UINT16 array_size; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + HASH_STATE_SHA1_VERSION, + HASH_STATE_SHA1_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->h0, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->h1, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->h2, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->h3, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->h4, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->Nl, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->Nh, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != sizeof(data->data)) { + TPMLIB_LogTPM2Error("HASH_STATE_SHA1: Bad array size for data; " + "expected %zu, got %u\n", + sizeof(data->data), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal((BYTE *)&data->data[0], array_size, + buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->num, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "HASH_STATE_SHA1", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} +#endif + +#if ALG_SHA256 +#define HASH_STATE_SHA256_MAGIC 0x6ea059d0 +#define HASH_STATE_SHA256_VERSION 2 + +static UINT16 +tpmHashStateSHA256_Marshal(tpmHashStateSHA256_t *data, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + UINT16 array_size; + size_t i; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + HASH_STATE_SHA256_VERSION, + HASH_STATE_SHA256_MAGIC, 1); + + array_size = ARRAY_SIZE(data->h); + written += UINT16_Marshal(&array_size, buffer, size); + for (i = 0; i < array_size; i++) { + written += SHA_LONG_Marshal(&data->h[i], buffer, size); + } + written += SHA_LONG_Marshal(&data->Nl, buffer, size); + written += SHA_LONG_Marshal(&data->Nh, buffer, size); + + /* data must be written as array */ + array_size = sizeof(data->data); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal((BYTE *)&data->data[0], array_size, + buffer, size); + + written += UINT32_Marshal(&data->num, buffer, size); + written += UINT32_Marshal(&data->md_len, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static UINT16 +tpmHashStateSHA256_Unmarshal(tpmHashStateSHA256_t *data, BYTE **buffer, INT32 *size) +{ + UINT16 rc = TPM_RC_SUCCESS; + size_t i; + UINT16 array_size; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + HASH_STATE_SHA256_VERSION, + HASH_STATE_SHA256_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(data->h)) { + TPMLIB_LogTPM2Error("HASH_STATE_SHA256: Bad array size for h; " + "expected %zu, got %u\n", + ARRAY_SIZE(data->h), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + for (i = 0; rc == TPM_RC_SUCCESS && i < array_size; i++) { + rc = SHA_LONG_Unmarshal(&data->h[i], buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->Nl, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG_Unmarshal(&data->Nh, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != sizeof(data->data)) { + TPMLIB_LogTPM2Error("HASH_STATE_SHA256: Bad array size for data; " + "expected %zu, got %u\n", + sizeof(data->data), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal((BYTE *)&data->data[0], array_size, + buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->num, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->md_len, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "HASH_STATE_SHA256", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} +#endif + +#if ALG_SHA384 || ALG_SHA512 + +#define HASH_STATE_SHA384_MAGIC 0x14814b08 +#define HASH_STATE_SHA384_VERSION 2 + +#define HASH_STATE_SHA512_MAGIC 0x269e8ae0 +#define HASH_STATE_SHA512_VERSION 2 + +static UINT16 +tpmHashStateSHA512_Marshal(SHA512_CTX *data, BYTE **buffer, INT32 *size, + UINT16 hashAlg) +{ + UINT16 written = 0; + UINT16 array_size; + size_t i; + BLOCK_SKIP_INIT; + UINT16 version = HASH_STATE_SHA512_VERSION; + UINT32 magic = HASH_STATE_SHA512_MAGIC; + + if (hashAlg == ALG_SHA384_VALUE) { + version = HASH_STATE_SHA384_VERSION; + magic = HASH_STATE_SHA384_MAGIC; + } + + written = NV_HEADER_Marshal(buffer, size, + version, magic, 1); + + array_size = ARRAY_SIZE(data->h); + written += UINT16_Marshal(&array_size, buffer, size); + for (i = 0; i < array_size; i++) { + written += SHA_LONG64_Marshal(&data->h[i], buffer, size); + } + written += SHA_LONG64_Marshal(&data->Nl, buffer, size); + written += SHA_LONG64_Marshal(&data->Nh, buffer, size); + + array_size = sizeof(data->u.p); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal(&data->u.p[0], array_size, buffer, size); + + written += UINT32_Marshal(&data->num, buffer, size); + written += UINT32_Marshal(&data->md_len, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static UINT16 +tpmHashStateSHA512_Unmarshal(SHA512_CTX *data, BYTE **buffer, INT32 *size, + UINT16 hashAlg) +{ + UINT16 rc = TPM_RC_SUCCESS; + size_t i; + UINT16 array_size; + NV_HEADER hdr; + UINT16 version = HASH_STATE_SHA512_VERSION; + UINT32 magic = HASH_STATE_SHA512_MAGIC; + + if (hashAlg == ALG_SHA384_VALUE) { + version = HASH_STATE_SHA384_VERSION; + magic = HASH_STATE_SHA384_MAGIC; + } + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + version, magic); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(data->h)) { + TPMLIB_LogTPM2Error("HASH_STATE_SHA512: Bad array size for h; " + "expected %zu, got %u\n", + ARRAY_SIZE(data->h), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + for (i = 0; rc == TPM_RC_SUCCESS && i < array_size; i++) { + rc = SHA_LONG64_Unmarshal(&data->h[i], buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG64_Unmarshal(&data->Nl, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = SHA_LONG64_Unmarshal(&data->Nh, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != sizeof(data->u.p)) { + TPMLIB_LogTPM2Error("HASH_STATE_SHA512: Bad array size for u.p; " + "expected %zu, got %u\n", + sizeof(data->u.p), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal(&data->u.p[0], array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->num, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->md_len, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "HASH_STATE_SHA512", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} +#endif + +#define ANY_HASH_STATE_MAGIC 0x349d494b +#define ANY_HASH_STATE_VERSION 2 + +static UINT16 +ANY_HASH_STATE_Marshal(ANY_HASH_STATE *data, BYTE **buffer, INT32 *size, + UINT16 hashAlg) +{ + UINT16 written; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + ANY_HASH_STATE_VERSION, + ANY_HASH_STATE_MAGIC, 1); + + switch (hashAlg) { +#if ALG_SHA1 + case ALG_SHA1_VALUE: + written += tpmHashStateSHA1_Marshal(&data->Sha1, buffer, size); + break; +#endif +#if ALG_SHA256 + case ALG_SHA256_VALUE: + written += tpmHashStateSHA256_Marshal(&data->Sha256, buffer, size); + break; +#endif +#if ALG_SHA384 + case ALG_SHA384_VALUE: + written += tpmHashStateSHA512_Marshal(&data->Sha384, buffer, size, + ALG_SHA384_VALUE); + break; +#endif +#if ALG_SHA512 + case ALG_SHA512_VALUE: + written += tpmHashStateSHA512_Marshal(&data->Sha512, buffer, size, + ALG_SHA512_VALUE); + break; +#endif + default: + break; + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static UINT16 +ANY_HASH_STATE_Unmarshal(ANY_HASH_STATE *data, BYTE **buffer, INT32 *size, + UINT16 hashAlg) +{ + UINT16 rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + ANY_HASH_STATE_VERSION, + ANY_HASH_STATE_MAGIC); + } + + switch (hashAlg) { +#if ALG_SHA1 + case ALG_SHA1_VALUE: + rc = tpmHashStateSHA1_Unmarshal(&data->Sha1, buffer, size); + break; +#endif +#if ALG_SHA256 + case ALG_SHA256_VALUE: + rc = tpmHashStateSHA256_Unmarshal(&data->Sha256, buffer, size); + break; +#endif +#if ALG_SHA384 + case ALG_SHA384_VALUE: + rc = tpmHashStateSHA512_Unmarshal(&data->Sha384, buffer, size, + ALG_SHA384_VALUE); + break; +#endif +#if ALG_SHA512 + case ALG_SHA512_VALUE: + rc = tpmHashStateSHA512_Unmarshal(&data->Sha512, buffer, size, + ALG_SHA512_VALUE); + break; +#endif + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "ANY_HASH_STATE", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} + +#define HASH_STATE_MAGIC 0x562878a2 +#define HASH_STATE_VERSION 2 + +static UINT16 +HASH_STATE_Marshal(HASH_STATE *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + HASH_STATE_VERSION, + HASH_STATE_MAGIC, 1); + + written += HASH_STATE_TYPE_Marshal(&data->type, buffer, size); + written += TPM_ALG_ID_Marshal(&data->hashAlg, buffer, size); + /* def does not need to be written */ + written += ANY_HASH_STATE_Marshal(&data->state, buffer, size, data->hashAlg); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static UINT16 +HASH_STATE_Unmarshal(HASH_STATE *data, BYTE **buffer, INT32 *size) +{ + UINT16 rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + HASH_STATE_VERSION, HASH_STATE_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = HASH_STATE_TYPE_Unmarshal(&data->type, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&data->hashAlg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + data->def = CryptGetHashDef(data->hashAlg); + if (!data->def) { + TPMLIB_LogTPM2Error("Could not get hash function interface for " + "hashAlg 0x%02x\n", data->hashAlg); + rc = TPM_RC_BAD_PARAMETER; + } + } + if (rc == TPM_RC_SUCCESS) { + rc = ANY_HASH_STATE_Unmarshal(&data->state, buffer, size, data->hashAlg); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "HASH_STATE", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + return rc; +} + +static inline UINT16 +TPM2B_HASH_BLOCK_Marshal(TPM2B_HASH_BLOCK *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + + written = TPM2B_Marshal(&data->b, sizeof(data->t.buffer), buffer, size); + + return written; +} + +static inline UINT16 +TPM2B_HASH_BLOCK_Unmarshal(TPM2B_HASH_BLOCK *data, BYTE **buffer, INT32 *size) +{ + UINT16 rc; + + rc = TPM2B_Unmarshal(&data->b, sizeof(data->t.buffer), buffer, size); + + return rc; +} + +static UINT16 +HMAC_STATE_Marshal(HMAC_STATE *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + + written = HASH_STATE_Marshal(&data->hashState, buffer, size); + written += TPM2B_HASH_BLOCK_Marshal(&data->hmacKey, buffer, size); + + return written; +} + +static UINT16 +HMAC_STATE_Unmarshal(HMAC_STATE *data, BYTE **buffer, INT32 *size) +{ + UINT16 rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = HASH_STATE_Unmarshal(&data->hashState, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_HASH_BLOCK_Unmarshal(&data->hmacKey, buffer, size); + } + + return rc; +} + +#define HASH_OBJECT_MAGIC 0xb874fe38 +#define HASH_OBJECT_VERSION 3 + +static UINT16 +HASH_OBJECT_Marshal(HASH_OBJECT *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + size_t i; + UINT16 array_size; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + HASH_OBJECT_VERSION, HASH_OBJECT_MAGIC, 1); + written += TPMI_ALG_PUBLIC_Marshal(&data->type, buffer, size); + written += TPMI_ALG_HASH_Marshal(&data->nameAlg, buffer, size); + written += TPMA_OBJECT_Marshal(&data->objectAttributes, buffer, size); + written += TPM2B_AUTH_Marshal(&data->auth, buffer, size); + if (data->attributes.hashSeq == SET || + data->attributes.eventSeq == SET /* since v3 */) { + array_size = ARRAY_SIZE(data->state.hashState); + written += UINT16_Marshal(&array_size, buffer, size); + for (i = 0; i < array_size; i++) { + written += HASH_STATE_Marshal(&data->state.hashState[i], buffer, + size); + } + } else if (data->attributes.hmacSeq == SET) { + written += HMAC_STATE_Marshal(&data->state.hmacState, buffer, size); + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static UINT16 +HASH_OBJECT_Unmarshal(HASH_OBJECT *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + size_t i; + UINT16 array_size; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + HASH_OBJECT_VERSION, HASH_OBJECT_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_PUBLIC_Unmarshal(&data->type, buffer, size); + if (rc == TPM_RC_TYPE) + rc = TPM_RC_SUCCESS; + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&data->nameAlg, buffer, size, TRUE); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMA_OBJECT_Unmarshal(&data->objectAttributes, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&data->auth, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + /* hashSeq was always written correctly; eventSeq only appeared in v3 */ + if (data->attributes.hashSeq == SET || + (data->attributes.eventSeq == SET && hdr.version >= 3)) { + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (array_size != ARRAY_SIZE(data->state.hashState)) { + TPMLIB_LogTPM2Error("HASH_OBJECT: Bad array size for state.hashState; " + "expected %zu, got %u\n", + ARRAY_SIZE(data->state.hashState), + array_size); + rc = TPM_RC_SIZE; + } + } + for (i = 0; rc == TPM_RC_SUCCESS && i < array_size; i++) { + rc = HASH_STATE_Unmarshal(&data->state.hashState[i], + buffer, size); + } + } else if (data->attributes.hmacSeq == SET) { + rc = HMAC_STATE_Unmarshal(&data->state.hmacState, buffer, size); + } + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "HASH_OBJECT", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} + +/* Local version of TPMT_SENSITIVE_Marshal handling public keys that don't have much in TPM_SENSITIVE */ +static UINT16 +NV_TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_ALG_ID_Marshal(&source->sensitiveType, buffer, size); + written += TPM2B_AUTH_Marshal(&source->authValue, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->seedValue, buffer, size); + + switch (source->sensitiveType) { + case TPM_ALG_RSA: + case TPM_ALG_ECC: + case TPM_ALG_KEYEDHASH: + case TPM_ALG_SYMCIPHER: + written += TPMU_SENSITIVE_COMPOSITE_Marshal(&source->sensitive, buffer, size, source->sensitiveType); + break; + default: + /* we wrote these but they must have been 0 in this case */ + pAssert(source->authValue.t.size == 0); + pAssert(source->seedValue.t.size == 0); + pAssert(source->sensitiveType == TPM_ALG_ERROR) + /* public keys */ + } + return written; +} + +/* local version of TPM_SENSITIVE_Unmarshal handling public keys that don't have much in TPMT_SENSITVE */ +static TPM_RC +NV_TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + /* TPMI_ALG_PUBLIC_Unmarshal would test the sensitiveType; we don't want this */ + rc = TPM_ALG_ID_Unmarshal(&target->sensitiveType, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&target->authValue, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->seedValue, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (target->sensitiveType) { + case TPM_ALG_RSA: + case TPM_ALG_ECC: + case TPM_ALG_KEYEDHASH: + case TPM_ALG_SYMCIPHER: + rc = TPMU_SENSITIVE_COMPOSITE_Unmarshal(&target->sensitive, buffer, size, target->sensitiveType); + break; + default: + pAssert(target->authValue.t.size == 0); + pAssert(target->seedValue.t.size == 0); + pAssert(target->sensitiveType == TPM_ALG_ERROR) + /* nothing do to do */ + } + } + return rc; +} + +#define OBJECT_MAGIC 0x75be73af +#define OBJECT_VERSION 3 + +static UINT16 +OBJECT_Marshal(OBJECT *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + BOOL has_block; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + OBJECT_VERSION, OBJECT_MAGIC, 3); + + /* + * attributes are written in ANY_OBJECT_Marshal + */ + written += TPMT_PUBLIC_Marshal(&data->publicArea, buffer, size); + written += NV_TPMT_SENSITIVE_Marshal(&data->sensitive, buffer, size); + +#if ALG_RSA + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); +#if ALG_RSA + written += privateExponent_t_Marshal(&data->privateExponent, + buffer, size); +#endif + BLOCK_SKIP_WRITE_POP(size); + + written += TPM2B_NAME_Marshal(&data->qualifiedName, buffer, size); + written += TPM_HANDLE_Marshal(&data->evictHandle, buffer, size); + written += TPM2B_NAME_Marshal(&data->name, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + written += SEED_COMPAT_LEVEL_Marshal(&data->seedCompatLevel, + buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +OBJECT_Unmarshal(OBJECT *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + BOOL needs_block; + + /* + * attributes are read in ANY_OBJECT_Unmarshal + */ + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + OBJECT_VERSION, OBJECT_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_PUBLIC_Unmarshal(&data->publicArea, buffer, size, TRUE); + } + if (rc == TPM_RC_SUCCESS) { + rc = NV_TPMT_SENSITIVE_Unmarshal(&data->sensitive, buffer, size); + } + +#if ALG_RSA + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_alg_rsa, needs_block, buffer, size, + "OBJECT", "privateExponent"); + } +#if ALG_RSA + if (rc == TPM_RC_SUCCESS) { + rc = privateExponent_t_Unmarshal(&data->privateExponent, + buffer, size); + } +#endif +skip_alg_rsa: + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NAME_Unmarshal(&data->qualifiedName, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&data->evictHandle, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NAME_Unmarshal(&data->name, buffer, size); + } + + /* default values before conditional block */ + data->seedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, + "OBJECT", "version 3 or later"); + if (rc == TPM_RC_SUCCESS) { + rc = SEED_COMPAT_LEVEL_Unmarshal(&data->seedCompatLevel, + buffer, size, + "OBJECT seedCompatLevel"); + } + + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "OBJECT", "version 4 or later"); + } + /* future versions nest-append here */ + } + +skip_future_versions: + return rc; +} + +#define ANY_OBJECT_MAGIC 0xfe9a3974 +#define ANY_OBJECT_VERSION 2 + +UINT16 +ANY_OBJECT_Marshal(OBJECT *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + UINT32 *ptr = (UINT32 *)&data->attributes; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + ANY_OBJECT_VERSION, ANY_OBJECT_MAGIC, 1); + + written += UINT32_Marshal(ptr, buffer, size); + /* the slot must be occupied, otherwise the rest may not be initialized */ + if (data->attributes.occupied) { + if (ObjectIsSequence(data)) + written += HASH_OBJECT_Marshal((HASH_OBJECT *)data, buffer, size); + else + written += OBJECT_Marshal(data, buffer, size); + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +TPM_RC +ANY_OBJECT_Unmarshal(OBJECT *data, BYTE **buffer, INT32 *size, BOOL verbose) +{ + TPM_RC rc = TPM_RC_SUCCESS; + UINT32 *ptr = (UINT32 *)&data->attributes; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_UnmarshalVerbose(&hdr, buffer, size, + ANY_OBJECT_VERSION, ANY_OBJECT_MAGIC, + verbose); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(ptr, buffer, size); + } + + if (rc == TPM_RC_SUCCESS && data->attributes.occupied) { + if (ObjectIsSequence(data)) + rc = HASH_OBJECT_Unmarshal((HASH_OBJECT *)data, buffer, size); + else + rc = OBJECT_Unmarshal(data, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "ANY_OBJECT", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + return rc; +} + +static UINT16 +TPMT_SYM_DEF_Marshal(TPMT_SYM_DEF *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + + written = UINT16_Marshal(&data->algorithm, buffer, size); + written += TPMU_SYM_KEY_BITS_Marshal(&data->keyBits, buffer, size, data->algorithm); + written += TPMU_SYM_MODE_Marshal(&data->mode, buffer, size, data->algorithm); + + return written; +} + +#define SESSION_MAGIC 0x44be9f45 +#define SESSION_VERSION 2 + +static UINT16 +SESSION_Marshal(SESSION *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + UINT8 clocksize; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + SESSION_VERSION, SESSION_MAGIC, 1); + written += UINT32_Marshal((UINT32 *)&data->attributes, buffer, size); + written += UINT32_Marshal(&data->pcrCounter, buffer, size); + written += UINT64_Marshal(&data->startTime, buffer, size); + written += UINT64_Marshal(&data->timeout, buffer, size); + +#if CLOCK_STOPS + clocksize = sizeof(UINT64); + written += UINT8_Marshal(&clocksize, buffer, size); + written += UINT64_Marshal(&data->epoch, buffer, size); +#else + clocksize = sizeof(UINT32); + written += UINT8_Marshal(&clocksize, buffer, size); + written += UINT32_Marshal(&data->epoch, buffer, size); +#endif + + written += UINT32_Marshal(&data->commandCode, buffer, size); + written += UINT16_Marshal(&data->authHashAlg, buffer, size); + written += UINT8_Marshal(&data->commandLocality, buffer, size); + written += TPMT_SYM_DEF_Marshal(&data->symmetric, buffer, size); + written += TPM2B_AUTH_Marshal(&data->sessionKey, buffer, size); + written += TPM2B_NONCE_Marshal(&data->nonceTPM, buffer, size); + // TPM2B_NAME or TPM2B_DIGEST could be used for marshalling + written += TPM2B_NAME_Marshal(&data->u1.boundEntity, buffer, size); + written += TPM2B_DIGEST_Marshal(&data->u2.auditDigest, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +SESSION_Unmarshal(SESSION *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + UINT8 clocksize; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + SESSION_VERSION, SESSION_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)&data->attributes, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->pcrCounter, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->startTime, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->timeout, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(&clocksize, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { +#if CLOCK_STOPS + if (clocksize != sizeof(UINT64)) { + TPMLIB_LogTPM2Error("Unexpected clocksize for epoch; " + "Expected %zu, got %u\n", + sizeof(UINT64), clocksize); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->epoch, buffer, size); + } +#else + if (clocksize != sizeof(UINT32)) { + TPMLIB_LogTPM2Error("Unexpected clocksize for epoch; " + "Expected %zu, got %u\n", + sizeof(UINT32), clocksize); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->epoch, buffer, size); + } +#endif + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->commandCode, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&data->authHashAlg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(&data->commandLocality, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_SYM_DEF_Unmarshal(&data->symmetric, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&data->sessionKey, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NONCE_Unmarshal(&data->nonceTPM, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NAME_Unmarshal(&data->u1.boundEntity, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&data->u2.auditDigest, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "SESSION", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + return rc; +} + +#define SESSION_SLOT_MAGIC 0x3664aebc +#define SESSION_SLOT_VERSION 2 + +static UINT16 +SESSION_SLOT_Marshal(SESSION_SLOT *data, BYTE **buffer, INT32* size) +{ + UINT16 written; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + SESSION_SLOT_VERSION, + SESSION_SLOT_MAGIC, 1); + + written += BOOL_Marshal(&data->occupied, buffer, size); + if (!data->occupied) + return written; + + written += SESSION_Marshal(&data->session, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +SESSION_SLOT_Unmarshal(SESSION_SLOT *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + SESSION_SLOT_VERSION, SESSION_SLOT_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&data->occupied, buffer, size); + } + if (!data->occupied) + return rc; + + if (rc == TPM_RC_SUCCESS) { + rc = SESSION_Unmarshal(&data->session, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "SESSION_SLOT", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + return rc; +} + +#define VOLATILE_STATE_VERSION 4 +#define VOLATILE_STATE_MAGIC 0x45637889 + +UINT16 +VolatileState_Marshal(BYTE **buffer, INT32 *size) +{ + UINT16 written; + size_t i; + BOOL tpmEst; + UINT64 tmp_uint64; + UINT32 tmp_uint32; + BOOL has_block; + UINT16 array_size; + BLOCK_SKIP_INIT; + PERSISTENT_DATA pd; + + written = NV_HEADER_Marshal(buffer, size, + VOLATILE_STATE_VERSION, VOLATILE_STATE_MAGIC, + 1); + + /* skip g_rcIndex: these are 'constants' */ + written += TPM_HANDLE_Marshal(&g_exclusiveAuditSession, buffer, size); /* line 423 */ + /* g_time: may not be necessary */ + written += UINT64_Marshal(&g_time, buffer, size); /* line 426 */ + /* g_timeEpoch: skipped so far -- needs investigation */ + /* g_phEnable: since we won't call TPM2_Starup, we need to write it */ + written += BOOL_Marshal(&g_phEnable, buffer, size); /* line 439 */ + /* g_pcrReconfig: must write */ + written += BOOL_Marshal(&g_pcrReConfig, buffer, size); /* line 443 */ + /* g_DRTMHandle: must write */ + written += TPM_HANDLE_Marshal(&g_DRTMHandle, buffer, size); /* line 448 */ + /* g_DrtmPreStartup: must write */ + written += BOOL_Marshal(&g_DrtmPreStartup, buffer, size); /* line 453 */ + /* g_StartupLocality3: must write */ + written += BOOL_Marshal(&g_StartupLocality3, buffer, size); /* line 458 */ + +#if USE_DA_USED + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if USE_DA_USED + /* g_daUsed: must write */ + written += BOOL_Marshal(&g_daUsed, buffer, size); /* line 484 */ +#endif + BLOCK_SKIP_WRITE_POP(size); + + /* g_updateNV: can skip since it seems to only be valid during execution of a command*/ + /* g_powerWasLost: must write */ + written += BOOL_Marshal(&g_powerWasLost, buffer, size); /* line 504 */ + /* g_clearOrderly: can skip since it seems to only be valid during execution of a command */ + /* g_prevOrderlyState: must write */ + written += UINT16_Marshal(&g_prevOrderlyState, buffer, size); /* line 516 */ + /* g_nvOk: must write */ + written += BOOL_Marshal(&g_nvOk, buffer, size); /* line 522 */ + /* g_NvStatus: can skip since it seems to only be valid during execution of a command */ + +#if 0 /* does not exist */ + written += TPM2B_AUTH_Marshal(&g_platformUniqueAuthorities, buffer, size); /* line 535 */ +#endif + written += TPM2B_AUTH_Marshal(&g_platformUniqueDetails, buffer, size); /* line 536 */ + + /* gp (persistent_data): skip; we assume its latest states in the persistent data file */ + + /* we store the next 3 because they may not have been written to NVRAM */ + written += ORDERLY_DATA_Marshal(&go, buffer, size); /* line 707 */ + written += STATE_CLEAR_DATA_Marshal(&gc, buffer, size); /* line 738 */ + written += STATE_RESET_DATA_Marshal(&gr, buffer, size); /* line 826 */ + + /* g_manufactured: must write */ + written += BOOL_Marshal(&g_manufactured, buffer, size); /* line 928 */ + /* g_initialized: must write */ + written += BOOL_Marshal(&g_initialized, buffer, size); /* line 932 */ + +#if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C + /* + * The session related variables may only be valid during the execution + * of a single command; safer to store + */ + array_size = ARRAY_SIZE(s_sessionHandles); + written += UINT16_Marshal(&array_size, buffer, size); + + for (i = 0; i < array_size; i++) { + written += TPM_HANDLE_Marshal(&s_sessionHandles[i], buffer, size); + written += TPMA_SESSION_Marshal(&s_attributes[i], buffer, size); + written += TPM_HANDLE_Marshal(&s_associatedHandles[i], buffer, size); + written += TPM2B_NONCE_Marshal(&s_nonceCaller[i], buffer, size); + written += TPM2B_AUTH_Marshal(&s_inputAuthValues[i], buffer, size); + /* s_usedSessions: cannot serialize this since it is a pointer; also, isn't used */ + } + written += TPM_HANDLE_Marshal(&s_encryptSessionIndex, buffer, size); + written += TPM_HANDLE_Marshal(&s_decryptSessionIndex, buffer, size); + written += TPM_HANDLE_Marshal(&s_auditSessionIndex, buffer, size); + +#if CC_GetCommandAuditDigest + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if CC_GetCommandAuditDigest + /* s_cpHashForCommandAudit: seems not used; better to write it */ + written += TPM2B_DIGEST_Marshal(&s_cpHashForCommandAudit, buffer, size); +#endif + BLOCK_SKIP_WRITE_POP(size); + + /* s_DAPendingOnNV: needs investigation ... */ + written += BOOL_Marshal(&s_DAPendingOnNV, buffer, size); +#endif // SESSION_PROCESS_C + BLOCK_SKIP_WRITE_POP(size); + +#if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C + +#if !ACCUMULATE_SELF_HEAL_TIMER + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if !ACCUMULATE_SELF_HEAL_TIMER + written += UINT64_Marshal(&s_selfHealTimer, buffer, size); /* line 975 */ + written += UINT64_Marshal(&s_lockoutTimer, buffer, size); /* line 977 */ +#endif // ACCUMULATE_SELF_HEAL_TIMER + BLOCK_SKIP_WRITE_POP(size); +#endif // DA_C + BLOCK_SKIP_WRITE_POP(size); + +#if defined NV_C || defined GLOBAL_C + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + /* s_evictNvEnd set in NvInitStatic called by NvPowerOn in case g_powerWasLost + * Unless we set g_powerWasLost=TRUE and call NvPowerOn, we have to include it. + */ +#if defined NV_C || defined GLOBAL_C + written += UINT32_Marshal(&s_evictNvEnd, buffer, size); /* line 984 */ + /* s_indexOrderlyRam read from NVRAM in NvEntityStartup and written to it + * in NvUpdateIndexOrderlyData called by TPM2_Shutdown and initialized + * in NvManufacture -- since we don't call TPM2_Shutdown we serialize it here + */ + array_size = sizeof(s_indexOrderlyRam); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal(s_indexOrderlyRam, array_size, buffer, size); + + written += UINT64_Marshal(&s_maxCounter, buffer, size); /* line 992 */ + /* the following need not be written; NvIndexCacheInit initializes them partly + * and NvIndexCacheInit() is called during ExecuteCommand() + * - s_cachedNvIndex + * - s_cachedNvRef + * - s_cachedNvRamRef + */ +#endif + BLOCK_SKIP_WRITE_POP(size); + +#if defined OBJECT_C || defined GLOBAL_C + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if defined OBJECT_C || defined GLOBAL_C + /* used in many places; it doesn't look like TPM2_Shutdown writes this into + * persistent memory, so what is lost upon TPM2_Shutdown? + */ + array_size = ARRAY_SIZE(s_objects); + written += UINT16_Marshal(&array_size, buffer, size); + + for (i = 0; i < array_size; i++) { + written += ANY_OBJECT_Marshal(&s_objects[i], buffer, size); + } +#endif + BLOCK_SKIP_WRITE_POP(size); + +#if defined PCR_C || defined GLOBAL_C + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if defined PCR_C || defined GLOBAL_C + /* s_pcrs: Marshal *all* PCRs, even those for which stateSave bit is not set */ + array_size = ARRAY_SIZE(s_pcrs); + written += UINT16_Marshal(&array_size, buffer, size); + + for (i = 0; i < array_size; i++) { + written += PCR_Marshal(&s_pcrs[i], buffer, size); + } +#endif + BLOCK_SKIP_WRITE_POP(size); + +#if defined SESSION_C || defined GLOBAL_C + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if defined SESSION_C || defined GLOBAL_C + /* s_sessions: */ + array_size = ARRAY_SIZE(s_sessions); + written += UINT16_Marshal(&array_size, buffer, size); + + for (i = 0; i < array_size; i++) { + written += SESSION_SLOT_Marshal(&s_sessions[i], buffer, size); + } + /* s_oldestSavedSession: */ + written += UINT32_Marshal(&s_oldestSavedSession, buffer, size); + /* s_freeSessionSlots: */ + written += UINT32_Marshal((UINT32 *)&s_freeSessionSlots, buffer, size); +#endif + BLOCK_SKIP_WRITE_POP(size); + +#if defined IO_BUFFER_C || defined GLOBAL_C + /* s_actionInputBuffer: skip; only used during a single command */ + /* s_actionOutputBuffer: skip; only used during a single command */ +#endif + written += BOOL_Marshal(&g_inFailureMode, buffer, size); /* line 1078 */ + + /* TPM established bit */ + tpmEst = _rpc__Signal_GetTPMEstablished(); + written += BOOL_Marshal(&tpmEst, buffer, size); + +#if defined TPM_FAIL_C || defined GLOBAL_C || 1 + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if defined TPM_FAIL_C || defined GLOBAL_C || 1 + written += UINT32_Marshal(&s_failFunction, buffer, size); + written += UINT32_Marshal(&s_failLine, buffer, size); + written += UINT32_Marshal(&s_failCode, buffer, size); +#endif // TPM_FAIL_C + BLOCK_SKIP_WRITE_POP(size); + +#ifndef HARDWARE_CLOCK + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#ifndef HARDWARE_CLOCK + tmp_uint64 = s_realTimePrevious; + written += UINT64_Marshal(&tmp_uint64, buffer, size); + tmp_uint64 = s_tpmTime; + written += UINT64_Marshal(&tmp_uint64, buffer, size); +#endif + BLOCK_SKIP_WRITE_POP(size); + + written += BOOL_Marshal(&s_timerReset, buffer, size); + written += BOOL_Marshal(&s_timerStopped, buffer, size); + written += UINT32_Marshal(&s_adjustRate, buffer, size); + + tmp_uint64 = ClockGetTime(CLOCK_REALTIME); + written += UINT64_Marshal(&tmp_uint64, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* v3 */ + + /* tie the volatile state to the EP,SP, and PPSeed */ + NvRead(&pd, NV_PERSISTENT_DATA, sizeof(pd)); + written += TPM2B_Marshal(&pd.EPSeed.b, sizeof(pd.EPSeed.t.buffer), buffer, size); + written += TPM2B_Marshal(&pd.SPSeed.b, sizeof(pd.SPSeed.t.buffer), buffer, size); + written += TPM2B_Marshal(&pd.PPSeed.b, sizeof(pd.PPSeed.t.buffer), buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* v4 */ + + tmp_uint64 = ClockGetTime(CLOCK_MONOTONIC) + s_hostMonotonicAdjustTime; + written += UINT64_Marshal(&tmp_uint64, buffer, size); + + written += UINT64_Marshal(&s_suspendedElapsedTime, buffer, size); + written += UINT64_Marshal(&s_lastSystemTime, buffer, size); + written += UINT64_Marshal(&s_lastReportedTime, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* v5 */ + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); /* v5 */ + BLOCK_SKIP_WRITE_POP(size); /* v4 */ + BLOCK_SKIP_WRITE_POP(size); /* v3 */ + + /* keep marker at end */ + tmp_uint32 = VOLATILE_STATE_MAGIC; + written += UINT32_Marshal(&tmp_uint32, buffer, size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +VolatileState_TailV4_Unmarshal(BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + UINT64 tmp_uint64; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&tmp_uint64, buffer, size); + s_hostMonotonicAdjustTime = tmp_uint64 - ClockGetTime(CLOCK_MONOTONIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&s_suspendedElapsedTime, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&s_lastSystemTime, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&s_lastReportedTime, buffer, size); + } + + return rc; +} + +static TPM_RC +VolatileState_TailV3_Unmarshal(BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + PERSISTENT_DATA pd; + TPM2B_SEED seed = { + .b.size = 0, + }; + + NvRead(&pd, NV_PERSISTENT_DATA, sizeof(pd)); + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&seed.b, PRIMARY_SEED_SIZE, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (seed.b.size > PRIMARY_SEED_SIZE) /* coverity */ + rc = TPM_RC_SIZE; + } + if (rc == TPM_RC_SUCCESS) { + if (TPM2B_Cmp(&seed.b, &pd.EPSeed.b)) { + TPMLIB_LogTPM2Error("%s: EPSeed does not match\n", + __func__); + rc = TPM_RC_VALUE; + } + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&seed.b, PRIMARY_SEED_SIZE, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (seed.b.size > PRIMARY_SEED_SIZE) /* coverity */ + rc = TPM_RC_SIZE; + } + if (rc == TPM_RC_SUCCESS) { + if (TPM2B_Cmp(&seed.b, &pd.SPSeed.b)) { + TPMLIB_LogTPM2Error("%s: SPSeed does not match\n", + __func__); + rc = TPM_RC_VALUE; + } + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&seed.b, PRIMARY_SEED_SIZE, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (seed.b.size > PRIMARY_SEED_SIZE) /* coverity */ + rc = TPM_RC_SIZE; + } + if (rc == TPM_RC_SUCCESS) { + if (TPM2B_Cmp(&seed.b, &pd.PPSeed.b)) { + TPMLIB_LogTPM2Error("%s: PPSeed does not match\n", + __func__); + rc = TPM_RC_VALUE; + } + } + + return rc; +} + +TPM_RC +VolatileState_Unmarshal(BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + size_t i; + UINT64 tmp_uint64; + UINT32 tmp_uint32; + NV_HEADER hdr; + BOOL needs_block; + UINT16 array_size = 0; + UINT64 backthen; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + VOLATILE_STATE_VERSION, VOLATILE_STATE_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&g_exclusiveAuditSession, buffer, size); /* line 423 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&g_time, buffer, size); /* line 426 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_phEnable, buffer, size); /* line 439 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_pcrReConfig, buffer, size); /* line 443 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&g_DRTMHandle, buffer, size); /* line 448 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_DrtmPreStartup, buffer, size); /* line 453 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_StartupLocality3, buffer, size); /* line 458 */ + } + +#if USE_DA_USED + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_da, needs_block, buffer, size, + "Volatile state", "g_daUsed"); + } +#if USE_DA_USED + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_daUsed, buffer, size); /* line 484 */ + } +#endif +skip_da: + + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_powerWasLost, buffer, size); /* line 504 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&g_prevOrderlyState, buffer, size); /* line 516 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_nvOk, buffer, size); /* line 522 */ + } +#if 0 /* does not exist */ + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&g_platformUniqueAuthorities, buffer, size); /* line 535 */ + } +#endif + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&g_platformUniqueDetails, buffer, size); /* line 536 */ + } + + if (rc == TPM_RC_SUCCESS) { + rc = ORDERLY_DATA_Unmarshal(&go, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = STATE_CLEAR_DATA_Unmarshal(&gc, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = STATE_RESET_DATA_Unmarshal(&gr, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_manufactured, buffer, size); /* line 928 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_initialized, buffer, size); /* line 932 */ + } + +#if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_session_process, needs_block, buffer, size, + "Volatile state", "s_sessionHandles"); + } +#if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(s_sessionHandles)) { + TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_sessionHandles; " + "expected %zu, got %u\n", + ARRAY_SIZE(s_sessionHandles), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&s_sessionHandles[i], buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMA_SESSION_Unmarshal(&s_attributes[i], buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&s_associatedHandles[i], buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NONCE_Unmarshal(&s_nonceCaller[i], buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[i], buffer, size); + } + } + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&s_encryptSessionIndex, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&s_decryptSessionIndex, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&s_auditSessionIndex, buffer, size); + } + +#if CC_GetCommandAuditDigest + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_cc_getcommandauditdigest, needs_block, buffer, size, + "Volatile state", "s_cpHashForCommandAudit"); + } +#if CC_GetCommandAuditDigest + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&s_cpHashForCommandAudit, buffer, size); + } +#endif +skip_cc_getcommandauditdigest: + + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&s_DAPendingOnNV, buffer, size); + } +#endif /* SESSION_PROCESS_C */ +skip_session_process: + +#if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_accumulate_self_heal_timer_1, needs_block, buffer, size, + "Volatile state", "s_selfHealTimer.1"); + } + +#if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C +#if !ACCUMULATE_SELF_HEAL_TIMER + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_accumulate_self_heal_timer_2, needs_block, buffer, size, + "Volatile state", "s_selfHealTimer.2"); + } +#if !ACCUMULATE_SELF_HEAL_TIMER + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&s_selfHealTimer, buffer, size); /* line 975 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&s_lockoutTimer, buffer, size); /* line 977 */ + } +#endif +skip_accumulate_self_heal_timer_2: +#endif +skip_accumulate_self_heal_timer_1: + +#if defined NV_C || defined GLOBAL_C + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_nv, needs_block, buffer, size, + "Volatile state", "s_evictNvEnd"); + } + +#if defined NV_C || defined GLOBAL_C + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&s_evictNvEnd, buffer, size); /* line 984 */ + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(s_indexOrderlyRam)) { + TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_indexOrderlyRam; " + "expected %zu, got %u\n", + ARRAY_SIZE(s_indexOrderlyRam), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal(s_indexOrderlyRam, array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&s_maxCounter, buffer, size); /* line 992 */ + } + /* The following are not included: + * - s_cachedNvIndex + * - s_cachedNvRef + * - s_cachedNvRamRef + */ +#endif +skip_nv: + +#if defined OBJECT_C || defined GLOBAL_C + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_object, needs_block, buffer, size, + "Volatile state", "s_objects"); + } +#if defined OBJECT_C || defined GLOBAL_C + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(s_objects)) { + TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_objects; " + "expected %zu, got %u\n", + ARRAY_SIZE(s_objects), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { + rc = ANY_OBJECT_Unmarshal(&s_objects[i], buffer, size, true); + } +#endif +skip_object: + +#if defined PCR_C || defined GLOBAL_C + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_pcr, needs_block, buffer, size, + "Volatile state", "s_pcrs"); + } +#if defined PCR_C || defined GLOBAL_C + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(s_pcrs)) { + TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_pcrs; " + "expected %zu, got %u\n", + ARRAY_SIZE(s_pcrs), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { + rc = PCR_Unmarshal(&s_pcrs[i], buffer, size, &shadow.pcrAllocated); + } +#endif +skip_pcr: + +#if defined SESSION_C || defined GLOBAL_C + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_session, needs_block, buffer, size, + "Volatile state", "s_sessions"); + } +#if defined SESSION_C || defined GLOBAL_C + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS && + array_size != ARRAY_SIZE(s_sessions)) { + TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_sessions; " + "expected %zu, got %u\n", + ARRAY_SIZE(s_sessions), array_size); + rc = TPM_RC_BAD_PARAMETER; + } + /* s_sessions: */ + for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { + rc = SESSION_SLOT_Unmarshal(&s_sessions[i], buffer, size); + } + /* s_oldestSavedSession: */ + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&s_oldestSavedSession, buffer, size); + } + /* s_freeSessionSlots: */ + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)&s_freeSessionSlots, buffer, size); + } +#endif +skip_session: + + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&g_inFailureMode, buffer, size); /* line 1078 */ + } + + /* TPM established bit */ + if (rc == TPM_RC_SUCCESS) { + BOOL tpmEst; + rc = BOOL_Unmarshal(&tpmEst, buffer, size); + if (rc == TPM_RC_SUCCESS) { + if (tpmEst) + _rpc__Signal_SetTPMEstablished(); + else + _rpc__Signal_ResetTPMEstablished(); + } + } + +#if defined TPM_FAIL_C || defined GLOBAL_C || 1 + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_fail, needs_block, buffer, size, + "Volatile state", "s_failFunction"); + } + +#if defined TPM_FAIL_C || defined GLOBAL_C || 1 + /* appended in v2 */ + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&s_failFunction, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&s_failLine, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&s_failCode, buffer, size); + } +#endif +skip_fail: + +#ifndef HARDWARE_CLOCK + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_hardware_clock, needs_block, buffer, size, + "Volatile state", "s_realTimePrevious"); + } + +#ifndef HARDWARE_CLOCK + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&tmp_uint64, buffer, size); + s_realTimePrevious = tmp_uint64; + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&tmp_uint64, buffer, size); + s_tpmTime = tmp_uint64; + } +#endif +skip_hardware_clock: + + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&s_timerReset, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&s_timerStopped, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&s_adjustRate, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&backthen, buffer, size); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, + "Volatile State", "version 3 or later"); + if (rc == TPM_RC_SUCCESS) { + rc = VolatileState_TailV3_Unmarshal(buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 4, buffer, size, + "Volatile State", "version 4 or later"); + } + if (rc == TPM_RC_SUCCESS) { + rc = VolatileState_TailV4_Unmarshal(buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "Volatile State", "version 5 or later"); + } + /* future versions append here */ + } + +skip_future_versions: + + /* keep marker at end: */ + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&tmp_uint32, buffer, size); + if (rc == TPM_RC_SUCCESS) { + if (tmp_uint32 != VOLATILE_STATE_MAGIC) { + TPMLIB_LogTPM2Error("Invalid volatile state magic. " + "Expected 0x%08x, got 0x%08x\n", + VOLATILE_STATE_MAGIC, tmp_uint32); + rc = TPM_RC_BAD_TAG; + } + } + } + + if (rc == TPM_RC_SUCCESS) { + BOOL timesAreRealtime = hdr.version <= 3; + /* Before Rev148 (header version <= 3), times were reported in + realtime; we need to account for this now */ + ClockAdjustPostResume(backthen, timesAreRealtime); + } + return rc; +} + +/******************************************************************** + * The following is a list of compile-time constants that we verify against + * when state is presented to us. Comparison operators allow us to verify + * compile time constants' values against what we would accept when reading + * state. So for example a value of 1024 for a buffer size that is read can + * be compared against the value that this implementation has been compiled + * with. In some case a 'less or equal' [LE] (1024 < 2048) may be acceptable + * but that depends on the purpose of the compile time constant. The most + * conservative approach is to force that the unmarshalled values are equal + * [EQ] to the ones of this implementation. + * + * Meanings of comparison operators: + * EQ: The read state must match the state the implementation would produce + * The algorithm must have been enabled at the previously implementation + * and at the current implementation; or it must have been disabled at + * both + * + * LE: The read state may have been written by a version that did not + * implement an algorithm ('0') but the current implementation does + * implement it ('1'); this does NOT allow an implementation to accept + * the state anymore if the state was written by an implementation that + * implemented it ('1') but the current implementation does not im- + * plement it + * + * DONTCARE: Implementation that wrote the state can either have implemented + * an algorithm or not and implementation reading the state may + * also either implement it or not + */ +static const struct _entry { + UINT32 constant; + char *name; + enum CompareOp { EQ, LE, GE, DONTCARE } cmp; +} pa_compile_constants[] = { +#define COMPILE_CONSTANT(CONST, CMP) \ + .constant = CONST, .name = #CONST, .cmp = CMP + { COMPILE_CONSTANT(ALG_RSA, EQ) }, + { COMPILE_CONSTANT(ALG_SHA1, EQ) }, + { COMPILE_CONSTANT(ALG_HMAC, EQ) }, + { COMPILE_CONSTANT(ALG_TDES, LE) }, + { COMPILE_CONSTANT(ALG_AES, EQ) }, + { COMPILE_CONSTANT(ALG_MGF1, EQ) }, + { COMPILE_CONSTANT(ALG_XOR, EQ) }, + { COMPILE_CONSTANT(ALG_KEYEDHASH, EQ) }, + { COMPILE_CONSTANT(ALG_SHA256, EQ) }, + { COMPILE_CONSTANT(ALG_SHA384, EQ) }, + { COMPILE_CONSTANT(ALG_SHA512, EQ) }, + { COMPILE_CONSTANT(ALG_SM3_256, EQ) }, + { COMPILE_CONSTANT(ALG_SM4, EQ) }, + { COMPILE_CONSTANT(ALG_RSASSA, EQ) }, + { COMPILE_CONSTANT(ALG_RSAES, EQ) }, + { COMPILE_CONSTANT(ALG_RSAPSS, EQ) }, + { COMPILE_CONSTANT(ALG_OAEP, EQ) }, + { COMPILE_CONSTANT(ALG_ECC, EQ) }, + { COMPILE_CONSTANT(ALG_ECDH, EQ) }, + { COMPILE_CONSTANT(ALG_ECDSA, EQ) }, + { COMPILE_CONSTANT(ALG_ECDAA, EQ) }, + { COMPILE_CONSTANT(ALG_SM2, LE) }, + { COMPILE_CONSTANT(ALG_ECSCHNORR, EQ) }, + { COMPILE_CONSTANT(ALG_ECMQV, LE) }, + { COMPILE_CONSTANT(ALG_SYMCIPHER, EQ) }, + { COMPILE_CONSTANT(ALG_KDF1_SP800_56A, EQ) }, + { COMPILE_CONSTANT(ALG_KDF2, LE) }, + { COMPILE_CONSTANT(ALG_KDF1_SP800_108, EQ) }, + { COMPILE_CONSTANT(ALG_CMAC, LE) }, + { COMPILE_CONSTANT(ALG_CTR, EQ) }, + { COMPILE_CONSTANT(ALG_OFB, EQ) }, + { COMPILE_CONSTANT(ALG_CBC, EQ) }, + { COMPILE_CONSTANT(ALG_CFB, EQ) }, + { COMPILE_CONSTANT(ALG_ECB, EQ) }, + { COMPILE_CONSTANT(MAX_RSA_KEY_BITS, LE) }, /* old: 2048 */ + { COMPILE_CONSTANT(MAX_TDES_KEY_BITS, EQ) }, + { COMPILE_CONSTANT(MAX_AES_KEY_BITS, EQ) }, + { COMPILE_CONSTANT(128, EQ) }, /* MAX_SM4_KEY_BITS in older code was 128 also with SM4 not active */ + { COMPILE_CONSTANT(128, EQ) }, /* MAX_CAMELLIA_KEY_BITS in older code was 128 also with CAMELLIA not active */ + { COMPILE_CONSTANT(ECC_NIST_P192, LE) }, + { COMPILE_CONSTANT(ECC_NIST_P224, LE) }, + { COMPILE_CONSTANT(ECC_NIST_P256, LE) }, + { COMPILE_CONSTANT(ECC_NIST_P384, LE) }, + { COMPILE_CONSTANT(ECC_NIST_P521, LE) }, + { COMPILE_CONSTANT(ECC_BN_P256, LE) }, + { COMPILE_CONSTANT(ECC_BN_P638, LE) }, + { COMPILE_CONSTANT(ECC_SM2_P256, LE) }, + { COMPILE_CONSTANT(MAX_ECC_KEY_BITS, LE) }, + { COMPILE_CONSTANT(4, EQ) }, /* was: HASH_ALIGNMENT, which is not relevant */ + { COMPILE_CONSTANT(SYM_ALIGNMENT, EQ) }, + { COMPILE_CONSTANT(IMPLEMENTATION_PCR, EQ) }, + { COMPILE_CONSTANT(PLATFORM_PCR, EQ) }, + { COMPILE_CONSTANT(DRTM_PCR, EQ) }, + { COMPILE_CONSTANT(HCRTM_PCR, EQ) }, + { COMPILE_CONSTANT(NUM_LOCALITIES, EQ) }, + { COMPILE_CONSTANT(MAX_HANDLE_NUM, EQ) }, + { COMPILE_CONSTANT(MAX_ACTIVE_SESSIONS, EQ) }, + { COMPILE_CONSTANT(MAX_LOADED_SESSIONS, EQ) }, + { COMPILE_CONSTANT(MAX_SESSION_NUM, EQ) }, + { COMPILE_CONSTANT(MAX_LOADED_OBJECTS, EQ) }, + { COMPILE_CONSTANT(MIN_EVICT_OBJECTS, LE) }, + { COMPILE_CONSTANT(NUM_POLICY_PCR_GROUP, EQ) }, + { COMPILE_CONSTANT(NUM_AUTHVALUE_PCR_GROUP, EQ) }, + { COMPILE_CONSTANT(MAX_CONTEXT_SIZE, LE) }, /* old: 2474 */ + { COMPILE_CONSTANT(MAX_DIGEST_BUFFER, EQ) }, + { COMPILE_CONSTANT(MAX_NV_INDEX_SIZE, EQ) }, + { COMPILE_CONSTANT(MAX_NV_BUFFER_SIZE, EQ) }, + { COMPILE_CONSTANT(MAX_CAP_BUFFER, EQ) }, + { COMPILE_CONSTANT(NV_MEMORY_SIZE, LE) }, + { COMPILE_CONSTANT(MIN_COUNTER_INDICES, EQ) }, + { COMPILE_CONSTANT(NUM_STATIC_PCR, EQ) }, + { COMPILE_CONSTANT(MAX_ALG_LIST_SIZE, EQ) }, + { COMPILE_CONSTANT(PRIMARY_SEED_SIZE, EQ) }, +#if CONTEXT_ENCRYPT_ALGORITHM == AES +#define CONTEXT_ENCRYPT_ALGORITHM_ TPM_ALG_AES +#endif + { COMPILE_CONSTANT(CONTEXT_ENCRYPT_ALGORITHM_, EQ) }, + { COMPILE_CONSTANT(NV_CLOCK_UPDATE_INTERVAL, EQ) }, + { COMPILE_CONSTANT(NUM_POLICY_PCR, EQ) }, + { COMPILE_CONSTANT(ORDERLY_BITS, EQ) }, + { COMPILE_CONSTANT(MAX_SYM_DATA, EQ) }, + { COMPILE_CONSTANT(MAX_RNG_ENTROPY_SIZE, EQ) }, + { COMPILE_CONSTANT(RAM_INDEX_SPACE, EQ) }, + { COMPILE_CONSTANT(RSA_DEFAULT_PUBLIC_EXPONENT, EQ) }, + { COMPILE_CONSTANT(ENABLE_PCR_NO_INCREMENT, EQ) }, + { COMPILE_CONSTANT(CRT_FORMAT_RSA, EQ) }, + { COMPILE_CONSTANT(VENDOR_COMMAND_COUNT, EQ) }, + { COMPILE_CONSTANT(MAX_VENDOR_BUFFER_SIZE, EQ) }, + { COMPILE_CONSTANT(TPM_MAX_DERIVATION_BITS, EQ) }, + { COMPILE_CONSTANT(PROOF_SIZE, EQ) }, + { COMPILE_CONSTANT(HASH_COUNT, EQ) }, + + /* added for PA_COMPILE_CONSTANTS_VERSION == 3 */ + { COMPILE_CONSTANT(AES_128, LE) }, + { COMPILE_CONSTANT(AES_192, LE) }, + { COMPILE_CONSTANT(AES_256, LE) }, + { COMPILE_CONSTANT(SM4_128, LE) }, + { COMPILE_CONSTANT(ALG_CAMELLIA, LE) }, + { COMPILE_CONSTANT(CAMELLIA_128, LE) }, + { COMPILE_CONSTANT(CAMELLIA_192, LE) }, + { COMPILE_CONSTANT(CAMELLIA_256, LE) }, + { COMPILE_CONSTANT(ALG_SHA3_256, LE) }, + { COMPILE_CONSTANT(ALG_SHA3_384, LE) }, + { COMPILE_CONSTANT(ALG_SHA3_512, LE) }, + { COMPILE_CONSTANT(RSA_1024, LE) }, + { COMPILE_CONSTANT(RSA_2048, LE) }, + { COMPILE_CONSTANT(RSA_3072, LE) }, + { COMPILE_CONSTANT(RSA_4096, LE) }, + { COMPILE_CONSTANT(RSA_16384, LE) }, + { COMPILE_CONSTANT(RH_ACT_0, LE) }, + { COMPILE_CONSTANT(RH_ACT_1, LE) }, + { COMPILE_CONSTANT(RH_ACT_2, LE) }, + { COMPILE_CONSTANT(RH_ACT_3, LE) }, + { COMPILE_CONSTANT(RH_ACT_4, LE) }, + { COMPILE_CONSTANT(RH_ACT_5, LE) }, + { COMPILE_CONSTANT(RH_ACT_6, LE) }, + { COMPILE_CONSTANT(RH_ACT_7, LE) }, + { COMPILE_CONSTANT(RH_ACT_8, LE) }, + { COMPILE_CONSTANT(RH_ACT_9, LE) }, + { COMPILE_CONSTANT(RH_ACT_A, LE) }, + { COMPILE_CONSTANT(RH_ACT_B, LE) }, + { COMPILE_CONSTANT(RH_ACT_C, LE) }, + { COMPILE_CONSTANT(RH_ACT_D, LE) }, + { COMPILE_CONSTANT(RH_ACT_E, LE) }, + { COMPILE_CONSTANT(RH_ACT_F, LE) }, +}; + +static TPM_RC +UINT32_Unmarshal_CheckConstant(BYTE **buffer, INT32 *size, UINT32 constant, + const char *name, + enum CompareOp cmp, UINT16 struct_version) +{ + TPM_RC rc = TPM_RC_SUCCESS; + UINT32 value; + const char *op = NULL; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&value, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (cmp) { + case EQ: + if (!(constant == value)) + op = "="; + break; + case LE: + if (!(value <= constant)) + op = "<="; + break; + case GE: + if (!(value >= constant)) + op = ">="; + break; + case DONTCARE: + break; + } + if (op) { + TPMLIB_LogTPM2Error("Unexpected value for %s; " + "its value %d is not %s %d; " + "(version: %u)\n", + name, value, op, constant, + struct_version); + rc = TPM_RC_BAD_PARAMETER; + } + } + return rc; +} + +#define PA_COMPILE_CONSTANTS_MAGIC 0xc9ea6431 +#define PA_COMPILE_CONSTANTS_VERSION 3 + +/* Marshal compile-time constants related to persistent-all state */ +static UINT32 +PACompileConstants_Marshal(BYTE **buffer, INT32 *size) +{ + unsigned i; + UINT32 written, tmp_uint32; + UINT32 array_size = ARRAY_SIZE(pa_compile_constants); + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + PA_COMPILE_CONSTANTS_VERSION, + PA_COMPILE_CONSTANTS_MAGIC, 1); + + written += UINT32_Marshal(&array_size, buffer, size); + + for (i = 0; i < array_size; i++) { + tmp_uint32 = pa_compile_constants[i].constant; + written += UINT32_Marshal(&tmp_uint32, buffer, size); + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +PACompileConstants_Unmarshal(BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + unsigned i; + NV_HEADER hdr; + UINT32 array_size; + UINT32 exp_array_size = 0; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + PA_COMPILE_CONSTANTS_VERSION, + PA_COMPILE_CONSTANTS_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + switch (hdr.version) { + case 1: + case 2: + /* PA_COMPILE_CONSTANTS_VERSION 1 and 2 had 88 entries */ + exp_array_size = 88; + break; + case 3: + /* PA_COMPILE_CONSTANTS_VERSION 3 had 104 entries */ + exp_array_size = 120; + break; + default: + /* we don't suport anything newer - no downgrade */ + TPMLIB_LogTPM2Error("Unsupported PA_COMPILE_CONSTANTS version %d. " + "Supporting up to version %d.\n", + hdr.version, PA_COMPILE_CONSTANTS_VERSION); + rc = TPM_RC_BAD_VERSION; + } + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&array_size, buffer, size); + } + + if (rc == TPM_RC_SUCCESS && + array_size != exp_array_size) { + TPMLIB_LogTPM2Error("PA_COMPILE_CONSTANTS v%d has non-matching number of " + "elements; found %u, expected %u\n", + hdr.version, array_size, exp_array_size); + } + + for (i = 0; rc == TPM_RC_SUCCESS && i < exp_array_size; i++) + rc = UINT32_Unmarshal_CheckConstant( + buffer, size, pa_compile_constants[i].constant, + pa_compile_constants[i].name, + pa_compile_constants[i].cmp, hdr.version); + + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "PA_COMPILE_CONSTANTS", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + /* keep marker at end: */ + return rc; +} + +#define PERSISTENT_DATA_MAGIC 0x12213443 +#define PERSISTENT_DATA_VERSION 4 + +static UINT16 +PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size) +{ + UINT16 written; + UINT16 array_size; + UINT8 clocksize; + BOOL has_block; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + PERSISTENT_DATA_VERSION, + PERSISTENT_DATA_MAGIC, 4); + written += BOOL_Marshal(&data->disableClear, buffer, size); + written += TPM_ALG_ID_Marshal(&data->ownerAlg, buffer, size); + written += TPM_ALG_ID_Marshal(&data->endorsementAlg, buffer, size); + written += TPM_ALG_ID_Marshal(&data->lockoutAlg, buffer, size); + written += TPM2B_DIGEST_Marshal(&data->ownerPolicy, buffer, size); + written += TPM2B_DIGEST_Marshal(&data->endorsementPolicy, buffer, size); + written += TPM2B_DIGEST_Marshal(&data->lockoutPolicy, buffer, size); + written += TPM2B_AUTH_Marshal(&data->ownerAuth, buffer, size); + written += TPM2B_AUTH_Marshal(&data->endorsementAuth, buffer, size); + written += TPM2B_AUTH_Marshal(&data->lockoutAuth, buffer, size); + written += TPM2B_Marshal(&data->EPSeed.b, sizeof(data->EPSeed.t.buffer), buffer, size); + written += TPM2B_Marshal(&data->SPSeed.b, sizeof(data->SPSeed.t.buffer), buffer, size); + written += TPM2B_Marshal(&data->PPSeed.b, sizeof(data->PPSeed.t.buffer), buffer, size); + written += TPM2B_PROOF_Marshal(&data->phProof, buffer, size); + written += TPM2B_PROOF_Marshal(&data->shProof, buffer, size); + written += TPM2B_PROOF_Marshal(&data->ehProof, buffer, size); + written += UINT64_Marshal(&data->totalResetCount, buffer, size); + written += UINT32_Marshal(&data->resetCount, buffer, size); + +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + has_block = TRUE; +#else + has_block = FALSE; +#endif + written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); + +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + written += PCR_POLICY_Marshal(&data->pcrPolicies, buffer, size); +#endif + BLOCK_SKIP_WRITE_POP(size); + + written += TPML_PCR_SELECTION_Marshal(&data->pcrAllocated, buffer, size); + + /* ppList may grow */ + array_size = sizeof(data->ppList); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal(&data->ppList[0], array_size, buffer, size); + + written += UINT32_Marshal(&data->failedTries, buffer, size); + written += UINT32_Marshal(&data->maxTries, buffer, size); + written += UINT32_Marshal(&data->recoveryTime, buffer, size); + written += UINT32_Marshal(&data->lockoutRecovery, buffer, size); + written += BOOL_Marshal(&data->lockOutAuthEnabled, buffer, size); + written += UINT16_Marshal(&data->orderlyState, buffer, size); + + /* auditCommands may grow */ + array_size = sizeof(data->auditCommands); + written += UINT16_Marshal(&array_size, buffer, size); + written += Array_Marshal(&data->auditCommands[0], array_size, + buffer, size); + + written += TPM_ALG_ID_Marshal(&data->auditHashAlg, buffer, size); + written += UINT64_Marshal(&data->auditCounter, buffer, size); + written += UINT32_Marshal(&data->algorithmSet, buffer, size); + written += UINT32_Marshal(&data->firmwareV1, buffer, size); + written += UINT32_Marshal(&data->firmwareV2, buffer, size); +#if CLOCK_STOPS + clocksize = sizeof(UINT64); + written += UINT8_Marshal(&clocksize, buffer, size); + written += UINT64_Marshal(&data->timeEpoch, buffer, size); +#else + clocksize = sizeof(UINT32); + written += UINT8_Marshal(&clocksize, buffer, size); + written += UINT32_Marshal(&data->timeEpoch, buffer, size); +#endif + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + + /* there's a 'shadow' pcrAllocated as well */ + written += TPML_PCR_SELECTION_Marshal(&gp.pcrAllocated, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + written += SEED_COMPAT_LEVEL_Marshal(&data->EPSeedCompatLevel, + buffer, size); + written += SEED_COMPAT_LEVEL_Marshal(&data->SPSeedCompatLevel, + buffer, size); + written += SEED_COMPAT_LEVEL_Marshal(&data->PPSeedCompatLevel, + buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + BLOCK_SKIP_WRITE_POP(size); + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +PERSISTENT_DATA_Unmarshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + UINT16 array_size; + UINT8 clocksize; + BOOL needs_block; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + PERSISTENT_DATA_VERSION, + PERSISTENT_DATA_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&data->disableClear, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&data->ownerAlg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&data->endorsementAlg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&data->lockoutAlg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&data->ownerPolicy, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&data->endorsementPolicy, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&data->lockoutPolicy, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&data->ownerAuth, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&data->endorsementAuth, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&data->lockoutAuth, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&data->EPSeed.b, PRIMARY_SEED_SIZE, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&data->SPSeed.b, PRIMARY_SEED_SIZE, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&data->PPSeed.b, PRIMARY_SEED_SIZE, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_PROOF_Unmarshal(&data->phProof, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_PROOF_Unmarshal(&data->shProof, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_PROOF_Unmarshal(&data->ehProof, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->totalResetCount, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->resetCount, buffer, size); + } + +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + needs_block = TRUE; +#else + needs_block = FALSE; +#endif + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_num_policy_pcr_group, needs_block, buffer, size, + "PERSISTENT_DATA", "pcrPolicies"); + } +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + if (rc == TPM_RC_SUCCESS) { + rc = PCR_POLICY_Unmarshal(&data->pcrPolicies, buffer, size); + } +#endif +skip_num_policy_pcr_group: + + if (rc == TPM_RC_SUCCESS) { + rc = TPML_PCR_SELECTION_Unmarshal(&data->pcrAllocated, buffer, size); + + shadow.pcrAllocated = data->pcrAllocated; + shadow.pcrAllocatedIsNew = TRUE; + } + + /* ppList array may not be our size */ + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BYTE buf[array_size]; + rc = Array_Unmarshal(buf, array_size, buffer, size); + memcpy(data->ppList, buf, MIN(array_size, sizeof(data->ppList))); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->failedTries, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->maxTries, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->recoveryTime, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->lockoutRecovery, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = BOOL_Unmarshal(&data->lockOutAuthEnabled, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + /* TPM_SU_Unmarshal returns error if value is 0 */ + rc = UINT16_Unmarshal(&data->orderlyState, buffer, size); + } + + /* auditCommands array may not be our size */ + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&array_size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BYTE buf[array_size]; + rc = Array_Unmarshal(buf, array_size, buffer, size); + memcpy(data->auditCommands, buf, + MIN(array_size, sizeof(data->auditCommands))); + } + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&data->auditHashAlg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->auditCounter, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->algorithmSet, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->firmwareV1, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->firmwareV2, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(&clocksize, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { +#if CLOCK_STOPS + if (clocksize != sizeof(UINT64)) { + TPMLIB_LogTPM2Error("Unexpected clocksize for epoch; " + "Expected %u, got %u\n", + sizeof(UINT64), clocksize); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&data->timeEpoch, buffer, size); + } +#else + if (clocksize != sizeof(UINT32)) { + TPMLIB_LogTPM2Error("Unexpected clocksize for epoch; " + "Expected %zu, got %u\n", + sizeof(UINT32), clocksize); + rc = TPM_RC_BAD_PARAMETER; + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&data->timeEpoch, buffer, size); + } +#endif + } + + /* default values before conditional block */ + data->EPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; + data->SPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; + data->PPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, + "PERSISTENT_DATA", "version 3 or later"); + if (rc == TPM_RC_SUCCESS) { + rc = TPML_PCR_SELECTION_Unmarshal(&shadow.pcrAllocated, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 4, buffer, size, + "PERSISTENT_DATA", "version 4 or later"); + } + + if (rc == TPM_RC_SUCCESS) { + rc = SEED_COMPAT_LEVEL_Unmarshal(&data->EPSeedCompatLevel, + buffer, size, "EPSeed"); + } + if (rc == TPM_RC_SUCCESS) { + rc = SEED_COMPAT_LEVEL_Unmarshal(&data->SPSeedCompatLevel, + buffer, size, "SPSeed"); + } + if (rc == TPM_RC_SUCCESS) { + rc = SEED_COMPAT_LEVEL_Unmarshal(&data->PPSeedCompatLevel, + buffer, size, "PPSeed"); + } + + if (rc == TPM_RC_SUCCESS) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "PERSISTENT_DATA", "version 5 or later"); + } + /* future versions nest-append here */ + } + +skip_future_versions: + + if (rc != TPM_RC_SUCCESS) { + TPMLIB_LogTPM2Error("Failed to unmarshal PERSISTENT_DATA version %u\n", + hdr.version); + } + return rc; +} + +#define INDEX_ORDERLY_RAM_VERSION 2 +#define INDEX_ORDERLY_RAM_MAGIC 0x5346feab +static UINT32 +INDEX_ORDERLY_RAM_Marshal(void *array, size_t array_size, + BYTE **buffer, INT32 *size) +{ + UINT16 written; + NV_RAM_HEADER nrh, *nrhp; + UINT16 offset = 0; + UINT16 datasize; + UINT32 sourceside_size = array_size; + BLOCK_SKIP_INIT; + + written = NV_HEADER_Marshal(buffer, size, + INDEX_ORDERLY_RAM_VERSION, + INDEX_ORDERLY_RAM_MAGIC, 1); + + /* the size of the array we are using here */ + written += UINT32_Marshal(&sourceside_size, buffer, size); + + while (TRUE) { + nrhp = array + offset; + /* nrhp may point to misaligned address (ubsan), so use 'nrh'; first access only 'size' */ + memcpy(&nrh, nrhp, sizeof(nrh.size)); + + /* write the NVRAM header; + nrh->size holds the complete size including data; + nrh->size = 0 indicates the end */ + written += UINT32_Marshal(&nrh.size, buffer, size); + if (nrh.size == 0) + break; + /* copy the entire structure now; ubsan does not allow 'nrh = *nrhp' */ + memcpy(&nrh, nrhp, sizeof(nrh)); + + written += TPM_HANDLE_Marshal(&nrh.handle, buffer, size); + written += TPMA_NV_Marshal(&nrh.attributes, buffer, size); + + if (offset + nrh.size > array_size) { + TPMLIB_LogTPM2Error("INDEX_ORDERLY_RAM: nrh->size corrupted: %d\n", + nrh.size); + break; + } + /* write data size before array */ + if (nrh.size < sizeof(NV_RAM_HEADER)) { + TPMLIB_LogTPM2Error( + "INDEX_ORDERLY_RAM: nrh->size < sizeof(NV_RAM_HEADER): %d < %zu\n", + (int)nrh.size, sizeof(NV_RAM_HEADER)); + break; + } + datasize = nrh.size - sizeof(NV_RAM_HEADER); + written += UINT16_Marshal(&datasize, buffer, size); + if (datasize > 0) { + /* append the data */ + written += Array_Marshal(array + offset + sizeof(NV_RAM_HEADER), + datasize, buffer, size); + } + offset += nrh.size; + if (offset + sizeof(NV_RAM_HEADER) > array_size) { + /* nothing will fit anymore and there won't be a 0-sized + * terminating node (@1). + */ + break; + } + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +static TPM_RC +INDEX_ORDERLY_RAM_Unmarshal(void *array, size_t array_size, + BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + NV_RAM_HEADER nrh, *nrhp; + UINT16 offset = 0; + UINT16 datasize = 0; + UINT32 sourceside_size; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + INDEX_ORDERLY_RAM_VERSION, + INDEX_ORDERLY_RAM_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + /* get the size of the array on the source side + we can accommodate different sizes when rebuilding + but if it doesn't fit we'll error out and report the sizes */ + rc = UINT32_Unmarshal(&sourceside_size, buffer, size); + } + + while (rc == TPM_RC_SUCCESS) { + memset(&nrh, 0, sizeof(nrh)); /* coverity */ + /* nrhp may point to misaligned address (ubsan) + * we read 'into' nrh and copy to nrhp at end + */ + nrhp = array + offset; + + if (offset + sizeof(NV_RAM_HEADER) > sourceside_size) { + /* this case can occur with the previous entry filling up the + * space; in this case there will not be a 0-sized terminating + * node (see @1 above). We clear the rest of our space. + */ + if (array_size > offset) + memset(nrhp, 0, array_size - offset); + break; + } + + /* write the NVRAM header; + nrh->size holds the complete size including data; + nrh->size = 0 indicates the end */ + if (offset + sizeof(nrh.size) > array_size) { + offset += sizeof(nrh.size); + goto exit_size; + } + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&nrh.size, buffer, size); + if (rc == TPM_RC_SUCCESS && nrh.size == 0) { + memcpy(nrhp, &nrh, sizeof(nrh.size)); + break; + } + } + if (offset + sizeof(NV_RAM_HEADER) > array_size) { + offset += sizeof(NV_RAM_HEADER); + goto exit_size; + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&nrh.handle, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMA_NV_Unmarshal(&nrh.attributes, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&datasize, buffer, size); + } + if (offset + sizeof(NV_RAM_HEADER) + datasize > array_size) { + offset += sizeof(NV_RAM_HEADER) + datasize; + goto exit_size; + } + if (rc == TPM_RC_SUCCESS && datasize > 0) { + /* append the data */ + rc = Array_Unmarshal(array + offset + sizeof(NV_RAM_HEADER), + datasize, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + /* fix up size in case it is architecture-dependent */ + nrh.size = sizeof(nrh) + datasize; + offset += nrh.size; + /* copy header into possibly misaligned address in NVRAM */ + *nrhp = nrh; + } + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "INDEX_ORDERLY_RAM", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + return rc; + +exit_size: + TPMLIB_LogTPM2Error("INDEX_ORDERLY_RAM:" + "Insufficient space to write to offset %u;" + "Source had %u bytes, we have %zu bytes.\n", + offset, sourceside_size, array_size); + return TPM_RC_SIZE; +} + +static void +USER_NVRAM_Display(const char *msg) +{ + NV_REF entryRef = NV_USER_DYNAMIC; + UINT32 entrysize; + UINT64 offset = 0; + TPM_HANDLE handle; + UINT32 datasize; + NV_INDEX nvi; + OBJECT obj; + UINT64 maxCount; + + fprintf(stderr, "USER_NVRAM contents %s:\n", msg); + + while (TRUE) { + /* 1st: entrysize */ + NvRead(&entrysize, entryRef, sizeof(entrysize)); + fprintf(stderr, " offset: %5"PRIu32" entry size: %5u ", + (UINT32)(entryRef - NV_USER_DYNAMIC), entrysize); + offset = sizeof(UINT32); + + if (entrysize == 0) + break; + + /* 2nd: the handle -- it will tell us what datatype this is */ + NvRead(&handle, entryRef + offset, sizeof(handle)); + fprintf(stderr, "handle: 0x%08x ", handle); + + switch (HandleGetType(handle)) { + case TPM_HT_NV_INDEX: + fprintf(stderr, " (NV_INDEX) "); + /* NV_INDEX has the index again at offset 0! */ + NvReadNvIndexInfo(entryRef + offset, &nvi); + offset += sizeof(nvi); + datasize = entrysize - sizeof(UINT32) - sizeof(nvi); + fprintf(stderr, " datasize: %u\n",datasize); + break; + break; + case TPM_HT_PERSISTENT: + fprintf(stderr, " (PERSISTENT)"); + offset += sizeof(handle); + + NvRead(&obj, entryRef + offset, sizeof(obj)); + offset += sizeof(obj); + fprintf(stderr, " sizeof(obj): %zu\n", sizeof(obj)); + break; + default: + TPMLIB_LogTPM2Error("USER_NVRAM: Corrupted handle: %08x\n", handle); + } + /* advance to next entry */ + entryRef += entrysize; + } + fprintf(stderr, "\n"); + + NvRead(&maxCount, entryRef + offset, sizeof(maxCount)); + fprintf(stderr, " maxCount: %"PRIu64"\n", maxCount); + fprintf(stderr, "-----------------------------\n"); +} + +#define USER_NVRAM_VERSION 2 +#define USER_NVRAM_MAGIC 0x094f22c3 +static UINT32 +USER_NVRAM_Marshal(BYTE **buffer, INT32 *size) +{ + UINT32 written; + UINT32 entrysize; + UINT64 offset; + NV_REF entryRef = NV_USER_DYNAMIC; + NV_INDEX nvi; + UINT64 maxCount; + TPM_HANDLE handle; + OBJECT obj; + UINT32 datasize; + UINT64 sourceside_size = NV_USER_DYNAMIC_END - NV_USER_DYNAMIC; + BLOCK_SKIP_INIT; + + if (FALSE) + USER_NVRAM_Display("before marshalling"); + + written = NV_HEADER_Marshal(buffer, size, + USER_NVRAM_VERSION, USER_NVRAM_MAGIC, + 1); + + written += UINT64_Marshal(&sourceside_size, buffer, size); + + while (TRUE) { + /* 1st: entrysize */ + NvRead(&entrysize, entryRef, sizeof(entrysize)); + offset = sizeof(UINT32); + + /* entrysize is in native format now */ + written += UINT32_Marshal(&entrysize, buffer, size); + if (entrysize == 0) + break; + + /* 2nd: the handle -- it will tell us what datatype this is */ + NvRead(&handle, entryRef + offset, sizeof(handle)); + written += TPM_HANDLE_Marshal(&handle, buffer, size); + + switch (HandleGetType(handle)) { + case TPM_HT_NV_INDEX: + /* NV_INDEX has the index again at offset 0! */ + NvReadNvIndexInfo(entryRef + offset, &nvi); + offset += sizeof(nvi); + + written += NV_INDEX_Marshal(&nvi, buffer, size); + /* after that: bulk data */ + datasize = entrysize - sizeof(UINT32) - sizeof(nvi); + written += UINT32_Marshal(&datasize, buffer, size); + if (datasize > 0) { + BYTE buf[datasize]; + NvRead(buf, entryRef + offset, datasize); + written += Array_Marshal(buf, datasize, buffer, size); + } + break; + case TPM_HT_PERSISTENT: + offset += sizeof(handle); + + NvRead(&obj, entryRef + offset, sizeof(obj)); + offset += sizeof(obj); + written += ANY_OBJECT_Marshal(&obj, buffer, size); + break; + default: + TPMLIB_LogTPM2Error("USER_NVRAM: Corrupted handle: %08x\n", handle); + } + /* advance to next entry */ + entryRef += entrysize; + } + NvRead(&maxCount, entryRef + offset, sizeof(maxCount)); + written += UINT64_Marshal(&maxCount, buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +/* + * USER_NVRAM_Unmarshal: + * + * Unmarshal the byte stream directly into the NVRAM. Ensure that the + * the data fit into the user NVRAM before writing them. + * + * This function fails if there's not enough NVRAM to write the data into + * or if an unknown handle type was encountered. + */ +static TPM_RC +USER_NVRAM_Unmarshal(BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + NV_REF entryRef = NV_USER_DYNAMIC; + UINT32 entrysize; + UINT64 offset, o = 0; + NV_INDEX nvi; + UINT64 maxCount; + TPM_HANDLE handle; + OBJECT obj; + UINT32 datasize = 0; + UINT64 sourceside_size; + UINT64 array_size = NV_USER_DYNAMIC_END - NV_USER_DYNAMIC; + UINT64 entrysize_offset; + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + USER_NVRAM_VERSION, + USER_NVRAM_MAGIC); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&sourceside_size, buffer, size); + } + + while (rc == TPM_RC_SUCCESS) { + /* 1st: entrysize */ + if (o + sizeof(UINT32) > array_size) { + o += sizeof(UINT32); + goto exit_size; + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&entrysize, buffer, size); + + /* the entrysize also depends on the sizeof(nvi); we may have to + update it if sizeof(nvi) changed between versions */ + entrysize_offset = o; + NvWrite(entryRef + o, sizeof(entrysize), &entrysize); + offset = sizeof(UINT32); + if (entrysize == 0) + break; + } + /* 2nd: handle */ + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&handle, buffer, size); + } + + if (rc == TPM_RC_SUCCESS) { + switch (HandleGetType(handle)) { + case TPM_HT_NV_INDEX: + /* we need to read the handle again */ + if (rc == TPM_RC_SUCCESS && + o + offset + sizeof(nvi) > array_size) { + o += offset + sizeof(nvi); + goto exit_size; + } + if (rc == TPM_RC_SUCCESS) { + rc = NV_INDEX_Unmarshal(&nvi, buffer, size); + NvWrite(entryRef + o + offset, sizeof(nvi), &nvi); + offset += sizeof(nvi); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&datasize, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + /* datasize cannot exceed 64k + a few bytes */ + if (datasize > (0x10000 + 0x100)) { + TPMLIB_LogTPM2Error("datasize for NV_INDEX too " + "large: %u\n", datasize); + rc = TPM_RC_SIZE; + } + } + if (rc == TPM_RC_SUCCESS && + o + offset + datasize > array_size) { + o += offset + datasize; + goto exit_size; + } + if (rc == TPM_RC_SUCCESS && datasize > 0) { + BYTE buf[datasize]; + rc = Array_Unmarshal(buf, datasize, buffer, size); + NvWrite(entryRef + o + offset, datasize, buf); + offset += datasize; + + /* update the entry size; account for expanding nvi */ + entrysize = sizeof(UINT32) + sizeof(nvi) + datasize; + } + break; + case TPM_HT_PERSISTENT: + if (rc == TPM_RC_SUCCESS && + o + offset + sizeof(TPM_HANDLE) + sizeof(obj) > + array_size) { + o += offset + sizeof(TPM_HANDLE) + sizeof(obj); + goto exit_size; + } + + if (rc == TPM_RC_SUCCESS) { + NvWrite(entryRef + o + offset, sizeof(handle), &handle); + offset += sizeof(TPM_HANDLE); + + memset(&obj, 0, sizeof(obj)); + rc = ANY_OBJECT_Unmarshal(&obj, buffer, size, true); + NvWrite(entryRef + o + offset, sizeof(obj), &obj); + offset += sizeof(obj); + } + entrysize = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(obj); + break; + default: + TPMLIB_LogTPM2Error("USER_NVRAM: " + "Read handle 0x%08x of unknown type\n", + handle); + rc = TPM_RC_HANDLE; + } + + if (rc == TPM_RC_SUCCESS) { + NvWrite(entryRef + entrysize_offset, sizeof(entrysize), &entrysize); + } + } + if (rc == TPM_RC_SUCCESS) { + o += offset; + } + } + if (rc == TPM_RC_SUCCESS && + o + offset + sizeof(UINT64) > array_size) { + o += offset + sizeof(UINT64); + goto exit_size; + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&maxCount, buffer, size); + NvWrite(entryRef + o + offset, sizeof(maxCount), &maxCount); + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "USER_NVRAM", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + + if (FALSE) + USER_NVRAM_Display("after unmarshalling"); + + return rc; + +exit_size: + TPMLIB_LogTPM2Error("USER_NVRAM:" + "Insufficient space to write to offset %"PRIu64";" + "Source had %"PRIu64" bytes, we have %"PRIu64" " + "bytes.\n", + o, sourceside_size, array_size); + return TPM_RC_SIZE; +} + +/* + * Write out all persistent data by reading them from the NVRAM + * and then writing them out. + * + * - PERSISTENT_DATA (NV_PERSISTENT_DATA) + * - ORDERLY_DATA (NV_STATE_RESET_DATA) + * - STATE_RESET_DATA (NV_STATE_RESET_DATA) + * - STATE_CLEAR_DATA (NV_STATE_CLEAR_DATA) + * - indexOrderlyRAM (NV_INDEX_RAM_DATA) + * - NVRAM locations (NV_USER_DYNAMIC) + */ +#define PERSISTENT_ALL_VERSION 3 +#define PERSISTENT_ALL_MAGIC 0xab364723 +UINT32 +PERSISTENT_ALL_Marshal(BYTE **buffer, INT32 *size) +{ + UINT32 magic; + PERSISTENT_DATA pd; + ORDERLY_DATA od; + STATE_RESET_DATA srd; + STATE_CLEAR_DATA scd; + UINT32 written = 0; + BYTE indexOrderlyRam[sizeof(s_indexOrderlyRam)]; + BLOCK_SKIP_INIT; + BOOL writeSuState; + + NvRead(&pd, NV_PERSISTENT_DATA, sizeof(pd)); + NvRead(&od, NV_ORDERLY_DATA, sizeof(od)); + NvRead(&srd, NV_STATE_RESET_DATA, sizeof(srd)); + NvRead(&scd, NV_STATE_CLEAR_DATA, sizeof(scd)); + + /* indexOrderlyRam was never endianess-converted; so it's native */ + NvRead(indexOrderlyRam, NV_INDEX_RAM_DATA, sizeof(indexOrderlyRam)); + + written = NV_HEADER_Marshal(buffer, size, + PERSISTENT_ALL_VERSION, + PERSISTENT_ALL_MAGIC, 3); + written += PACompileConstants_Marshal(buffer, size); + written += PERSISTENT_DATA_Marshal(&pd, buffer, size); + written += ORDERLY_DATA_Marshal(&od, buffer, size); + writeSuState = (pd.orderlyState & TPM_SU_STATE_MASK) == TPM_SU_STATE; + /* starting with v3 we only write STATE_RESET and STATE_CLEAR if needed */ + if (writeSuState) { + written += STATE_RESET_DATA_Marshal(&srd, buffer, size); + written += STATE_CLEAR_DATA_Marshal(&scd, buffer, size); + } + written += INDEX_ORDERLY_RAM_Marshal(indexOrderlyRam, sizeof(indexOrderlyRam), + buffer, size); + written += USER_NVRAM_Marshal(buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + + BLOCK_SKIP_WRITE_POP(size); + + magic = PERSISTENT_ALL_MAGIC; + written += UINT32_Marshal(&magic, buffer, size); + + BLOCK_SKIP_WRITE_CHECK; + + return written; +} + +TPM_RC +PERSISTENT_ALL_Unmarshal(BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; + PERSISTENT_DATA pd; + ORDERLY_DATA od; + STATE_RESET_DATA srd; + STATE_CLEAR_DATA scd; + BYTE indexOrderlyRam[sizeof(s_indexOrderlyRam)]; + BOOL readSuState = false; + + memset(&pd, 0, sizeof(pd)); + memset(&od, 0, sizeof(od)); + memset(&srd, 0, sizeof(srd)); + memset(&scd, 0, sizeof(scd)); + memset(indexOrderlyRam, 0, sizeof(indexOrderlyRam)); + + if (rc == TPM_RC_SUCCESS) { + rc = NV_HEADER_Unmarshal(&hdr, buffer, size, + PERSISTENT_ALL_VERSION, + PERSISTENT_ALL_MAGIC); + } + + if (rc == TPM_RC_SUCCESS) { + rc = PACompileConstants_Unmarshal(buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = PERSISTENT_DATA_Unmarshal(&pd, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (hdr.version < 3) { + /* STATE_RESET and STATE_CLEAR were always written before version 3 */ + readSuState = true; + } else { + readSuState = (pd.orderlyState & TPM_SU_STATE_MASK) == TPM_SU_STATE; + } + rc = ORDERLY_DATA_Unmarshal(&od, buffer, size); + } + if (rc == TPM_RC_SUCCESS && readSuState) { + rc = STATE_RESET_DATA_Unmarshal(&srd, buffer, size); + } + if (rc == TPM_RC_SUCCESS && readSuState) { + rc = STATE_CLEAR_DATA_Unmarshal(&scd, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = INDEX_ORDERLY_RAM_Unmarshal(indexOrderlyRam, sizeof(indexOrderlyRam), + buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + /* this will write it into NVRAM right away */ + rc = USER_NVRAM_Unmarshal(buffer, size); + /* if rc == TPM_RC_SUCCESS, we know that there is enough + NVRAM to fit everything. */ + } + + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { + BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, + "USER NVRAM", "version 3 or later"); + /* future versions nest-append here */ + } + +skip_future_versions: + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal_Check(&hdr.magic, + PERSISTENT_ALL_MAGIC, buffer, size, + "PERSISTENT_ALL_MAGIC after USER_NVRAM"); + } + + if (rc == TPM_RC_SUCCESS) { + NvWrite(NV_PERSISTENT_DATA, sizeof(pd), &pd); + NvWrite(NV_ORDERLY_DATA, sizeof(od), &od); + NvWrite(NV_STATE_RESET_DATA, sizeof(srd), &srd); + NvWrite(NV_STATE_CLEAR_DATA, sizeof(scd), &scd); + NvWrite(NV_INDEX_RAM_DATA, sizeof(indexOrderlyRam), indexOrderlyRam); + } + + return rc; +} + +void +NVShadowRestore(void) +{ + if (shadow.pcrAllocatedIsNew) { + gp.pcrAllocated = shadow.pcrAllocated; + shadow.pcrAllocatedIsNew = FALSE; + } +} diff --git a/src/tpm2/NVMarshal.h b/src/tpm2/NVMarshal.h new file mode 100644 index 0000000..92a74fb --- /dev/null +++ b/src/tpm2/NVMarshal.h @@ -0,0 +1,61 @@ +/********************************************************************************/ +/* */ +/* Marshalling and unmarshalling of state */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef NVMARSHAL_H +#define NVMARSHAL_H + +#include + +#include "Tpm.h" +#include "TpmTypes.h" + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +UINT16 VolatileState_Marshal(BYTE **buffer, INT32 *size); +TPM_RC VolatileState_Unmarshal(BYTE **buffer, INT32 *size); + +UINT32 PERSISTENT_ALL_Marshal(BYTE **buffer, INT32 *size); +TPM_RC PERSISTENT_ALL_Unmarshal(BYTE **buffer, INT32 *size); + +void NVShadowRestore(void); + +UINT16 ANY_OBJECT_Marshal(OBJECT *data, BYTE **buffer, INT32 *size); +TPM_RC ANY_OBJECT_Unmarshal(OBJECT *data, BYTE **buffer, INT32 *size, BOOL verbose); + +#endif /* NVMARSHAL_H */ + diff --git a/src/tpm2/NVMem.c b/src/tpm2/NVMem.c new file mode 100644 index 0000000..3d27770 --- /dev/null +++ b/src/tpm2/NVMem.c @@ -0,0 +1,494 @@ +/********************************************************************************/ +/* */ +/* NV read and write access methods */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NVMem.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* C.6 NVMem.c */ +/* C.6.1. Description */ +/* This file contains the NV read and write access methods. This implementation uses RAM/file and + does not manage the RAM/file as NV blocks. The implementation may become more sophisticated over + time. */ +/* C.6.2. Includes and Local */ +#include +#include +#include +#include "Platform.h" +/* libtpms added begin */ +#include "NVMarshal.h" +#include "LibtpmsCallbacks.h" +#include +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" +/* libtpms added end */ + +#if FILE_BACKED_NV +# include +static FILE *s_NvFile = NULL; /* kgold made these static */ +static int s_NeedsManufacture = FALSE; +#endif + +/* C.6.2. Functions */ +/* C.6.2.1. NvFileOpen() */ + +#if FILE_BACKED_NV + +/* This function opens the file used to hold the NV image. + Return Type: int */ +/* Return Value Meaning */ +/* >=0 success */ +/* -1 error */ +static int +NvFileOpen( + const char *mode + ) +{ +#if defined(NV_FILE_PATH) +# define TO_STRING(s) TO_STRING_IMPL(s) +# define TO_STRING_IMPL(s) #s + const char* s_NvFilePath = TO_STRING(NV_FILE_PATH); +# undef TO_STRING +# undef TO_STRING_IMPL +#else + const char* s_NvFilePath = "NVChip"; +#endif + + // Try to open an exist NVChip file for read/write +# if defined _MSC_VER && 1 + if(fopen_s(&s_NvFile, s_NvFilePath, mode) != 0) + s_NvFile = NULL; +# else + s_NvFile = fopen(s_NvFilePath, mode); +# endif + return (s_NvFile == NULL) ? -1 : 0; +} + +/* C.6.2.2. NvFileCommit() */ +/* Write all of the contents of the NV image to a file. */ +/* Return Value Meaning */ +/* TRUE success */ +/* FALSE failure */ +static int +NvFileCommit( + void + ) +{ + int OK; + // If NV file is not available, return failure + if(s_NvFile == NULL) + return 1; + // Write RAM data to NV + fseek(s_NvFile, 0, SEEK_SET); + OK = (NV_MEMORY_SIZE == fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NvFile)); + OK = OK && (0 == fflush(s_NvFile)); + assert(OK); + return OK; +} +/* C.6.2.3. NvFileSize() */ +/* This function gets the size of the NV file and puts the file pointer where desired using the seek + method values. SEEK_SET => beginning; SEEK_CUR => current position and SEEK_END => to the end of + the file. */ +static long +NvFileSize( + int leaveAt + ) +{ + int irc; /* kgold, added return code checks */ + long fileSize; + long filePos; + // + assert(NULL != s_NvFile); + + filePos = ftell(s_NvFile); // libtpms changed begin + if (filePos < 0) + return -1; // libtpms changed end + + int fseek_result = fseek(s_NvFile, 0, SEEK_END); + NOT_REFERENCED(fseek_result); // Fix compiler warning for NDEBUG + assert(fseek_result == 0); + fileSize = ftell(s_NvFile); + assert(fileSize >= 0); + switch(leaveAt) + { + case SEEK_SET: + filePos = 0; + /* fall through */ + case SEEK_CUR: + irc = fseek(s_NvFile, filePos, SEEK_SET); + assert(irc == 0); + break; + case SEEK_END: + break; + default: + assert(FALSE); + break; + } + return fileSize; +} +#endif + +#if 0 /* libtpms added */ +/* C.6.2.4. _plat__NvErrors() */ +/* This function is used by the simulator to set the error flags in the NV subsystem to simulate an + error in the NV loading process */ +LIB_EXPORT void +_plat__NvErrors( + int recoverable, + int unrecoverable + ) +{ + s_NV_unrecoverable = unrecoverable; + s_NV_recoverable = recoverable; +} +#endif /* libtpms added */ +/* C.6.2.5. _plat__NVEnable() */ +/* Enable NV memory. */ +/* This version just pulls in data from a file. In a real TPM, with NV on chip, this function would + verify the integrity of the saved context. If the NV memory was not on chip but was in something + like RPMB, the NV state would be read in, decrypted and integrity checked. */ +/* The recovery from an integrity failure depends on where the error occurred. It it was in the + state that is discarded by TPM Reset, then the error is recoverable if the TPM is + reset. Otherwise, the TPM must go into failure mode. */ +/* Return Values Meaning */ +/* 0 if success */ +/* > 0 if receive recoverable error */ +/* <0 if unrecoverable error */ +LIB_EXPORT int +_plat__NVEnable( + void *platParameter // IN: platform specific parameters + ) +{ +#ifdef TPM_LIBTPMS_CALLBACKS + int ret; +#endif + // + // Start assuming everything is OK + s_NV_unrecoverable = FALSE; + s_NV_recoverable = FALSE; + +#ifdef TPM_LIBTPMS_CALLBACKS + ret = libtpms_plat__NVEnable(); + if (ret != LIBTPMS_CALLBACK_FALLTHROUGH) + return ret; +#endif /* TPM_LIBTPMS_CALLBACKS */ + return _plat__NVEnable_NVChipFile(platParameter); +} + +int +_plat__NVEnable_NVChipFile( + void *platParameter // IN: platform specific parameters + ) +{ + NOT_REFERENCED(platParameter); // to keep compiler quiet + // + // Start assuming everything is OK + s_NV_unrecoverable = FALSE; + s_NV_recoverable = FALSE; +#if FILE_BACKED_NV + if(s_NvFile != NULL) + return 0; + // Initialize all the bytes in the ram copy of the NV + _plat__NvMemoryClear(0, NV_MEMORY_SIZE); + + // If the file exists + if(NvFileOpen("r+b") >= 0) + { + long fileSize = NvFileSize(SEEK_SET); // get the file size and leave the + // file pointer at the start + // + // If the size is right, read the data + if(NV_MEMORY_SIZE == fileSize) + { + s_NeedsManufacture = + fread(s_NV, 1, NV_MEMORY_SIZE, s_NvFile) != NV_MEMORY_SIZE; + if (s_NeedsManufacture) { // libtpms changes start: set s_NV_unrecoverable on error + s_NV_unrecoverable = TRUE; + TPMLIB_LogTPM2Error("Could not read NVChip file: %s\n", + strerror(errno)); // libtpms changes end + } + } + else + { + NvFileCommit(); // for any other size, initialize it + s_NeedsManufacture = TRUE; + } + } + // If NVChip file does not exist, try to create it for read/write. + else if(NvFileOpen("w+b") >= 0) + { + NvFileCommit(); // Initialize the file + s_NeedsManufacture = TRUE; + } + assert(NULL != s_NvFile); // Just in case we are broken for some reason. +#endif + // NV contents have been initialized and the error checks have been performed. For + // simulation purposes, use the signaling interface to indicate if an error is + // to be simulated and the type of the error. + if(s_NV_unrecoverable) + return -1; + return s_NV_recoverable; +} + +/* C.6.2.6. _plat__NVDisable() */ +/* Disable NV memory */ +LIB_EXPORT void +_plat__NVDisable( + int delete // IN: If TRUE, delete the NV contents. + ) +{ +#ifdef TPM_LIBTPMS_CALLBACKS + int ret = libtpms_plat__NVDisable(); + if (ret != LIBTPMS_CALLBACK_FALLTHROUGH) + return; +#endif /* TPM_LIBTPMS_CALLBACKS */ + +#if FILE_BACKED_NV + if(NULL != s_NvFile) + { + fclose(s_NvFile); // Close NV file + // Alternative to deleting the file is to set its size to 0. This will not + // match the NV size so the TPM will need to be remanufactured. + if(delete) + { + // Open for writing at the start. Sets the size to zero. + if(NvFileOpen("w") >= 0) + { + fflush(s_NvFile); + fclose(s_NvFile); + } + } + } + s_NvFile = NULL; // Set file handle to NULL +#endif + return; +} + +/* C.6.2.7. _plat__IsNvAvailable() */ +/* Check if NV is available */ +/* Return Values Meaning */ +/* 0 NV is available */ +/* 1 NV is not available due to write failure */ +/* 2 NV is not available due to rate limit */ +LIB_EXPORT int +_plat__IsNvAvailable( + void + ) +{ + int retVal = 0; + +#ifdef TPM_LIBTPMS_CALLBACKS + if (libtpms_plat__IsNvAvailable() == 1) + return 0; +#endif /* TPM_LIBTPMS_CALLBACKS */ + + // NV is not available if the TPM is in failure mode + if(!s_NvIsAvailable) + retVal = 1; +#if FILE_BACKED_NV + else + retVal = (s_NvFile == NULL); +#endif + return retVal; +} + +/* C.6.2.8. _plat__NvMemoryRead() */ +/* Function: Read a chunk of NV memory */ +LIB_EXPORT void +_plat__NvMemoryRead( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // OUT: data buffer + ) +{ + assert(startOffset + size <= NV_MEMORY_SIZE); + memcpy(data, &s_NV[startOffset], size); // Copy data from RAM + return; +} +/* C.6.2.9. _plat__NvIsDifferent() */ +/* This function checks to see if the NV is different from the test value. This is so that NV will + not be written if it has not changed. */ +/* Return Values Meaning */ +/* TRUE(1) the NV location is different from the test value */ +/* FALSE(0) the NV location is the same as the test value */ +LIB_EXPORT int +_plat__NvIsDifferent( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // IN: data buffer + ) +{ + return (memcmp(&s_NV[startOffset], data, size) != 0); +} +/* C.6.2.10. _plat__NvMemoryWrite() */ +/* This function is used to update NV memory. The write is to a memory copy of NV. At the end of the + current command, any changes are written to the actual NV memory. */ +/* NOTE: A useful optimization would be for this code to compare the current contents of NV with the + local copy and note the blocks that have changed. Then only write those blocks when + _plat__NvCommit() is called. */ + +LIB_EXPORT int +_plat__NvMemoryWrite( + unsigned int startOffset, // IN: write start + unsigned int size, // IN: size of bytes to write + void *data // OUT: data buffer + ) +{ + if(startOffset + size <= NV_MEMORY_SIZE) + { + memcpy(&s_NV[startOffset], data, size); // Copy the data to the NV image + return TRUE; + } + return FALSE; +} +/* C.6.2.11. _plat__NvMemoryClear() */ +/* Function is used to set a range of NV memory bytes to an implementation-dependent value. The + value represents the erase state of the memory. */ +LIB_EXPORT void +_plat__NvMemoryClear( + unsigned int start, // IN: clear start + unsigned int size // IN: number of bytes to clear + ) +{ + assert(start + size <= NV_MEMORY_SIZE); + // In this implementation, assume that the erase value for NV is all 1s + memset(&s_NV[start], 0xff, size); +} +/* C.6.2.12. _plat__NvMemoryMove() */ +/* Function: Move a chunk of NV memory from source to destination This function should ensure that + if there overlap, the original data is copied before it is written */ +LIB_EXPORT void +_plat__NvMemoryMove( + unsigned int sourceOffset, // IN: source offset + unsigned int destOffset, // IN: destination offset + unsigned int size // IN: size of data being moved + ) +{ + assert(sourceOffset + size <= NV_MEMORY_SIZE); + assert(destOffset + size <= NV_MEMORY_SIZE); + memmove(&s_NV[destOffset], &s_NV[sourceOffset], size); // Move data in RAM +#if 1 /* libtpms added begin */ + if (destOffset > sourceOffset) + memset(&s_NV[sourceOffset], 0, destOffset-sourceOffset); + else + memset(&s_NV[destOffset+size], 0, sourceOffset-destOffset); +#endif /* libtpms added end */ + return; +} +/* C.6.2.13. _plat__NvCommit() */ +/* This function writes the local copy of NV to NV for permanent store. It will write NV_MEMORY_SIZE + bytes to NV. If a file is use, the entire file is written. */ +/* Return Values Meaning */ +/* 0 NV write success */ +/* non-0 NV write fail */ +LIB_EXPORT int +_plat__NvCommit( + void + ) +{ +#ifdef TPM_LIBTPMS_CALLBACKS + int ret = libtpms_plat__NvCommit(); + if (ret != LIBTPMS_CALLBACK_FALLTHROUGH) + return ret; +#endif /* TPM_LIBTPMS_CALLBACKS */ + +#if FILE_BACKED_NV + return (NvFileCommit() ? 0 : 1); +#else + return 0; +#endif +} + +/* C.6.2.14. _plat__SetNvAvail() */ +/* Set the current NV state to available. This function is for testing purpose only. It is not + part of the platform NV logic */ +LIB_EXPORT void +_plat__SetNvAvail( + void + ) +{ + s_NvIsAvailable = TRUE; + return; +} +#if 0 /* libtpms added */ +/* C.6.2.15. _plat__ClearNvAvail() */ +/* Set the current NV state to unavailable. This function is for testing purpose only. It is not + part of the platform NV logic */ +LIB_EXPORT void +_plat__ClearNvAvail( + void + ) +{ + s_NvIsAvailable = FALSE; + return; +} + +/* C.6.2.15. _plat__NVNeedsManufacture() */ +/* This function is used by the simulator to determine when the TPM's NV state needs to be manufactured. */ + +LIB_EXPORT int +_plat__NVNeedsManufacture( + void + ) +{ +#if FILE_BACKED_NV + return s_NeedsManufacture; +#else + return FALSE; +#endif +} +#endif /* libtpms added */ diff --git a/src/tpm2/NVReserved.c b/src/tpm2/NVReserved.c new file mode 100644 index 0000000..fa1053c --- /dev/null +++ b/src/tpm2/NVReserved.c @@ -0,0 +1,230 @@ +/********************************************************************************/ +/* */ +/* NV TPM persistent and state save data */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NVReserved.c 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +// 8.5 NVReserved.c +/* 8.5.2 Includes, Defines and Data Definitions */ +#define NV_C +#include "Tpm.h" +/* 8.5.3 Functions */ +/* 8.5.3.1 NvInitStatic() */ +/* This function initializes the static variables used in the NV subsystem. */ +static void +NvInitStatic( + void + ) +{ + // In some implementations, the end of NV is variable and is set at boot time. + // This value will be the same for each boot, but is not necessarily known + // at compile time. + s_evictNvEnd = (NV_REF)NV_MEMORY_SIZE; + return; +} +/* 8.5.3.2 NvCheckState() */ +/* Function to check the NV state by accessing the platform-specific function to get the NV state. + The result state is registered in s_NvIsAvailable that will be reported by NvIsAvailable(). */ +/* This function is called at the beginning of ExecuteCommand() before any potential check of + g_NvStatus. */ +void +NvCheckState( + void + ) +{ + int func_return; + // + func_return = _plat__IsNvAvailable(); + if(func_return == 0) + g_NvStatus = TPM_RC_SUCCESS; + else if(func_return == 1) + g_NvStatus = TPM_RC_NV_UNAVAILABLE; + else + g_NvStatus = TPM_RC_NV_RATE; + return; +} +/* 8.5.3.3 NvCommit */ +/* This is a wrapper for the platform function to commit pending NV writes. */ +BOOL +NvCommit( + void + ) +{ + return (_plat__NvCommit() == 0); +} +/* 8.5.3.4 NvPowerOn() */ +/* This function is called at _TPM_Init() to initialize the NV environment. */ +/* Return Values Meaning */ +/* TRUE all NV was initialized */ +/* FALSE the NV containing saved state had an error and TPM2_Startup(CLEAR) is required */ +BOOL +NvPowerOn( + void + ) +{ + int nvError = 0; + // If power was lost, need to re-establish the RAM data that is loaded from + // NV and initialize the static variables + if(g_powerWasLost) + { + if((nvError = _plat__NVEnable(0)) < 0) + LOG_FAILURE(FATAL_ERROR_NV_UNRECOVERABLE); /* libtpms changed */ + NvInitStatic(); + } + return nvError == 0; +} +/* 8.5.3.5 NvManufacture() */ +/* This function initializes the NV system at pre-install time. */ +/* This function should only be called in a manufacturing environment or in a simulation. */ +/* The layout of NV memory space is an implementation choice. */ +void +NvManufacture( + void + ) +{ +#if SIMULATION + // Simulate the NV memory being in the erased state. + _plat__NvMemoryClear(0, NV_MEMORY_SIZE); +#endif + // Initialize static variables + NvInitStatic(); + // Clear the RAM used for Orderly Index data + MemorySet(s_indexOrderlyRam, 0, RAM_INDEX_SPACE); + // Write that Orderly Index data to NV + NvUpdateIndexOrderlyData(); + // Initialize the next offset of the first entry in evict/index list to 0 (the + // end of list marker) and the initial s_maxCounterValue; + NvSetMaxCount(0); + // Put the end of list marker at the end of memory. This contains the MaxCount + // value as well as the end marker. + NvWriteNvListEnd(NV_USER_DYNAMIC); + return; +} +/* 8.5.3.6 NvRead() */ +/* This function is used to move reserved data from NV memory to RAM. */ +void +NvRead( + void *outBuffer, // OUT: buffer to receive data + UINT32 nvOffset, // IN: offset in NV of value + UINT32 size // IN: size of the value to read + ) +{ + // Input type should be valid + pAssert(nvOffset + size < NV_MEMORY_SIZE); + _plat__NvMemoryRead(nvOffset, size, outBuffer); + return; +} +/* 8.5.3.7 NvWrite() */ +/* This function is used to post reserved data for writing to NV memory. Before the TPM completes + the operation, the value will be written. */ +BOOL +NvWrite( + UINT32 nvOffset, // IN: location in NV to receive data + UINT32 size, // IN: size of the data to move + void *inBuffer // IN: location containing data to write + ) +{ + // Input type should be valid + if(nvOffset + size <= NV_MEMORY_SIZE) + { + // Set the flag that a NV write happened + SET_NV_UPDATE(UT_NV); + return _plat__NvMemoryWrite(nvOffset, size, inBuffer); + } + return FALSE; +} + +#if 0 // libtpms added being (for Coverity) +/* 8.5.3.8 NvUpdatePersistent() */ +/* This function is used to update a value in the PERSISTENT_DATA structure and commits the value to + NV. */ +void +NvUpdatePersistent( + UINT32 offset, // IN: location in PERMANENT_DATA to be updated + UINT32 size, // IN: size of the value + void *buffer // IN: the new data + ) +{ + pAssert(offset + size <= sizeof(gp)); + MemoryCopy(&gp + offset, buffer, size); + NvWrite(offset, size, buffer); +} +/* 8.5.3.9 NvClearPersistent() */ +/* This function is used to clear a persistent data entry and commit it to NV */ +void +NvClearPersistent( + UINT32 offset, // IN: the offset in the PERMANENT_DATA + // structure to be cleared (zeroed) + UINT32 size // IN: number of bytes to clear + ) +{ + pAssert(offset + size <= sizeof(gp)); + MemorySet((&gp) + offset, 0, size); + NvWrite(offset, size, (&gp) + offset); +} +#endif // libtpms added end +/* 8.5.3.10 NvReadPersistent() */ +/* This function reads persistent data to the RAM copy of the gp structure. */ +void +NvReadPersistent( + void + ) +{ + NvRead(&gp, NV_PERSISTENT_DATA, sizeof(gp)); + return; +} diff --git a/src/tpm2/NVReserved_fp.h b/src/tpm2/NVReserved_fp.h new file mode 100644 index 0000000..16bfb20 --- /dev/null +++ b/src/tpm2/NVReserved_fp.h @@ -0,0 +1,113 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NVReserved_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef NVRESERVED_FP_H +#define NVRESERVED_FP_H + +#include "NVMarshal.h" /* libtpms added */ + +void +NvCheckState( + void + ); +BOOL +NvCommit( + void + ); +BOOL +NvPowerOn( + void + ); +void +NvManufacture( + void + ); +void +NvRead( + void *outBuffer, // OUT: buffer to receive data + UINT32 nvOffset, // IN: offset in NV of value + UINT32 size // IN: size of the value to read + ); +BOOL +NvWrite( + UINT32 nvOffset, // IN: location in NV to receive data + UINT32 size, // IN: size of the data to move + void *inBuffer // IN: location containing data to write + ); +void +NvUpdatePersistent( + UINT32 offset, // IN: location in PERMANENT_DATA to be updated + UINT32 size, // IN: size of the value + void *buffer // IN: the new data + ); +void +NvClearPersistent( + UINT32 offset, // IN: the offset in the PERMANENT_DATA + // structure to be cleared (zeroed) + UINT32 size // IN: number of bytes to clear + ); +void +NvReadPersistent( + void + ); + + +#endif diff --git a/src/tpm2/NV_Certify_fp.h b/src/tpm2/NV_Certify_fp.h new file mode 100644 index 0000000..a58af30 --- /dev/null +++ b/src/tpm2/NV_Certify_fp.h @@ -0,0 +1,98 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_Certify_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_CERTIFY_FP_H +#define NV_CERTIFY_FP_H + +typedef struct { + TPMI_DH_OBJECT signHandle; + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; + UINT16 size; + UINT16 offset; +} NV_Certify_In; + +#define RC_NV_Certify_signHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_Certify_authHandle (TPM_RC_H + TPM_RC_2) +#define RC_NV_Certify_nvIndex (TPM_RC_H + TPM_RC_3) +#define RC_NV_Certify_qualifyingData (TPM_RC_P + TPM_RC_1) +#define RC_NV_Certify_inScheme (TPM_RC_P + TPM_RC_2) +#define RC_NV_Certify_size (TPM_RC_P + TPM_RC_3) +#define RC_NV_Certify_offset (TPM_RC_P + TPM_RC_4) + + +typedef struct { + TPM2B_ATTEST certifyInfo; + TPMT_SIGNATURE signature; +} NV_Certify_Out; + +TPM_RC +TPM2_NV_Certify( + NV_Certify_In *in, // IN: input parameter list + NV_Certify_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/NV_ChangeAuth_fp.h b/src/tpm2/NV_ChangeAuth_fp.h new file mode 100644 index 0000000..fb26a73 --- /dev/null +++ b/src/tpm2/NV_ChangeAuth_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_ChangeAuth_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_CHANGEAUTH_FP_H +#define NV_CHANGEAUTH_FP_H + +typedef struct { + TPMI_RH_NV_INDEX nvIndex; + TPM2B_AUTH newAuth; +} NV_ChangeAuth_In; + +#define RC_NV_ChangeAuth_nvIndex (TPM_RC_H + TPM_RC_1) +#define RC_NV_ChangeAuth_newAuth (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_NV_ChangeAuth( + NV_ChangeAuth_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_DefineSpace_fp.h b/src/tpm2/NV_DefineSpace_fp.h new file mode 100644 index 0000000..03d81c3 --- /dev/null +++ b/src/tpm2/NV_DefineSpace_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_DefineSpace_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_DEFINESPACE_FP_H +#define NV_DEFINESPACE_FP_H + +typedef struct { + TPMI_RH_PROVISION authHandle; + TPM2B_AUTH auth; + TPM2B_NV_PUBLIC publicInfo; +} NV_DefineSpace_In; + +#define RC_NV_DefineSpace_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_DefineSpace_auth (TPM_RC_P + TPM_RC_1) +#define RC_NV_DefineSpace_publicInfo (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_NV_DefineSpace( + NV_DefineSpace_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_Extend_fp.h b/src/tpm2/NV_Extend_fp.h new file mode 100644 index 0000000..58d4c2f --- /dev/null +++ b/src/tpm2/NV_Extend_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_Extend_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_EXTEND_FP_H +#define NV_EXTEND_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPM2B_MAX_NV_BUFFER data; +} NV_Extend_In; + +#define RC_NV_Extend_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_Extend_nvIndex (TPM_RC_H + TPM_RC_2) +#define RC_NV_Extend_data (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_NV_Extend( + NV_Extend_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_GlobalWriteLock_fp.h b/src/tpm2/NV_GlobalWriteLock_fp.h new file mode 100644 index 0000000..4f6b26b --- /dev/null +++ b/src/tpm2/NV_GlobalWriteLock_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_GlobalWriteLock_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_GLOBALWRITELOCK_FP_H +#define NV_GLOBALWRITELOCK_FP_H + +typedef struct { + TPMI_RH_PROVISION authHandle; +} NV_GlobalWriteLock_In; + +#define RC_NV_GlobalWriteLock_authHandle (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_NV_GlobalWriteLock( + NV_GlobalWriteLock_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_Increment_fp.h b/src/tpm2/NV_Increment_fp.h new file mode 100644 index 0000000..260e0cb --- /dev/null +++ b/src/tpm2/NV_Increment_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_Increment_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_INCREMENT_FP_H +#define NV_INCREMENT_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; +} NV_Increment_In;; + +#define RC_NV_Increment_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_Increment_nvIndex (TPM_RC_H + TPM_RC_2) + +TPM_RC +TPM2_NV_Increment( + NV_Increment_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_ReadLock_fp.h b/src/tpm2/NV_ReadLock_fp.h new file mode 100644 index 0000000..f50479b --- /dev/null +++ b/src/tpm2/NV_ReadLock_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_ReadLock_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_READLOCK_FP_H +#define NV_READLOCK_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; +} NV_ReadLock_In; + +#define RC_NV_ReadLock_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_ReadLock_nvIndex (TPM_RC_H + TPM_RC_2) + +TPM_RC +TPM2_NV_ReadLock( + NV_ReadLock_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_ReadPublic_fp.h b/src/tpm2/NV_ReadPublic_fp.h new file mode 100644 index 0000000..bcad306 --- /dev/null +++ b/src/tpm2/NV_ReadPublic_fp.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_ReadPublic_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_READPUBLIC_FP_H +#define NV_READPUBLIC_FP_H + +typedef struct { + TPMI_RH_NV_INDEX nvIndex; +} NV_ReadPublic_In; + +#define RC_NV_ReadPublic_nvIndex (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPM2B_NV_PUBLIC nvPublic; + TPM2B_NAME nvName; +} NV_ReadPublic_Out; + +TPM_RC +TPM2_NV_ReadPublic( + NV_ReadPublic_In *in, // IN: input parameter list + NV_ReadPublic_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/NV_Read_fp.h b/src/tpm2/NV_Read_fp.h new file mode 100644 index 0000000..660fbd1 --- /dev/null +++ b/src/tpm2/NV_Read_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_Read_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_READ_FP_H +#define NV_READ_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + UINT16 size; + UINT16 offset; +} NV_Read_In; + +#define RC_NV_Read_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_Read_nvIndex (TPM_RC_H + TPM_RC_2) +#define RC_NV_Read_size (TPM_RC_P + TPM_RC_1) +#define RC_NV_Read_offset (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPM2B_MAX_NV_BUFFER data; +} NV_Read_Out; + +TPM_RC +TPM2_NV_Read( + NV_Read_In *in, // IN: input parameter list + NV_Read_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/NV_SetBits_fp.h b/src/tpm2/NV_SetBits_fp.h new file mode 100644 index 0000000..b860d64 --- /dev/null +++ b/src/tpm2/NV_SetBits_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_SetBits_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_SETBITS_FP_H +#define NV_SETBITS_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + UINT64 bits; +} NV_SetBits_In; + +#define RC_NV_SetBits_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_SetBits_nvIndex (TPM_RC_H + TPM_RC_2) +#define RC_NV_SetBits_bits (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_NV_SetBits( + NV_SetBits_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_UndefineSpaceSpecial_fp.h b/src/tpm2/NV_UndefineSpaceSpecial_fp.h new file mode 100644 index 0000000..d2016a4 --- /dev/null +++ b/src/tpm2/NV_UndefineSpaceSpecial_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_UndefineSpaceSpecial_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_UNDEFINESPACESPECIAL_FP_H +#define NV_UNDEFINESPACESPECIAL_FP_H + +typedef struct { + TPMI_RH_NV_INDEX nvIndex; + TPMI_RH_PLATFORM platform; +} NV_UndefineSpaceSpecial_In; + +#define RC_NV_UndefineSpaceSpecial_nvIndex (TPM_RC_H + TPM_RC_1) +#define RC_NV_UndefineSpaceSpecial_platform (TPM_RC_H + TPM_RC_2) + +TPM_RC +TPM2_NV_UndefineSpaceSpecial( + NV_UndefineSpaceSpecial_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_UndefineSpace_fp.h b/src/tpm2/NV_UndefineSpace_fp.h new file mode 100644 index 0000000..fc6897e --- /dev/null +++ b/src/tpm2/NV_UndefineSpace_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_UndefineSpace_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_UNDEFINESPACE_FP_H +#define NV_UNDEFINESPACE_FP_H + +typedef struct { + TPMI_RH_PROVISION authHandle; + TPMI_RH_NV_INDEX nvIndex; +} NV_UndefineSpace_In; + +#define RC_NV_UndefineSpace_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_UndefineSpace_nvIndex (TPM_RC_H + TPM_RC_2) + +TPM_RC +TPM2_NV_UndefineSpace( + NV_UndefineSpace_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_WriteLock_fp.h b/src/tpm2/NV_WriteLock_fp.h new file mode 100644 index 0000000..7771343 --- /dev/null +++ b/src/tpm2/NV_WriteLock_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_WriteLock_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_WRITELOCK_FP_H +#define NV_WRITELOCK_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; +} NV_WriteLock_In; + +#define RC_NV_WriteLock_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_WriteLock_nvIndex (TPM_RC_H + TPM_RC_2) + +TPM_RC +TPM2_NV_WriteLock( + NV_WriteLock_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_Write_fp.h b/src/tpm2/NV_Write_fp.h new file mode 100644 index 0000000..2880c6e --- /dev/null +++ b/src/tpm2/NV_Write_fp.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_Write_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef NV_WRITE_FP_H +#define NV_WRITE_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPM2B_MAX_NV_BUFFER data; + UINT16 offset; +} NV_Write_In; + +#define RC_NV_Write_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_NV_Write_nvIndex (TPM_RC_H + TPM_RC_2) +#define RC_NV_Write_data (TPM_RC_P + TPM_RC_1) +#define RC_NV_Write_offset (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_NV_Write( + NV_Write_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/NV_spt.c b/src/tpm2/NV_spt.c new file mode 100644 index 0000000..9e4351f --- /dev/null +++ b/src/tpm2/NV_spt.c @@ -0,0 +1,179 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016, 2017 */ +/* */ +/********************************************************************************/ + +/* 7.5 NV Command Support (NV_spt.c) */ +/* 7.5.1 Includes */ +#include "Tpm.h" +#include "NV_spt_fp.h" +/* 7.5.2 Functions */ +/* 7.5.2.1 NvReadAccessChecks() */ +/* Common routine for validating a read Used by TPM2_NV_Read(), TPM2_NV_ReadLock() and + TPM2_PolicyNV() */ +/* Error Returns Meaning */ +/* TPM_RC_NV_AUTHORIZATION autHandle is not allowed to authorize read of the index */ +/* TPM_RC_NV_LOCKED Read locked */ +/* TPM_RC_NV_UNINITIALIZED Try to read an uninitialized index */ +TPM_RC +NvReadAccessChecks( + TPM_HANDLE authHandle, // IN: the handle that provided the + // authorization + TPM_HANDLE nvHandle, // IN: the handle of the NV index to be read + TPMA_NV attributes // IN: the attributes of 'nvHandle' + ) +{ + // If data is read locked, returns an error + if(IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED)) + return TPM_RC_NV_LOCKED; + // If the authorization was provided by the owner or platform, then check + // that the attributes allow the read. If the authorization handle + // is the same as the index, then the checks were made when the authorization + // was checked.. + if(authHandle == TPM_RH_OWNER) + { + // If Owner provided authorization then ONWERWRITE must be SET + if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD)) + return TPM_RC_NV_AUTHORIZATION; + } + else if(authHandle == TPM_RH_PLATFORM) + { + // If Platform provided authorization then PPWRITE must be SET + if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD)) + return TPM_RC_NV_AUTHORIZATION; + } + // If neither Owner nor Platform provided authorization, make sure that it was + // provided by this index. + else if(authHandle != nvHandle) + return TPM_RC_NV_AUTHORIZATION; + // If the index has not been written, then the value cannot be read + // NOTE: This has to come after other access checks to make sure that + // the proper authorization is given to TPM2_NV_ReadLock() + if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN)) + return TPM_RC_NV_UNINITIALIZED; + return TPM_RC_SUCCESS; +} +/* 7.5.2.2 NvWriteAccessChecks() */ +/* Common routine for validating a write Used by TPM2_NV_Write(), TPM2_NV_Increment(), + TPM2_SetBits(), and TPM2_NV_WriteLock() */ +/* Error Returns Meaning */ +/* TPM_RC_NV_AUTHORIZATION Authorization fails */ +/* TPM_RC_NV_LOCKED Write locked */ +TPM_RC +NvWriteAccessChecks( + TPM_HANDLE authHandle, // IN: the handle that provided the + // authorization + TPM_HANDLE nvHandle, // IN: the handle of the NV index to be written + TPMA_NV attributes // IN: the attributes of 'nvHandle' + ) +{ + // If data is write locked, returns an error + if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED)) + return TPM_RC_NV_LOCKED; + // If the authorization was provided by the owner or platform, then check + // that the attributes allow the write. If the authorization handle + // is the same as the index, then the checks were made when the authorization + // was checked.. + if(authHandle == TPM_RH_OWNER) + { + // If Owner provided authorization then ONWERWRITE must be SET + if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE)) + return TPM_RC_NV_AUTHORIZATION; + } + else if(authHandle == TPM_RH_PLATFORM) + { + // If Platform provided authorization then PPWRITE must be SET + if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE)) + return TPM_RC_NV_AUTHORIZATION; + } + // If neither Owner nor Platform provided authorization, make sure that it was + // provided by this index. + else if(authHandle != nvHandle) + return TPM_RC_NV_AUTHORIZATION; + return TPM_RC_SUCCESS; +} +/* 7.5.2.3 NvClearOrderly() */ +/* This function is used to cause gp.orderlyState to be cleared to the non-orderly state. */ +TPM_RC +NvClearOrderly( + void + ) +{ + if(gp.orderlyState < SU_DA_USED_VALUE) + RETURN_IF_NV_IS_NOT_AVAILABLE; + g_clearOrderly = TRUE; + return TPM_RC_SUCCESS; +} +/* 7.5.2.4 NvIsPinPassIndex() */ +/* Function to check to see if an NV index is a PIN Pass Index */ +/* Return Value Meaning */ +/* TRUE is pin pass */ +/* FALSE is not pin pass */ +BOOL +NvIsPinPassIndex( + TPM_HANDLE index // IN: Handle to check + ) +{ + if(HandleGetType(index) == TPM_HT_NV_INDEX) + { + NV_INDEX *nvIndex = NvGetIndexInfo(index, NULL); + return IsNvPinPassIndex(nvIndex->publicArea.attributes); + } + return FALSE; +} diff --git a/src/tpm2/NV_spt_fp.h b/src/tpm2/NV_spt_fp.h new file mode 100644 index 0000000..dc7906f --- /dev/null +++ b/src/tpm2/NV_spt_fp.h @@ -0,0 +1,87 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: NV_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef NV_SPT_FP_H +#define NV_SPT_FP_H + +TPM_RC +NvReadAccessChecks( + TPM_HANDLE authHandle, // IN: the handle that provided the + // authorization + TPM_HANDLE nvHandle, // IN: the handle of the NV index to be read + TPMA_NV attributes // IN: the attributes of 'nvHandle' + ); +TPM_RC +NvWriteAccessChecks( + TPM_HANDLE authHandle, // IN: the handle that provided the + // authorization + TPM_HANDLE nvHandle, // IN: the handle of the NV index to be written + TPMA_NV attributes // IN: the attributes of 'nvHandle' + ); +TPM_RC +NvClearOrderly( + void + ); +BOOL +NvIsPinPassIndex( + TPM_HANDLE index // IN: Handle to check + ); +#endif diff --git a/src/tpm2/OIDs.h b/src/tpm2/OIDs.h new file mode 100644 index 0000000..7147518 --- /dev/null +++ b/src/tpm2/OIDs.h @@ -0,0 +1,280 @@ +/********************************************************************************/ +/* */ +/* OID values */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: OIDs.h 1628 2020-05-27 19:35:29Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2020 */ +/* */ +/********************************************************************************/ + +// 10.1.16 OIDs.h + +#include "Tpm.h" + +#ifndef _OIDS_H_ +#define _OIDS_H_ + +// All the OIDs in this file are defined as DER-encoded values with a leading tag 0x06 +// (ASN1_OBJECT_IDENTIFIER), followed by a single length byte. This allows the OID size to be +// determined by looking at octet[1] of the OID (total size is OID[1] + 2). + +// These macros allow OIDs to be defined (or not) depending on whether the associated hash +// algorithm is implemented. + +// NOTE: When one of these macros is used, the NAME needs '_" on each side. The exception is when +// the macro is used for the hash OID when only a single _ is used. + +#ifndef ALG_SHA1 +# define ALG_SHA1 NO +#endif +#if ALG_SHA1 +#define SHA1_OID(NAME) MAKE_OID(NAME##SHA1) +#else +#define SHA1_OID(NAME) +#endif +#ifndef ALG_SHA256 +# define ALG_SHA256 NO +#endif +#if ALG_SHA256 +#define SHA256_OID(NAME) MAKE_OID(NAME##SHA256) +#else +#define SHA256_OID(NAME) +#endif +#ifndef ALG_SHA384 +# define ALG_SHA384 NO +#endif +#if ALG_SHA384 +#define SHA384_OID(NAME) MAKE_OID(NAME##SHA384) +#else +#define SHA384_OID(NAME) +#endif +#ifndef ALG_SHA512 +# define ALG_SHA512 NO +#endif +#if ALG_SHA512 +#define SHA512_OID(NAME) MAKE_OID(NAME##SHA512) +#else +#define SHA512_OID(NAME) +#endif +#ifndef ALG_SM3_256 +# define ALG_SM3_256 NO +#endif +#if ALG_SM3_256 +#define SM3_256_OID(NAME) MAKE_OID(NAME##SM3_256) +#else +#define SM3_256_OID(NAME) +#endif +#ifndef ALG_SHA3_256 +# define ALG_SHA3_256 NO +#endif +#if ALG_SHA3_256 +#define SHA3_256_OID(NAME) MAKE_OID(NAME##SHA3_256) +#else +#define SHA3_256_OID(NAME) +#endif +#ifndef ALG_SHA3_384 +# define ALG_SHA3_384 NO +#endif +#if ALG_SHA3_384 +#define SHA3_384_OID(NAME) MAKE_OID(NAME##SHA3_384) +#else +#define SHA3_384_OID(NAME) +#endif +#ifndef ALG_SHA3_512 +# define ALG_SHA3_512 NO +#endif +#if ALG_SHA3_512 +#define SHA3_512_OID(NAME) MAKE_OID(NAME##SHA3_512) +#else +#define SHA3_512_OID(NAME) +#endif +// These are encoded to take one additional byte of algorithm selector +#define NIST_HASH 0x06, 0x09, 0x60, 0x86, 0x48, 1, 101, 3, 4, 2 +#define NIST_SIG 0x06, 0x09, 0x60, 0x86, 0x48, 1, 101, 3, 4, 3 + +// These hash OIDs used in a lot of places. +#define OID_SHA1_VALUE 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A +SHA1_OID(_); // Expands to: +// MAKE_OID(_SHA1) +// which expands to: +// EXTERN const BYTE OID_SHA1[] INITIALIZER({OID_SHA1_VALUE}) +// which, depending on the setting of EXTERN and +// INITIALIZER, expands to either: +// extern const BYTE OID_SHA1[] +// or +// const BYTE OID_SHA1[] = {OID_SHA1_VALUE} +// which is: +// const BYTE OID_SHA1[] = {0x06, 0x05, 0x2B, 0x0E, +// 0x03, 0x02, 0x1A} +#define OID_SHA256_VALUE NIST_HASH, 1 +SHA256_OID(_); +#define OID_SHA384_VALUE NIST_HASH, 2 +SHA384_OID(_); +#define OID_SHA512_VALUE NIST_HASH, 3 +SHA512_OID(_); +#define OID_SM3_256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \ + 0x83, 0x11 +SM3_256_OID(_); // (1.2.156.10197.1.401) +#define OID_SHA3_256_VALUE NIST_HASH, 8 +SHA3_256_OID(_); +#define OID_SHA3_384_VALUE NIST_HASH, 9 +SHA3_384_OID(_); +#define OID_SHA3_512_VALUE NIST_HASH, 10 +SHA3_512_OID(_); +// These are used for RSA-PSS +#if ALG_RSA +#define OID_MGF1_VALUE 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \ + 0x01, 0x01, 0x08 +MAKE_OID(_MGF1); +#define OID_RSAPSS_VALUE 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \ + 0x01, 0x01, 0x0A +MAKE_OID(_RSAPSS); +// This is the OID to designate the public part of an RSA key. +#define OID_PKCS1_PUB_VALUE 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \ + 0x01, 0x01, 0x01 +MAKE_OID(_PKCS1_PUB); +// These are used for RSA PKCS1 signature Algorithms +#define OID_PKCS1_SHA1_VALUE 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, \ + 0x0D, 0x01, 0x01, 0x05 +SHA1_OID(_PKCS1_); // (1.2.840.113549.1.1.5) +#define OID_PKCS1_SHA256_VALUE 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, \ + 0x0D, 0x01, 0x01, 0x0B +SHA256_OID(_PKCS1_); // (1.2.840.113549.1.1.11) +#define OID_PKCS1_SHA384_VALUE 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, \ + 0x0D, 0x01, 0x01, 0x0C +SHA384_OID(_PKCS1_); // (1.2.840.113549.1.1.12) +#define OID_PKCS1_SHA512_VALUE 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, \ + 0x0D, 0x01, 0x01, 0x0D +SHA512_OID(_PKCS1_); //(1.2.840.113549.1.1.13) +#define OID_PKCS1_SM3_256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, \ + 0x01, 0x83, 0x78 +SM3_256_OID(_PKCS1_); // 1.2.156.10197.1.504 +#define OID_PKCS1_SHA3_256_VALUE NIST_SIG, 14 +SHA3_256_OID(_PKCS1_); +#define OID_PKCS1_SHA3_384_VALUE NIST_SIG, 15 +SHA3_384_OID(_PKCS1_); +#define OID_PKCS1_SHA3_512_VALUE NIST_SIG, 16 +SHA3_512_OID(_PKCS1_); +#endif // ALG_RSA +#if ALG_ECDSA +#define OID_ECDSA_SHA1_VALUE 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \ + 0x01 +SHA1_OID(_ECDSA_); // (1.2.840.10045.4.1) SHA1 digest signed by an ECDSA key. +#define OID_ECDSA_SHA256_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \ + 0x03, 0x02 +SHA256_OID(_ECDSA_); // (1.2.840.10045.4.3.2) SHA256 digest signed by an ECDSA key. +#define OID_ECDSA_SHA384_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \ + 0x03, 0x03 +SHA384_OID(_ECDSA_); // (1.2.840.10045.4.3.3) SHA384 digest signed by an ECDSA key. +#define OID_ECDSA_SHA512_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \ + 0x03, 0x04 +SHA512_OID(_ECDSA_); // (1.2.840.10045.4.3.4) SHA512 digest signed by an ECDSA key. +#define OID_ECDSA_SM3_256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \ + 0x83, 0x75 +SM3_256_OID(_ECDSA_); // 1.2.156.10197.1.501 +#define OID_ECDSA_SHA3_256_VALUE NIST_SIG, 10 +SHA3_256_OID(_ECDSA_); +#define OID_ECDSA_SHA3_384_VALUE NIST_SIG, 11 +SHA3_384_OID(_ECDSA_); +#define OID_ECDSA_SHA3_512_VALUE NIST_SIG, 12 +SHA3_512_OID(_ECDSA_); +#endif // ALG_ECDSA +#if ALG_ECC +#define OID_ECC_PUBLIC_VALUE 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, \ + 0x01 +MAKE_OID(_ECC_PUBLIC); +#define OID_ECC_NIST_P192_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, \ + 0x01, 0x01 +#if ECC_NIST_P192 +MAKE_OID(_ECC_NIST_P192); // (1.2.840.10045.3.1.1) 'nistP192' +#endif // ECC_NIST_P192 +#define OID_ECC_NIST_P224_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x21 +#if ECC_NIST_P224 +MAKE_OID(_ECC_NIST_P224); // (1.3.132.0.33) 'nistP224' +#endif // ECC_NIST_P224 +#define OID_ECC_NIST_P256_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, \ + 0x01, 0x07 +#if ECC_NIST_P256 +MAKE_OID(_ECC_NIST_P256); // (1.2.840.10045.3.1.7) 'nistP256' +#endif // ECC_NIST_P256 +#define OID_ECC_NIST_P384_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 +#if ECC_NIST_P384 +MAKE_OID(_ECC_NIST_P384); // (1.3.132.0.34) 'nistP384' +#endif // ECC_NIST_P384 +#define OID_ECC_NIST_P521_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23 +#if ECC_NIST_P521 +MAKE_OID(_ECC_NIST_P521); // (1.3.132.0.35) 'nistP521' +#endif // ECC_NIST_P521 +// No OIDs defined for these anonymous curves +#define OID_ECC_BN_P256_VALUE 0x00 +#if ECC_BN_P256 +MAKE_OID(_ECC_BN_P256); +#endif // ECC_BN_P256 +#define OID_ECC_BN_P638_VALUE 0x00 +#if ECC_BN_P638 +MAKE_OID(_ECC_BN_P638); +#endif // ECC_BN_P638 +#define OID_ECC_SM2_P256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \ + 0x82, 0x2D +#if ECC_SM2_P256 +MAKE_OID(_ECC_SM2_P256); // Don't know where I found this OID. It needs checking +#endif // ECC_SM2_P256 +#if ECC_BN_P256 +#define OID_ECC_BN_P256 NULL +#endif // ECC_BN_P256 +#endif // ALG_ECC +// #undef MAKE_OID +#define OID_SIZE(OID) (OID[1] + 2) +#endif // !_OIDS_H_ diff --git a/src/tpm2/Object.c b/src/tpm2/Object.c new file mode 100644 index 0000000..aa69a53 --- /dev/null +++ b/src/tpm2/Object.c @@ -0,0 +1,970 @@ +/********************************************************************************/ +/* */ +/* Manage the object store of the TPM. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Object.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 8.6 Object.c */ +/* 8.6.1 Introduction */ +/* This file contains the functions that manage the object store of the TPM. */ +/* 8.6.2 Includes and Data Definitions */ +#define OBJECT_C +#include "Tpm.h" +#include "NVMarshal.h" // libtpms added +#include "BackwardsCompatibilityObject.h" // libtpms added +/* 8.6.3 Functions */ +/* 8.6.3.1 ObjectFlush() */ +/* This function marks an object slot as available. Since there is no checking of the input + parameters, it should be used judiciously. */ +/* NOTE: This could be converted to a macro. */ +void +ObjectFlush( + OBJECT *object + ) +{ + object->attributes.occupied = CLEAR; +} +/* 8.6.3.2 ObjectSetInUse() */ +/* This access function sets the occupied attribute of an object slot. */ +void +ObjectSetInUse( + OBJECT *object + ) +{ + object->attributes.occupied = SET; +} +/* 8.6.3.3 ObjectStartup() */ +/* This function is called at TPM2_Startup() to initialize the object subsystem. */ +BOOL +ObjectStartup( + void + ) +{ + UINT32 i; + // object slots initialization + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + //Set the slot to not occupied + ObjectFlush(&s_objects[i]); + } + return TRUE; +} +/* 8.6.3.4 ObjectCleanupEvict() */ +/* In this implementation, a persistent object is moved from NV into an object slot for + processing. It is flushed after command execution. This function is called from + ExecuteCommand(). */ +void +ObjectCleanupEvict( + void + ) +{ + UINT32 i; + // This has to be iterated because a command may have two handles + // and they may both be persistent. + // This could be made to be more efficient so that a search is not needed. + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + // If an object is a temporary evict object, flush it from slot + OBJECT *object = &s_objects[i]; + if(object->attributes.evict == SET) + ObjectFlush(object); + } + return; +} +/* 8.6.3.5 IsObjectPresent() */ +/* This function checks to see if a transient handle references a loaded object. This routine + should not be called if the handle is not a transient handle. The function validates that the + handle is in the implementation-dependent allowed in range for loaded transient objects. */ +/* Return Values Meaning */ +/* TRUE if the handle references a loaded object */ +/* FALSE if the handle is not an object handle, or it does not reference to a loaded object */ +BOOL +IsObjectPresent( + TPMI_DH_OBJECT handle // IN: handle to be checked + ) +{ + UINT32 slotIndex = handle - TRANSIENT_FIRST; + // Since the handle is just an index into the array that is zero based, any + // handle value outsize of the range of: + // TRANSIENT_FIRST -- (TRANSIENT_FIRST + MAX_LOADED_OBJECT - 1) + // will now be greater than or equal to MAX_LOADED_OBJECTS + if(slotIndex >= MAX_LOADED_OBJECTS) + return FALSE; + // Indicate if the slot is occupied + return (s_objects[slotIndex].attributes.occupied == TRUE); +} +/* 8.6.3.6 ObjectIsSequence() */ +/* This function is used to check if the object is a sequence object. This function should not be + called if the handle does not reference a loaded object. */ +/* Return Values Meaning */ +/* TRUE object is an HMAC, hash, or event sequence object */ +/* FALSE object is not an HMAC, hash, or event sequence object */ +BOOL +ObjectIsSequence( + OBJECT *object // IN: handle to be checked + ) +{ + pAssert(object != NULL); + return (object->attributes.hmacSeq == SET + || object->attributes.hashSeq == SET + || object->attributes.eventSeq == SET); +} +/* 8.6.3.7 HandleToObject() */ +/* This function is used to find the object structure associated with a handle. */ +/* This function requires that handle references a loaded object or a permanent handle. */ +OBJECT* +HandleToObject( + TPMI_DH_OBJECT handle // IN: handle of the object + ) +{ + UINT32 index; + // Return NULL if the handle references a permanent handle because there is no + // associated OBJECT. + if(HandleGetType(handle) == TPM_HT_PERMANENT) + return NULL; + // In this implementation, the handle is determined by the slot occupied by the + // object. + index = handle - TRANSIENT_FIRST; + pAssert(index < MAX_LOADED_OBJECTS); + pAssert(s_objects[index].attributes.occupied); + return &s_objects[index]; +} +/* 8.6.3.9 GetQualifiedName() */ +/* This function returns the Qualified Name of the object. In this implementation, the Qualified + Name is computed when the object is loaded and is saved in the internal representation of the + object. The alternative would be to retain the Name of the parent and compute the QN when + needed. This would take the same amount of space so it is not recommended that the alternate be + used. */ +/* This function requires that handle references a loaded object. */ +void +GetQualifiedName( + TPMI_DH_OBJECT handle, // IN: handle of the object + TPM2B_NAME *qualifiedName // OUT: qualified name of the object + ) +{ + OBJECT *object; + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + qualifiedName->t.size = sizeof(TPM_HANDLE); + UINT32_TO_BYTE_ARRAY(handle, qualifiedName->t.name); + break; + case TPM_HT_TRANSIENT: + object = HandleToObject(handle); + if(object == NULL || object->publicArea.nameAlg == TPM_ALG_NULL) + qualifiedName->t.size = 0; + else + // Copy the name + *qualifiedName = object->qualifiedName; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + } + return; +} +/* 8.6.3.10 ObjectGetHierarchy() */ +/* This function returns the handle for the hierarchy of an object. */ +TPMI_RH_HIERARCHY +ObjectGetHierarchy( + OBJECT *object // IN :object + ) +{ + if(object->attributes.spsHierarchy) + { + return TPM_RH_OWNER; + } + else if(object->attributes.epsHierarchy) + { + return TPM_RH_ENDORSEMENT; + } + else if(object->attributes.ppsHierarchy) + { + return TPM_RH_PLATFORM; + } + else + { + return TPM_RH_NULL; + } +} +/* 8.6.3.11 GetHierarchy() */ +/* This function returns the handle of the hierarchy to which a handle belongs. This function is + similar to ObjectGetHierarchy() but this routine takes a handle while ObjectGetHierarchy() takes + a pointer to an object. */ +/* This function requires that handle references a loaded object. */ +TPMI_RH_HIERARCHY +GetHieriarchy( + TPMI_DH_OBJECT handle // IN :object handle + ) +{ + OBJECT *object = HandleToObject(handle); + return ObjectGetHierarchy(object); +} +/* 8.6.3.12 FindEmptyObjectSlot() */ +/* This function finds an open object slot, if any. It will clear the attributes but will not set + the occupied attribute. This is so that a slot may be used and discarded if everything does not + go as planned. */ +/* Return Values Meaning */ +/* null no open slot found */ +/* !=null pointer to available slot */ +OBJECT * +FindEmptyObjectSlot( + TPMI_DH_OBJECT *handle // OUT: (optional) + ) +{ + UINT32 i; + OBJECT *object; + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + object = &s_objects[i]; + if(object->attributes.occupied == CLEAR) + { + if(handle) + *handle = i + TRANSIENT_FIRST; + // Initialize the object attributes + // MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES)); + MemorySet(object, 0, sizeof(*object)); // libtpms added: Initialize the whole object + return object; + } + } + return NULL; +} +/* 8.6.3.13 ObjectAllocateSlot() */ +/* This function is used to allocate a slot in internal object array. */ +/* Return Values Meaning */ +OBJECT * +ObjectAllocateSlot( + TPMI_DH_OBJECT *handle // OUT: handle of allocated object + ) +{ + OBJECT *object = FindEmptyObjectSlot(handle); + if(object != NULL) + { + // if found, mark as occupied + ObjectSetInUse(object); + } + return object; +} +/* 8.6.3.14 ObjectSetLoadedAttributes() */ +/* This function sets the internal attributes for a loaded object. It is called to finalize the + OBJECT attributes (not the TPMA_OBJECT attributes) for a loaded object. */ +void +ObjectSetLoadedAttributes( + OBJECT *object, // IN: object attributes to finalize + TPM_HANDLE parentHandle, // IN: the parent handle + SEED_COMPAT_LEVEL seedCompatLevel // IN: seed compat level to use for children + ) +{ + OBJECT *parent = HandleToObject(parentHandle); + TPMA_OBJECT objectAttributes = object->publicArea.objectAttributes; + + object->seedCompatLevel = seedCompatLevel; // libtpms added + // + // Copy the stClear attribute from the public area. This could be overwritten + // if the parent has stClear SET + object->attributes.stClear = + IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear); + // If parent handle is a permanent handle, it is a primary (unless it is NULL + if(parent == NULL) + { + object->attributes.primary = SET; + switch(parentHandle) + { + case TPM_RH_ENDORSEMENT: + object->attributes.epsHierarchy = SET; + break; + case TPM_RH_OWNER: + object->attributes.spsHierarchy = SET; + break; + case TPM_RH_PLATFORM: + object->attributes.ppsHierarchy = SET; + break; + default: + // Treat the temporary attribute as a hierarchy + object->attributes.temporary = SET; + object->attributes.primary = CLEAR; + break; + } + } + else + { + // is this a stClear object + object->attributes.stClear = + (IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear) + || (parent->attributes.stClear == SET)); + object->attributes.epsHierarchy = parent->attributes.epsHierarchy; + object->attributes.spsHierarchy = parent->attributes.spsHierarchy; + object->attributes.ppsHierarchy = parent->attributes.ppsHierarchy; + // An object is temporary if its parent is temporary or if the object + // is external + object->attributes.temporary = parent->attributes.temporary + || object->attributes.external; + } + // If this is an external object, set the QN == name but don't SET other + // key properties ('parent' or 'derived') + if(object->attributes.external) + object->qualifiedName = object->name; + else + { + // check attributes for different types of parents + if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted) + && !object->attributes.publicOnly + && IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt) + && object->publicArea.nameAlg != TPM_ALG_NULL) + { + // This is a parent. If it is not a KEYEDHASH, it is an ordinary parent. + // Otherwise, it is a derivation parent. + if(object->publicArea.type == TPM_ALG_KEYEDHASH) + object->attributes.derivation = SET; + else + object->attributes.isParent = SET; + } + ComputeQualifiedName(parentHandle, object->publicArea.nameAlg, + &object->name, &object->qualifiedName); + } + // Set slot occupied + ObjectSetInUse(object); + return; +} +/* 8.6.3.15 ObjectLoad() */ +/* Common function to load an object. A loaded object has its public area validated (unless its + nameAlg is TPM_ALG_NULL). If a sensitive part is loaded, it is verified to be correct and if both + public and sensitive parts are loaded, then the cryptographic binding between the objects is + validated. This function does not cause the allocated slot to be marked as in use. */ +TPM_RC +ObjectLoad( + OBJECT *object, // IN: pointer to object slot + // object + OBJECT *parent, // IN: (optional) the parent object + TPMT_PUBLIC *publicArea, // IN: public area to be installed in the object + TPMT_SENSITIVE *sensitive, // IN: (optional) sensitive area to be + // installed in the object + TPM_RC blamePublic, // IN: parameter number to associate with the + // publicArea errors + TPM_RC blameSensitive,// IN: parameter number to associate with the + // sensitive area errors + TPM2B_NAME *name // IN: (optional) + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + BOOL doCheck; + // + // Do validations of public area object descriptions + // Is this public only or a no-name object? + if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL) + { + // Need to have schemes checked so that we do the right thing with the + // public key. + result = SchemeChecks(NULL, publicArea); + } + else + { + // For any sensitive area, make sure that the seedSize is no larger than the + // digest size of nameAlg + if(sensitive->seedValue.t.size + > CryptHashGetDigestSize(publicArea->nameAlg)) + return TPM_RCS_KEY_SIZE + blameSensitive; + // Check attributes and schemes for consistency + result = PublicAttributesValidation(parent, publicArea); + } + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, blamePublic); + // If object == NULL, then this is am import. For import, load is not called + // unless the parent is fixedTPM. + if(object == NULL) + doCheck = TRUE;// // + // If the parent is not NULL, then this is an ordinary load and we only check + // if the parent is not fixedTPM + else if(parent != NULL) + doCheck = !IS_ATTRIBUTE(parent->publicArea.objectAttributes, + TPMA_OBJECT, fixedTPM); + else + // This is a loadExternal. Check everything. + // Note: the check functions will filter things based on the name algorithm + // and whether or not both parts are loaded. + doCheck = TRUE; + // Note: the parent will be NULL if this is a load external. CryptValidateKeys() + // will only check the parts that need to be checked based on the settings + // of publicOnly and nameAlg. + // Note: For an RSA key, the keys sizes are checked but the binding is not + // checked. + if(doCheck) + { + // Do the cryptographic key validation + result = CryptValidateKeys(publicArea, sensitive, blamePublic, + blameSensitive); + } + // If this is an import, we are done + if(object == NULL || result != TPM_RC_SUCCESS) + return result; + // Set the name, if one was provided + if(name != NULL) + object->name = *name; + else + object->name.t.size = 0; + // Initialize public + object->publicArea = *publicArea; + // If there is a sensitive area, load it + if(sensitive == NULL) + object->attributes.publicOnly = SET; + else + { + object->sensitive = *sensitive; +#if ALG_RSA + // If this is an RSA key that is not a parent, complete the load by + // computing the private exponent. + if(publicArea->type == ALG_RSA_VALUE) + result = CryptRsaLoadPrivateExponent(object); +#endif + } + return result; +} +/* 8.6.3.16 AllocateSequenceSlot() */ +/* This function allocates a sequence slot and initializes the parts that are used by the normal + objects so that a sequence object is not inadvertently used for an operation that is not + appropriate for a sequence. */ +static HASH_OBJECT * +AllocateSequenceSlot( + TPM_HANDLE *newHandle, // OUT: receives the allocated handle + TPM2B_AUTH *auth // IN: the authValue for the slot + ) +{ + HASH_OBJECT *object = (HASH_OBJECT *)ObjectAllocateSlot(newHandle); + // + // Validate that the proper location of the hash state data relative to the + // object state data. It would be good if this could have been done at compile + // time but it can't so do it in something that can be removed after debug. + cAssert(offsetof(HASH_OBJECT, auth) == offsetof(OBJECT, publicArea.authPolicy)); + if(object != NULL) + { + // Set the common values that a sequence object shares with an ordinary object + // First, clear all attributes + MemorySet(&object->objectAttributes, 0, sizeof(TPMA_OBJECT)); + // The type is TPM_ALG_NULL + object->type = TPM_ALG_NULL; + // This has no name algorithm and the name is the Empty Buffer + object->nameAlg = TPM_ALG_NULL; + // A sequence object is considered to be in the NULL hierarchy so it should + // be marked as temporary so that it can't be persisted + object->attributes.temporary = SET; + // A sequence object is DA exempt. + SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA); + // Copy the authorization value + if(auth != NULL) + object->auth = *auth; + else + object->auth.t.size = 0; + } + return object; +} +/* 8.6.3.17 ObjectCreateHMACSequence() */ +/* This function creates an internal HMAC sequence object. */ +/* Error Returns Meaning */ +/* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */ +#if CC_HMAC_Start || CC_MAC_Start +TPM_RC +ObjectCreateHMACSequence( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + OBJECT *keyObject, // IN: the object containing the HMAC key + TPM2B_AUTH *auth, // IN: authValue + TPMI_DH_OBJECT *newHandle // OUT: HMAC sequence object handle + ) +{ + HASH_OBJECT *hmacObject; + // + // Try to allocate a slot for new object + hmacObject = AllocateSequenceSlot(newHandle, auth); + if(hmacObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Set HMAC sequence bit + hmacObject->attributes.hmacSeq = SET; +#if !SMAC_IMPLEMENTED + if(CryptHmacStart(&hmacObject->state.hmacState, hashAlg, + keyObject->sensitive.sensitive.bits.b.size, + keyObject->sensitive.sensitive.bits.b.buffer) == 0) +#else + if(CryptMacStart(&hmacObject->state.hmacState, + &keyObject->publicArea.parameters, + hashAlg, &keyObject->sensitive.sensitive.any.b) == 0) +#endif // SMAC_IMPLEMENTED + return TPM_RC_FAILURE; + return TPM_RC_SUCCESS; +} +#endif + +/* 8.6.3.18 ObjectCreateHashSequence() */ +/* This function creates a hash sequence object. */ +/* Error Returns Meaning */ +/* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */ +TPM_RC +ObjectCreateHashSequence( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + TPM2B_AUTH *auth, // IN: authValue + TPMI_DH_OBJECT *newHandle // OUT: sequence object handle + ) +{ + HASH_OBJECT *hashObject = AllocateSequenceSlot(newHandle, auth); + // See if slot allocated + if(hashObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Set hash sequence bit + hashObject->attributes.hashSeq = SET; + // Start hash for hash sequence + CryptHashStart(&hashObject->state.hashState[0], hashAlg); + return TPM_RC_SUCCESS; +} +/* 8.6.3.19 ObjectCreateEventSequence() */ +/* This function creates an event sequence object. */ +/* Error Returns Meaning */ +/* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */ +TPM_RC +ObjectCreateEventSequence( + TPM2B_AUTH *auth, // IN: authValue + TPMI_DH_OBJECT *newHandle // OUT: sequence object handle + ) +{ + HASH_OBJECT *hashObject = AllocateSequenceSlot(newHandle, auth); + UINT32 count; + TPM_ALG_ID hash; + // See if slot allocated + if(hashObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Set the event sequence attribute + hashObject->attributes.eventSeq = SET; + // Initialize hash states for each implemented PCR algorithms + for(count = 0; (hash = CryptHashGetAlgByIndex(count)) != TPM_ALG_NULL; count++) + CryptHashStart(&hashObject->state.hashState[count], hash); + return TPM_RC_SUCCESS; +} +/* 8.6.3.20 ObjectTerminateEvent() */ +/* This function is called to close out the event sequence and clean up the hash context states. */ +void +ObjectTerminateEvent( + void + ) +{ + HASH_OBJECT *hashObject; + int count; + BYTE buffer[MAX_DIGEST_SIZE]; + hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle); + // Don't assume that this is a proper sequence object + if(hashObject->attributes.eventSeq) + { + // If it is, close any open hash contexts. This is done in case + // the cryptographic implementation has some context values that need to be + // cleaned up (hygiene). + // + for(count = 0; CryptHashGetAlgByIndex(count) != TPM_ALG_NULL; count++) + { + CryptHashEnd(&hashObject->state.hashState[count], 0, buffer); + } + // Flush sequence object + FlushObject(g_DRTMHandle); + } + g_DRTMHandle = TPM_RH_UNASSIGNED; +} +/* 8.6.3.21 ObjectContextLoad() */ +/* This function loads an object from a saved object context. */ +/* Return Values Meaning */ +/* NULL if there is no free slot for an object */ +/* NON_NULL points to the loaded object */ +#if 0 // libtpms added +OBJECT * +ObjectContextLoad( + ANY_OBJECT_BUFFER *object, // IN: pointer to object structure in saved + // context + TPMI_DH_OBJECT *handle // OUT: object handle + ) +{ + OBJECT *newObject = ObjectAllocateSlot(handle); + // Try to allocate a slot for new object + if(newObject != NULL) + { + // Copy the first part of the object + MemoryCopy(newObject, object, offsetof(HASH_OBJECT, state)); + // See if this is a sequence object + if(ObjectIsSequence(newObject)) + { + // If this is a sequence object, import the data + SequenceDataImport((HASH_OBJECT *)newObject, + (HASH_OBJECT_BUFFER *)object); + } + else + { + // Copy input object data to internal structure + MemoryCopy(newObject, object, sizeof(OBJECT)); + } + } + return newObject; +} +#endif // libtpms added begin + +OBJECT * +ObjectContextLoadLibtpms(BYTE *buffer, + INT32 size, + TPMI_DH_OBJECT *handle + ) +{ + OBJECT *newObject = ObjectAllocateSlot(handle); + TPM_RC rc; + BYTE *mybuf = buffer; + INT32 mysize = size; + + pAssert(handle); + + // Try to allocate a slot for new object + if(newObject != NULL) + { + rc = ANY_OBJECT_Unmarshal(newObject, &mybuf, &mysize, false); + if (rc) { + /* Attempt to load an old OBJECT that was copied out directly from + * an older version of OBJECT. + */ + rc = OLD_OBJECTToOBJECT(newObject, buffer, size); + if (rc) { + FlushObject(*handle); + newObject = NULL; + } + } + } + return newObject; +} // libtpms added end + +/* 8.6.3.22 FlushObject() */ +/* This function frees an object slot. */ +/* This function requires that the object is loaded. */ +void +FlushObject( + TPMI_DH_OBJECT handle // IN: handle to be freed + ) +{ + UINT32 index = handle - TRANSIENT_FIRST; + pAssert(index < MAX_LOADED_OBJECTS); + // Clear all the object attributes + MemorySet((BYTE*)&(s_objects[index].attributes), + 0, sizeof(OBJECT_ATTRIBUTES)); + return; +} +/* 8.6.3.23 ObjectFlushHierarchy() */ +/* This function is called to flush all the loaded transient objects associated with a hierarchy + when the hierarchy is disabled. */ +void +ObjectFlushHierarchy( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush + ) +{ + UINT16 i; + // iterate object slots + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + if(s_objects[i].attributes.occupied) // If found an occupied slot + { + switch(hierarchy) + { + case TPM_RH_PLATFORM: + if(s_objects[i].attributes.ppsHierarchy == SET) + s_objects[i].attributes.occupied = FALSE; + break; + case TPM_RH_OWNER: + if(s_objects[i].attributes.spsHierarchy == SET) + s_objects[i].attributes.occupied = FALSE; + break; + case TPM_RH_ENDORSEMENT: + if(s_objects[i].attributes.epsHierarchy == SET) + s_objects[i].attributes.occupied = FALSE; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + } + } + return; +} +/* 8.6.3.24 ObjectLoadEvict() */ +/* This function loads a persistent object into a transient object slot. */ +/* This function requires that handle is associated with a persistent object. */ +/* Error Returns Meaning */ +/* TPM_RC_HANDLE the persistent object does not exist or the associated hierarchy is disabled. */ +/* TPM_RC_OBJECT_MEMORY no object slot */ +TPM_RC +ObjectLoadEvict( + TPM_HANDLE *handle, // IN:OUT: evict object handle. If success, it + // will be replace by the loaded object handle + COMMAND_INDEX commandIndex // IN: the command being processed + ) +{ + TPM_RC result; + TPM_HANDLE evictHandle = *handle; // Save the evict handle + OBJECT *object; + // If this is an index that references a persistent object created by + // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE + if(*handle >= PLATFORM_PERSISTENT) + { + // belongs to platform + if(g_phEnable == CLEAR) + return TPM_RC_HANDLE; + } + // belongs to owner + else if(gc.shEnable == CLEAR) + return TPM_RC_HANDLE; + // Try to allocate a slot for an object + object = ObjectAllocateSlot(handle); + if(object == NULL) + return TPM_RC_OBJECT_MEMORY; + // Copy persistent object to transient object slot. A TPM_RC_HANDLE + // may be returned at this point. This will mark the slot as containing + // a transient object so that it will be flushed at the end of the + // command + result = NvGetEvictObject(evictHandle, object); + // Bail out if this failed + if(result != TPM_RC_SUCCESS) + return result; + // check the object to see if it is in the endorsement hierarchy + // if it is and this is not a TPM2_EvictControl() command, indicate + // that the hierarchy is disabled. + // If the associated hierarchy is disabled, make it look like the + // handle is not defined + if(ObjectGetHierarchy(object) == TPM_RH_ENDORSEMENT + && gc.ehEnable == CLEAR + && GetCommandCode(commandIndex) != TPM_CC_EvictControl) + return TPM_RC_HANDLE; + return result; +} +/* 8.6.3.25 ObjectComputeName() */ +/* This does the name computation from a public area (can be marshaled or not). */ +TPM2B_NAME * +ObjectComputeName( + UINT32 size, // IN: the size of the area to digest + BYTE *publicArea, // IN: the public area to digest + TPM_ALG_ID nameAlg, // IN: the hash algorithm to use + TPM2B_NAME *name // OUT: Computed name + ) +{ + // Hash the publicArea into the name buffer leaving room for the nameAlg + name->t.size = CryptHashBlock(nameAlg, size, publicArea, + sizeof(name->t.name) - 2, + &name->t.name[2]); + // set the nameAlg + UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name); + name->t.size += 2; + return name; +} +/* 8.6.3.26 PublicMarshalAndComputeName() */ +/* This function computes the Name of an object from its public area. */ +TPM2B_NAME * +PublicMarshalAndComputeName( + TPMT_PUBLIC *publicArea, // IN: public area of an object + TPM2B_NAME *name // OUT: name of the object + ) +{ + // Will marshal a public area into a template. This is because the internal + // format for a TPM2B_PUBLIC is a structure and not a simple BYTE buffer. + TPM2B_TEMPLATE marshaled; // this is big enough to hold a + // marshaled TPMT_PUBLIC + BYTE *buffer = (BYTE *)&marshaled.t.buffer; + // if the nameAlg is NULL then there is no name. + if(publicArea->nameAlg == TPM_ALG_NULL) + name->t.size = 0; + else + { + // Marshal the public area into its canonical form + marshaled.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL); + // and compute the name + ObjectComputeName(marshaled.t.size, marshaled.t.buffer, + publicArea->nameAlg, name); + } + return name; +} +/* 8.6.3.28 ComputeQualifiedName() */ +/* This function computes the qualified name of an object. */ +void +ComputeQualifiedName( + TPM_HANDLE parentHandle, // IN: parent's handle + TPM_ALG_ID nameAlg, // IN: name hash + TPM2B_NAME *name, // IN: name of the object + TPM2B_NAME *qualifiedName // OUT: qualified name of the object + ) +{ + HASH_STATE hashState; // hash state + TPM2B_NAME parentName; + if(parentHandle == TPM_RH_UNASSIGNED) + { + MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name)); + *qualifiedName = *name; + } + else + { + GetQualifiedName(parentHandle, &parentName); + // QN_A = hash_A (QN of parent || NAME_A) + // Start hash + qualifiedName->t.size = CryptHashStart(&hashState, nameAlg); + // Add parent's qualified name + CryptDigestUpdate2B(&hashState, &parentName.b); + // Add self name + CryptDigestUpdate2B(&hashState, &name->b); + // Complete hash leaving room for the name algorithm + CryptHashEnd(&hashState, qualifiedName->t.size, + &qualifiedName->t.name[2]); + UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name); + qualifiedName->t.size += 2; + } + return; +} +/* 8.6.3.29 ObjectIsStorage() */ +/* This function determines if an object has the attributes associated with a parent. A parent is an + asymmetric or symmetric block cipher key that has its restricted and decrypt attributes SET, and + sign CLEAR. */ +/* Return Values Meaning */ +/* TRUE if the object is a storage key */ +/* FALSE if the object is not a storage key */ +BOOL +ObjectIsStorage( + TPMI_DH_OBJECT handle // IN: object handle + ) +{ + OBJECT *object = HandleToObject(handle); + TPMT_PUBLIC *publicArea = ((object != NULL) ? &object->publicArea : NULL); + // + return (publicArea != NULL + && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) + && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) + && !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign) + && (object->publicArea.type == ALG_RSA_VALUE + || object->publicArea.type == ALG_ECC_VALUE)); +} +/* 8.6.3.30 ObjectCapGetLoaded() */ +/* This function returns a a list of handles of loaded object, starting from handle. Handle must be + in the range of valid transient object handles, but does not have to be the handle of a loaded + transient object. */ +/* Return Values Meaning */ +/* YES if there are more handles available */ +/* NO all the available handles has been returned */ +TPMI_YES_NO +ObjectCapGetLoaded( + TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ) +{ + TPMI_YES_NO more = NO; + UINT32 i; + pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT); + // Initialize output handle list + handleList->count = 0; + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; + // Iterate object slots to get loaded object handles + for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++) + { + if(s_objects[i].attributes.occupied == TRUE) + { + // A valid transient object can not be the copy of a persistent object + pAssert(s_objects[i].attributes.evict == CLEAR); + if(handleList->count < count) + { + // If we have not filled up the return list, add this object + // handle to it + handleList->handle[handleList->count] = i + TRANSIENT_FIRST; + handleList->count++; + } + else + { + // If the return list is full but we still have loaded object + // available, report this and stop iterating + more = YES; + break; + } + } + } + return more; +} +/* 8.6.3.31 ObjectCapGetTransientAvail() */ +/* This function returns an estimate of the number of additional transient objects that could be + loaded into the TPM. */ +UINT32 +ObjectCapGetTransientAvail( + void + ) +{ + UINT32 i; + UINT32 num = 0; + // Iterate object slot to get the number of unoccupied slots + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + if(s_objects[i].attributes.occupied == FALSE) num++; + } + return num; +} +/* 8.6.3.32 ObjectGetPublicAttributes() */ +/* Returns the attributes associated with an object handles. */ +TPMA_OBJECT +ObjectGetPublicAttributes( + TPM_HANDLE handle + ) +{ + return HandleToObject(handle)->publicArea.objectAttributes; +} +#if 0 /* libtpms added */ +OBJECT_ATTRIBUTES +ObjectGetProperties( + TPM_HANDLE handle + ) +{ + return HandleToObject(handle)->attributes; +} +#endif /* libtpms added */ diff --git a/src/tpm2/ObjectChangeAuth_fp.h b/src/tpm2/ObjectChangeAuth_fp.h new file mode 100644 index 0000000..05a97c3 --- /dev/null +++ b/src/tpm2/ObjectChangeAuth_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ObjectChangeAuth_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef OBJECTCHANGEAUTH_FP_H +#define OBJECTCHANGEAUTH_FP_H + +typedef struct { + TPMI_DH_OBJECT objectHandle; + TPMI_DH_OBJECT parentHandle; + TPM2B_AUTH newAuth; +} ObjectChangeAuth_In; + +#define RC_ObjectChangeAuth_objectHandle (TPM_RC_H + TPM_RC_1) +#define RC_ObjectChangeAuth_parentHandle (TPM_RC_H + TPM_RC_2) +#define RC_ObjectChangeAuth_newAuth (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPM2B_PRIVATE outPrivate; +} ObjectChangeAuth_Out; + + +TPM_RC +TPM2_ObjectChangeAuth( + ObjectChangeAuth_In *in, // IN: input parameter list + ObjectChangeAuth_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/ObjectCommands.c b/src/tpm2/ObjectCommands.c new file mode 100644 index 0000000..27f6637 --- /dev/null +++ b/src/tpm2/ObjectCommands.c @@ -0,0 +1,549 @@ +/********************************************************************************/ +/* */ +/* Object Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ObjectCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "Object_spt_fp.h" +#include "Create_fp.h" +#if CC_Create // Conditional expansion of this file +TPM_RC +TPM2_Create( + Create_In *in, // IN: input parameter list + Create_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT *parentObject; + OBJECT *newObject; + TPMT_PUBLIC *publicArea; + // Input Validation + parentObject = HandleToObject(in->parentHandle); + pAssert(parentObject != NULL); + // Does parent have the proper attributes? + if(!ObjectIsParent(parentObject)) + return TPM_RCS_TYPE + RC_Create_parentHandle; + // Get a slot for the creation + newObject = FindEmptyObjectSlot(NULL); + if(newObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // If the TPM2B_PUBLIC was passed as a structure, marshal it into is canonical + // form for processing + // to save typing. + publicArea = &newObject->publicArea; + // Copy the input structure to the allocated structure + *publicArea = in->inPublic.publicArea; + // Check attributes in input public area. CreateChecks() checks the things that + // are unique to creation and then validates the attributes and values that are + // common to create and load. + result = CreateChecks(parentObject, publicArea, + in->inSensitive.sensitive.data.t.size); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Create_inPublic); + // Clean up the authValue if necessary + if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) + return TPM_RCS_SIZE + RC_Create_inSensitive; + // Command Output + // Create the object using the default TPM random-number generator + result = CryptCreateObject(newObject, &in->inSensitive.sensitive, NULL); + if(result != TPM_RC_SUCCESS) + return result; + // Fill in creation data + FillInCreationData(in->parentHandle, publicArea->nameAlg, + &in->creationPCR, &in->outsideInfo, + &out->creationData, &out->creationHash); + // Compute creation ticket + TicketComputeCreation(EntityGetHierarchy(in->parentHandle), &newObject->name, + &out->creationHash, &out->creationTicket); + // Prepare output private data from sensitive + SensitiveToPrivate(&newObject->sensitive, &newObject->name, parentObject, + publicArea->nameAlg, + &out->outPrivate); + // Finish by copying the remaining return values + out->outPublic.publicArea = newObject->publicArea; + return TPM_RC_SUCCESS; +} +#endif // CC_Create +#include "Tpm.h" +#include "Load_fp.h" +#if CC_Load // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_Load( + Load_In *in, // IN: input parameter list + Load_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + TPMT_SENSITIVE sensitive = {0}; // libtpms changed (valgrind) + OBJECT *parentObject; + OBJECT *newObject; + // Input Validation + // Don't get invested in loading if there is no place to put it. + newObject = FindEmptyObjectSlot(&out->objectHandle); + if(newObject == NULL) + return TPM_RC_OBJECT_MEMORY; + if(in->inPrivate.t.size == 0) + return TPM_RCS_SIZE + RC_Load_inPrivate; + parentObject = HandleToObject(in->parentHandle); + pAssert(parentObject != NULL); + // Is the object that is being used as the parent actually a parent. + if(!ObjectIsParent(parentObject)) + return TPM_RCS_TYPE + RC_Load_parentHandle; + // Compute the name of object. If there isn't one, it is because the nameAlg is + // not valid. + PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name); + if(out->name.t.size == 0) + return TPM_RCS_HASH + RC_Load_inPublic; + // Retrieve sensitive data. + result = PrivateToSensitive(&in->inPrivate.b, &out->name.b, parentObject, + in->inPublic.publicArea.nameAlg, + &sensitive); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Load_inPrivate); + // Internal Data Update + // Load and validate object + result = ObjectLoad(newObject, parentObject, + &in->inPublic.publicArea, &sensitive, + RC_Load_inPublic, RC_Load_inPrivate, + &out->name); + if(result == TPM_RC_SUCCESS) + { + // Set the common OBJECT attributes for a loaded object. + ObjectSetLoadedAttributes(newObject, in->parentHandle, + parentObject->seedCompatLevel); // libtpms added + } + return result; +} +#endif // CC_Load +#include "Tpm.h" +#include "LoadExternal_fp.h" +#if CC_LoadExternal // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_LoadExternal( + LoadExternal_In *in, // IN: input parameter list + LoadExternal_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *object; + TPMT_SENSITIVE *sensitive = NULL; + // Input Validation + // Don't get invested in loading if there is no place to put it. + object = FindEmptyObjectSlot(&out->objectHandle); + if(object == NULL) + return TPM_RC_OBJECT_MEMORY; + // If the hierarchy to be associated with this object is turned off, the object + // cannot be loaded. + if(!HierarchyIsEnabled(in->hierarchy)) + return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy; + // For loading an object with both public and sensitive + if(in->inPrivate.size != 0) + { + // An external object with a sensitive area can only be loaded in the + // NULL hierarchy + if(in->hierarchy != TPM_RH_NULL) + return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy; + // An external object with a sensitive area must have fixedTPM == CLEAR + // fixedParent == CLEAR so that it does not appear to be a key created by + // this TPM. + if(IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedTPM) + || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, + fixedParent) + || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, + restricted)) + return TPM_RCS_ATTRIBUTES + RC_LoadExternal_inPublic; + // Have sensitive point to something other than NULL so that object + // initialization will load the sensitive part too + sensitive = &in->inPrivate.sensitiveArea; + } + // Need the name to initialize the object structure + PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name); + // Load and validate key + result = ObjectLoad(object, NULL, + &in->inPublic.publicArea, sensitive, + RC_LoadExternal_inPublic, RC_LoadExternal_inPrivate, + &out->name); + if(result == TPM_RC_SUCCESS) + { + object->attributes.external = SET; + // Set the common OBJECT attributes for a loaded object. + ObjectSetLoadedAttributes(object, in->hierarchy, + // if anything can be derived from an external object, + // we make sure it always uses the old algorithm + SEED_COMPAT_LEVEL_ORIGINAL); // libtpms added + } + return result; +} +#endif // CC_LoadExternal +#include "Tpm.h" +#include "ReadPublic_fp.h" +#if CC_ReadPublic // Conditional expansion of this file +TPM_RC +TPM2_ReadPublic( + ReadPublic_In *in, // IN: input parameter list + ReadPublic_Out *out // OUT: output parameter list + ) +{ + OBJECT *object = HandleToObject(in->objectHandle); + // Input Validation + // Can not read public area of a sequence object + if(ObjectIsSequence(object)) + return TPM_RC_SEQUENCE; + // Command Output + out->outPublic.publicArea = object->publicArea; + out->name = object->name; + out->qualifiedName = object->qualifiedName; + return TPM_RC_SUCCESS; +} +#endif // CC_ReadPublic +#include "Tpm.h" +#include "ActivateCredential_fp.h" +#if CC_ActivateCredential // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_ActivateCredential( + ActivateCredential_In *in, // IN: input parameter list + ActivateCredential_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT *object; // decrypt key + OBJECT *activateObject; // key associated with credential + TPM2B_DATA data; // credential data + // Input Validation + // Get decrypt key pointer + object = HandleToObject(in->keyHandle); + // Get certificated object pointer + activateObject = HandleToObject(in->activateHandle); + // input decrypt key must be an asymmetric, restricted decryption key + if(!CryptIsAsymAlgorithm(object->publicArea.type) + || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) + || !IS_ATTRIBUTE(object->publicArea.objectAttributes, + TPMA_OBJECT, restricted)) + return TPM_RCS_TYPE + RC_ActivateCredential_keyHandle; + // Command output + // Decrypt input credential data via asymmetric decryption. A + // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this + // point + result = CryptSecretDecrypt(object, NULL, IDENTITY_STRING, &in->secret, &data); + if(result != TPM_RC_SUCCESS) + { + if(result == TPM_RC_KEY) + return TPM_RC_FAILURE; + return RcSafeAddToResult(result, RC_ActivateCredential_secret); + } + // Retrieve secret data. A TPM_RC_INTEGRITY error or unmarshal + // errors may be returned at this point + result = CredentialToSecret(&in->credentialBlob.b, + &activateObject->name.b, + &data.b, + object, + &out->certInfo); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_ActivateCredential_credentialBlob); + return TPM_RC_SUCCESS; +} +#endif // CC_ActivateCredential +#include "Tpm.h" +#include "MakeCredential_fp.h" +#if CC_MakeCredential // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_MakeCredential( + MakeCredential_In *in, // IN: input parameter list + MakeCredential_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT *object; + TPM2B_DATA data; + // Input Validation + // Get object pointer + object = HandleToObject(in->handle); + // input key must be an asymmetric, restricted decryption key + // NOTE: Needs to be restricted to have a symmetric value. + if(!CryptIsAsymAlgorithm(object->publicArea.type) + || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) + || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_TYPE + RC_MakeCredential_handle; + // The credential information may not be larger than the digest size used for + // the Name of the key associated with handle. + if(in->credential.t.size > CryptHashGetDigestSize(object->publicArea.nameAlg)) + return TPM_RCS_SIZE + RC_MakeCredential_credential; + // Command Output + // Make encrypt key and its associated secret structure. + out->secret.t.size = sizeof(out->secret.t.secret); + result = CryptSecretEncrypt(object, IDENTITY_STRING, &data, &out->secret); + if(result != TPM_RC_SUCCESS) + return result; + // Prepare output credential data from secret + SecretToCredential(&in->credential, &in->objectName.b, &data.b, + object, &out->credentialBlob); + return TPM_RC_SUCCESS; +} +#endif // CC_MakeCredential +#include "Tpm.h" +#include "Unseal_fp.h" +#if CC_Unseal // Conditional expansion of this file +TPM_RC +TPM2_Unseal( + Unseal_In *in, + Unseal_Out *out + ) +{ + OBJECT *object; + // Input Validation + // Get pointer to loaded object + object = HandleToObject(in->itemHandle); + // Input handle must be a data object + if(object->publicArea.type != TPM_ALG_KEYEDHASH) + return TPM_RCS_TYPE + RC_Unseal_itemHandle; + if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) + || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign) + || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_Unseal_itemHandle; + // Command Output + // Copy data + out->outData = object->sensitive.sensitive.bits; + return TPM_RC_SUCCESS; +} +#endif // CC_Unseal +#include "Tpm.h" +#include "ObjectChangeAuth_fp.h" +#if CC_ObjectChangeAuth // Conditional expansion of this file +#include "Object_spt_fp.h" +TPM_RC +TPM2_ObjectChangeAuth( + ObjectChangeAuth_In *in, // IN: input parameter list + ObjectChangeAuth_Out *out // OUT: output parameter list + ) +{ + TPMT_SENSITIVE sensitive; + OBJECT *object = HandleToObject(in->objectHandle); + TPM2B_NAME QNCompare; + // Input Validation + // Can not change authorization on sequence object + if(ObjectIsSequence(object)) + return TPM_RCS_TYPE + RC_ObjectChangeAuth_objectHandle; + // Make sure that the authorization value is consistent with the nameAlg + if(!AdjustAuthSize(&in->newAuth, object->publicArea.nameAlg)) + return TPM_RCS_SIZE + RC_ObjectChangeAuth_newAuth; + // Parent handle should be the parent of object handle. In this + // implementation we verify this by checking the QN of object. Other + // implementation may choose different method to verify this attribute. + ComputeQualifiedName(in->parentHandle, + object->publicArea.nameAlg, + &object->name, &QNCompare); + if(!MemoryEqual2B(&object->qualifiedName.b, &QNCompare.b)) + return TPM_RCS_TYPE + RC_ObjectChangeAuth_parentHandle; + // Command Output + // Prepare the sensitive area with the new authorization value + sensitive = object->sensitive; + sensitive.authValue = in->newAuth; + // Protect the sensitive area + SensitiveToPrivate(&sensitive, &object->name, HandleToObject(in->parentHandle), + object->publicArea.nameAlg, + &out->outPrivate); + return TPM_RC_SUCCESS; +} +#endif // CC_ObjectChangeAuth +#include "Tpm.h" +#include "CreateLoaded_fp.h" +#if CC_CreateLoaded // Conditional expansion of this file +TPM_RC +TPM2_CreateLoaded( + CreateLoaded_In *in, // IN: input parameter list + CreateLoaded_Out *out // OUT: output parameter list + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT *parent = HandleToObject(in->parentHandle); + OBJECT *newObject; + BOOL derivation; + TPMT_PUBLIC *publicArea; + RAND_STATE randState; + RAND_STATE *rand = &randState; + TPMS_DERIVE labelContext; + SEED_COMPAT_LEVEL seedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + // Input Validation + // How the public area is unmarshaled is determined by the parent, so + // see if parent is a derivation parent + derivation = (parent != NULL && parent->attributes.derivation); + // If the parent is an object, then make sure that it is either a parent or + // derivation parent + if(parent != NULL && !parent->attributes.isParent && !derivation) + return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle; + // Get a spot in which to create the newObject + newObject = FindEmptyObjectSlot(&out->objectHandle); + if(newObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Do this to save typing + publicArea = &newObject->publicArea; + // Unmarshal the template into the object space. TPM2_Create() and + // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher. + // This command is different because of an unfortunate property of the + // unique field of an ECC key. It is a structure rather than a single TPM2B. If + // if had been a TPM2B, then the label and context could be within a TPM2B and + // unmarshaled like other public areas. Since it is not, this command needs its + // on template that is a TPM2B that is unmarshaled as a BYTE array with a + // its own unmarshal function. + result = UnmarshalToPublic(publicArea, &in->inPublic, derivation, + &labelContext); + if(result != TPM_RC_SUCCESS) + return result + RC_CreateLoaded_inPublic; + // Validate that the authorization size is appropriate + if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) + return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive; + // Command output + if(derivation) + { + TPMT_KEYEDHASH_SCHEME *scheme; + scheme = &parent->publicArea.parameters.keyedHashDetail.scheme; + // SP800-108 is the only KDF supported by this implementation and there is + // no default hash algorithm. + pAssert(scheme->details.xorr.hashAlg != TPM_ALG_NULL + && scheme->details.xorr.kdf == TPM_ALG_KDF1_SP800_108); + // Don't derive RSA keys + if(publicArea->type == TPM_ALG_RSA) + return TPM_RCS_TYPE + RC_CreateLoaded_inPublic; + // sensitiveDataOrigin has to be CLEAR in a derived object. Since this + // is specific to a derived object, it is checked here. + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, + sensitiveDataOrigin)) + return TPM_RCS_ATTRIBUTES; + // Check the reset of the attributes + result = PublicAttributesValidation(parent, publicArea); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); + // Process the template and sensitive areas to get the actual 'label' and + // 'context' values to be used for this derivation. + result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data); + if(result != TPM_RC_SUCCESS) + return result; + // Set up the KDF for object generation + DRBG_InstantiateSeededKdf((KDF_STATE *)rand, + scheme->details.xorr.hashAlg, + scheme->details.xorr.kdf, + &parent->sensitive.sensitive.bits.b, + &labelContext.label.b, + &labelContext.context.b, + TPM_MAX_DERIVATION_BITS); + // Clear the sensitive size so that the creation functions will not try + // to use this value. + in->inSensitive.sensitive.data.t.size = 0; + seedCompatLevel = parent->seedCompatLevel; // libtpms added + } + else + { + // Check attributes in input public area. CreateChecks() checks the things + // that are unique to creation and then validates the attributes and values + // that are common to create and load. + result = CreateChecks(parent, publicArea, + in->inSensitive.sensitive.data.t.size); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); + // Creating a primary object + if(parent == NULL) + { + TPM2B_NAME name; + newObject->attributes.primary = SET; + if(in->parentHandle == TPM_RH_ENDORSEMENT) + newObject->attributes.epsHierarchy = SET; + seedCompatLevel = + HierarchyGetPrimarySeedCompatLevel(in->parentHandle); // libtpms added + // If so, use the primary seed and the digest of the template + // to seed the DRBG + result = DRBG_InstantiateSeeded((DRBG_STATE *)rand, + &HierarchyGetPrimarySeed(in->parentHandle)->b, + PRIMARY_OBJECT_CREATION, + (TPM2B *)PublicMarshalAndComputeName(publicArea,&name), + &in->inSensitive.sensitive.data.b, + seedCompatLevel); // libtpms added + if (result != TPM_RC_SUCCESS) + return result; + } + else + // This is an ordinary object so use the normal random number generator + rand = NULL; + } + // Internal data update + // Create the object + result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand); + if(result != TPM_RC_SUCCESS) + return result; + // if this is not a Primary key and not a derived key, then return the sensitive + // area + if(parent != NULL && !derivation) + // Prepare output private data from sensitive + SensitiveToPrivate(&newObject->sensitive, &newObject->name, + parent, newObject->publicArea.nameAlg, + &out->outPrivate); + else + out->outPrivate.t.size = 0; + // Set the remaining return values + out->outPublic.publicArea = newObject->publicArea; + out->name = newObject->name; + // Set the remaining attributes for a loaded object + ObjectSetLoadedAttributes(newObject, in->parentHandle, + seedCompatLevel); // libtpms added + return result; +} +#endif // CC_CreateLoaded diff --git a/src/tpm2/Object_fp.h b/src/tpm2/Object_fp.h new file mode 100644 index 0000000..327fd82 --- /dev/null +++ b/src/tpm2/Object_fp.h @@ -0,0 +1,236 @@ +/********************************************************************************/ +/* */ +/* Functions That Manage the Object Store of the TPM */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Object_fp.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#ifndef OBJECT_FP_H +#define OBJECT_FP_H + +void +ObjectFlush( + OBJECT *object + ); +void +ObjectSetInUse( + OBJECT *object + ); +BOOL +ObjectStartup( + void + ); +void +ObjectCleanupEvict( + void + ); +BOOL +IsObjectPresent( + TPMI_DH_OBJECT handle // IN: handle to be checked + ); +BOOL +ObjectIsSequence( + OBJECT *object // IN: handle to be checked + ); +OBJECT* +HandleToObject( + TPMI_DH_OBJECT handle // IN: handle of the object + ); +UINT16 +GetName( + TPMI_DH_OBJECT handle, // IN: handle of the object + NAME *name // OUT: name of the object + ); +void +GetQualifiedName( + TPMI_DH_OBJECT handle, // IN: handle of the object + TPM2B_NAME *qualifiedName // OUT: qualified name of the object + ); +TPMI_RH_HIERARCHY +ObjectGetHierarchy( + OBJECT *object // IN :object + ); +TPMI_RH_HIERARCHY +GetHieriarchy( + TPMI_DH_OBJECT handle // IN :object handle + ); +OBJECT * +FindEmptyObjectSlot( + TPMI_DH_OBJECT *handle // OUT: (optional) + ); +OBJECT * +ObjectAllocateSlot( + TPMI_DH_OBJECT *handle // OUT: handle of allocated object + ); +void +ObjectSetLoadedAttributes( + OBJECT *object, // IN: object attributes to finalize + TPM_HANDLE parentHandle, // IN: the parent handle + SEED_COMPAT_LEVEL seedCompatLevel // IN: seedCompatLevel to use for children + ); +TPM_RC +ObjectLoad( + OBJECT *object, // IN: pointer to object slot + // object + OBJECT *parent, // IN: (optional) the parent object + TPMT_PUBLIC *publicArea, // IN: public area to be installed in the object + TPMT_SENSITIVE *sensitive, // IN: (optional) sensitive area to be + // installed in the object + TPM_RC blamePublic, // IN: parameter number to associate with the + // publicArea errors + TPM_RC blameSensitive,// IN: parameter number to associate with the + // sensitive area errors + TPM2B_NAME *name // IN: (optional) + ); +TPM_RC +ObjectCreateHMACSequence( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + OBJECT *keyObject, // IN: the object containing the HMAC key + TPM2B_AUTH *auth, // IN: authValue + TPMI_DH_OBJECT *newHandle // OUT: HMAC sequence object handle + ); +TPM_RC +ObjectCreateHashSequence( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + TPM2B_AUTH *auth, // IN: authValue + TPMI_DH_OBJECT *newHandle // OUT: sequence object handle + ); +TPM_RC +ObjectCreateEventSequence( + TPM2B_AUTH *auth, // IN: authValue + TPMI_DH_OBJECT *newHandle // OUT: sequence object handle + ); +void +ObjectTerminateEvent( + void + ); +#if 0 // libtpms added +OBJECT * +ObjectContextLoad( + ANY_OBJECT_BUFFER *object, // IN: pointer to object structure in saved + // context + TPMI_DH_OBJECT *handle // OUT: object handle + ); +#endif // libtpms added begin +OBJECT * +ObjectContextLoadLibtpms(BYTE *buffer, // IN: buffer holding the marshaled object + INT32 size, // IN: size of buffer + TPMI_DH_OBJECT *handle // OUT: object handle + ); + // libtpms added end +void +FlushObject( + TPMI_DH_OBJECT handle // IN: handle to be freed + ); +void +ObjectFlushHierarchy( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush + ); +TPM_RC +ObjectLoadEvict( + TPM_HANDLE *handle, // IN:OUT: evict object handle. If success, it + // will be replace by the loaded object handle + COMMAND_INDEX commandIndex // IN: the command being processed + ); +TPM2B_NAME * +ObjectComputeName( + UINT32 size, // IN: the size of the area to digest + BYTE *publicArea, // IN: the public area to digest area + TPM_ALG_ID nameAlg, // IN: the hash algorithm to use + TPM2B_NAME *name // OUT: Computed name + ); +TPM2B_NAME * +PublicMarshalAndComputeName( + TPMT_PUBLIC *publicArea, // IN: public area of an object + TPM2B_NAME *name // OUT: name of the object + ); +TPMI_ALG_HASH +AlgOfName( + TPM2B_NAME *name + ); +void +ComputeQualifiedName( + TPM_HANDLE parentHandle, // IN: parent's name + TPM_ALG_ID nameAlg, // IN: name hash + TPM2B_NAME *name, // IN: name of the object + TPM2B_NAME *qualifiedName // OUT: qualified name of the object + ); +BOOL +ObjectIsStorage( + TPMI_DH_OBJECT handle // IN: object handle + ); +TPMI_YES_NO +ObjectCapGetLoaded( + TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ); +UINT32 +ObjectCapGetTransientAvail( + void + ); +TPMA_OBJECT +ObjectGetPublicAttributes( + TPM_HANDLE handle + ); +OBJECT_ATTRIBUTES +ObjectGetProperties( + TPM_HANDLE handle + ); + + +#endif diff --git a/src/tpm2/Object_spt.c b/src/tpm2/Object_spt.c new file mode 100644 index 0000000..3be6717 --- /dev/null +++ b/src/tpm2/Object_spt.c @@ -0,0 +1,1419 @@ +/********************************************************************************/ +/* */ +/* Object Command Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Object_spt.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 7.6 Object Command Support (Object_spt.c) */ +/* 7.6.1 Includes */ +#include "Tpm.h" +#include "Object_spt_fp.h" +/* 7.6.2 Local Functions */ +/* 7.6.2.1 GetIV2BSize() */ +/* Get the size of TPM2B_IV in canonical form that will be append to the start of the sensitive + data. It includes both size of size field and size of iv data */ +/* Return Values Meaning */ +static UINT16 +GetIV2BSize( + OBJECT *protector // IN: the protector handle + ) +{ + TPM_ALG_ID symAlg; + UINT16 keyBits; + // Determine the symmetric algorithm and size of key + if(protector == NULL) + { + // Use the context encryption algorithm and key size + symAlg = CONTEXT_ENCRYPT_ALG; + keyBits = CONTEXT_ENCRYPT_KEY_BITS; + } + else + { + symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm; + keyBits = protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym; + } + // The IV size is a UINT16 size field plus the block size of the symmetric + // algorithm + return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits); +} +/* 7.6.2.2 ComputeProtectionKeyParms() */ +/* This function retrieves the symmetric protection key parameters for the sensitive data The + parameters retrieved from this function include encryption algorithm, key size in bit, and a + TPM2B_SYM_KEY containing the key material as well as the key size in bytes This function is used + for any action that requires encrypting or decrypting of the sensitive area of an object or a + credential blob */ +static void +ComputeProtectionKeyParms( + OBJECT *protector, // IN: the protector object + TPM_ALG_ID hashAlg, // IN: hash algorithm for KDFa + TPM2B *name, // IN: name of the object + TPM2B *seedIn, /* IN: optional seed for duplication + blob. */ + // For non duplication blob, this parameter should be NULL + TPM_ALG_ID *symAlg, // OUT: the symmetric algorithm + UINT16 *keyBits, // OUT: the symmetric key size in bits + TPM2B_SYM_KEY *symKey // OUT: the symmetric key + ) +{ + const TPM2B *seed = seedIn; + // Determine the algorithms for the KDF and the encryption/decryption + // For TPM_RH_NULL, using context settings + if(protector == NULL) + { + // Use the context encryption algorithm and key size + *symAlg = CONTEXT_ENCRYPT_ALG; + symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; + *keyBits = CONTEXT_ENCRYPT_KEY_BITS; + } + else + { + TPMT_SYM_DEF_OBJECT *symDef; + symDef = &protector->publicArea.parameters.asymDetail.symmetric; + *symAlg = symDef->algorithm; + *keyBits = symDef->keyBits.sym; + symKey->t.size = (*keyBits + 7) / 8; + } + // Get seed for KDF + if(seed == NULL) + seed = GetSeedForKDF(protector); + // KDFa to generate symmetric key and IV value + CryptKDFa(hashAlg, seed, STORAGE_KEY, name, NULL, + symKey->t.size * 8, symKey->t.buffer, NULL, FALSE); + return; +} +/* 7.6.2.3 ComputeOuterIntegrity() */ +/* The sensitive area parameter is a buffer that holds a space for the integrity value and the + marshaled sensitive area. The caller should skip over the area set aside for the integrity value + and compute the hash of the remainder of the object. The size field of sensitive is in + unmarshaled form and the sensitive area contents is an array of bytes. */ +static void +ComputeOuterIntegrity( + TPM2B *name, // IN: the name of the object + OBJECT *protector, // IN: the object that + // provides protection. For an object, + // it is a parent. For a credential, it + // is the encrypt object. For + // a Temporary Object, it is NULL + TPMI_ALG_HASH hashAlg, // IN: algorithm to use for integrity + TPM2B *seedIn, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL + UINT32 sensitiveSize, // IN: size of the marshaled sensitive data + BYTE *sensitiveData, // IN: sensitive area + TPM2B_DIGEST *integrity // OUT: integrity + ) +{ + HMAC_STATE hmacState; + TPM2B_DIGEST hmacKey; + const TPM2B *seed = seedIn; + // + // Get seed for KDF + if(seed == NULL) + seed = GetSeedForKDF(protector); + // Determine the HMAC key bits + hmacKey.t.size = CryptHashGetDigestSize(hashAlg); + // KDFa to generate HMAC key + CryptKDFa(hashAlg, seed, INTEGRITY_KEY, NULL, NULL, + hmacKey.t.size * 8, hmacKey.t.buffer, NULL, FALSE); + // Start HMAC and get the size of the digest which will become the integrity + integrity->t.size = CryptHmacStart2B(&hmacState, hashAlg, &hmacKey.b); + // Adding the marshaled sensitive area to the integrity value + CryptDigestUpdate(&hmacState.hashState, sensitiveSize, sensitiveData); + // Adding name + CryptDigestUpdate2B(&hmacState.hashState, name); + // Compute HMAC + CryptHmacEnd2B(&hmacState, &integrity->b); + return; +} +/* 7.6.2.4 ComputeInnerIntegrity() */ +/* This function computes the integrity of an inner wrap */ +static void +ComputeInnerIntegrity( + TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap + TPM2B *name, // IN: the name of the object + UINT16 dataSize, // IN: the size of sensitive data + BYTE *sensitiveData, // IN: sensitive data + TPM2B_DIGEST *integrity // OUT: inner integrity + ) +{ + HASH_STATE hashState; + // + // Start hash and get the size of the digest which will become the integrity + integrity->t.size = CryptHashStart(&hashState, hashAlg); + // Adding the marshaled sensitive area to the integrity value + CryptDigestUpdate(&hashState, dataSize, sensitiveData); + // Adding name + CryptDigestUpdate2B(&hashState, name); + // Compute hash + CryptHashEnd2B(&hashState, &integrity->b); + return; +} +/* 7.6.2.5 ProduceInnerIntegrity() */ +/* This function produces an inner integrity for regular private, credential or duplication blob It + requires the sensitive data being marshaled to the innerBuffer, with the leading bytes reserved + for integrity hash. It assume the sensitive data starts at address (innerBuffer + integrity + size). This function integrity at the beginning of the inner buffer It returns the total size of + buffer with the inner wrap */ +static UINT16 +ProduceInnerIntegrity( + TPM2B *name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap + UINT16 dataSize, /* IN: the size of sensitive data, excluding + the leading integrity buffer size */ + BYTE *innerBuffer // IN/OUT: inner buffer with sensitive data in + // it. At input, the leading bytes of this + // buffer is reserved for integrity + ) +{ + BYTE *sensitiveData; // pointer to the sensitive data + TPM2B_DIGEST integrity; + UINT16 integritySize; + BYTE *buffer; // Auxiliary buffer pointer + // sensitiveData points to the beginning of sensitive data in innerBuffer + integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); + sensitiveData = innerBuffer + integritySize; + ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity); + // Add integrity at the beginning of inner buffer + buffer = innerBuffer; + TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); + return dataSize + integritySize; +} +/* 7.6.2.6 CheckInnerIntegrity() */ +/* This function check integrity of inner blob */ +/* Error Returns Meaning */ +/* TPM_RC_INTEGRITY if the outer blob integrity is bad */ +/* unmarshal errors unmarshal errors while unmarshaling integrity */ +static TPM_RC +CheckInnerIntegrity( + TPM2B *name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap + UINT16 dataSize, // IN: the size of sensitive data, including the + // leading integrity buffer size + BYTE *innerBuffer // IN/OUT: inner buffer with sensitive data in + // it + ) +{ + TPM_RC result; + TPM2B_DIGEST integrity; + TPM2B_DIGEST integrityToCompare; + BYTE *buffer; // Auxiliary buffer pointer + INT32 size; + // Unmarshal integrity + buffer = innerBuffer; + size = (INT32)dataSize; + result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); + if(result == TPM_RC_SUCCESS) + { + // Compute integrity to compare + ComputeInnerIntegrity(hashAlg, name, (UINT16)size, buffer, + &integrityToCompare); + // Compare outer blob integrity + if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) + result = TPM_RC_INTEGRITY; + } + return result; +} +/* 7.6.3 Public Functions */ +/* 7.6.3.1 AdjustAuthSize() */ +/* This function will validate that the input authValue is no larger than the digestSize for the + nameAlg. It will then pad with zeros to the size of the digest. */ +BOOL +AdjustAuthSize( + TPM2B_AUTH *auth, // IN/OUT: value to adjust + TPMI_ALG_HASH nameAlg // IN: + ) +{ + UINT16 digestSize; + // If there is no nameAlg, then this is a LoadExternal and the authVale can + // be any size up to the maximum allowed by the implementation + digestSize = (nameAlg == TPM_ALG_NULL) ? sizeof(TPMU_HA) + : CryptHashGetDigestSize(nameAlg); + if(digestSize < MemoryRemoveTrailingZeros(auth)) + return FALSE; + else if(digestSize > auth->t.size) + MemoryPad2B(&auth->b, digestSize); + auth->t.size = digestSize; + return TRUE; +} +/* 7.6.3.2 AreAttributesForParent() */ +/* This function is called by create, load, and import functions. */ +/* NOTE: The isParent attribute is SET when an object is loaded and it has attributes that are + suitable for a parent object. */ +/* Return Values Meaning */ +/* TRUE properties are those of a parent */ +/* FALSE properties are not those of a parent */ +BOOL +ObjectIsParent( + OBJECT *parentObject // IN: parent handle + ) +{ + return parentObject->attributes.isParent; +} +/* 7.6.3.3 CreateChecks() */ +/* Attribute checks that are unique to creation. */ +/* Error Returns Meaning */ +/* TPM_RC_ATTRIBUTES sensitiveDataOrigin is not consistent with the object type */ +/* other returns from PublicAttributesValidation() */ +TPM_RC +CreateChecks( + OBJECT *parentObject, + TPMT_PUBLIC *publicArea, + UINT16 sensitiveDataSize + ) +{ + TPMA_OBJECT attributes = publicArea->objectAttributes; + TPM_RC result = TPM_RC_SUCCESS; + // + // If the caller indicates that they have provided the data, then make sure that + // they have provided some data. + if((!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + && (sensitiveDataSize == 0)) + return TPM_RCS_ATTRIBUTES; + // For an ordinary object, data can only be provided when sensitiveDataOrigin + // is CLEAR + if((parentObject != NULL) + && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + && (sensitiveDataSize != 0)) + return TPM_RCS_ATTRIBUTES; + switch(publicArea->type) + { + case TPM_ALG_KEYEDHASH: + // if this is a data object (sign == decrypt == CLEAR) then the + // TPM cannot be the data source. + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt) + && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + result = TPM_RC_ATTRIBUTES; + // comment out the next line in order to prevent a fixedTPM derivation + // parent + // break; + case TPM_ALG_SYMCIPHER: + // A restricted key symmetric key (SYMCIPHER and KEYEDHASH) + // must have sensitiveDataOrigin SET unless it has fixedParent and + // fixedTPM CLEAR. + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) + || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) + result = TPM_RCS_ATTRIBUTES; + break; + default: // Asymmetric keys cannot have the sensitive portion provided + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + result = TPM_RCS_ATTRIBUTES; + break; + } + if(TPM_RC_SUCCESS == result) + { + result = PublicAttributesValidation(parentObject, publicArea); + } + return result; +} +/* 7.6.3.4 SchemeChecks */ +/* This function is called by TPM2_LoadExternal() and PublicAttributesValidation(). This function + validates the schemes in the public area of an object. */ +/* Error Returns Meaning */ +/* TPM_RC_HASH non-duplicable storage key and its parent have different name algorithm */ +/* TPM_RC_KDF incorrect KDF specified for decrypting keyed hash object */ +/* TPM_RC_KEY invalid key size values in an asymmetric key public area */ +/* TPM_RCS_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID; or hash + algorithm is inconsistent with the scheme ID for keyed hash object */ +/* TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; or non-storage key with + symmetric algorithm different from TPM_ALG_NULL */ +TPM_RC +SchemeChecks( + OBJECT *parentObject, // IN: parent (null if primary seed) + TPMT_PUBLIC *publicArea // IN: public area of the object + ) +{ + TPMT_SYM_DEF_OBJECT *symAlgs = NULL; + TPM_ALG_ID scheme = TPM_ALG_NULL; + TPMA_OBJECT attributes = publicArea->objectAttributes; + TPMU_PUBLIC_PARMS *parms = &publicArea->parameters; + // + switch(publicArea->type) + { + case TPM_ALG_SYMCIPHER: + symAlgs = &parms->symDetail.sym; + // If this is a decrypt key, then only the block cipher modes (not + // SMAC) are valid. TPM_ALG_NULL is OK too. If this is a 'sign' key, + // then any mode that got through the unmarshaling is OK. + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt) + && !CryptSymModeIsValid(symAlgs->mode.sym, TRUE)) + return TPM_RCS_SCHEME; + break; + case TPM_ALG_KEYEDHASH: + scheme = parms->keyedHashDetail.scheme.scheme; + // if both sign and decrypt + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + // if both sign and decrypt are set or clear, then need + // TPM_ALG_NULL as scheme + if(scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + && scheme != TPM_ALG_HMAC) + return TPM_RCS_SCHEME; + else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + if(scheme != TPM_ALG_XOR) + return TPM_RCS_SCHEME; + // If this is a derivation parent, then the KDF needs to be + // SP800-108 for this implementation. This is the only derivation + // supported by this implementation. Other implementations could + // support additional schemes. There is no default. + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) + { + if(parms->keyedHashDetail.scheme.details.xorr.kdf + != TPM_ALG_KDF1_SP800_108) + return TPM_RCS_SCHEME; + // Must select a digest. + if(CryptHashGetDigestSize + (parms->keyedHashDetail.scheme.details.xorr.hashAlg) == 0) + return TPM_RCS_HASH; + } + } + break; + default: // handling for asymmetric + scheme = parms->asymDetail.scheme.scheme; + symAlgs = &parms->asymDetail.symmetric; + // if the key is both sign and decrypt, then the scheme must be + // TPM_ALG_NULL because there is no way to specify both a sign and a + // decrypt scheme in the key. + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + // scheme must be TPM_ALG_NULL + if(scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)) + { + // If this is a signing key, see if it has a signing scheme + if(CryptIsAsymSignScheme(publicArea->type, scheme)) + { + // if proper signing scheme then it needs a proper hash + if(parms->asymDetail.scheme.details.anySig.hashAlg + == TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + else + { + // signing key that does not have a proper signing scheme. + // This is OK if the key is not restricted and its scheme + // is TPM_ALG_NULL + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) + || scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + } + else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) + { + // for a restricted decryption key (a parent), scheme + // is required to be TPM_ALG_NULL + if(scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + else + { + // For an unrestricted decryption key, the scheme has to + // be a valid scheme or TPM_ALG_NULL + if(scheme != TPM_ALG_NULL && + !CryptIsAsymDecryptScheme(publicArea->type, scheme)) + return TPM_RCS_SCHEME; + } + } + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + // For an asymmetric key that is not a parent, the symmetric + // algorithms must be TPM_ALG_NULL + if(symAlgs->algorithm != TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC; + } + // Special checks for an ECC key +#if ALG_ECC + if(publicArea->type == TPM_ALG_ECC) + { + TPM_ECC_CURVE curveID; + const TPMT_ECC_SCHEME *curveScheme; + curveID = publicArea->parameters.eccDetail.curveID; + curveScheme = CryptGetCurveSignScheme(curveID); + // The curveId must be valid or the unmarshaling is busted. + pAssert(curveScheme != NULL); + // If the curveID requires a specific scheme, then the key must + // select the same scheme + if(curveScheme->scheme != TPM_ALG_NULL) + { + TPMS_ECC_PARMS *ecc = &publicArea->parameters.eccDetail; + if(scheme != curveScheme->scheme) + return TPM_RCS_SCHEME; + // The scheme can allow any hash, or not... + if(curveScheme->details.anySig.hashAlg != TPM_ALG_NULL + && (ecc->scheme.details.anySig.hashAlg + != curveScheme->details.anySig.hashAlg)) + return TPM_RCS_SCHEME; + } + // For now, the KDF must be TPM_ALG_NULL + if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL) + return TPM_RCS_KDF; + } +#endif + break; + } + // If this is a restricted decryption key with symmetric algorithms, then it + // is an ordinary parent (not a derivation parent). It needs to specific + // symmetric algorithms other than TPM_ALG_NULL + if(symAlgs != NULL + && IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) + && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + if(symAlgs->algorithm == TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC; +#if 0 //?? + // This next check is under investigation. Need to see if it will break Windows + // before it is enabled. If it does not, then it should be default because a + // the mode used with a parent is always CFB and Part 2 indicates as much. + if(symAlgs->mode.sym != TPM_ALG_CFB) + return TPM_RCS_MODE; +#endif + // If this parent is not duplicable, then the symmetric algorithms + // (encryption and hash) must match those of its parent + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) + && (parentObject != NULL)) + { + if(publicArea->nameAlg != parentObject->publicArea.nameAlg) + return TPM_RCS_HASH; + if(!MemoryEqual(symAlgs, &parentObject->publicArea.parameters, + sizeof(TPMT_SYM_DEF_OBJECT))) + return TPM_RCS_SYMMETRIC; + } + } + return TPM_RC_SUCCESS; +} +/* 7.6.3.5 PublicAttributesValidation() */ +/* This function validates the values in the public area of an object. This function is used in the + processing of TPM2_Create(), TPM2_CreatePrimary(), TPM2_CreateLoaded(), TPM2_Load(), + TPM2_Import(), and TPM2_LoadExternal(). For TPM2_Import() this is only used if the new parent has + fixedTPM SET. For TPM2_LoadExternal(), this is not used for a public-only key */ +/* Error Returns Meaning */ +/* TPM_RC_ATTRIBUTES fixedTPM, fixedParent, or encryptedDuplication attributes are inconsistent + between themselves or with those of the parent object; inconsistent restricted, decrypt and sign + attributes; attempt to inject sensitive data for an asymmetric key; attempt to create a symmetric + cipher key that is not a decryption key */ +/* TPM_RC_HASH nameAlg is TPM_ALG_NULL */ +/* TPM_RC_SIZE authPolicy size does not match digest size of the name algorithm in publicArea */ +/* other returns from SchemeChecks() */ +TPM_RC +PublicAttributesValidation( + OBJECT *parentObject, // IN: input parent object + TPMT_PUBLIC *publicArea // IN: public area of the object + ) +{ + TPMA_OBJECT attributes = publicArea->objectAttributes; + TPMA_OBJECT parentAttributes = TPMA_ZERO_INITIALIZER(); + // + if(parentObject != NULL) + parentAttributes = parentObject->publicArea.objectAttributes; + if(publicArea->nameAlg == TPM_ALG_NULL) + return TPM_RCS_HASH; + // If there is an authPolicy, it needs to be the size of the digest produced + // by the nameAlg of the object + if((publicArea->authPolicy.t.size != 0 + && (publicArea->authPolicy.t.size + != CryptHashGetDigestSize(publicArea->nameAlg)))) + return TPM_RCS_SIZE; + // If the parent is fixedTPM (including a Primary Object) the object must have + // the same value for fixedTPM and fixedParent + if(parentObject == NULL + || IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) + { + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) + != IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) + return TPM_RCS_ATTRIBUTES; + } + else + { + // The parent is not fixedTPM so the object can't be fixedTPM + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) + return TPM_RCS_ATTRIBUTES; + } + // See if sign and decrypt are the same + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + // a restricted key cannot have both SET or both CLEAR + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) + return TPM_RC_ATTRIBUTES; + // only a data object may have both sign and decrypt CLEAR + // BTW, since we know that decrypt==sign, no need to check both + if(publicArea->type != TPM_ALG_KEYEDHASH + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)) + return TPM_RC_ATTRIBUTES; + } + // If the object can't be duplicated (directly or indirectly) then there + // is no justification for having encryptedDuplication SET + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) + && IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) + return TPM_RCS_ATTRIBUTES; + // If a parent object has fixedTPM CLEAR, the child must have the + // same encryptedDuplication value as its parent. + // Primary objects are considered to have a fixedTPM parent (the seeds). + if(parentObject != NULL + && !IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) + { + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication) + != IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, encryptedDuplication)) + return TPM_RCS_ATTRIBUTES; + } + // Special checks for derived objects + if((parentObject != NULL) && (parentObject->attributes.derivation == SET)) + { + // A derived object has the same settings for fixedTPM as its parent + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) + != IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) + return TPM_RCS_ATTRIBUTES; + // A derived object is required to be fixedParent + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)) + return TPM_RCS_ATTRIBUTES; + } + return SchemeChecks(parentObject, publicArea); +} +/* 7.6.3.6 FillInCreationData() */ +/* Fill in creation data for an object. */ +void +FillInCreationData( + TPMI_DH_OBJECT parentHandle, // IN: handle of parent + TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm + TPML_PCR_SELECTION *creationPCR, // IN: PCR selection + TPM2B_DATA *outsideData, // IN: outside data + TPM2B_CREATION_DATA *outCreation, // OUT: creation data for output + TPM2B_DIGEST *creationDigest // OUT: creation digest + ) +{ + BYTE creationBuffer[sizeof(TPMS_CREATION_DATA)]; + BYTE *buffer; + HASH_STATE hashState; + // Fill in TPMS_CREATION_DATA in outCreation + // Compute PCR digest + PCRComputeCurrentDigest(nameHashAlg, creationPCR, + &outCreation->creationData.pcrDigest); + // Put back PCR selection list + outCreation->creationData.pcrSelect = *creationPCR; + // Get locality + outCreation->creationData.locality + = LocalityGetAttributes(_plat__LocalityGet()); + outCreation->creationData.parentNameAlg = TPM_ALG_NULL; + // If the parent is either a primary seed or TPM_ALG_NULL, then the Name + // and QN of the parent are the parent's handle. + if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) + { + buffer = &outCreation->creationData.parentName.t.name[0]; + outCreation->creationData.parentName.t.size = + TPM_HANDLE_Marshal(&parentHandle, &buffer, NULL); + // For a primary or temporary object, the parent name (a handle) and the + // parent's QN are the same + outCreation->creationData.parentQualifiedName + = outCreation->creationData.parentName; + } + else // Regular object + { + OBJECT *parentObject = HandleToObject(parentHandle); + // Set name algorithm + outCreation->creationData.parentNameAlg = + parentObject->publicArea.nameAlg; + // Copy parent name + outCreation->creationData.parentName = parentObject->name; + // Copy parent qualified name + outCreation->creationData.parentQualifiedName = + parentObject->qualifiedName; + } + // Copy outside information + outCreation->creationData.outsideInfo = *outsideData; + // Marshal creation data to canonical form + buffer = creationBuffer; + outCreation->size = TPMS_CREATION_DATA_Marshal(&outCreation->creationData, + &buffer, NULL); + // Compute hash for creation field in public template + creationDigest->t.size = CryptHashStart(&hashState, nameHashAlg); + CryptDigestUpdate(&hashState, outCreation->size, creationBuffer); + CryptHashEnd2B(&hashState, &creationDigest->b); + return; +} +/* 7.6.3.7 GetSeedForKDF() */ +/* Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. */ +/* Return Values Meaning */ +const TPM2B * +GetSeedForKDF( + OBJECT *protector // IN: the protector handle + ) +{ + // Get seed for encryption key. Use input seed if provided. + // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only + // exception that we may not have a loaded object as protector. In such a + // case, use nullProof as seed. + if(protector == NULL) + return &gr.nullProof.b; + else + return &protector->sensitive.seedValue.b; +} +/* 7.6.3.8 ProduceOuterWrap() */ +/* This function produce outer wrap for a buffer containing the sensitive data. It requires the + sensitive data being marshaled to the outerBuffer, with the leading bytes reserved for integrity + hash. If iv is used, iv space should be reserved at the beginning of the buffer. It assumes the + sensitive data starts at address (outerBuffer + integrity size {+ iv size}). This function: */ +/* a) adds IV before sensitive area if required */ +/* b) encrypts sensitive data with IV or a NULL IV as required */ +/* c) adds HMAC integrity at the beginning of the buffer */ +/* d) returns the total size of blob with outer wrap */ + +UINT16 +ProduceOuterWrap( + OBJECT *protector, // IN: The handle of the object that provides + // protection. For object, it is parent + // handle. For credential, it is the handle + // of encrypt object. + TPM2B *name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap + TPM2B *seed, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL + BOOL useIV, // IN: indicate if an IV is used + UINT16 dataSize, // IN: the size of sensitive data, excluding the + // leading integrity buffer size or the + // optional iv size + BYTE *outerBuffer // IN/OUT: outer buffer with sensitive data in + // it + ) +{ + TPM_ALG_ID symAlg; + UINT16 keyBits; + TPM2B_SYM_KEY symKey; + TPM2B_IV ivRNG; // IV from RNG + TPM2B_IV *iv = NULL; + UINT16 ivSize = 0; // size of iv area, including the size field + BYTE *sensitiveData; // pointer to the sensitive data + TPM2B_DIGEST integrity; + UINT16 integritySize; + BYTE *buffer; // Auxiliary buffer pointer + // Compute the beginning of sensitive data. The outer integrity should + // always exist if this function is called to make an outer wrap + integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); + sensitiveData = outerBuffer + integritySize; + // If iv is used, adjust the pointer of sensitive data and add iv before it + if(useIV) + { + ivSize = GetIV2BSize(protector); + // Generate IV from RNG. The iv data size should be the total IV area + // size minus the size of size field + ivRNG.t.size = ivSize - sizeof(UINT16); + CryptRandomGenerate(ivRNG.t.size, ivRNG.t.buffer); + // Marshal IV to buffer + buffer = sensitiveData; + TPM2B_IV_Marshal(&ivRNG, &buffer, NULL); + // adjust sensitive data starting after IV area + sensitiveData += ivSize; + // Use iv for encryption + iv = &ivRNG; + } + // Compute symmetric key parameters for outer buffer encryption + ComputeProtectionKeyParms(protector, hashAlg, name, seed, + &symAlg, &keyBits, &symKey); + // Encrypt inner buffer in place + CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits, + symKey.t.buffer, iv, TPM_ALG_CFB, dataSize, + sensitiveData); + // Compute outer integrity. Integrity computation includes the optional IV + // area + ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize, + outerBuffer + integritySize, &integrity); + // Add integrity at the beginning of outer buffer + buffer = outerBuffer; + TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); + // return the total size in outer wrap + return dataSize + integritySize + ivSize; +} +/* 7.6.3.9 UnwrapOuter() */ +/* This function remove the outer wrap of a blob containing sensitive data This function + performs: */ +/* a) check integrity of outer blob */ +/* b) decrypt outer blob */ +/* Error Returns Meaning */ +/* TPM_RCS_INSUFFICIENT error during sensitive data unmarshaling */ +/* TPM_RCS_INTEGRITY sensitive data integrity is broken */ +/* TPM_RCS_SIZE error during sensitive data unmarshaling */ +/* TPM_RCS_VALUE IV size for CFB does not match the encryption algorithm block size */ +TPM_RC +UnwrapOuter( + OBJECT *protector, // IN: The object that provides + // protection. For object, it is parent + // handle. For credential, it is the + // encrypt object. + TPM2B *name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap + TPM2B *seed, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL. + BOOL useIV, // IN: indicates if an IV is used + UINT16 dataSize, // IN: size of sensitive data in outerBuffer, + // including the leading integrity buffer + // size, and an optional iv area + BYTE *outerBuffer // IN/OUT: sensitive data + ) +{ + TPM_RC result; + TPM_ALG_ID symAlg = TPM_ALG_NULL; + TPM2B_SYM_KEY symKey; + UINT16 keyBits = 0; + TPM2B_IV ivIn; // input IV retrieved from input buffer + TPM2B_IV *iv = NULL; + BYTE *sensitiveData; // pointer to the sensitive data + TPM2B_DIGEST integrityToCompare; + TPM2B_DIGEST integrity; + INT32 size; + // Unmarshal integrity + sensitiveData = outerBuffer; + size = (INT32)dataSize; + result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size); + if(result == TPM_RC_SUCCESS) + { + // Compute integrity to compare + ComputeOuterIntegrity(name, protector, hashAlg, seed, + (UINT16)size, sensitiveData, + &integrityToCompare); + // Compare outer blob integrity + if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) + return TPM_RCS_INTEGRITY; + // Get the symmetric algorithm parameters used for encryption + ComputeProtectionKeyParms(protector, hashAlg, name, seed, + &symAlg, &keyBits, &symKey); + // Retrieve IV if it is used + if(useIV) + { + result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size); + if(result == TPM_RC_SUCCESS) + { + // The input iv size for CFB must match the encryption algorithm + // block size + if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits)) + result = TPM_RC_VALUE; + else + iv = &ivIn; + } + } + } + // If no errors, decrypt private in place. Since this function uses CFB, + // CryptSymmetricDecrypt() will not return any errors. It may fail but it will + // not return an error. + if(result == TPM_RC_SUCCESS) + CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits, + symKey.t.buffer, iv, TPM_ALG_CFB, + (UINT16)size, sensitiveData); + return result; +} +/* 7.6.3.10 MarshalSensitive() */ +/* This function is used to marshal a sensitive area. Among other things, it adjusts the size of the + authValue to be no smaller than the digest of nameAlg. + + Returns the size of the marshaled area. */ +static UINT16 +MarshalSensitive( + BYTE *buffer, // OUT: receiving buffer + TPMT_SENSITIVE *sensitive, // IN: the sensitive area to marshal + TPMI_ALG_HASH nameAlg // IN: + ) +{ + BYTE *sizeField = buffer; // saved so that size can be + // marshaled after it is known + UINT16 retVal; + // Pad the authValue if needed + MemoryPad2B(&sensitive->authValue.b, CryptHashGetDigestSize(nameAlg)); + buffer += 2; + // Marshal the structure + retVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL); + // Marshal the size + retVal = (UINT16)(retVal + UINT16_Marshal(&retVal, &sizeField, NULL)); + return retVal; +} +/* 7.6.3.11 SensitiveToPrivate() */ +/* This function prepare the private blob for off the chip storage The operations in this + function: */ +/* a) marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE */ +/* b) apply encryption to the sensitive area. */ +/* c) apply outer integrity computation. */ +void +SensitiveToPrivate( + TPMT_SENSITIVE *sensitive, // IN: sensitive structure + TPM2B_NAME *name, // IN: the name of the object + OBJECT *parent, // IN: The parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This + // parameter is used when parentHandle is + // NULL, in which case the object is + // temporary. + TPM2B_PRIVATE *outPrivate // OUT: output private structure + ) +{ + BYTE *sensitiveData; // pointer to the sensitive data + UINT16 dataSize; // data blob size + TPMI_ALG_HASH hashAlg; // hash algorithm for integrity + UINT16 integritySize; + UINT16 ivSize; + // + pAssert(name != NULL && name->t.size != 0); + // Find the hash algorithm for integrity computation + if(parent == NULL) + { + // For Temporary Object, using self name algorithm + hashAlg = nameAlg; + } + else + { + // Otherwise, using parent's name algorithm + hashAlg = parent->publicArea.nameAlg; + } + // Starting of sensitive data without wrappers + sensitiveData = outPrivate->t.buffer; + // Compute the integrity size + integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); + // Reserve space for integrity + sensitiveData += integritySize; + // Get iv size + ivSize = GetIV2BSize(parent); + // Reserve space for iv + sensitiveData += ivSize; + // Marshal the sensitive area including authValue size adjustments. + dataSize = MarshalSensitive(sensitiveData, sensitive, nameAlg); + //Produce outer wrap, including encryption and HMAC + outPrivate->t.size = ProduceOuterWrap(parent, &name->b, hashAlg, NULL, + TRUE, dataSize, outPrivate->t.buffer); + return; +} +/* 7.6.3.12 PrivateToSensitive() */ +/* Unwrap an input private area. Check the integrity, decrypt and retrieve data to a sensitive + structure. The operations in this function: */ +/* a) check the integrity HMAC of the input private area */ +/* b) decrypt the private buffer */ +/* c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE */ +/* Error Returns Meaning */ +/* TPM_RCS_INTEGRITY if the private area integrity is bad */ +/* TPM_RC_SENSITIVE unmarshal errors while unmarshaling TPMS_ENCRYPT from input private */ +/* TPM_RCS_SIZE error during sensitive data unmarshaling */ +/* TPM_RCS_VALUE outer wrapper does not have an iV of the correct size */ +TPM_RC +PrivateToSensitive( + TPM2B *inPrivate, // IN: input private structure + TPM2B *name, // IN: the name of the object + OBJECT *parent, // IN: parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is + // passed separately because we only pass + // name, rather than the whole public area + // of the object. This parameter is used in + // the following two cases: 1. primary + // objects. 2. duplication blob with inner + // wrap. In other cases, this parameter + // will be ignored + TPMT_SENSITIVE *sensitive // OUT: sensitive structure + ) +{ + TPM_RC result; + BYTE *buffer; + INT32 size; + BYTE *sensitiveData; // pointer to the sensitive data + UINT16 dataSize; + UINT16 dataSizeInput; + TPMI_ALG_HASH hashAlg; // hash algorithm for integrity + UINT16 integritySize; + UINT16 ivSize; + // + // Make sure that name is provided + pAssert(name != NULL && name->size != 0); + // Find the hash algorithm for integrity computation + if(parent == NULL) + { + // For Temporary Object, using self name algorithm + hashAlg = nameAlg; + } + else + { + // Otherwise, using parent's name algorithm + hashAlg = parent->publicArea.nameAlg; + } + // unwrap outer + result = UnwrapOuter(parent, name, hashAlg, NULL, TRUE, + inPrivate->size, inPrivate->buffer); + if(result != TPM_RC_SUCCESS) + return result; + // Compute the inner integrity size. + integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); + // Get iv size + ivSize = GetIV2BSize(parent); + // The starting of sensitive data and data size without outer wrapper + sensitiveData = inPrivate->buffer + integritySize + ivSize; + dataSize = inPrivate->size - integritySize - ivSize; + // Unmarshal input data size + buffer = sensitiveData; + size = (INT32)dataSize; + result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); + if(result == TPM_RC_SUCCESS) + { + if((dataSizeInput + sizeof(UINT16)) != dataSize) + result = TPM_RC_SENSITIVE; + else + { + // Unmarshal sensitive buffer to sensitive structure + result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); + if(result != TPM_RC_SUCCESS || size != 0) + { + result = TPM_RC_SENSITIVE; + } + } + } + return result; +} +/* 7.6.3.13 SensitiveToDuplicate() */ +/* This function prepare the duplication blob from the sensitive area. The operations in this + function: */ +/* a) marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE */ +/* b) apply inner wrap to the sensitive area if required */ +/* c) apply outer wrap if required */ +void +SensitiveToDuplicate( + TPMT_SENSITIVE *sensitive, // IN: sensitive structure + TPM2B *name, // IN: the name of the object + OBJECT *parent, // IN: The new parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It + // is passed separately because we + // only pass name, rather than the + // whole public area of the object. + TPM2B *seed, // IN: the external seed. If external + // seed is provided with size of 0, + // no outer wrap should be applied + // to duplication blob. + TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the + // symmetric key algorithm is NULL, + // no inner wrap should be applied. + TPM2B_DATA *innerSymKey, // IN/OUT: a symmetric key may be + // provided to encrypt the inner + // wrap of a duplication blob. May + // be generated here if needed. + TPM2B_PRIVATE *outPrivate // OUT: output private structure + ) +{ + BYTE *sensitiveData; // pointer to the sensitive data + TPMI_ALG_HASH outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap + TPMI_ALG_HASH innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap + UINT16 dataSize; // data blob size + BOOL doInnerWrap = FALSE; + BOOL doOuterWrap = FALSE; + // + // Make sure that name is provided + pAssert(name != NULL && name->size != 0); + // Make sure symDef and innerSymKey are not NULL + pAssert(symDef != NULL && innerSymKey != NULL); + // Starting of sensitive data without wrappers + sensitiveData = outPrivate->t.buffer; + // Find out if inner wrap is required + if(symDef->algorithm != TPM_ALG_NULL) + { + doInnerWrap = TRUE; + // Use self nameAlg as inner hash algorithm + innerHash = nameAlg; + // Adjust sensitive data pointer + sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(innerHash); + } + // Find out if outer wrap is required + if(seed->size != 0) + { + doOuterWrap = TRUE; + // Use parent nameAlg as outer hash algorithm + outerHash = parent->publicArea.nameAlg; + // Adjust sensitive data pointer + sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + } + // Marshal sensitive area + dataSize = MarshalSensitive(sensitiveData, sensitive, nameAlg); + // Apply inner wrap for duplication blob. It includes both integrity and + // encryption + if(doInnerWrap) + { + BYTE *innerBuffer = NULL; + BOOL symKeyInput = TRUE; + innerBuffer = outPrivate->t.buffer; + // Skip outer integrity space + if(doOuterWrap) + innerBuffer += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + dataSize = ProduceInnerIntegrity(name, innerHash, dataSize, + innerBuffer); + // Generate inner encryption key if needed + if(innerSymKey->t.size == 0) + { + innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8; + CryptRandomGenerate(innerSymKey->t.size, innerSymKey->t.buffer); + // TPM generates symmetric encryption. Set the flag to FALSE + symKeyInput = FALSE; + } + else + { + // assume the input key size should matches the symmetric definition + pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); + } + // Encrypt inner buffer in place + CryptSymmetricEncrypt(innerBuffer, symDef->algorithm, + symDef->keyBits.sym, innerSymKey->t.buffer, NULL, + TPM_ALG_CFB, dataSize, innerBuffer); + // If the symmetric encryption key is imported, clear the buffer for + // output + if(symKeyInput) + innerSymKey->t.size = 0; + } + // Apply outer wrap for duplication blob. It includes both integrity and + // encryption + if(doOuterWrap) + { + dataSize = ProduceOuterWrap(parent, name, outerHash, seed, FALSE, + dataSize, outPrivate->t.buffer); + } + // Data size for output + outPrivate->t.size = dataSize; + return; +} +/* 7.6.3.14 DuplicateToSensitive() */ +/* Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive + structure. The operations in this function: */ +/* a) check the integrity HMAC of the input private area */ +/* b) decrypt the private buffer */ +/* c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE */ +/* Error Returns Meaning */ +/* TPM_RC_INSUFFICIENT unmarshaling sensitive data from inPrivate failed */ +/* TPM_RC_INTEGRITY inPrivate data integrity is broken */ +/* TPM_RC_SIZE unmarshaling sensitive data from inPrivate failed */ +TPM_RC +DuplicateToSensitive( + TPM2B *inPrivate, // IN: input private structure + TPM2B *name, // IN: the name of the object + OBJECT *parent, // IN: the parent + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. + TPM2B *seed, // IN: an external seed may be provided. + // If external seed is provided with + // size of 0, no outer wrap is + // applied + TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the + // symmetric key algorithm is NULL, + // no inner wrap is applied + TPM2B *innerSymKey, // IN: a symmetric key may be provided + // to decrypt the inner wrap of a + // duplication blob. + TPMT_SENSITIVE *sensitive // OUT: sensitive structure + ) +{ + TPM_RC result; + BYTE *buffer; + INT32 size; + BYTE *sensitiveData; // pointer to the sensitive data + UINT16 dataSize; + UINT16 dataSizeInput; + // Make sure that name is provided + pAssert(name != NULL && name->size != 0); + // Make sure symDef and innerSymKey are not NULL + pAssert(symDef != NULL && innerSymKey != NULL); + // Starting of sensitive data + sensitiveData = inPrivate->buffer; + dataSize = inPrivate->size; + // Find out if outer wrap is applied + if(seed->size != 0) + { + // Use parent nameAlg as outer hash algorithm + TPMI_ALG_HASH outerHash = parent->publicArea.nameAlg; + result = UnwrapOuter(parent, name, outerHash, seed, FALSE, + dataSize, sensitiveData); + if(result != TPM_RC_SUCCESS) + return result; + // Adjust sensitive data pointer and size + sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + } + // Find out if inner wrap is applied + if(symDef->algorithm != TPM_ALG_NULL) + { + // assume the input key size matches the symmetric definition + pAssert(innerSymKey->size == (symDef->keyBits.sym + 7) / 8); + // Decrypt inner buffer in place + CryptSymmetricDecrypt(sensitiveData, symDef->algorithm, + symDef->keyBits.sym, innerSymKey->buffer, NULL, + TPM_ALG_CFB, dataSize, sensitiveData); + // Check inner integrity + result = CheckInnerIntegrity(name, nameAlg, dataSize, sensitiveData); + if(result != TPM_RC_SUCCESS) + return result; + // Adjust sensitive data pointer and size + sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(nameAlg); + dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(nameAlg); + } + // Unmarshal input data size + buffer = sensitiveData; + size = (INT32)dataSize; + result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); + if(result == TPM_RC_SUCCESS) + { + if((dataSizeInput + sizeof(UINT16)) != dataSize) + result = TPM_RC_SIZE; + else + { + // Unmarshal sensitive buffer to sensitive structure + result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); + // if the results is OK make sure that all the data was unmarshaled + if(result == TPM_RC_SUCCESS && size != 0) + result = TPM_RC_SIZE; + } + } + return result; +} +/* 7.6.3.15 SecretToCredential() */ +/* This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in this + function: */ +/* a) marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT */ +/* b) encrypt the private buffer, excluding the leading integrity HMAC area */ +/* c) compute integrity HMAC and append to the beginning of the buffer. */ +/* d) Set the total size of TPM2B_ID_OBJECT buffer */ +void +SecretToCredential( + TPM2B_DIGEST *secret, // IN: secret information + TPM2B *name, // IN: the name of the object + TPM2B *seed, // IN: an external seed. + OBJECT *protector, // IN: the protector + TPM2B_ID_OBJECT *outIDObject // OUT: output credential + ) +{ + BYTE *buffer; // Auxiliary buffer pointer + BYTE *sensitiveData; // pointer to the sensitive data + TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap + UINT16 dataSize; // data blob size + pAssert(secret != NULL && outIDObject != NULL); + // use protector's name algorithm as outer hash + outerHash = protector->publicArea.nameAlg; + // Marshal secret area to credential buffer, leave space for integrity + sensitiveData = outIDObject->t.credential + + sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + // Marshal secret area + buffer = sensitiveData; + dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, NULL); + // Apply outer wrap + outIDObject->t.size = ProduceOuterWrap(protector, name, outerHash, seed, FALSE, + dataSize, outIDObject->t.credential); + return; +} +/* 7.6.3.16 CredentialToSecret() */ +/* Unwrap a credential. Check the integrity, decrypt and retrieve data to a TPM2B_DIGEST + structure. The operations in this function: */ +/* a) check the integrity HMAC of the input credential area */ +/* b) decrypt the credential buffer */ +/* c) unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST */ +/* Error Returns Meaning */ +/* TPM_RC_INSUFFICIENT error during credential unmarshaling */ +/* TPM_RC_INTEGRITY credential integrity is broken */ +/* TPM_RC_SIZE error during credential unmarshaling */ +/* TPM_RC_VALUE IV size does not match the encryption algorithm block size */ +TPM_RC +CredentialToSecret( + TPM2B *inIDObject, // IN: input credential blob + TPM2B *name, // IN: the name of the object + TPM2B *seed, // IN: an external seed. + OBJECT *protector, // IN: the protector + TPM2B_DIGEST *secret // OUT: secret information + ) +{ + TPM_RC result; + BYTE *buffer; + INT32 size; + TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap + BYTE *sensitiveData; // pointer to the sensitive data + UINT16 dataSize; + // use protector's name algorithm as outer hash + outerHash = protector->publicArea.nameAlg; + // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point + result = UnwrapOuter(protector, name, outerHash, seed, FALSE, + inIDObject->size, inIDObject->buffer); + if(result == TPM_RC_SUCCESS) + { + // Compute the beginning of sensitive data + sensitiveData = inIDObject->buffer + + sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + dataSize = inIDObject->size + - (sizeof(UINT16) + CryptHashGetDigestSize(outerHash)); + // Unmarshal secret buffer to TPM2B_DIGEST structure + buffer = sensitiveData; + size = (INT32)dataSize; + result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size); + // If there were no other unmarshaling errors, make sure that the + // expected amount of data was recovered + if(result == TPM_RC_SUCCESS && size != 0) + return TPM_RC_SIZE; + } + return result; +} +/* 7.6.3.17 MemoryRemoveTrailingZeros() */ +/* This function is used to adjust the length of an authorization value. It adjusts the size of the + TPM2B so that it does not include octets at the end of the buffer that contain zero. The function + returns the number of non-zero octets in the buffer. */ +UINT16 +MemoryRemoveTrailingZeros( + TPM2B_AUTH *auth // IN/OUT: value to adjust + ) +{ + while((auth->t.size > 0) && (auth->t.buffer[auth->t.size - 1] == 0)) + auth->t.size--; + return auth->t.size; +} +/* 7.6.3.18 SetLabelAndContext() */ +/* This function sets the label and context for a derived key. It is possible that label or context + can end up being an Empty Buffer. */ +TPM_RC +SetLabelAndContext( + TPMS_DERIVE *labelContext, // IN/OUT: the recovered label and context + TPM2B_SENSITIVE_DATA *sensitive // IN: the sensitive data + ) +{ + TPMS_DERIVE sensitiveValue; + TPM_RC result; + INT32 size; + BYTE *buff; + // + // Unmarshal a TPMS_DERIVE from the TPM2B_SENSITIVE_DATA buffer + // If there is something to unmarshal... + if(sensitive->t.size != 0) + { + size = sensitive->t.size; + buff = sensitive->t.buffer; + result = TPMS_DERIVE_Unmarshal(&sensitiveValue, &buff, &size); + if(result != TPM_RC_SUCCESS) + return result; + // If there was a label in the public area leave it there, otherwise, copy + // the new value + if(labelContext->label.t.size == 0) + MemoryCopy2B(&labelContext->label.b, &sensitiveValue.label.b, + sizeof(labelContext->label.t.buffer)); + // if there was a context string in publicArea, it overrides + if(labelContext->context.t.size == 0) + MemoryCopy2B(&labelContext->context.b, &sensitiveValue.context.b, + sizeof(labelContext->label.t.buffer)); + } + return TPM_RC_SUCCESS; +} +/* 7.6.3.19 UnmarshalToPublic() */ +/* Support function to unmarshal the template. This is used because the Input may be a TPMT_TEMPLATE + and that structure does not have the same size as a TPMT_PUBLIC() because of the difference + between the unique and seed fields. If derive is not NULL, then the seed field is assumed to + contain a label and context that are unmarshaled into derive. */ +TPM_RC +UnmarshalToPublic( + TPMT_PUBLIC *tOut, // OUT: output + TPM2B_TEMPLATE *tIn, // IN: + BOOL derivation, // IN: indicates if this is for a derivation + TPMS_DERIVE *labelContext // OUT: label and context if derivation + ) +{ + BYTE *buffer = tIn->t.buffer; + INT32 size = tIn->t.size; + TPM_RC result; + // + // make sure that tOut is zeroed so that there are no remnants from previous + // uses + MemorySet(tOut, 0, sizeof(TPMT_PUBLIC)); + // Unmarshal the components of the TPMT_PUBLIC up to the unique field + result = TPMI_ALG_PUBLIC_Unmarshal(&tOut->type, &buffer, &size); + if(result != TPM_RC_SUCCESS) + return result; + result = TPMI_ALG_HASH_Unmarshal(&tOut->nameAlg, &buffer, &size, FALSE); + if(result != TPM_RC_SUCCESS) + return result; + result = TPMA_OBJECT_Unmarshal(&tOut->objectAttributes, &buffer, &size); + if(result != TPM_RC_SUCCESS) + return result; + result = TPM2B_DIGEST_Unmarshal(&tOut->authPolicy, &buffer, &size); + if(result != TPM_RC_SUCCESS) + return result; + result = TPMU_PUBLIC_PARMS_Unmarshal(&tOut->parameters, &buffer, &size, + tOut->type); + if(result != TPM_RC_SUCCESS) + return result; + // Now unmarshal a TPMS_DERIVE if this is for derivation + if(derivation) + result = TPMS_DERIVE_Unmarshal(labelContext, &buffer, &size); + else + // otherwise, unmarshal a TPMU_PUBLIC_ID + result = TPMU_PUBLIC_ID_Unmarshal(&tOut->unique, &buffer, &size, + tOut->type); + // Make sure the template was used up + if((result == TPM_RC_SUCCESS) && (size != 0)) + result = TPM_RC_SIZE; + return result; +} +#if 0 /* libtpms added */ +/* 7.6.3.20 ObjectSetExternal() */ +/* Set the external attributes for an object. */ +void +ObjectSetExternal( + OBJECT *object + ) +{ + object->attributes.external = SET; +} +#endif /* libtpms added */ diff --git a/src/tpm2/Object_spt_fp.h b/src/tpm2/Object_spt_fp.h new file mode 100644 index 0000000..16e1d92 --- /dev/null +++ b/src/tpm2/Object_spt_fp.h @@ -0,0 +1,250 @@ +/********************************************************************************/ +/* */ +/* Object Command Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Object_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef OBJECT_SPT_FP_H +#define OBJECT_SPT_FP_H + +BOOL +AdjustAuthSize( + TPM2B_AUTH *auth, // IN/OUT: value to adjust + TPMI_ALG_HASH nameAlg // IN: + ); +BOOL +ObjectIsParent( + OBJECT *parentObject // IN: parent handle + ); +TPM_RC +CreateChecks( + OBJECT *parentObject, + TPMT_PUBLIC *publicArea, + UINT16 sensitiveDataSize + ); +TPM_RC +SchemeChecks( + OBJECT *parentObject, // IN: parent (null if primary seed) + TPMT_PUBLIC *publicArea // IN: public area of the object + ); +TPM_RC +PublicAttributesValidation( + OBJECT *parentObject, // IN: input parent object + TPMT_PUBLIC *publicArea // IN: public area of the object + ); +void +FillInCreationData( + TPMI_DH_OBJECT parentHandle, // IN: handle of parent + TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm + TPML_PCR_SELECTION *creationPCR, // IN: PCR selection + TPM2B_DATA *outsideData, // IN: outside data + TPM2B_CREATION_DATA *outCreation, // OUT: creation data for output + TPM2B_DIGEST *creationDigest // OUT: creation digest + ); +const TPM2B * +GetSeedForKDF( + OBJECT *protector // IN: the protector handle + ); +UINT16 +ProduceOuterWrap( + OBJECT *protector, // IN: The handle of the object that provides + // protection. For object, it is parent + // handle. For credential, it is the handle + // of encrypt object. + TPM2B *name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap + TPM2B *seed, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL + BOOL useIV, // IN: indicate if an IV is used + UINT16 dataSize, // IN: the size of sensitive data, excluding the + // leading integrity buffer size or the + // optional iv size + BYTE *outerBuffer // IN/OUT: outer buffer with sensitive data in + // it + ); +TPM_RC +UnwrapOuter( + OBJECT *protector, // IN: The object that provides + // protection. For object, it is parent + // handle. For credential, it is the + // encrypt object. + TPM2B *name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap + TPM2B *seed, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL. + BOOL useIV, // IN: indicates if an IV is used + UINT16 dataSize, // IN: size of sensitive data in outerBuffer, + // including the leading integrity buffer + // size, and an optional iv area + BYTE *outerBuffer // IN/OUT: sensitive data + ); +void +SensitiveToPrivate( + TPMT_SENSITIVE *sensitive, // IN: sensitive structure + TPM2B_NAME *name, // IN: the name of the object + OBJECT *parent, // IN: The parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This + // parameter is used when parentHandle is + // NULL, in which case the object is + // temporary. + TPM2B_PRIVATE *outPrivate // OUT: output private structure + ); +TPM_RC +PrivateToSensitive( + TPM2B *inPrivate, // IN: input private structure + TPM2B *name, // IN: the name of the object + OBJECT *parent, // IN: parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is + // passed separately because we only pass + // name, rather than the whole public area + // of the object. This parameter is used in + // the following two cases: 1. primary + // objects. 2. duplication blob with inner + // wrap. In other cases, this parameter + // will be ignored + TPMT_SENSITIVE *sensitive // OUT: sensitive structure + ); +void +SensitiveToDuplicate( + TPMT_SENSITIVE *sensitive, // IN: sensitive structure + TPM2B *name, // IN: the name of the object + OBJECT *parent, // IN: The new parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It + // is passed separately because we + // only pass name, rather than the + // whole public area of the object. + TPM2B *seed, // IN: the external seed. If external + // seed is provided with size of 0, + // no outer wrap should be applied + // to duplication blob. + TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the + // symmetric key algorithm is NULL, + // no inner wrap should be applied. + TPM2B_DATA *innerSymKey, // IN/OUT: a symmetric key may be + // provided to encrypt the inner + // wrap of a duplication blob. May + // be generated here if needed. + TPM2B_PRIVATE *outPrivate // OUT: output private structure + ); +TPM_RC +DuplicateToSensitive( + TPM2B *inPrivate, // IN: input private structure + TPM2B *name, // IN: the name of the object + OBJECT *parent, // IN: the parent + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. + TPM2B *seed, // IN: an external seed may be provided. + // If external seed is provided with + // size of 0, no outer wrap is + // applied + TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the + // symmetric key algorithm is NULL, + // no inner wrap is applied + TPM2B *innerSymKey, // IN: a symmetric key may be provided + // to decrypt the inner wrap of a + // duplication blob. + TPMT_SENSITIVE *sensitive // OUT: sensitive structure + ); +void +SecretToCredential( + TPM2B_DIGEST *secret, // IN: secret information + TPM2B *name, // IN: the name of the object + TPM2B *seed, // IN: an external seed. + OBJECT *protector, // IN: the protector + TPM2B_ID_OBJECT *outIDObject // OUT: output credential + ); +TPM_RC +CredentialToSecret( + TPM2B *inIDObject, // IN: input credential blob + TPM2B *name, // IN: the name of the object + TPM2B *seed, // IN: an external seed. + OBJECT *protector, // IN: the protector + TPM2B_DIGEST *secret // OUT: secret information + ); +UINT16 +MemoryRemoveTrailingZeros( + TPM2B_AUTH *auth // IN/OUT: value to adjust + ); +TPM_RC +SetLabelAndContext( + TPMS_DERIVE *labelContext, // OUT: the recovered label and context + TPM2B_SENSITIVE_DATA *sensitive // IN: the sensitive data + ); +TPM_RC +UnmarshalToPublic( + TPMT_PUBLIC *tOut, // OUT: output + TPM2B_TEMPLATE *tIn, // IN: + BOOL derivation, // IN: indicates if this is for a derivation + TPMS_DERIVE *labelContext // OUT: label and context if derivation + ); +void +ObjectSetHierarchy( + OBJECT *object, + TPM_HANDLE parentHandle, + OBJECT *parent + ); +#if 0 /* libtpms added */ +void +ObjectSetExternal( + OBJECT *object + ); +#endif /* libtpms added */ + + +#endif diff --git a/src/tpm2/PCR.c b/src/tpm2/PCR.c new file mode 100644 index 0000000..464d9c0 --- /dev/null +++ b/src/tpm2/PCR.c @@ -0,0 +1,1185 @@ +/********************************************************************************/ +/* */ +/* PCR access and manipulation */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 8.7 PCR.c */ +/* 8.7.1 Introduction */ +/* This function contains the functions needed for PCR access and manipulation. */ +/* This implementation uses a static allocation for the PCR. The amount of memory is allocated based + on the number of PCR in the implementation and the number of implemented hash algorithms. This is + not the expected implementation. PCR SPACE DEFINITIONS. */ +/* In the definitions below, the g_hashPcrMap is a bit array that indicates which of the PCR are + implemented. The g_hashPcr array is an array of digests. In this implementation, the space is + allocated whether the PCR is implemented or not. */ +/* 8.7.2 Includes, Defines, and Data Definitions */ +#define PCR_C +#include "Tpm.h" +/* The initial value of PCR attributes. The value of these fields should be consistent with PC + Client specification In this implementation, we assume the total number of implemented PCR is + 24. */ +static const PCR_Attributes s_initAttributes[] = + { + // PCR 0 - 15, static RTM + {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, + {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, + {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, + {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, + {0, 0x0F, 0x1F}, // PCR 16, Debug + {0, 0x10, 0x1C}, // PCR 17, Locality 4 + {0, 0x10, 0x1C}, // PCR 18, Locality 3 + {0, 0x10, 0x0C}, // PCR 19, Locality 2 + {0, 0x14, 0x0E}, // PCR 20, Locality 1 + {0, 0x14, 0x04}, // PCR 21, Dynamic OS + {0, 0x14, 0x04}, // PCR 22, Dynamic OS + {0, 0x0F, 0x1F}, // PCR 23, Application specific + {0, 0x0F, 0x1F} // PCR 24, testing policy + }; +/* 8.7.2 Functions */ +/* 8.7.2.1 PCRBelongsAuthGroup() */ +/* This function indicates if a PCR belongs to a group that requires an authValue in order to modify + the PCR. If it does, groupIndex is set to value of the group index. This feature of PCR is + decided by the platform specification. */ +/* Return Type: BOOL */ +/* TRUE: PCR belongs an authorization group */ +/* FALSE: PCR does not belong an authorization group */ +BOOL +PCRBelongsAuthGroup( + TPMI_DH_PCR handle, // IN: handle of PCR + UINT32 *groupIndex // OUT: group index if PCR belongs a + // group that allows authValue. If PCR + // does not belong to an authorization + // group, the value in this parameter is + // invalid + ) +{ +#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 + // Platform specification determines to which authorization group a PCR belongs + // (if any). In this implementation, we assume there is only + // one authorization group which contains PCR[20-22]. If the platform + // specification requires differently, the implementation should be changed + // accordingly + if(handle >= 20 && handle <= 22) + { + *groupIndex = 0; + return TRUE; + } +#endif + return FALSE; +} +/* 8.7.2.2 PCRBelongsPolicyGroup() */ +/* This function indicates if a PCR belongs to a group that requires a policy authorization in order + to modify the PCR. If it does, groupIndex is set to value of the group index. This feature of + PCR is decided by the platform specification. */ +/* Return Values Meaning */ +/* TRUE: PCR belongs to a policy group */ +/* FALSE: PCR does not belong to a policy group */ +BOOL +PCRBelongsPolicyGroup( + TPMI_DH_PCR handle, // IN: handle of PCR + UINT32 *groupIndex // OUT: group index if PCR belongs a group that + // allows policy. If PCR does not belong to + // a policy group, the value in this + // parameter is invalid + ) +{ +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + // Platform specification decides if a PCR belongs to a policy group and + // belongs to which group. In this implementation, we assume there is only + // one policy group which contains PCR20-22. If the platform specification + // requires differently, the implementation should be changed accordingly + if(handle >= 20 && handle <= 22) + { + *groupIndex = 0; + return TRUE; + } +#endif + return FALSE; +} +/* 8.7.2.3 PCRBelongsTCBGroup() */ +/* This function indicates if a PCR belongs to the TCB group. */ +/* Return Values Meaning */ +/* TRUE: PCR belongs to a TCB group */ +/* FALSE: PCR does not belong to a TCB group */ +static BOOL +PCRBelongsTCBGroup( + TPMI_DH_PCR handle // IN: handle of PCR + ) +{ +#if ENABLE_PCR_NO_INCREMENT == YES +#if 0 + // Platform specification decides if a PCR belongs to a TCB group. In this + // implementation, we assume PCR[20-22] belong to TCB group. If the platform + // specification requires differently, the implementation should be + // changed accordingly + if(handle >= 20 && handle <= 22) + return TRUE; +#endif + /* kgold - changed for PC Client, 16, 21-23 no increment */ + if ((handle == 16) || + ((handle >= 21) && (handle <= 23))) { + return TRUE; + } +#endif + return FALSE; +} +/* 8.7.2.4 PCRPolicyIsAvailable() */ +/* This function indicates if a policy is available for a PCR. */ +/* Return Values Meaning */ +/* TRUE the PCR may be authorized by policy */ +/* FALSE the PCR does not allow policy */ +BOOL +PCRPolicyIsAvailable( + TPMI_DH_PCR handle // IN: PCR handle + ) +{ + UINT32 groupIndex; + return PCRBelongsPolicyGroup(handle, &groupIndex); +} +/* 8.7.2.5 PCRGetAuthValue() */ +/* This function is used to access the authValue of a PCR. If PCR does not belong to an authValue + group, an EmptyAuth() will be returned. */ +TPM2B_AUTH * +PCRGetAuthValue( + TPMI_DH_PCR handle // IN: PCR handle + ) +{ + UINT32 groupIndex; + if(PCRBelongsAuthGroup(handle, &groupIndex)) + { + return &gc.pcrAuthValues.auth[groupIndex]; + } + else + { + return NULL; + } +} +/* 8.7.2.6 PCRGetAuthPolicy() */ +/* This function is used to access the authorization policy of a PCR. It sets policy to the + authorization policy and returns the hash algorithm for policy If the PCR does not allow a + policy, TPM_ALG_NULL is returned. */ +TPMI_ALG_HASH +PCRGetAuthPolicy( + TPMI_DH_PCR handle, // IN: PCR handle + TPM2B_DIGEST *policy // OUT: policy of PCR + ) +{ + UINT32 groupIndex; + if(PCRBelongsPolicyGroup(handle, &groupIndex)) + { + *policy = gp.pcrPolicies.policy[groupIndex]; + return gp.pcrPolicies.hashAlg[groupIndex]; + } + else + { + policy->t.size = 0; + return TPM_ALG_NULL; + } +} +/* 8.7.2.7 PCRSimStart() */ +/* This function is used to initialize the policies when a TPM is manufactured. This function would + only be called in a manufacturing environment or in a TPM simulator. */ +void +PCRSimStart( + void + ) +{ + UINT32 i; +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) + { + gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; + gp.pcrPolicies.policy[i].t.size = 0; + } +#endif +#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 + for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++) + { + gc.pcrAuthValues.auth[i].t.size = 0; + } +#endif + // We need to give an initial configuration on allocated PCR before + // receiving any TPM2_PCR_Allocate command to change this configuration + // When the simulation environment starts, we allocate all the PCRs + for(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT; + gp.pcrAllocated.count++) + { + gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash + = CryptHashGetAlgByIndex(gp.pcrAllocated.count); + gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelect + = PCR_SELECT_MAX; + for(i = 0; i < PCR_SELECT_MAX; i++) + gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i] + = 0xFF; + } + // Store the initial configuration to NV + NV_SYNC_PERSISTENT(pcrPolicies); + NV_SYNC_PERSISTENT(pcrAllocated); + return; +} +/* 8.7.3.8 GetSavedPcrPointer() */ +/* This function returns the address of an array of state saved PCR based on the hash algorithm. */ +/* Return Values Meaning */ +/* NULL no such algorithm */ +/* not NULL pointer to the 0th byte of the 0th PCR */ + +static BYTE * +GetSavedPcrPointer( + TPM_ALG_ID alg, // IN: algorithm for bank + UINT32 pcrIndex // IN: PCR index in PCR_SAVE + ) +{ + BYTE *retVal; + switch(alg) + { +#define HASH_CASE(HASH, Hash) \ + case TPM_ALG_##HASH: \ + retVal = gc.pcrSave.Hash[pcrIndex]; \ + break; + + FOR_EACH_HASH(HASH_CASE) +#undef HASH_CASE + + default: + FAIL(FATAL_ERROR_INTERNAL); + } + return retVal; +} + +/* 8.7.2.9 PcrIsAllocated() */ +/* This function indicates if a PCR number for the particular hash algorithm is allocated. */ +/* Return Values Meaning */ +/* FALSE PCR is not allocated */ +/* TRUE PCR is allocated */ +BOOL +PcrIsAllocated( + UINT32 pcr, // IN: The number of the PCR + TPMI_ALG_HASH hashAlg // IN: The PCR algorithm + ) +{ + UINT32 i; + BOOL allocated = FALSE; + if(pcr < IMPLEMENTATION_PCR) + { + for(i = 0; i < gp.pcrAllocated.count; i++) + { + if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg) + { + if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr / 8]) + & (1 << (pcr % 8))) != 0) + allocated = TRUE; + else + allocated = FALSE; + break; + } + } + } + return allocated; +} +/* 8.7.3.10 GetPcrPointer() */ +/* This function returns the address of an array of PCR based on the hash algorithm. */ +/* Return Values Meaning */ +/* NULL no such algorithm */ +/* not NULL pointer to the 0th byte of the 0th PCR */ + +static BYTE * +GetPcrPointer( + TPM_ALG_ID alg, // IN: algorithm for bank + UINT32 pcrNumber // IN: PCR number + ) +{ + static BYTE *pcr = NULL; + + if(!PcrIsAllocated(pcrNumber, alg)) + return NULL; + switch(alg) + { +#define HASH_CASE(HASH, Hash) \ + case TPM_ALG_##HASH: \ + pcr = s_pcrs[pcrNumber].Hash##Pcr; \ + break; + + FOR_EACH_HASH(HASH_CASE) +#undef HASH_CASE + + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return pcr; +} + +/* 8.7.2.11 IsPcrSelected() */ +/* This function indicates if an indicated PCR number is selected by the bit map in selection. */ +/* Return Values Meaning */ +/* FALSE PCR is not selected */ +/* TRUE PCR is selected */ +static BOOL +IsPcrSelected( + UINT32 pcr, // IN: The number of the PCR + TPMS_PCR_SELECTION *selection // IN: The selection structure + ) +{ + BOOL selected; + selected = (pcr < IMPLEMENTATION_PCR + && ((selection->pcrSelect[pcr / 8]) & (1 << (pcr % 8))) != 0); + return selected; +} +/* 8.7.2.12 FilterPcr() */ +/* This function modifies a PCR selection array based on the implemented PCR. */ +static void +FilterPcr( + TPMS_PCR_SELECTION *selection // IN: input PCR selection + ) +{ + UINT32 i; + TPMS_PCR_SELECTION *allocated = NULL; + // If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR + for(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++) + selection->pcrSelect[i] = 0; + // Find the internal configuration for the bank + for(i = 0; i < gp.pcrAllocated.count; i++) + { + if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash) + { + allocated = &gp.pcrAllocated.pcrSelections[i]; + break; + } + } + for(i = 0; i < selection->sizeofSelect; i++) + { + if(allocated == NULL) + { + // If the required bank does not exist, clear input selection + selection->pcrSelect[i] = 0; + } + else + selection->pcrSelect[i] &= allocated->pcrSelect[i]; + } + return; +} +/* 8.7.2.13 PcrDrtm() */ +/* This function does the DRTM and H-CRTM processing it is called from _TPM_Hash_End(). */ +void +PcrDrtm( + const TPMI_DH_PCR pcrHandle, // IN: the index of the PCR to be + // modified + const TPMI_ALG_HASH hash, // IN: the bank identifier + const TPM2B_DIGEST *digest // IN: the digest to modify the PCR + ) +{ + BYTE *pcrData = GetPcrPointer(hash, pcrHandle); + if(pcrData != NULL) + { + // Rest the PCR to zeros + MemorySet(pcrData, 0, digest->t.size); + // if the TPM has not started, then set the PCR to 0...04 and then extend + if(!TPMIsStarted()) + { + pcrData[digest->t.size - 1] = 4; + } + // Now, extend the value + PCRExtend(pcrHandle, hash, digest->t.size, (BYTE *)digest->t.buffer); + } +} +/* 8.7.2.14 PCR_ClearAuth() */ +/* This function is used to reset the PCR authorization values. It is called on TPM2_Startup(CLEAR) + and TPM2_Clear(). */ +void +PCR_ClearAuth( + void + ) +{ +#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 + int j; + for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++) + { + gc.pcrAuthValues.auth[j].t.size = 0; + } +#endif +} +/* 8.7.2.15 PCRStartup() */ +/* This function initializes the PCR subsystem at TPM2_Startup(). */ +BOOL +PCRStartup( + STARTUP_TYPE type, // IN: startup type + BYTE locality // IN: startup locality + ) +{ + UINT32 pcr, j; + UINT32 saveIndex = 0; + g_pcrReConfig = FALSE; + // Don't test for SU_RESET because that should be the default when nothing + // else is selected + if(type != SU_RESUME && type != SU_RESTART) + { + // PCR generation counter is cleared at TPM_RESET + gr.pcrCounter = 0; + } + // Initialize/Restore PCR values + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + // On resume, need to know if this PCR had its state saved or not + UINT32 stateSaved; + if(type == SU_RESUME + && s_initAttributes[pcr].stateSave == SET) + { + stateSaved = 1; + } + else + { + stateSaved = 0; + PCRChanged(pcr); + } + // If this is the H-CRTM PCR and we are not doing a resume and we + // had an H-CRTM event, then we don't change this PCR + if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE) + continue; + // Iterate each hash algorithm bank + for(j = 0; j < gp.pcrAllocated.count; j++) + { + TPMI_ALG_HASH hash = gp.pcrAllocated.pcrSelections[j].hash; + BYTE *pcrData = GetPcrPointer(hash, pcr); + UINT16 pcrSize = CryptHashGetDigestSize(hash); + if(pcrData != NULL) + { + // if state was saved + if(stateSaved == 1) + { + // Restore saved PCR value + BYTE *pcrSavedData; + pcrSavedData = GetSavedPcrPointer( + gp.pcrAllocated.pcrSelections[j].hash, + saveIndex); + if(pcrSavedData == NULL) + return FALSE; + MemoryCopy(pcrData, pcrSavedData, pcrSize); + } + else + // PCR was not restored by state save + { + // If the reset locality of the PCR is 4, then + // the reset value is all one's, otherwise it is + // all zero. + if((s_initAttributes[pcr].resetLocality & 0x10) != 0) + MemorySet(pcrData, 0xFF, pcrSize); + else + { + MemorySet(pcrData, 0, pcrSize); + if(pcr == HCRTM_PCR) + pcrData[pcrSize - 1] = locality; + } + } + } + } + saveIndex += stateSaved; + } + // Reset authValues on TPM2_Startup(CLEAR) + if(type != SU_RESUME) + PCR_ClearAuth(); + return TRUE; +} +/* 8.7.2.16 PCRStateSave() */ +/* This function is used to save the PCR values that will be restored on TPM Resume. */ +void +PCRStateSave( + TPM_SU type // IN: startup type + ) +{ + UINT32 pcr, j; + UINT32 saveIndex = 0; + // if state save CLEAR, nothing to be done. Return here + if(type == TPM_SU_CLEAR) + return; + // Copy PCR values to the structure that should be saved to NV + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0; + // Iterate each hash algorithm bank + for(j = 0; j < gp.pcrAllocated.count; j++) + { + BYTE *pcrData; + UINT32 pcrSize; + pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr); + if(pcrData != NULL) + { + pcrSize + = CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[j].hash); + if(stateSaved == 1) + { + // Restore saved PCR value + BYTE *pcrSavedData; + pcrSavedData + = GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, + saveIndex); + MemoryCopy(pcrSavedData, pcrData, pcrSize); + } + } + } + saveIndex += stateSaved; + } + return; +} +/* 8.7.2.17 PCRIsStateSaved() */ +/* This function indicates if the selected PCR is a PCR that is state saved on + TPM2_Shutdown(STATE). The return value is based on PCR attributes. */ +/* Return Values Meaning */ +/* TRUE PCR is state saved */ +/* FALSE PCR is not state saved */ +BOOL +PCRIsStateSaved( + TPMI_DH_PCR handle // IN: PCR handle to be extended + ) +{ + UINT32 pcr = handle - PCR_FIRST; + if(s_initAttributes[pcr].stateSave == SET) + return TRUE; + else + return FALSE; +} +/* 8.7.2.18 PCRIsResetAllowed() */ +/* This function indicates if a PCR may be reset by the current command locality. The return value + is based on PCR attributes, and not the PCR allocation. */ +/* Return Values Meaning */ +/* TRUE TPM2_PCR_Reset() is allowed */ +/* FALSE TPM2_PCR_Reset() is not allowed */ +BOOL +PCRIsResetAllowed( + TPMI_DH_PCR handle // IN: PCR handle to be extended + ) +{ + UINT8 commandLocality; + UINT8 localityBits = 1; + UINT32 pcr = handle - PCR_FIRST; + // Check for the locality + commandLocality = _plat__LocalityGet(); +#ifdef DRTM_PCR + // For a TPM that does DRTM, Reset is not allowed at locality 4 + if(commandLocality == 4) + return FALSE; +#endif + localityBits = localityBits << commandLocality; + if((localityBits & s_initAttributes[pcr].resetLocality) == 0) + return FALSE; + else + return TRUE; +} +/* 8.7.2.19 PCRChanged() */ +/* This function checks a PCR handle to see if the attributes for the PCR are set so that any change + to the PCR causes an increment of the pcrCounter. If it does, then the function increments the + counter. Will also bump the counter if the handle is zero which means that PCR 0 can not be in + the TCB group. Bump on zero is used by TPM2_Clear(). */ +void +PCRChanged( + TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. + ) +{ + // For the reference implementation, the only change that does not cause + // increment is a change to a PCR in the TCB group. + if((pcrHandle == 0) || !PCRBelongsTCBGroup(pcrHandle)) + { + gr.pcrCounter++; + if(gr.pcrCounter == 0) + FAIL(FATAL_ERROR_COUNTER_OVERFLOW); + } +} +/* 8.7.2.20 PCRIsExtendAllowed() */ +/* This function indicates a PCR may be extended at the current command locality. The return value + is based on PCR attributes, and not the PCR allocation. */ +/* Return Values Meaning */ +/* TRUE extend is allowed */ +/* FALSE extend is not allowed */ +BOOL +PCRIsExtendAllowed( + TPMI_DH_PCR handle // IN: PCR handle to be extended + ) +{ + UINT8 commandLocality; + UINT8 localityBits = 1; + UINT32 pcr = handle - PCR_FIRST; + // Check for the locality + commandLocality = _plat__LocalityGet(); + localityBits = localityBits << commandLocality; + if((localityBits & s_initAttributes[pcr].extendLocality) == 0) + return FALSE; + else + return TRUE; +} +/* 8.7.2.21 PCRExtend() */ +/* This function is used to extend a PCR in a specific bank. */ +void +PCRExtend( + TPMI_DH_PCR handle, // IN: PCR handle to be extended + TPMI_ALG_HASH hash, // IN: hash algorithm of PCR + UINT32 size, // IN: size of data to be extended + BYTE *data // IN: data to be extended + ) +{ + BYTE *pcrData; + HASH_STATE hashState; + UINT16 pcrSize; + pcrData = GetPcrPointer(hash, handle - PCR_FIRST); + // Extend PCR if it is allocated + if(pcrData != NULL) + { + pcrSize = CryptHashGetDigestSize(hash); + CryptHashStart(&hashState, hash); + CryptDigestUpdate(&hashState, pcrSize, pcrData); + CryptDigestUpdate(&hashState, size, data); + CryptHashEnd(&hashState, pcrSize, pcrData); + // PCR has changed so update the pcrCounter if necessary + PCRChanged(handle); + } + return; +} +/* 8.7.2.22 PCRComputeCurrentDigest() */ +/* This function computes the digest of the selected PCR. */ +/* As a side-effect, selection is modified so that only the implemented PCR will have their bits + still set. */ +void +PCRComputeCurrentDigest( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest + TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on + // output) + TPM2B_DIGEST *digest // OUT: digest + ) +{ + HASH_STATE hashState; + TPMS_PCR_SELECTION *select; + BYTE *pcrData; // will point to a digest + UINT32 pcrSize; + UINT32 pcr; + UINT32 i; + // Initialize the hash + digest->t.size = CryptHashStart(&hashState, hashAlg); + pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX); + // Iterate through the list of PCR selection structures + for(i = 0; i < selection->count; i++) + { + // Point to the current selection + select = &selection->pcrSelections[i]; // Point to the current selection + FilterPcr(select); // Clear out the bits for unimplemented PCR + // Need the size of each digest + pcrSize = CryptHashGetDigestSize(selection->pcrSelections[i].hash); + // Iterate through the selection + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + if(IsPcrSelected(pcr, select)) // Is this PCR selected + { + // Get pointer to the digest data for the bank + pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); + pAssert(pcrData != NULL); + CryptDigestUpdate(&hashState, pcrSize, pcrData); // add to digest + } + } + } + // Complete hash stack + CryptHashEnd2B(&hashState, &digest->b); + return; +} +/* 8.7.2.23 PCRRead() */ +/* This function is used to read a list of selected PCR. If the requested PCR number exceeds the + maximum number that can be output, the selection is adjusted to reflect the actual output PCR. */ +void +PCRRead( + TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on + // output) + TPML_DIGEST *digest, // OUT: digest + UINT32 *pcrCounter // OUT: the current value of PCR generation + // number + ) +{ + TPMS_PCR_SELECTION *select; + BYTE *pcrData; // will point to a digest + UINT32 pcr; + UINT32 i; + digest->count = 0; + // Iterate through the list of PCR selection structures + for(i = 0; i < selection->count; i++) + { + // Point to the current selection + select = &selection->pcrSelections[i]; // Point to the current selection + FilterPcr(select); // Clear out the bits for unimplemented PCR + // Iterate through the selection + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + if(IsPcrSelected(pcr, select)) // Is this PCR selected + { + // Check if number of digest exceed upper bound + if(digest->count > 7) + { + // Clear rest of the current select bitmap + while(pcr < IMPLEMENTATION_PCR + // do not round up! + && (pcr / 8) < select->sizeofSelect) + { + // do not round up! + select->pcrSelect[pcr / 8] &= (BYTE)~(1 << (pcr % 8)); + pcr++; + } + // Exit inner loop + break; + } + // Need the size of each digest + digest->digests[digest->count].t.size = + CryptHashGetDigestSize(selection->pcrSelections[i].hash); + // Get pointer to the digest data for the bank + pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); + pAssert(pcrData != NULL); + // Add to the data to digest + MemoryCopy(digest->digests[digest->count].t.buffer, + pcrData, + digest->digests[digest->count].t.size); + digest->count++; + } + } + // If we exit inner loop because we have exceed the output upper bound + if(digest->count > 7 && pcr < IMPLEMENTATION_PCR) + { + // Clear rest of the selection + while(i < selection->count) + { + MemorySet(selection->pcrSelections[i].pcrSelect, 0, + selection->pcrSelections[i].sizeofSelect); + i++; + } + // exit outer loop + break; + } + } + *pcrCounter = gr.pcrCounter; + return; +} +/* 8.7.2.25 PCRAllocate() */ +/* This function is used to change the PCR allocation. */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT allocate failed */ +/* TPM_RC_PCR improper allocation */ +TPM_RC +PCRAllocate( + TPML_PCR_SELECTION *allocate, // IN: required allocation + UINT32 *maxPCR, // OUT: Maximum number of PCR + UINT32 *sizeNeeded, // OUT: required space + UINT32 *sizeAvailable // OUT: available space + ) +{ + UINT32 i, j, k; + TPML_PCR_SELECTION newAllocate; + // Initialize the flags to indicate if HCRTM PCR and DRTM PCR are allocated. + BOOL pcrHcrtm = FALSE; + BOOL pcrDrtm = FALSE; + // Create the expected new PCR allocation based on the existing allocation + // and the new input: + // 1. if a PCR bank does not appear in the new allocation, the existing + // allocation of this PCR bank will be preserved. + // 2. if a PCR bank appears multiple times in the new allocation, only the + // last one will be in effect. + newAllocate = gp.pcrAllocated; + for(i = 0; i < allocate->count; i++) + { + for(j = 0; j < newAllocate.count; j++) + { + // If hash matches, the new allocation covers the old allocation + // for this particular bank. + // The assumption is the initial PCR allocation (from manufacture) + // has all the supported hash algorithms with an assigned bank + // (possibly empty). So there must be a match for any new bank + // allocation from the input. + if(newAllocate.pcrSelections[j].hash == + allocate->pcrSelections[i].hash) + { + newAllocate.pcrSelections[j] = allocate->pcrSelections[i]; + break; + } + } + // The j loop must exit with a match. + pAssert(j < newAllocate.count); + } + // Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined) + *maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes); + if(*maxPCR > IMPLEMENTATION_PCR) + *maxPCR = IMPLEMENTATION_PCR; + // Compute required size for allocation + *sizeNeeded = 0; + for(i = 0; i < newAllocate.count; i++) + { + UINT32 digestSize + = CryptHashGetDigestSize(newAllocate.pcrSelections[i].hash); +#if defined(DRTM_PCR) + // Make sure that we end up with at least one DRTM PCR + pcrDrtm = pcrDrtm || TestBit(DRTM_PCR, + newAllocate.pcrSelections[i].pcrSelect, + newAllocate.pcrSelections[i].sizeofSelect); +#else // if DRTM PCR is not required, indicate that the allocation is OK + pcrDrtm = TRUE; +#endif +#if defined(HCRTM_PCR) + // and one HCRTM PCR (since this is usually PCR 0...) + pcrHcrtm = pcrHcrtm || TestBit(HCRTM_PCR, + newAllocate.pcrSelections[i].pcrSelect, + newAllocate.pcrSelections[i].sizeofSelect); +#else + pcrHcrtm = TRUE; +#endif + for(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++) + { + BYTE mask = 1; + for(k = 0; k < 8; k++) + { + if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0) + *sizeNeeded += digestSize; + mask = mask << 1; + } + } + } + if(!pcrDrtm || !pcrHcrtm) + return TPM_RC_PCR; + // In this particular implementation, we always have enough space to + // allocate PCR. Different implementation may return a sizeAvailable less + // than the sizeNeed. + *sizeAvailable = sizeof(s_pcrs); + // Save the required allocation to NV. Note that after NV is written, the + // PCR allocation in NV is no longer consistent with the RAM data + // gp.pcrAllocated. The NV version reflect the allocate after next + // TPM_RESET, while the RAM version reflects the current allocation + NV_WRITE_PERSISTENT(pcrAllocated, newAllocate); + return TPM_RC_SUCCESS; +} +/* 8.7.2.26 PCRSetValue() */ +/* This function is used to set the designated PCR in all banks to an initial value. The initial + value is signed and will be sign extended into the entire PCR. */ +void +PCRSetValue( + TPM_HANDLE handle, // IN: the handle of the PCR to set + INT8 initialValue // IN: the value to set + ) +{ + int i; + UINT32 pcr = handle - PCR_FIRST; + TPMI_ALG_HASH hash; + UINT16 digestSize; + BYTE *pcrData; + // Iterate supported PCR bank algorithms to reset + for(i = 0; i < HASH_COUNT; i++) + { + hash = CryptHashGetAlgByIndex(i); + // Prevent runaway + if(hash == TPM_ALG_NULL) + break; + // Get a pointer to the data + pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); + // If the PCR is allocated + if(pcrData != NULL) + { + // And the size of the digest + digestSize = CryptHashGetDigestSize(hash); + // Set the LSO to the input value + pcrData[digestSize - 1] = initialValue; + // Sign extend + if(initialValue >= 0) + MemorySet(pcrData, 0, digestSize - 1); + else + MemorySet(pcrData, -1, digestSize - 1); + } + } +} +/* 8.7.2.27 PCRResetDynamics */ +/* This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence. */ +void +PCRResetDynamics( + void + ) +{ + UINT32 pcr, i; + // Initialize PCR values + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + // Iterate each hash algorithm bank + for(i = 0; i < gp.pcrAllocated.count; i++) + { + BYTE *pcrData; + UINT32 pcrSize; + pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); + if(pcrData != NULL) + { + pcrSize = + CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[i].hash); + // Reset PCR + // Any PCR can be reset by locality 4 should be reset to 0 + if((s_initAttributes[pcr].resetLocality & 0x10) != 0) + MemorySet(pcrData, 0, pcrSize); + } + } + } + return; +} +/* 8.7.2.28 PCRCapGetAllocation() */ +/* This function is used to get the current allocation of PCR banks. */ +/* Return Values Meaning */ +/* YES: if the return count is 0 */ +/* NO: if the return count is not 0 */ +TPMI_YES_NO +PCRCapGetAllocation( + UINT32 count, // IN: count of return + TPML_PCR_SELECTION *pcrSelection // OUT: PCR allocation list + ) +{ + if(count == 0) + { + pcrSelection->count = 0; + return YES; + } + else + { + *pcrSelection = gp.pcrAllocated; + return NO; + } +} +/* 8.7.2.29 PCRSetSelectBit() */ +/* This function sets a bit in a bitmap array. */ +static void +PCRSetSelectBit( + UINT32 pcr, // IN: PCR number + BYTE *bitmap // OUT: bit map to be set + ) +{ + bitmap[pcr / 8] |= (1 << (pcr % 8)); + return; +} +/* 8.7.2.30 PCRGetProperty() */ +/* This function returns the selected PCR property. */ +/* Return Values Meaning */ +/* TRUE the property type is implemented */ +/* FALSE the property type is not implemented */ +static BOOL +PCRGetProperty( + TPM_PT_PCR property, + TPMS_TAGGED_PCR_SELECT *select + ) +{ + UINT32 pcr; + UINT32 groupIndex; + select->tag = property; + // Always set the bitmap to be the size of all PCR + select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8; + // Initialize bitmap + MemorySet(select->pcrSelect, 0, select->sizeofSelect); + // Collecting properties + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + switch(property) + { + case TPM_PT_PCR_SAVE: + if(s_initAttributes[pcr].stateSave == SET) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L0: + if((s_initAttributes[pcr].extendLocality & 0x01) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L0: + if((s_initAttributes[pcr].resetLocality & 0x01) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L1: + if((s_initAttributes[pcr].extendLocality & 0x02) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L1: + if((s_initAttributes[pcr].resetLocality & 0x02) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L2: + if((s_initAttributes[pcr].extendLocality & 0x04) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L2: + if((s_initAttributes[pcr].resetLocality & 0x04) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L3: + if((s_initAttributes[pcr].extendLocality & 0x08) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L3: + if((s_initAttributes[pcr].resetLocality & 0x08) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L4: + if((s_initAttributes[pcr].extendLocality & 0x10) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L4: + if((s_initAttributes[pcr].resetLocality & 0x10) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_DRTM_RESET: + // DRTM reset PCRs are the PCR reset by locality 4 + if((s_initAttributes[pcr].resetLocality & 0x10) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + case TPM_PT_PCR_POLICY: + if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex)) + PCRSetSelectBit(pcr, select->pcrSelect); + break; +#endif +#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 + case TPM_PT_PCR_AUTH: + if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex)) + PCRSetSelectBit(pcr, select->pcrSelect); + break; +#endif +#if ENABLE_PCR_NO_INCREMENT == YES + case TPM_PT_PCR_NO_INCREMENT: + if(PCRBelongsTCBGroup(pcr + PCR_FIRST)) + PCRSetSelectBit(pcr, select->pcrSelect); + break; +#endif + default: + // If property is not supported, stop scanning PCR attributes + // and return. + return FALSE; + break; + } + } + return TRUE; +} +/* 8.7.2.31 PCRCapGetProperties() */ +/* This function returns a list of PCR properties starting at property. */ +/* Return Values Meaning */ +/* YES: if no more property is available */ +/* NO: if there are more properties not reported */ +TPMI_YES_NO +PCRCapGetProperties( + TPM_PT_PCR property, // IN: the starting PCR property + UINT32 count, // IN: count of returned properties + TPML_TAGGED_PCR_PROPERTY *select // OUT: PCR select + ) +{ + TPMI_YES_NO more = NO; + UINT32 i; + // Initialize output property list + select->count = 0; + // The maximum count of properties we may return is MAX_PCR_PROPERTIES + if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES; + // TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property + // value would never be less than TPM_PT_PCR_FIRST + cAssert(TPM_PT_PCR_FIRST == 0); + // Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property + // implemented on the TPM. + for(i = property; i <= TPM_PT_PCR_LAST; i++) + { + if(select->count < count) + { + // If we have not filled up the return list, add more properties to it + if(PCRGetProperty(i, &select->pcrProperty[select->count])) + // only increment if the property is implemented + select->count++; + } + else + { + // If the return list is full but we still have properties + // available, report this and stop iterating. + more = YES; + break; + } + } + return more; +} +/* 8.7.2.32 PCRCapGetHandles() */ +/* This function is used to get a list of handles of PCR, started from handle. If handle exceeds the + maximum PCR handle range, an empty list will be returned and the return value will be NO. */ +/* Return Values Meaning */ +/* YES if there are more handles available */ +/* NO all the available handles has been returned */ +TPMI_YES_NO +PCRCapGetHandles( + TPMI_DH_PCR handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ) +{ + TPMI_YES_NO more = NO; + UINT32 i; + pAssert(HandleGetType(handle) == TPM_HT_PCR); + // Initialize output handle list + handleList->count = 0; + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; + // Iterate PCR handle range + for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++) + { + if(handleList->count < count) + { + // If we have not filled up the return list, add this PCR + // handle to it + handleList->handle[handleList->count] = i + PCR_FIRST; + handleList->count++; + } + else + { + // If the return list is full but we still have PCR handle + // available, report this and stop iterating + more = YES; + break; + } + } + return more; +} diff --git a/src/tpm2/PCR_Allocate_fp.h b/src/tpm2/PCR_Allocate_fp.h new file mode 100644 index 0000000..30f9299 --- /dev/null +++ b/src/tpm2/PCR_Allocate_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR_Allocate_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef PCR_ALLOCATE_FP_H +#define PCR_ALLOCATE_FP_H + +typedef struct { + TPMI_RH_PLATFORM authHandle; + TPML_PCR_SELECTION pcrAllocation; +} PCR_Allocate_In; + +#define RC_PCR_Allocate_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_PCR_Allocate_pcrAllocation (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPMI_YES_NO allocationSuccess; + UINT32 maxPCR; + UINT32 sizeNeeded; + UINT32 sizeAvailable; +} PCR_Allocate_Out; + +TPM_RC +TPM2_PCR_Allocate( + PCR_Allocate_In *in, // IN: input parameter list + PCR_Allocate_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/PCR_Event_fp.h b/src/tpm2/PCR_Event_fp.h new file mode 100644 index 0000000..3c36851 --- /dev/null +++ b/src/tpm2/PCR_Event_fp.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR_Event_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef PCR_EVENT_FP_H +#define PCR_EVENT_FP_H + +typedef struct { + TPMI_DH_PCR pcrHandle; + TPM2B_EVENT eventData; +} PCR_Event_In; + +#define RC_PCR_Event_pcrHandle (TPM_RC_H + TPM_RC_1) +#define RC_PCR_Event_eventData (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPML_DIGEST_VALUES digests; +} PCR_Event_Out; + +TPM_RC +TPM2_PCR_Event( + PCR_Event_In *in, // IN: input parameter list + PCR_Event_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/PCR_Extend_fp.h b/src/tpm2/PCR_Extend_fp.h new file mode 100644 index 0000000..37ca3f9 --- /dev/null +++ b/src/tpm2/PCR_Extend_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR_Extend_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef PCR_EXTEND_FP_H +#define PCR_EXTEND_FP_H + +typedef struct { + TPMI_DH_PCR pcrHandle; + TPML_DIGEST_VALUES digests; +} PCR_Extend_In; + +#define RC_PCR_Extend_pcrHandle (TPM_RC_H + TPM_RC_1) +#define RC_PCR_Extend_digests (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PCR_Extend( + PCR_Extend_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PCR_Read_fp.h b/src/tpm2/PCR_Read_fp.h new file mode 100644 index 0000000..ec3ef40 --- /dev/null +++ b/src/tpm2/PCR_Read_fp.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR_Read_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef PCR_READ_FP_H +#define PCR_READ_FP_H + +typedef struct { + TPML_PCR_SELECTION pcrSelectionIn; +} PCR_Read_In; + +#define RC_PCR_Read_pcrSelectionIn (TPM_RC_P + TPM_RC_1) + +typedef struct { + UINT32 pcrUpdateCounter; + TPML_PCR_SELECTION pcrSelectionOut; + TPML_DIGEST pcrValues; +} PCR_Read_Out; + +TPM_RC +TPM2_PCR_Read( + PCR_Read_In *in, // IN: input parameter list + PCR_Read_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/PCR_Reset_fp.h b/src/tpm2/PCR_Reset_fp.h new file mode 100644 index 0000000..835d2a0 --- /dev/null +++ b/src/tpm2/PCR_Reset_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR_Reset_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef PCR_RESET_FP_H +#define PCR_RESET_FP_H + +typedef struct { + TPMI_DH_PCR pcrHandle; +} PCR_Reset_In; + +#define RC_PCR_Reset__pcrHandle (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_PCR_Reset( + PCR_Reset_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/PCR_SetAuthPolicy_fp.h b/src/tpm2/PCR_SetAuthPolicy_fp.h new file mode 100644 index 0000000..3d8a02b --- /dev/null +++ b/src/tpm2/PCR_SetAuthPolicy_fp.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR_SetAuthPolicy_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef PCR_SETAUTHPOLICY_FP_H +#define PCR_SETAUTHPOLICY_FP_H + +typedef struct { + TPMI_RH_PLATFORM authHandle; + TPM2B_DIGEST authPolicy; + TPMI_ALG_HASH hashAlg; + TPMI_DH_PCR pcrNum; +} PCR_SetAuthPolicy_In; + +#define RC_PCR_SetAuthPolicy_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_PCR_SetAuthPolicy_authPolicy (TPM_RC_P + TPM_RC_1) +#define RC_PCR_SetAuthPolicy_hashAlg (TPM_RC_P + TPM_RC_2) +#define RC_PCR_SetAuthPolicy_pcrNum (TPM_RC_P + TPM_RC_3) + +TPM_RC +TPM2_PCR_SetAuthPolicy( + PCR_SetAuthPolicy_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PCR_SetAuthValue_fp.h b/src/tpm2/PCR_SetAuthValue_fp.h new file mode 100644 index 0000000..a06c3f6 --- /dev/null +++ b/src/tpm2/PCR_SetAuthValue_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR_SetAuthValue_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef PCR_SETAUTHVALUE_FP_H +#define PCR_SETAUTHVALUE_FP_H + +typedef struct { + TPMI_DH_PCR pcrHandle; + TPM2B_DIGEST auth; +} PCR_SetAuthValue_In; + +#define RC_PCR_SetAuthValue_pcrHandle (TPM_RC_H + TPM_RC_1) +#define RC_PCR_SetAuthValue_auth (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PCR_SetAuthValue( + PCR_SetAuthValue_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PCR_fp.h b/src/tpm2/PCR_fp.h new file mode 100644 index 0000000..cfad535 --- /dev/null +++ b/src/tpm2/PCR_fp.h @@ -0,0 +1,197 @@ +/********************************************************************************/ +/* */ +/* Functions Needed for PCR Access and Manipulation */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PCR_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef PCR_FP_H +#define PCR_FP_H + +BOOL +PCRBelongsAuthGroup( + TPMI_DH_PCR handle, // IN: handle of PCR + UINT32 *groupIndex // OUT: group index if PCR belongs a + // group that allows authValue. If PCR + // does not belong to an authorization + // group, the value in this parameter is + // invalid + ); +BOOL +PCRBelongsPolicyGroup( + TPMI_DH_PCR handle, // IN: handle of PCR + UINT32 *groupIndex // OUT: group index if PCR belongs a group that + // allows policy. If PCR does not belong to + // a policy group, the value in this + // parameter is invalid + ); +BOOL +PCRPolicyIsAvailable( + TPMI_DH_PCR handle // IN: PCR handle + ); +TPM2B_AUTH * +PCRGetAuthValue( + TPMI_DH_PCR handle // IN: PCR handle + ); +TPMI_ALG_HASH +PCRGetAuthPolicy( + TPMI_DH_PCR handle, // IN: PCR handle + TPM2B_DIGEST *policy // OUT: policy of PCR + ); +void +PCRSimStart( + void + ); +BOOL +PcrIsAllocated( + UINT32 pcr, // IN: The number of the PCR + TPMI_ALG_HASH hashAlg // IN: The PCR algorithm + ); +void +PcrDrtm( + const TPMI_DH_PCR pcrHandle, // IN: the index of the PCR to be + // modified + const TPMI_ALG_HASH hash, // IN: the bank identifier + const TPM2B_DIGEST *digest // IN: the digest to modify the PCR + ); +void +PCR_ClearAuth( + void + ); +BOOL +PCRStartup( + STARTUP_TYPE type, // IN: startup type + BYTE locality // IN: startup locality + ); +void +PCRStateSave( + TPM_SU type // IN: startup type + ); +BOOL +PCRIsStateSaved( + TPMI_DH_PCR handle // IN: PCR handle to be extended + ); +BOOL +PCRIsResetAllowed( + TPMI_DH_PCR handle // IN: PCR handle to be extended + ); +void +PCRChanged( + TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. + ); +BOOL +PCRIsExtendAllowed( + TPMI_DH_PCR handle // IN: PCR handle to be extended + ); +void +PCRExtend( + TPMI_DH_PCR handle, // IN: PCR handle to be extended + TPMI_ALG_HASH hash, // IN: hash algorithm of PCR + UINT32 size, // IN: size of data to be extended + BYTE *data // IN: data to be extended + ); +void +PCRComputeCurrentDigest( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest + TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on + // output) + TPM2B_DIGEST *digest // OUT: digest + ); +void +PCRRead( + TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on + // output) + TPML_DIGEST *digest, // OUT: digest + UINT32 *pcrCounter // OUT: the current value of PCR generation + // number + ); +TPM_RC +PCRAllocate( + TPML_PCR_SELECTION *allocate, // IN: required allocation + UINT32 *maxPCR, // OUT: Maximum number of PCR + UINT32 *sizeNeeded, // OUT: required space + UINT32 *sizeAvailable // OUT: available space + ); +void +PCRSetValue( + TPM_HANDLE handle, // IN: the handle of the PCR to set + INT8 initialValue // IN: the value to set + ); +void +PCRResetDynamics( + void + ); +TPMI_YES_NO +PCRCapGetAllocation( + UINT32 count, // IN: count of return + TPML_PCR_SELECTION *pcrSelection // OUT: PCR allocation list + ); +TPMI_YES_NO +PCRCapGetProperties( + TPM_PT_PCR property, // IN: the starting PCR property + UINT32 count, // IN: count of returned properties + TPML_TAGGED_PCR_PROPERTY *select // OUT: PCR select + ); +TPMI_YES_NO +PCRCapGetHandles( + TPMI_DH_PCR handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ); + + +#endif diff --git a/src/tpm2/PP.c b/src/tpm2/PP.c new file mode 100644 index 0000000..2c73010 --- /dev/null +++ b/src/tpm2/PP.c @@ -0,0 +1,182 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PP.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +/* 8.8 PP.c */ +/* 8.8.1 Introduction */ +/* This file contains the functions that support the physical presence operations of the TPM. */ +/* 8.8.2 Includes */ +#include "Tpm.h" +/* 8.8.3 Functions */ +/* 8.8.3.1 PhysicalPresencePreInstall_Init() */ +/* This function is used to initialize the array of commands that always require confirmation with + physical presence. The array is an array of bits that has a correspondence with the command + code. */ +/* This command should only ever be executable in a manufacturing setting or in a simulation. */ +/* When set, these cannot be cleared. */ +void +PhysicalPresencePreInstall_Init( + void + ) +{ + COMMAND_INDEX commandIndex; + // Clear all the PP commands + MemorySet(&gp.ppList, 0, sizeof(gp.ppList)); + // Any command that is PP_REQUIRED should be SET + for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++) + { + if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED + && s_commandAttributes[commandIndex] & PP_REQUIRED) + SET_BIT(commandIndex, gp.ppList); + } + // Write PP list to NV + NV_SYNC_PERSISTENT(ppList); + return; +} +/* 8.8.3.2 PhysicalPresenceCommandSet() */ +/* This function is used to set the indicator that a command requires PP confirmation. */ +void +PhysicalPresenceCommandSet( + TPM_CC commandCode // IN: command code + ) +{ + COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); + // if the command isn't implemented, the do nothing + if(commandIndex == UNIMPLEMENTED_COMMAND_INDEX) + return; + // only set the bit if this is a command for which PP is allowed + if(s_commandAttributes[commandIndex] & PP_COMMAND) + SET_BIT(commandIndex, gp.ppList); + return; +} +/* 8.8.3.3 PhysicalPresenceCommandClear() */ +/* This function is used to clear the indicator that a command requires PP confirmation. */ +void +PhysicalPresenceCommandClear( + TPM_CC commandCode // IN: command code + ) +{ + COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); + // If the command isn't implemented, then don't do anything + if(commandIndex == UNIMPLEMENTED_COMMAND_INDEX) + return; + // Only clear the bit if the command does not require PP + if((s_commandAttributes[commandIndex] & PP_REQUIRED) == 0) + CLEAR_BIT(commandIndex, gp.ppList); + return; +} +/* 8.8.3.4 PhysicalPresenceIsRequired() */ +/* This function indicates if PP confirmation is required for a command. */ +/* Return Values Meaning */ +/* TRUE if physical presence is required */ +/* FALSE if physical presence is not required */ +BOOL +PhysicalPresenceIsRequired( + COMMAND_INDEX commandIndex // IN: command index + ) +{ + // Check the bit map. If the bit is SET, PP authorization is required + return (TEST_BIT(commandIndex, gp.ppList)); +} +/* 8.8.3.5 PhysicalPresenceCapGetCCList() */ +/* This function returns a list of commands that require PP confirmation. The list starts from the + first implemented command that has a command code that the same or greater than commandCode. */ +/* Return Values Meaning */ +/* YES if there are more command codes available */ +/* NO all the available command codes have been returned */ +TPMI_YES_NO +PhysicalPresenceCapGetCCList( + TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: count of returned TPM_CC + TPML_CC *commandList // OUT: list of TPM_CC + ) +{ + TPMI_YES_NO more = NO; + COMMAND_INDEX commandIndex; + // Initialize output handle list + commandList->count = 0; + // The maximum count of command we may return is MAX_CAP_CC + if(count > MAX_CAP_CC) count = MAX_CAP_CC; + // Collect PP commands + for(commandIndex = GetClosestCommandIndex(commandCode); + commandIndex != UNIMPLEMENTED_COMMAND_INDEX; + commandIndex = GetNextCommandIndex(commandIndex)) + { + if(PhysicalPresenceIsRequired(commandIndex)) + { + if(commandList->count < count) + { + // If we have not filled up the return list, add this command + // code to it + commandList->commandCodes[commandList->count] + = GetCommandCode(commandIndex); + commandList->count++; + } + else + { + // If the return list is full but we still have PP command + // available, report this and stop iterating + more = YES; + break; + } + } + } + return more; +} diff --git a/src/tpm2/PPPlat.c b/src/tpm2/PPPlat.c new file mode 100644 index 0000000..edb0007 --- /dev/null +++ b/src/tpm2/PPPlat.c @@ -0,0 +1,112 @@ +/********************************************************************************/ +/* */ +/* Simulates the Physical Present Interface */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PPPlat.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* C.10 PPPlat.c */ +/* C.10.1. Description */ +/* This module simulates the physical presence interface pins on the TPM. */ +/* C.10.2. Includes */ +#include "Platform.h" +#include "LibtpmsCallbacks.h" /* libtpms added */ +/* C.10.3. Functions */ +/* C.10.3.1. _plat__PhysicalPresenceAsserted() */ +/* Check if physical presence is signaled */ +/* Return Values Meaning */ +/* TRUE(1) if physical presence is signaled */ +/* FALSE(0) if physical presence is not signaled */ +LIB_EXPORT int +_plat__PhysicalPresenceAsserted( + void + ) +{ +#ifdef TPM_LIBTPMS_CALLBACKS + BOOL pp; + int ret = libtpms_plat__PhysicalPresenceAsserted(&pp); + + if (ret != LIBTPMS_CALLBACK_FALLTHROUGH) + return pp; +#endif /* TPM_LIBTPMS_CALLBACKS */ + + // Do not know how to check physical presence without real hardware. + // so always return TRUE; + return s_physicalPresence; +} +#if 0 /* libtpms added */ +/* C.10.3.2. _plat__Signal_PhysicalPresenceOn() */ +/* Signal physical presence on */ +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOn( + void + ) +{ + s_physicalPresence = TRUE; + return; +} +/* C.10.3.3. _plat__Signal_PhysicalPresenceOff() */ +/* Signal physical presence off */ +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOff( + void + ) +{ + s_physicalPresence = FALSE; + return; +} +#endif /* libtpms added */ diff --git a/src/tpm2/PP_Commands_fp.h b/src/tpm2/PP_Commands_fp.h new file mode 100644 index 0000000..7f858c6 --- /dev/null +++ b/src/tpm2/PP_Commands_fp.h @@ -0,0 +1,80 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PP_Commands_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef PP_COMMANDS_FP_H +#define PP_COMMANDS_FP_H + +typedef struct { + TPMI_RH_PLATFORM auth; + TPML_CC setList; + TPML_CC clearList; +} PP_Commands_In; + +#define RC_PP_Commands_auth (TPM_RC_H + TPM_RC_1) +#define RC_PP_Commands_setList (TPM_RC_P + TPM_RC_1) +#define RC_PP_Commands_clearList (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_PP_Commands( + PP_Commands_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/PP_fp.h b/src/tpm2/PP_fp.h new file mode 100644 index 0000000..fb78176 --- /dev/null +++ b/src/tpm2/PP_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PP_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef PP_FP_H +#define PP_FP_H + +void +PhysicalPresencePreInstall_Init( + void + ); +void +PhysicalPresenceCommandSet( + TPM_CC commandCode // IN: command code + ); +void +PhysicalPresenceCommandClear( + TPM_CC commandCode // IN: command code + ); +BOOL +PhysicalPresenceIsRequired( + COMMAND_INDEX commandIndex // IN: command index + ); +TPMI_YES_NO +PhysicalPresenceCapGetCCList( + TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: count of returned TPM_CC + TPML_CC *commandList // OUT: list of TPM_CC + ); + + +#endif diff --git a/src/tpm2/PRNG_TestVectors.h b/src/tpm2/PRNG_TestVectors.h new file mode 100644 index 0000000..eca09b1 --- /dev/null +++ b/src/tpm2/PRNG_TestVectors.h @@ -0,0 +1,110 @@ +/********************************************************************************/ +/* */ +/* PRNG Test Vectors */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PRNG_TestVectors.h 1529 2019-11-21 23:29:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 10.1.17 PRNG_TestVectors.h */ + +#ifndef _MSBN_DRBG_TEST_VECTORS_H +#define _MSBN_DRBG_TEST_VECTORS_H +//#if DRBG_ALGORITHM == TPM_ALG_AES && DRBG_KEY_BITS == 256 +#if DRBG_KEY_SIZE_BITS == 256 + +/* Entropy is the size of the state. The state is the size of the key plus the IV. The IV is a + block. If Key = 256 and Block = 128 then State = 384 */ + +#define DRBG_TEST_INITIATE_ENTROPY \ + 0x0d, 0x15, 0xaa, 0x80, 0xb1, 0x6c, 0x3a, 0x10, \ + 0x90, 0x6c, 0xfe, 0xdb, 0x79, 0x5d, 0xae, 0x0b, \ + 0x5b, 0x81, 0x04, 0x1c, 0x5c, 0x5b, 0xfa, 0xcb, \ + 0x37, 0x3d, 0x44, 0x40, 0xd9, 0x12, 0x0f, 0x7e, \ + 0x3d, 0x6c, 0xf9, 0x09, 0x86, 0xcf, 0x52, 0xd8, \ + 0x5d, 0x3e, 0x94, 0x7d, 0x8c, 0x06, 0x1f, 0x91 +#define DRBG_TEST_RESEED_ENTROPY \ + 0x6e, 0xe7, 0x93, 0xa3, 0x39, 0x55, 0xd7, 0x2a, \ + 0xd1, 0x2f, 0xd8, 0x0a, 0x8a, 0x3f, 0xcf, 0x95, \ + 0xed, 0x3b, 0x4d, 0xac, 0x57, 0x95, 0xfe, 0x25, \ + 0xcf, 0x86, 0x9f, 0x7c, 0x27, 0x57, 0x3b, 0xbc, \ + 0x56, 0xf1, 0xac, 0xae, 0x13, 0xa6, 0x50, 0x42, \ + 0xb3, 0x40, 0x09, 0x3c, 0x46, 0x4a, 0x7a, 0x22 +#define DRBG_TEST_GENERATED_INTERM \ + 0x28, 0xe0, 0xeb, 0xb8, 0x21, 0x01, 0x66, 0x50, \ + 0x8c, 0x8f, 0x65, 0xf2, 0x20, 0x7b, 0xd0, 0xa3 +#define DRBG_TEST_GENERATED \ + 0x94, 0x6f, 0x51, 0x82, 0xd5, 0x45, 0x10, 0xb9, \ + 0x46, 0x12, 0x48, 0xf5, 0x71, 0xca, 0x06, 0xc9 +#elif DRBG_KEY_SIZE_BITS == 128 +#define DRBG_TEST_INITIATE_ENTROPY \ + 0x8f, 0xc1, 0x1b, 0xdb, 0x5a, 0xab, 0xb7, 0xe0, \ + 0x93, 0xb6, 0x14, 0x28, 0xe0, 0x90, 0x73, 0x03, \ + 0xcb, 0x45, 0x9f, 0x3b, 0x60, 0x0d, 0xad, 0x87, \ + 0x09, 0x55, 0xf2, 0x2d, 0xa8, 0x0a, 0x44, 0xf8 +#define DRBG_TEST_RESEED_ENTROPY \ + 0x0c, 0xd5, 0x3c, 0xd5, 0xec, 0xcd, 0x5a, 0x10, \ + 0xd7, 0xea, 0x26, 0x61, 0x11, 0x25, 0x9b, 0x05, \ + 0x57, 0x4f, 0xc6, 0xdd, 0xd8, 0xbe, 0xd8, 0xbd, \ + 0x72, 0x37, 0x8c, 0xf8, 0x2f, 0x1d, 0xba, 0x2a +#define DRBG_TEST_GENERATED_INTERM \ + 0xdc, 0x3c, 0xf6, 0xbf, 0x5b, 0xd3, 0x41, 0x13, \ + 0x5f, 0x2c, 0x68, 0x11, 0xa1, 0x07, 0x1c, 0x87 +#define DRBG_TEST_GENERATED \ + 0xb6, 0x18, 0x50, 0xde, 0xcf, 0xd7, 0x10, 0x6d, \ + 0x44, 0x76, 0x9a, 0x8e, 0x6e, 0x8c, 0x1a, 0xd4 +#endif +#endif // _MSBN_DRBG_TEST_VECTORS_H diff --git a/src/tpm2/Platform.h b/src/tpm2/Platform.h new file mode 100644 index 0000000..126d0fe --- /dev/null +++ b/src/tpm2/Platform.h @@ -0,0 +1,75 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Platform.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019. */ +/* */ +/********************************************************************************/ + +/* C.14 Platform.h */ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ +#include "TpmBuildSwitches.h" +#include "BaseTypes.h" +#include "TPMB.h" +#include "MinMax.h" +#include "TpmProfile.h" +#include "PlatformACT.h" +#include "PlatformClock.h" +#include "PlatformData.h" +#include "Platform_fp.h" +#endif // _PLATFORM_H_ diff --git a/src/tpm2/PlatformACT.c b/src/tpm2/PlatformACT.c new file mode 100644 index 0000000..7d62dcb --- /dev/null +++ b/src/tpm2/PlatformACT.c @@ -0,0 +1,353 @@ +/********************************************************************************/ +/* */ +/* Platform Authenticated Countdown Timer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PlatformACT.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2020 */ +/* */ +/********************************************************************************/ +/* C.16 PlatformACT.c */ +/* C.16.1. Includes */ +#include "Platform.h" +#include "PlatformACT_fp.h" +/* C.16.2. Functions */ +/* C.16.2.1. ActSignal() */ +/* Function called when there is an ACT event to signal or unsignal */ +#ifndef __ACT_DISABLED // libtpms added +static void +ActSignal( + P_ACT_DATA actData, + int on + ) +{ + if(actData == NULL) + return; + // If this is to turn a signal on, don't do anything if it is already on. If this + // is to turn the signal off, do it anyway because this might be for + // initialization. + if(on && (actData->signaled == TRUE)) + return; + actData->signaled = (uint8_t)on; + + // If there is an action, then replace the "Do something" with the correct action. + // It should test 'on' to see if it is turning the signal on or off. + switch(actData->number) + { +#if RH_ACT_0 + case 0: // Do something + return; +#endif +#if RH_ACT_1 + case 1: // Do something + return; +#endif +#if RH_ACT_2 + case 2: // Do something + return; +#endif +#if RH_ACT_3 + case 3: // Do something + return; +#endif +#if RH_ACT_4 + case 4: // Do something + return; +#endif +#if RH_ACT_5 + case 5: // Do something + return; +#endif +#if RH_ACT_6 + case 6: // Do something + return; +#endif +#if RH_ACT_7 + case 7: // Do something + return; +#endif +#if RH_ACT_8 + case 8: // Do something + return; +#endif +#if RH_ACT_9 + case 9: // Do something + return; +#endif +#if RH_ACT_A + case 0xA: // Do something + return; +#endif +#if RH_ACT_B + case 0xB: + // Do something + return; +#endif +#if RH_ACT_C + case 0xC: // Do something + return; +#endif +#if RH_ACT_D + case 0xD: // Do something + return; +#endif +#if RH_ACT_E + case 0xE: // Do something + return; +#endif +#if RH_ACT_F + case 0xF: // Do something + return; +#endif + default: + return; + } +} +#endif // libtpms added +/* C.16.2.2. ActGetDataPointer() */ +static P_ACT_DATA +ActGetDataPointer( + uint32_t act + ) +{ + +#define RETURN_ACT_POINTER(N) if(0x##N == act) return &ACT_##N; + + FOR_EACH_ACT(RETURN_ACT_POINTER) + + return (P_ACT_DATA)NULL; +} +/* C.16.2.3. _plat__ACT_GetImplemented() */ +/* This function tests to see if an ACT is implemented. It is a belt and suspenders function because + the TPM should not be calling to manipulate an ACT that is not implemented. However, this + could help the simulator code which doesn't necessarily know if an ACT is implemented or not. */ +LIB_EXPORT int +_plat__ACT_GetImplemented( + uint32_t act + ) +{ + return (ActGetDataPointer(act) != NULL); +} +/* C.16.2.4. _plat__ACT_GetRemaining() */ +/* This function returns the remaining time. If an update is pending, newValue is + returned. Otherwise, the current counter value is returned. Note that since the timers keep + running, the returned value can get stale immediately. The actual count value will be no greater + than the returned value. */ +LIB_EXPORT uint32_t +_plat__ACT_GetRemaining( + uint32_t act //IN: the ACT selector + ) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + uint32_t remain; + // + if(actData == NULL) + return 0; + remain = actData->remaining; + if(actData->pending) + remain = actData->newValue; + return remain; +} +/* C.16.2.5. _plat__ACT_GetSignaled() */ +LIB_EXPORT int +_plat__ACT_GetSignaled( + uint32_t act //IN: number of ACT to check + ) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + // + if(actData == NULL) + return 0; + return (int)actData->signaled; +} +/* C.16.2.6. _plat__ACT_SetSignaled() */ +#ifndef __ACT_DISABLED // libtpms added +LIB_EXPORT void +_plat__ACT_SetSignaled( + uint32_t act, + int on + ) +{ + ActSignal(ActGetDataPointer(act), on); +} +/* C.16.2.7. _plat__ACT_GetPending() */ +LIB_EXPORT int +_plat__ACT_GetPending( + uint32_t act //IN: number of ACT to check + ) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + // + if(actData == NULL) + return 0; + return (int)actData->pending; +} +/* C.16.2.8. _plat__ACT_UpdateCounter() */ +/* This function is used to write the newValue for the counter. If an update is pending, then no + update occurs and the function returns FALSE. If setSignaled is TRUE, then the ACT signaled state + is SET and if newValue is 0, nothing is posted. */ +LIB_EXPORT int +_plat__ACT_UpdateCounter( + uint32_t act, // IN: ACT to update + uint32_t newValue // IN: the value to post + ) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + // + if(actData == NULL) + // actData doesn't exist but pretend update is pending rather than indicate + // that a retry is necessary. + return TRUE; + // if an update is pending then return FALSE so that there will be a retry + if(actData->pending != 0) + return FALSE; + actData->newValue = newValue; + actData->pending = TRUE; + + return TRUE; +} +#endif // libtpms added +/* C.16.2.9. _plat__ACT_EnableTicks() */ +/* This enables and disables the processing of the once-per-second ticks. This should be turned off + (enable = FALSE) by _TPM_Init() and turned on (enable = TRUE) by TPM2_Startup() after all the + initializations have completed. */ +LIB_EXPORT void +_plat__ACT_EnableTicks( + int enable + ) +{ + actTicksAllowed = enable; +} +/* C.16.2.10. ActDecrement() */ +/* If newValue is non-zero it is copied to remaining and then newValue is set to zero. Then + remaining is decremented by one if it is not already zero. If the value is decremented to zero, + then the associated event is signaled. If setting remaining causes it to be greater than 1, then + the signal associated with the ACT is turned off. */ +#ifndef __ACT_DISABLED // libtpms added +static void +ActDecrement( + P_ACT_DATA actData + ) +{ + // Check to see if there is an update pending + if(actData->pending) + { + // If this update will cause the count to go from non-zero to zero, set + // the newValue to 1 so that it will timeout when decremented below. + if((actData->newValue == 0) && (actData->remaining != 0)) + actData->newValue = 1; + actData->remaining = actData->newValue; + + // Update processed + actData->pending = 0; + } + // no update so countdown if the count is non-zero but not max + if((actData->remaining != 0) && (actData->remaining != UINT32_MAX)) + { + // If this countdown causes the count to go to zero, then turn the signal for + // the ACT on. + if((actData->remaining -= 1) == 0) + ActSignal(actData, TRUE); + } + // If the current value of the counter is non-zero, then the signal should be + // off. + if(actData->signaled && (actData->remaining > 0)) + ActSignal(actData, FALSE); +} +/* C.16.2.11. _plat__ACT_Tick() */ +/* This processes the once-per-second clock tick from the hardware. This is set up for the simulator to use the control interface to send ticks to the TPM. These ticks do not have to be on a per second basis. They can be as slow or as fast as desired so that the simulation can be tested. */ +LIB_EXPORT void +_plat__ACT_Tick( + void + ) +{ + // Ticks processing is turned off at certain times just to make sure that nothing + // strange is happening before pointers and things are + if(actTicksAllowed) + { + // Handle the update for each counter. +#define DECREMENT_COUNT(N) ActDecrement(&ACT_##N); + + FOR_EACH_ACT(DECREMENT_COUNT) + } +} +/* C.16.2.12. ActZero() */ +/* This function initializes a single ACT */ +static void +ActZero( + uint32_t act, + P_ACT_DATA actData + ) +{ + actData->remaining = 0; + actData->newValue = 0; + actData->pending = 0; + actData->number = (uint8_t)act; + ActSignal(actData, FALSE); +} +#endif // libtpms added +/* C.16.2.13. _plat__ACT_Initialize() */ +/* This function initializes the ACT hardware and data structures */ +LIB_EXPORT int +_plat__ACT_Initialize( + void + ) +{ + actTicksAllowed = 0; +#define ZERO_ACT(N) ActZero(0x##N, &ACT_##N); + FOR_EACH_ACT(ZERO_ACT) + + return TRUE; +} + diff --git a/src/tpm2/PlatformACT.h b/src/tpm2/PlatformACT.h new file mode 100644 index 0000000..e57b445 --- /dev/null +++ b/src/tpm2/PlatformACT.h @@ -0,0 +1,210 @@ +/********************************************************************************/ +/* */ +/* Platform Authenticated Countdown Timer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PlatformACT.h 1531 2019-11-21 23:54:38Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019. */ +/* */ +/********************************************************************************/ + +/* C.15 PlatformACT.h */ + +// This file contains the definitions for the ACT macros and data types used in the ACT +// implementation. + +#ifndef PLATFORMACT_H +#define PLATFORMACT_H + +typedef struct ACT_DATA +{ + uint32_t remaining; + uint32_t newValue; + uint8_t signaled; + uint8_t pending; + uint8_t number; +} ACT_DATA, *P_ACT_DATA; + +#if !(defined RH_ACT_0) || (RH_ACT_0 != YES) +# undef RH_ACT_0 +# define RH_ACT_0 NO +# define IF_ACT_0_IMPLEMENTED(op) +#else +# define IF_ACT_0_IMPLEMENTED(op) op(0) +#endif +#if !(defined RH_ACT_1) || (RH_ACT_1 != YES) +# undef RH_ACT_1 +# define RH_ACT_1 NO +# define IF_ACT_1_IMPLEMENTED(op) +#else +# define IF_ACT_1_IMPLEMENTED(op) op(1) +#endif +#if !(defined RH_ACT_2) || (RH_ACT_2 != YES) +# undef RH_ACT_2 +# define RH_ACT_2 NO +# define IF_ACT_2_IMPLEMENTED(op) +#else +# define IF_ACT_2_IMPLEMENTED(op) op(2) +#endif +#if !(defined RH_ACT_3) || (RH_ACT_3 != YES) +# undef RH_ACT_3 +# define RH_ACT_3 NO +# define IF_ACT_3_IMPLEMENTED(op) +#else +# define IF_ACT_3_IMPLEMENTED(op) op(3) +#endif +#if !(defined RH_ACT_4) || (RH_ACT_4 != YES) +# undef RH_ACT_4 +# define RH_ACT_4 NO +# define IF_ACT_4_IMPLEMENTED(op) +#else +# define IF_ACT_4_IMPLEMENTED(op) op(4) +#endif +#if !(defined RH_ACT_5) || (RH_ACT_5 != YES) +# undef RH_ACT_5 +# define RH_ACT_5 NO +# define IF_ACT_5_IMPLEMENTED(op) +#else +# define IF_ACT_5_IMPLEMENTED(op) op(5) +#endif +#if !(defined RH_ACT_6) || (RH_ACT_6 != YES) +# undef RH_ACT_6 +# define RH_ACT_6 NO +# define IF_ACT_6_IMPLEMENTED(op) +#else +# define IF_ACT_6_IMPLEMENTED(op) op(6) +#endif +#if !(defined RH_ACT_7) || (RH_ACT_7 != YES) +# undef RH_ACT_7 +# define RH_ACT_7 NO +# define IF_ACT_7_IMPLEMENTED(op) +#else +# define IF_ACT_7_IMPLEMENTED(op) op(7) +#endif +#if !(defined RH_ACT_8) || (RH_ACT_8 != YES) +# undef RH_ACT_8 +# define RH_ACT_8 NO +# define IF_ACT_8_IMPLEMENTED(op) +#else +# define IF_ACT_8_IMPLEMENTED(op) op(8) +#endif +#if !(defined RH_ACT_9) || (RH_ACT_9 != YES) +# undef RH_ACT_9 +# define RH_ACT_9 NO +# define IF_ACT_9_IMPLEMENTED(op) +#else +# define IF_ACT_9_IMPLEMENTED(op) op(9) +#endif +#if !(defined RH_ACT_A) || (RH_ACT_A != YES) +# undef RH_ACT_A +# define RH_ACT_A NO +# define IF_ACT_A_IMPLEMENTED(op) +#else +# define IF_ACT_A_IMPLEMENTED(op) op(A) +#endif +#if !(defined RH_ACT_B) || (RH_ACT_B != YES) +# undef RH_ACT_B +# define RH_ACT_B NO +# define IF_ACT_B_IMPLEMENTED(op) +#else +# define IF_ACT_B_IMPLEMENTED(op) op(B) +#endif +#if !(defined RH_ACT_C) || (RH_ACT_C != YES) +# undef RH_ACT_C +# define RH_ACT_C NO +# define IF_ACT_C_IMPLEMENTED(op) +#else +# define IF_ACT_C_IMPLEMENTED(op) op(C) +#endif +#if !(defined RH_ACT_D) || (RH_ACT_D != YES) +# undef RH_ACT_D +# define RH_ACT_D NO +# define IF_ACT_D_IMPLEMENTED(op) +#else +# define IF_ACT_D_IMPLEMENTED(op) op(D) +#endif +#if !(defined RH_ACT_E) || (RH_ACT_E != YES) +# undef RH_ACT_E +# define RH_ACT_E NO +# define IF_ACT_E_IMPLEMENTED(op) +#else +# define IF_ACT_E_IMPLEMENTED(op) op(E) +#endif +#if !(defined RH_ACT_F) || (RH_ACT_F != YES) +# undef RH_ACT_F +# define RH_ACT_F NO +# define IF_ACT_F_IMPLEMENTED(op) +#else +# define IF_ACT_F_IMPLEMENTED(op) op(F) +#endif + +#define FOR_EACH_ACT(op) \ + IF_ACT_0_IMPLEMENTED(op) \ + IF_ACT_1_IMPLEMENTED(op) \ + IF_ACT_2_IMPLEMENTED(op) \ + IF_ACT_3_IMPLEMENTED(op) \ + IF_ACT_4_IMPLEMENTED(op) \ + IF_ACT_5_IMPLEMENTED(op) \ + IF_ACT_6_IMPLEMENTED(op) \ + IF_ACT_7_IMPLEMENTED(op) \ + IF_ACT_8_IMPLEMENTED(op) \ + IF_ACT_9_IMPLEMENTED(op) \ + IF_ACT_A_IMPLEMENTED(op) \ + IF_ACT_B_IMPLEMENTED(op) \ + IF_ACT_C_IMPLEMENTED(op) \ + IF_ACT_D_IMPLEMENTED(op) \ + IF_ACT_E_IMPLEMENTED(op) \ + IF_ACT_F_IMPLEMENTED(op) + +#endif // _PLATFORM_ACT_H_ diff --git a/src/tpm2/PlatformACT_fp.h b/src/tpm2/PlatformACT_fp.h new file mode 100644 index 0000000..5d2caf5 --- /dev/null +++ b/src/tpm2/PlatformACT_fp.h @@ -0,0 +1,104 @@ +/********************************************************************************/ +/* */ +/* Platform Authenticated Countdown Timer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PlatformACT_fp.h 1531 2019-11-21 23:54:38Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#ifndef PLATFORMACT_FP_H +#define PLATFORMACT_FP_H + +LIB_EXPORT int +_plat__ACT_GetImplemented( + uint32_t act + ); +LIB_EXPORT uint32_t +_plat__ACT_GetRemaining( + uint32_t act //IN: the ACT selector + ); +LIB_EXPORT int +_plat__ACT_GetSignaled( + uint32_t act //IN: number of ACT to check + ); +LIB_EXPORT void +_plat__ACT_SetSignaled( + uint32_t act, + int on + ); +LIB_EXPORT int +_plat__ACT_GetPending( + uint32_t act //IN: number of ACT to check + ); +LIB_EXPORT int +_plat__ACT_UpdateCounter( + uint32_t act, // IN: ACT to update + uint32_t newValue // IN: the value to post + ); +LIB_EXPORT void +_plat__ACT_EnableTicks( + int enable + ); +LIB_EXPORT void +_plat__ACT_Tick( + void + ); +LIB_EXPORT int +_plat__ACT_Initialize( + void + ); + +#endif diff --git a/src/tpm2/PlatformClock.h b/src/tpm2/PlatformClock.h new file mode 100644 index 0000000..8f6ebb9 --- /dev/null +++ b/src/tpm2/PlatformClock.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* Platform Clock . */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PlatformClock.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2020 */ +/* */ +/********************************************************************************/ + +// C.16 PlatformClock.h This file contains the instance data for the Platform module. It is +// collected in this file so that the state of the module is easier to manage. +#ifndef _PLATFORM_CLOCK_H_ +#define _PLATFORM_CLOCK_H_ +#ifdef _MSC_VER +#include +#include +#else +#include +#include +#endif +// CLOCK_NOMINAL is the number of hardware ticks per mS. A value of 300000 means that the nominal +// clock rate used to drive the hardware clock is 30 MHz. The adjustment rates are used to determine +// the conversion of the hardware ticks to internal hardware clock value. In practice, we would +// expect that there would be a hardware register will accumulated mS. It would be incremented by +// the output of a pre-scaler. The pre-scaler would divide the ticks from the clock by some value +// that would compensate for the difference between clock time and real time. The code in Clock does +// the emulation of this function. +#define CLOCK_NOMINAL 30000 +// A 1% change in rate is 300 counts +#define CLOCK_ADJUST_COARSE 300 +// A 0.1% change in rate is 30 counts +#define CLOCK_ADJUST_MEDIUM 30 +// A minimum change in rate is 1 count +#define CLOCK_ADJUST_FINE 1 +// The clock tolerance is +/-15% (4500 counts) Allow some guard band (16.7%) +#define CLOCK_ADJUST_LIMIT 5000 +#endif // _PLATFORM_CLOCK_H_ diff --git a/src/tpm2/PlatformData.c b/src/tpm2/PlatformData.c new file mode 100644 index 0000000..d6fb0c5 --- /dev/null +++ b/src/tpm2/PlatformData.c @@ -0,0 +1,70 @@ +/********************************************************************************/ +/* */ +/* TPM variables that are not stack allocated */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PlatformData.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* C.9 PlatformData.c */ +/* C.9.1. Description */ +/* This file will instance the TPM variables that are not stack allocated. The descriptions for + these variables are in Global.h for this project. */ +/* C.9.2. Includes */ + +#define _PLATFORM_DATA_C_ +#include "Platform.h" + diff --git a/src/tpm2/PlatformData.h b/src/tpm2/PlatformData.h new file mode 100644 index 0000000..3555389 --- /dev/null +++ b/src/tpm2/PlatformData.h @@ -0,0 +1,142 @@ +/********************************************************************************/ +/* */ +/* Instance data for the Platform module. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PlatformData.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019. */ +/* */ +/********************************************************************************/ + +/* c.8 PlatformData.h */ +/* This file contains the instance data for the Platform module. It is collected in this file so + that the state of the module is easier to manage. */ + +#ifndef _PLATFORM_DATA_H_ +#define _PLATFORM_DATA_H_ +#ifdef _PLATFORM_DATA_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +/* From Cancel.c Cancel flag. It is initialized as FALSE, which indicate the command is not being + canceled */ +EXTERN int s_isCanceled; + +#ifndef HARDWARE_CLOCK +typedef uint64_t clock64_t; +// This is the value returned the last time that the system clock was read. This is only relevant +// for a simulator or virtual TPM. +EXTERN clock64_t s_realTimePrevious; +// These values are used to try to synthesize a long lived version of clock(). +EXTERN clock64_t s_lastSystemTime; +EXTERN clock64_t s_lastReportedTime; +// This is the rate adjusted value that is the equivalent of what would be read from a hardware +// register that produced rate adjusted time. +EXTERN clock64_t s_tpmTime; +/* libtpms added begin */ +EXTERN int64_t s_hostMonotonicAdjustTime; +EXTERN uint64_t s_suspendedElapsedTime; +/* libtpms added end */ +#endif // HARDWARE_CLOCK + +/* This value indicates that the timer was reset */ +EXTERN BOOL s_timerReset; +/* This value indicates that the timer was stopped. It causes a clock discontinuity. */ +EXTERN BOOL s_timerStopped; +/* This variable records the time when _plat__TimerReset() is called. This mechanism allow us to + subtract the time when TPM is power off from the total time reported by clock() function */ +EXTERN uint64_t s_initClock; +/* This variable records the timer adjustment factor. */ +EXTERN unsigned int s_adjustRate; +/* From LocalityPlat.c Locality of current command */ +EXTERN unsigned char s_locality; +/* From NVMem.c Choose if the NV memory should be backed by RAM or by file. If this macro is + defined, then a file is used as NV. If it is not defined, then RAM is used to back NV + memory. Comment out to use RAM. */ +#if (!defined VTPM) || ((VTPM != NO) && (VTPM != YES)) +# undef VTPM +# define VTPM NO // Default: Either YES or NO libtpms: NO +#endif + +// For a simulation, use a file to back up the NV + +#if (!defined FILE_BACKED_NV) || ((FILE_BACKED_NV != NO) && (FILE_BACKED_NV != YES)) +# undef FILE_BACKED_NV +# define FILE_BACKED_NV (VTPM && YES) // Default: Either YES or NO +#endif +#if !SIMULATION +# undef FILE_BACKED_NV +# define FILE_BACKED_NV YES // libtpms: write NvChip file if no callbacks are set +#else +#error Do not define SIMULATION for libtpms! +#endif // SIMULATION + +EXTERN unsigned char s_NV[NV_MEMORY_SIZE]; +EXTERN BOOL s_NvIsAvailable; +EXTERN BOOL s_NV_unrecoverable; +EXTERN BOOL s_NV_recoverable; +/* From PPPlat.c Physical presence. It is initialized to FALSE */ +EXTERN BOOL s_physicalPresence; +/* From Power */ +EXTERN BOOL s_powerLost; +/* From Entropy.c */ +EXTERN uint32_t lastEntropy; + +#define DEFINE_ACT(N) EXTERN ACT_DATA ACT_##N; +FOR_EACH_ACT(DEFINE_ACT) +EXTERN int actTicksAllowed; + +#endif // _PLATFORM_DATA_H_ diff --git a/src/tpm2/Platform_fp.h b/src/tpm2/Platform_fp.h new file mode 100644 index 0000000..4bc7cd4 --- /dev/null +++ b/src/tpm2/Platform_fp.h @@ -0,0 +1,407 @@ +/********************************************************************************/ +/* */ +/* NV read and write access methods */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Platform_fp.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* C.8 Platform_fp.h */ +#ifndef _PLATFORM_FP_H_ +#define _PLATFORM_FP_H_ + +#include "BaseTypes.h" + +/* C.8.1. From Cancel.c */ +/* C.8.1.1. _plat__IsCanceled() */ +/* Check if the cancel flag is set */ +/* Return Values Meaning */ +/* TRUE(1) if cancel flag is set */ +/* FALSE(0) if cancel flag is not set */ +LIB_EXPORT int +_plat__IsCanceled( + void + ); +/* Set cancel flag. */ +LIB_EXPORT void +_plat__SetCancel( + void + ); +/* C.8.1.2. _plat__ClearCancel() */ +/* Clear cancel flag */ +LIB_EXPORT void +_plat__ClearCancel( + void + ); +/* C.8.2. From Clock.c */ +/* C.8.2.1. _plat__TimerReset() */ +/* This function sets current system clock time as t0 for counting TPM time. This function is called + at a power on event to reset the clock. When the clock is reset, the indication that the clock + was stopped is also set. */ +LIB_EXPORT void +_plat__TimerReset( + void + ); +/* C.8.2.2. _plat__TimerRestart() */ +/* This function should be called in order to simulate the restart of the timer should it be stopped + while power is still applied. */ +LIB_EXPORT void +_plat__TimerRestart( + void + ); +// C.8.2.3. _plat__Time() This is another, probably futile, attempt to define a portable function +// that will return a 64-bit clock value that has mSec resolution. +LIB_EXPORT uint64_t +_plat__RealTime( + void + ); +/* C.8.2.4. _plat__TimerRead() */ +/* This function provides access to the tick timer of the platform. The TPM code uses this value to + drive the TPM Clock. */ +/* The tick timer is supposed to run when power is applied to the device. This timer should not be + reset by time events including _TPM_Init(). It should only be reset when TPM power is + re-applied. */ +/* If the TPM is run in a protected environment, that environment may provide the tick time to the + TPM as long as the time provided by the environment is not allowed to go backwards. If the time + provided by the system can go backwards during a power discontinuity, then the + _plat__Signal_PowerOn() should call _plat__TimerReset(). */ +LIB_EXPORT uint64_t +_plat__TimerRead( + void + ); +/* C.8.2.5. _plat__TimerWasReset() */ +/* This function is used to interrogate the flag indicating if the tick timer has been reset. */ +/* If the resetFlag parameter is SET, then the flag will be CLEAR before the function returns. */ +LIB_EXPORT int +_plat__TimerWasReset( + void + ); +/* C.8.2.6. _plat__TimerWasStopped() */ +/* This function is used to interrogate the flag indicating if the tick timer has been stopped. If + so, this is typically a reason to roll the nonce. */ +/* This function will CLEAR the s_timerStopped flag before returning. This provides functionality + that is similar to status register that is cleared when read. This is the model used here because + it is the one that has the most impact on the TPM code as the flag can only be accessed by one + entity in the TPM. Any other implementation of the hardware can be made to look like a read-once + register. */ +LIB_EXPORT int +_plat__TimerWasStopped( + void + ); +/* C.8.2.7. _plat__ClockAdjustRate() */ +/* Adjust the clock rate */ +LIB_EXPORT void +_plat__ClockAdjustRate( + int adjust // IN: the adjust number. It could be positive + // or negative + ); +/* C.8.3. From Entropy.c */ +// C.8.4. _plat__GetEntropy() +// This function is used to get available hardware entropy. In a hardware implementation of this +// function, there would be no call to the system to get entropy. +/* Return Values Meaning */ +/* < 0 hardware failure of the entropy generator, this is sticky */ +/* >= 0 the returned amount of entropy (bytes) */ +LIB_EXPORT int32_t +_plat__GetEntropy( + unsigned char *entropy, // output buffer + uint32_t amount // amount requested + ); +/* C.8.4. From LocalityPlat.c */ +/* C.8.4.1. _plat__LocalityGet() */ +/* Get the most recent command locality in locality value form. This is an integer value for + locality and not a locality structure The locality can be 0-4 or 32-255. 5-31 is not allowed. */ +LIB_EXPORT unsigned char +_plat__LocalityGet( + void + ); +/* C.8.4.2. _plat__LocalitySet() */ +/* Set the most recent command locality in locality value form */ +LIB_EXPORT void +_plat__LocalitySet( + unsigned char locality + ); +/* C.8.5. From NVMem.c */ +#if 0 /* libtpms added */ +/* C.8.5.1. _plat__NvErrors() */ +/* This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the NV loading process */ +LIB_EXPORT void +_plat__NvErrors( + int recoverable, + int unrecoverable + ); +#endif /* libtpms added */ +/* C.8.5.2. _plat__NVEnable() */ +/* Enable NV memory. */ +/* This version just pulls in data from a file. In a real TPM, with NV on chip, this function would + verify the integrity of the saved context. If the NV memory was not on chip but was in something + like RPMB, the NV state would be read in, decrypted and integrity checked. */ +/* The recovery from an integrity failure depends on where the error occurred. It it was in the + state that is discarded by TPM Reset, then the error is recoverable if the TPM is + reset. Otherwise, the TPM must go into failure mode. */ +/* Return Values Meaning */ +/* 0 if success */ +/* > 0 if receive recoverable error */ +/* <0 if unrecoverable error */ +LIB_EXPORT int +_plat__NVEnable( + void *platParameter // IN: platform specific parameters + ); +/* libtpms added begin */ +LIB_EXPORT int +_plat__NVEnable_NVChipFile( + void *platParameter // IN: platform specific parameters + ); +/* libtpms added end */ +/* C.8.5.3. _plat__NVDisable() */ +/* Disable NV memory */ +LIB_EXPORT void +_plat__NVDisable( + int delete // IN: If TRUE, delete the NV contents. + ); +/* C.8.6.4. _plat__IsNvAvailable() */ +/* Check if NV is available */ +/* Return Values Meaning */ +/* 0 NV is available */ +/* 1 NV is not available due to write failure */ +/* 2 NV is not available due to rate limit */ +LIB_EXPORT int +_plat__IsNvAvailable( + void + ); +/* C.8.5.5. _plat__NvMemoryRead() */ +/* Function: Read a chunk of NV memory */ +LIB_EXPORT void +_plat__NvMemoryRead( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // OUT: data buffer + ); +/* C.8.5.6. _plat__NvIsDifferent() */ +/* This function checks to see if the NV is different from the test value. This is so that NV will + not be written if it has not changed. */ +/* Return Values Meaning */ +/* TRUE(1) the NV location is different from the test value */ +/* FALSE(0) the NV location is the same as the test value */ +LIB_EXPORT int +_plat__NvIsDifferent( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // IN: data buffer + ); +/* C.8.5.7. _plat__NvMemoryWrite() */ +/* This function is used to update NV memory. The write is to a memory copy of NV. At the end of the + current command, any changes are written to the actual NV memory. */ +/* NOTE: A useful optimization would be for this code to compare the current contents of NV with the + local copy and note the blocks that have changed. Then only write those blocks when + _plat__NvCommit() is called. */ +LIB_EXPORT int +_plat__NvMemoryWrite( + unsigned int startOffset, // IN: write start + unsigned int size, // IN: size of bytes to write + void *data // OUT: data buffer + ); +/* C.8.6.8. _plat__NvMemoryClear() */ +/* Function is used to set a range of NV memory bytes to an implementation-dependent value. The + value represents the erase state of the memory. */ +LIB_EXPORT void +_plat__NvMemoryClear( + unsigned int start, // IN: clear start + unsigned int size // IN: number of bytes to clear + ); +/* C.8.5.9. _plat__NvMemoryMove() */ +/* Function: Move a chunk of NV memory from source to destination This function should ensure that + if there overlap, the original data is copied before it is written */ +LIB_EXPORT void +_plat__NvMemoryMove( + unsigned int sourceOffset, // IN: source offset + unsigned int destOffset, // IN: destination offset + unsigned int size // IN: size of data being moved + ); +/* C.8.5.10. _plat__NvCommit() */ +// This function writes the local copy of NV to NV for permanent store. It will write NV_MEMORY_SIZE +// bytes to NV. If a file is use, the entire file is written. +/* Return Values Meaning */ +/* 0 NV write success */ +/* non-0 NV write fail */ +LIB_EXPORT int +_plat__NvCommit( + void + ); +/* C.8.5.11. _plat__SetNvAvail() */ +/* Set the current NV state to available. This function is for testing purpose only. It is not + part of the platform NV logic */ +LIB_EXPORT void +_plat__SetNvAvail( + void + ); +/* C.8.5.12. _plat__ClearNvAvail() */ +/* Set the current NV state to unavailable. This function is for testing purpose only. It is not + part of the platform NV logic */ +LIB_EXPORT void +_plat__ClearNvAvail( + void + ); + +/* C.6.2.15. _plat__NVNeedsManufacture() */ +/* This function is used by the simulator to determine when the TPM's NV state needs to be manufactured. */ + +LIB_EXPORT int +_plat__NVNeedsManufacture( + void + ); + +/* C.8.6. From PowerPlat.c */ +/* C.8.6.1. _plat__Signal_PowerOn() */ +/* Signal platform power on */ +LIB_EXPORT int +_plat__Signal_PowerOn( + void + ); +/* C.8.6.2. _plat__WasPowerLost() */ +/* Test whether power was lost before a _TPM_Init(). */ +/* This function will clear the hardware indication of power loss before return. This means that + there can only be one spot in the TPM code where this value gets read. This method is used here + as it is the most difficult to manage in the TPM code and, if the hardware actually works this + way, it is hard to make it look like anything else. So, the burden is placed on the TPM code + rather than the platform code */ +/* Return Values Meaning */ +/* TRUE(1) power was lost */ +/* FALSE(0) power was not lost */ +LIB_EXPORT int +_plat__WasPowerLost( + void + ); +/* C.8.6.3. _plat_Signal_Reset() */ +/* This a TPM reset without a power loss. */ +LIB_EXPORT int +_plat__Signal_Reset( + void + ); +/* C.8.6.4. _plat__Signal_PowerOff() */ +/* Signal platform power off */ +LIB_EXPORT void +_plat__Signal_PowerOff( + void + ); + +/* C.8.7. From PPPlat.c */ +/* C.8.7.1. _plat__PhysicalPresenceAsserted() */ +/* Check if physical presence is signaled */ +/* Return Values Meaning */ +/* TRUE(1) if physical presence is signaled */ +/* FALSE(0) if physical presence is not signaled */ +LIB_EXPORT int +_plat__PhysicalPresenceAsserted( + void + ); +#if 0 /* libtpms added */ +/* C.8.7.2. _plat__Signal_PhysicalPresenceOn() */ +/* Signal physical presence on */ +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOn( + void + ); +/* C.8.7.3. _plat__Signal_PhysicalPresenceOff() */ +/* Signal physical presence off */ +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOff( + void + ); +#endif /* libtpms added */ + +/* C.8.8. From RunCommand.c */ +/* C.8.8.1. _plat__RunCommand() */ +/* This version of RunCommand() will set up a jum_buf and call ExecuteCommand(). If the command + executes without failing, it will return and RunCommand() will return. If there is a failure in + the command, then _plat__Fail() is called and it will longjump back to RunCommand() which will + call ExecuteCommand() again. However, this time, the TPM will be in failure mode so + ExecuteCommand() will simply build a failure response and return. */ +LIB_EXPORT void +_plat__RunCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + uint32_t *responseSize, // IN/OUT: response buffer size + unsigned char **response // IN/OUT: response buffer + ); +/* C.8.8.2. _plat__Fail() */ +/* This is the platform depended failure exit for the TPM. */ +LIB_EXPORT NORETURN void +_plat__Fail( + void + ); + +/* C.8.9. From Unique.c */ +/* C.8.9.1 _plat__GetUnique() */ +/* This function is used to access the platform-specific unique value. This function places the + unique value in the provided buffer (b) and returns the number of bytes transferred. The function + will not copy more data than bSize. */ +/* NOTE: If a platform unique value has unequal distribution of uniqueness and bSize is smaller than + the size of the unique value, the bSize portion with the most uniqueness should be returned. */ +LIB_EXPORT uint32_t +_plat__GetUnique( + uint32_t which, // authorities (0) or details + uint32_t bSize, // size of the buffer + unsigned char *b // output buffer + ); + +/* libtpms added begin */ +#include +void ClockAdjustPostResume(UINT64 backthen, BOOL timesAreRealtime); +uint64_t ClockGetTime(clockid_t clk_id); +/* libtpms added end */ + +#endif // _PLATFORM_FP_H_ diff --git a/src/tpm2/PolicyAuthValue_fp.h b/src/tpm2/PolicyAuthValue_fp.h new file mode 100644 index 0000000..836cea0 --- /dev/null +++ b/src/tpm2/PolicyAuthValue_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyAuthValue_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYAUTHVALUE_FP_H +#define POLICYAUTHVALUE_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; +} PolicyAuthValue_In; + +#define RC_PolicyAuthValue_policySession (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_PolicyAuthValue( + PolicyAuthValue_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyAuthorizeNV_fp.h b/src/tpm2/PolicyAuthorizeNV_fp.h new file mode 100644 index 0000000..03ebe52 --- /dev/null +++ b/src/tpm2/PolicyAuthorizeNV_fp.h @@ -0,0 +1,82 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyAuthorizeNV_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015, 2016 */ +/* */ +/********************************************************************************/ + +/* rev 136 */ + +#ifndef POLICYAUTHORIZENV_FP_H +#define POLICYAUTHORIZENV_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPMI_SH_POLICY policySession; +} PolicyAuthorizeNV_In; + +#define RC_PolicyAuthorizeNV_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_PolicyAuthorizeNV_nvIndex (TPM_RC_H + TPM_RC_2) +#define RC_PolicyAuthorizeNV_policySession (TPM_RC_H + TPM_RC_3) + +TPM_RC +TPM2_PolicyAuthorizeNV( + PolicyAuthorizeNV_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/PolicyAuthorize_fp.h b/src/tpm2/PolicyAuthorize_fp.h new file mode 100644 index 0000000..42b6704 --- /dev/null +++ b/src/tpm2/PolicyAuthorize_fp.h @@ -0,0 +1,86 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyAuthorize_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYAUTHORIZE_FP_H +#define POLICYAUTHORIZE_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM2B_DIGEST approvedPolicy; + TPM2B_NONCE policyRef; + TPM2B_NAME keySign; + TPMT_TK_VERIFIED checkTicket; +} PolicyAuthorize_In; + +#define RC_PolicyAuthorize_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyAuthorize_approvedPolicy (TPM_RC_P + TPM_RC_1) +#define RC_PolicyAuthorize_policyRef (TPM_RC_P + TPM_RC_2) +#define RC_PolicyAuthorize_keySign (TPM_RC_P + TPM_RC_3) +#define RC_PolicyAuthorize_checkTicket (TPM_RC_P + TPM_RC_4) + +TPM_RC +TPM2_PolicyAuthorize( + PolicyAuthorize_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/PolicyCommandCode_fp.h b/src/tpm2/PolicyCommandCode_fp.h new file mode 100644 index 0000000..698c5a5 --- /dev/null +++ b/src/tpm2/PolicyCommandCode_fp.h @@ -0,0 +1,80 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyCommandCode_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYCOMMANDCODE_FP_H +#define POLICYCOMMANDCODE_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM_CC code; +} PolicyCommandCode_In; + +#define RC_PolicyCommandCode_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyCommandCode_code (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PolicyCommandCode( + PolicyCommandCode_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/PolicyCounterTimer_fp.h b/src/tpm2/PolicyCounterTimer_fp.h new file mode 100644 index 0000000..2302b65 --- /dev/null +++ b/src/tpm2/PolicyCounterTimer_fp.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyCounterTimer_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYCOUNTERTIMER_FP_H +#define POLICYCOUNTERTIMER_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM2B_OPERAND operandB; + UINT16 offset; + TPM_EO operation; +} PolicyCounterTimer_In; + +#define RC_PolicyCounterTimer_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyCounterTimer_operandB (TPM_RC_P + TPM_RC_1) +#define RC_PolicyCounterTimer_offset (TPM_RC_P + TPM_RC_2) +#define RC_PolicyCounterTimer_operation (TPM_RC_P + TPM_RC_3) + +TPM_RC +TPM2_PolicyCounterTimer( + PolicyCounterTimer_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyCpHash_fp.h b/src/tpm2/PolicyCpHash_fp.h new file mode 100644 index 0000000..0ee1ea2 --- /dev/null +++ b/src/tpm2/PolicyCpHash_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyCpHash_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYCPHASH_FP_H +#define POLICYCPHASH_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM2B_DIGEST cpHashA; +} PolicyCpHash_In; + +#define RC_PolicyCpHash_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyCpHash_cpHashA (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PolicyCpHash( + PolicyCpHash_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyDuplicationSelect_fp.h b/src/tpm2/PolicyDuplicationSelect_fp.h new file mode 100644 index 0000000..c1010da --- /dev/null +++ b/src/tpm2/PolicyDuplicationSelect_fp.h @@ -0,0 +1,85 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyDuplicationSelect_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYDUPLICATIONSELECT_FP_H +#define POLICYDUPLICATIONSELECT_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM2B_NAME objectName; + TPM2B_NAME newParentName; + TPMI_YES_NO includeObject; +} PolicyDuplicationSelect_In; + +#define RC_PolicyDuplicationSelect_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyDuplicationSelect_objectName (TPM_RC_P + TPM_RC_1) +#define RC_PolicyDuplicationSelect_newParentName (TPM_RC_P + TPM_RC_2) +#define RC_PolicyDuplicationSelect_includeObject (TPM_RC_P + TPM_RC_3) + +TPM_RC +TPM2_PolicyDuplicationSelect( + PolicyDuplicationSelect_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyGetDigest_fp.h b/src/tpm2/PolicyGetDigest_fp.h new file mode 100644 index 0000000..921d55e --- /dev/null +++ b/src/tpm2/PolicyGetDigest_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyGetDigest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYGETDIGEST_FP_H +#define POLICYGETDIGEST_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; +} PolicyGetDigest_In; + +#define RC_PolicyGetDigest_policySession (TPM_RC_P + TPM_RC_1) + +typedef struct { + TPM2B_DIGEST policyDigest; +} PolicyGetDigest_Out; + +TPM_RC +TPM2_PolicyGetDigest( + PolicyGetDigest_In *in, // IN: input parameter list + PolicyGetDigest_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyLocality_fp.h b/src/tpm2/PolicyLocality_fp.h new file mode 100644 index 0000000..c9f0cc4 --- /dev/null +++ b/src/tpm2/PolicyLocality_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyLocality_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYLOCALITY_FP_H +#define POLICYLOCALITY_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPMA_LOCALITY locality; +} PolicyLocality_In; + +#define RC_PolicyLocality_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyLocality_locality (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PolicyLocality( + PolicyLocality_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyNV_fp.h b/src/tpm2/PolicyNV_fp.h new file mode 100644 index 0000000..4666e95 --- /dev/null +++ b/src/tpm2/PolicyNV_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyNV_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYNV_FP_H +#define POLICYNV_FP_H + +typedef struct { + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPMI_SH_POLICY policySession; + TPM2B_OPERAND operandB; + UINT16 offset; + TPM_EO operation; +} PolicyNV_In; + +#define RC_PolicyNV_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_PolicyNV_nvIndex (TPM_RC_H + TPM_RC_2) +#define RC_PolicyNV_policySession (TPM_RC_H + TPM_RC_3) +#define RC_PolicyNV_operandB (TPM_RC_P + TPM_RC_1) +#define RC_PolicyNV_offset (TPM_RC_P + TPM_RC_2) +#define RC_PolicyNV_operation (TPM_RC_P + TPM_RC_3) + +TPM_RC +TPM2_PolicyNV( + PolicyNV_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/PolicyNameHash_fp.h b/src/tpm2/PolicyNameHash_fp.h new file mode 100644 index 0000000..89945b1 --- /dev/null +++ b/src/tpm2/PolicyNameHash_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyNameHash_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYNAMEHASH_FP_H +#define POLICYNAMEHASH_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM2B_DIGEST nameHash; +} PolicyNameHash_In; + +#define RC_PolicyNameHash_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyNameHash_nameHash (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PolicyNameHash( + PolicyNameHash_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyNvWritten_fp.h b/src/tpm2/PolicyNvWritten_fp.h new file mode 100644 index 0000000..2e78a14 --- /dev/null +++ b/src/tpm2/PolicyNvWritten_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyNvWritten_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYNVWRITTEN_FP_H +#define POLICYNVWRITTEN_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPMI_YES_NO writtenSet; +} PolicyNvWritten_In; + +#define RC_PolicyNvWritten_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyNvWritten_writtenSet (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PolicyNvWritten( + PolicyNvWritten_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyOR_fp.h b/src/tpm2/PolicyOR_fp.h new file mode 100644 index 0000000..5af84b9 --- /dev/null +++ b/src/tpm2/PolicyOR_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyOR_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYOR_FP_H +#define POLICYOR_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPML_DIGEST pHashList; +} PolicyOR_In; + +#define RC_PolicyOR_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyOR_pHashList (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PolicyOR( + PolicyOR_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyPCR_fp.h b/src/tpm2/PolicyPCR_fp.h new file mode 100644 index 0000000..cc53313 --- /dev/null +++ b/src/tpm2/PolicyPCR_fp.h @@ -0,0 +1,82 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyPCR_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYPCR_FP_H +#define POLICYPCR_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM2B_DIGEST pcrDigest; + TPML_PCR_SELECTION pcrs; +} PolicyPCR_In; + +#define RC_PolicyPCR_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyPCR_pcrDigest (TPM_RC_P + TPM_RC_1) +#define RC_PolicyPCR_pcrs (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_PolicyPCR( + PolicyPCR_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/PolicyPassword_fp.h b/src/tpm2/PolicyPassword_fp.h new file mode 100644 index 0000000..7671a5e --- /dev/null +++ b/src/tpm2/PolicyPassword_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyPassword_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYPASSWORD_FP_H +#define POLICYPASSWORD_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; +} PolicyPassword_In; + +#define RC_PolicyPassword_policySession (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_PolicyPassword( + PolicyPassword_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyPhysicalPresence_fp.h b/src/tpm2/PolicyPhysicalPresence_fp.h new file mode 100644 index 0000000..aa59a6a --- /dev/null +++ b/src/tpm2/PolicyPhysicalPresence_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyPhysicalPresence_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYPHYSICALPRESENCE_FP_H +#define POLICYPHYSICALPRESENCE_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; +} PolicyPhysicalPresence_In; + +#define RC_PolicyPhysicalPresence_policySession (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_PolicyPhysicalPresence( + PolicyPhysicalPresence_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/PolicyRestart_fp.h b/src/tpm2/PolicyRestart_fp.h new file mode 100644 index 0000000..279b7ce --- /dev/null +++ b/src/tpm2/PolicyRestart_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyRestart_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYRESTART_FP_H +#define POLICYRESTART_FP_H + +typedef struct { + TPMI_SH_POLICY sessionHandle; +} PolicyRestart_In; + +#define RC_PolicyRestart_sessionHandle (TPM_RC_H + TPM_RC_1) + +TPM_RC +TPM2_PolicyRestart( + PolicyRestart_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicySecret_fp.h b/src/tpm2/PolicySecret_fp.h new file mode 100644 index 0000000..ff89a6c --- /dev/null +++ b/src/tpm2/PolicySecret_fp.h @@ -0,0 +1,95 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicySecret_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 124 */ + +#ifndef POLICYSECRET_FP_H +#define POLICYSECRET_FP_H + +typedef struct { + TPMI_DH_ENTITY authHandle; + TPMI_SH_POLICY policySession; + TPM2B_NONCE nonceTPM; + TPM2B_DIGEST cpHashA; + TPM2B_NONCE policyRef; + INT32 expiration; +} PolicySecret_In; + +#define RC_PolicySecret_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_PolicySecret_policySession (TPM_RC_H + TPM_RC_2) +#define RC_PolicySecret_nonceTPM (TPM_RC_P + TPM_RC_1) +#define RC_PolicySecret_cpHashA (TPM_RC_P + TPM_RC_2) +#define RC_PolicySecret_policyRef (TPM_RC_P + TPM_RC_3) +#define RC_PolicySecret_expiration (TPM_RC_P + TPM_RC_4) + +typedef struct { + TPM2B_TIMEOUT timeout; + TPMT_TK_AUTH policyTicket; +} PolicySecret_Out; + +TPM_RC +TPM2_PolicySecret( + PolicySecret_In *in, // IN: input parameter list + PolicySecret_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/PolicySigned_fp.h b/src/tpm2/PolicySigned_fp.h new file mode 100644 index 0000000..3c75b42 --- /dev/null +++ b/src/tpm2/PolicySigned_fp.h @@ -0,0 +1,96 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicySigned_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYSIGNED_FP_H +#define POLICYSIGNED_FP_H + +typedef struct { + TPMI_DH_OBJECT authObject; + TPMI_SH_POLICY policySession; + TPM2B_NONCE nonceTPM; + TPM2B_DIGEST cpHashA; + TPM2B_NONCE policyRef; + INT32 expiration; + TPMT_SIGNATURE auth; +} PolicySigned_In; + +#define RC_PolicySigned_authObject (TPM_RC_H + TPM_RC_1) +#define RC_PolicySigned_policySession (TPM_RC_H + TPM_RC_2) +#define RC_PolicySigned_nonceTPM (TPM_RC_P + TPM_RC_1) +#define RC_PolicySigned_cpHashA (TPM_RC_P + TPM_RC_2) +#define RC_PolicySigned_policyRef (TPM_RC_P + TPM_RC_3) +#define RC_PolicySigned_expiration (TPM_RC_P + TPM_RC_4) +#define RC_PolicySigned_auth (TPM_RC_P + TPM_RC_5) + +typedef struct { + TPM2B_TIMEOUT timeout; + TPMT_TK_AUTH policyTicket; +} PolicySigned_Out; + +TPM_RC +TPM2_PolicySigned( + PolicySigned_In *in, // IN: input parameter list + PolicySigned_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/PolicyTemplate_fp.h b/src/tpm2/PolicyTemplate_fp.h new file mode 100644 index 0000000..d56825b --- /dev/null +++ b/src/tpm2/PolicyTemplate_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyTemplate_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015, 2016 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYTEMPLATE_FP_H +#define POLICYTEMPLATE_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM2B_DIGEST templateHash; +} PolicyTemplate_In; + +#define RC_PolicyTemplate_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyTemplate_templateHash (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_PolicyTemplate( + PolicyTemplate_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/PolicyTicket_fp.h b/src/tpm2/PolicyTicket_fp.h new file mode 100644 index 0000000..8d78c87 --- /dev/null +++ b/src/tpm2/PolicyTicket_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PolicyTicket_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef POLICYTICKET_FP_H +#define POLICYTICKET_FP_H + +typedef struct { + TPMI_SH_POLICY policySession; + TPM2B_TIMEOUT timeout; + TPM2B_DIGEST cpHashA; + TPM2B_NONCE policyRef; + TPM2B_NAME authName; + TPMT_TK_AUTH ticket; +} PolicyTicket_In; + +#define RC_PolicyTicket_policySession (TPM_RC_H + TPM_RC_1) +#define RC_PolicyTicket_timeout (TPM_RC_P + TPM_RC_1) +#define RC_PolicyTicket_cpHashA (TPM_RC_P + TPM_RC_2) +#define RC_PolicyTicket_policyRef (TPM_RC_P + TPM_RC_3) +#define RC_PolicyTicket_authName (TPM_RC_P + TPM_RC_4) +#define RC_PolicyTicket_ticket (TPM_RC_P + TPM_RC_5) + +TPM_RC +TPM2_PolicyTicket( + PolicyTicket_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/Policy_spt.c b/src/tpm2/Policy_spt.c new file mode 100644 index 0000000..4c2de20 --- /dev/null +++ b/src/tpm2/Policy_spt.c @@ -0,0 +1,300 @@ +/********************************************************************************/ +/* */ +/* Policy Command Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Policy_spt.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 7.4 Policy Command Support (Policy_spt.c) */ +#include "Tpm.h" +#include "Policy_spt_fp.h" +#include "PolicySigned_fp.h" +#include "PolicySecret_fp.h" +#include "PolicyTicket_fp.h" +/* 7.4.1 PolicyParameterChecks() */ +/* This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The + common parameters are nonceTPM, expiration, and cpHashA. */ +TPM_RC +PolicyParameterChecks( + SESSION *session, + UINT64 authTimeout, + TPM2B_DIGEST *cpHashA, + TPM2B_NONCE *nonce, + TPM_RC blameNonce, + TPM_RC blameCpHash, + TPM_RC blameExpiration + ) +{ + // Validate that input nonceTPM is correct if present + if(nonce != NULL && nonce->t.size != 0) + { + if(!MemoryEqual2B(&nonce->b, &session->nonceTPM.b)) + return TPM_RCS_NONCE + blameNonce; + } + // If authTimeout is set (expiration != 0... + if(authTimeout != 0) + { + // Validate input expiration. + // Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE + // or TPM_RC_NV_RATE error may be returned here. + RETURN_IF_NV_IS_NOT_AVAILABLE; + // if the time has already passed or the time epoch has changed then the + // time value is no longer good. + if((authTimeout < g_time) + || (session->epoch != g_timeEpoch)) + return TPM_RCS_EXPIRED + blameExpiration; + } + // If the cpHash is present, then check it + if(cpHashA != NULL && cpHashA->t.size != 0) + { + // The cpHash input has to have the correct size + if(cpHashA->t.size != session->u2.policyDigest.t.size) + return TPM_RCS_SIZE + blameCpHash; + // If the cpHash has already been set, then this input value + // must match the current value. + if(session->u1.cpHash.b.size != 0 + && !MemoryEqual2B(&cpHashA->b, &session->u1.cpHash.b)) + return TPM_RC_CPHASH; + } + return TPM_RC_SUCCESS; +} +/* 7.4.2 PolicyContextUpdate() */ +/* Update policy hash Update the policyDigest in policy session by extending policyRef and + objectName to it. This will also update the cpHash if it is present. */ +void +PolicyContextUpdate( + TPM_CC commandCode, // IN: command code + TPM2B_NAME *name, // IN: name of entity + TPM2B_NONCE *ref, // IN: the reference data + TPM2B_DIGEST *cpHash, // IN: the cpHash (optional) + UINT64 policyTimeout, // IN: the timeout value for the policy + SESSION *session // IN/OUT: policy session to be updated + ) +{ + HASH_STATE hashState; + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + // policyDigest size should always be the digest size of session hash algorithm. + pAssert(session->u2.policyDigest.t.size + == CryptHashGetDigestSize(session->authHashAlg)); + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); + // add name if applicable + if(name != NULL) + CryptDigestUpdate2B(&hashState, &name->b); + // Complete the digest and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + // If the policy reference is not null, do a second update to the digest. + if(ref != NULL) + { + // Start second hash computation + CryptHashStart(&hashState, session->authHashAlg); + // add policyDigest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + // add policyRef + CryptDigestUpdate2B(&hashState, &ref->b); + // Complete second digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + } + // Deal with the cpHash. If the cpHash value is present + // then it would have already been checked to make sure that + // it is compatible with the current value so all we need + // to do here is copy it and set the isCpHashDefined attribute + if(cpHash != NULL && cpHash->t.size != 0) + { + session->u1.cpHash = *cpHash; + session->attributes.isCpHashDefined = SET; + } + // update the timeout if it is specified + if(policyTimeout != 0) + { + // If the timeout has not been set, then set it to the new value + // than the current timeout then set it to the new value + if(session->timeout == 0 || session->timeout > policyTimeout) + session->timeout = policyTimeout; + } + return; +} +/* 7.4.2.1 ComputeAuthTimeout() */ +/* This function is used to determine what the authorization timeout value for the session should + be. */ +UINT64 +ComputeAuthTimeout( + SESSION *session, // IN: the session containing the time + // values + INT32 expiration, // IN: either the number of seconds from + // the start of the session or the + // time in g_timer; + TPM2B_NONCE *nonce // IN: indicator of the time base + ) +{ + UINT64 policyTime; + // If no expiration, policy time is 0 + if(expiration == 0) + policyTime = 0; + else + { + if(expiration < 0) { + if (expiration == (INT32)0x80000000) /* libtpms changed begin; ubsan */ + expiration++; /* libtpms changed end */ + expiration = -expiration; + } + if(nonce->t.size == 0) + // The input time is absolute Time (not Clock), but it is expressed + // in seconds. To make sure that we don't time out too early, take the + // current value of milliseconds in g_time and add that to the input + // seconds value. + policyTime = (((UINT64)expiration) * 1000) + g_time % 1000; + else + // The policy timeout is the absolute value of the expiration in seconds + // added to the start time of the policy. + policyTime = session->startTime + (((UINT64)expiration) * 1000); + } + return policyTime; +} +/* 7.4.2.2 PolicyDigestClear() */ +/* Function to reset the policyDigest of a session */ +void +PolicyDigestClear( + SESSION *session + ) +{ + session->u2.policyDigest.t.size = CryptHashGetDigestSize(session->authHashAlg); + MemorySet(session->u2.policyDigest.t.buffer, 0, + session->u2.policyDigest.t.size); +} + +/* 7.4.2.5 PolicySptCheckCondition() */ +/* Checks to see if the condition in the policy is satisfied. */ + +BOOL +PolicySptCheckCondition( + TPM_EO operation, + BYTE *opA, + BYTE *opB, + UINT16 size + ) +{ + // Arithmetic Comparison + switch(operation) + { + case TPM_EO_EQ: + // compare A = B + return (UnsignedCompareB(size, opA, size, opB) == 0); + break; + case TPM_EO_NEQ: + // compare A != B + return (UnsignedCompareB(size, opA, size, opB) != 0); + break; + case TPM_EO_SIGNED_GT: + // compare A > B signed + return (SignedCompareB(size, opA, size, opB) > 0); + break; + case TPM_EO_UNSIGNED_GT: + // compare A > B unsigned + return (UnsignedCompareB(size, opA, size, opB) > 0); + break; + case TPM_EO_SIGNED_LT: + // compare A < B signed + return (SignedCompareB(size, opA, size, opB) < 0); + break; + case TPM_EO_UNSIGNED_LT: + // compare A < B unsigned + return (UnsignedCompareB(size, opA, size, opB) < 0); + break; + case TPM_EO_SIGNED_GE: + // compare A >= B signed + return (SignedCompareB(size, opA, size, opB) >= 0); + break; + case TPM_EO_UNSIGNED_GE: + // compare A >= B unsigned + return (UnsignedCompareB(size, opA, size, opB) >= 0); + break; + case TPM_EO_SIGNED_LE: + // compare A <= B signed + return (SignedCompareB(size, opA, size, opB) <= 0); + break; + case TPM_EO_UNSIGNED_LE: + // compare A <= B unsigned + return (UnsignedCompareB(size, opA, size, opB) <= 0); + break; + case TPM_EO_BITSET: + // All bits SET in B are SET in A. ((A&B)=B) + { + UINT32 i; + for(i = 0; i < size; i++) + if((opA[i] & opB[i]) != opB[i]) + return FALSE; + } + break; + case TPM_EO_BITCLEAR: + // All bits SET in B are CLEAR in A. ((A&B)=0) + { + UINT32 i; + for(i = 0; i < size; i++) + if((opA[i] & opB[i]) != 0) + return FALSE; + } + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return TRUE; +} diff --git a/src/tpm2/Policy_spt_fp.h b/src/tpm2/Policy_spt_fp.h new file mode 100644 index 0000000..86bd43e --- /dev/null +++ b/src/tpm2/Policy_spt_fp.h @@ -0,0 +1,110 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Policy_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef POLICY_SPT_FP_H +#define POLICY_SPT_FP_H + +TPM_RC +PolicyParameterChecks( + SESSION *session, + UINT64 authTimeout, + TPM2B_DIGEST *cpHashA, + TPM2B_NONCE *nonce, + TPM_RC blameNonce, + TPM_RC blameCpHash, + TPM_RC blameExpiration + ); +void +PolicyContextUpdate( + TPM_CC commandCode, // IN: command code + TPM2B_NAME *name, // IN: name of entity + TPM2B_NONCE *ref, // IN: the reference data + TPM2B_DIGEST *cpHash, // IN: the cpHash (optional) + UINT64 policyTimeout, // IN: the timeout value for the policy + SESSION *session // IN/OUT: policy session to be updated + ); +UINT64 +ComputeAuthTimeout( + SESSION *session, // IN: the session containing the time + // values + INT32 expiration, // IN: either the number of seconds from + // the start of the session or the + // time in g_timer; + TPM2B_NONCE *nonce // IN: indicator of the time base + ); +void +PolicyDigestClear( + SESSION *session + ); +BOOL +PolicySptCheckCondition( + TPM_EO operation, + BYTE *opA, + BYTE *opB, + UINT16 size + ); + + + + + + +#endif diff --git a/src/tpm2/Power.c b/src/tpm2/Power.c new file mode 100644 index 0000000..30363b5 --- /dev/null +++ b/src/tpm2/Power.c @@ -0,0 +1,109 @@ +/********************************************************************************/ +/* */ +/* Simulated Power State Transitions of the TPM */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Power.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 9.13 Power.c */ +/* 9.13.1 Description */ +/* This file contains functions that receive the simulated power state transitions of the TPM. */ +/* 9.13.2 Includes and Data Definitions */ +#define POWER_C +#include "Tpm.h" +/* 9.13.3 Functions */ +/* 9.13.3.1 TPMInit() */ +/* This function is used to process a power on event. */ + +void +TPMInit( + void + ) +{ + // Set state as not initialized. This means that Startup is required + g_initialized = FALSE; + return; +} + +/* 9.13.3.2 TPMRegisterStartup() */ +/* This function registers the fact that the TPM has been initialized (a TPM2_Startup() has + completed successfully). */ + +BOOL +TPMRegisterStartup( + void + ) +{ + g_initialized = TRUE; + return TRUE; +} + +/* 9.13.3.3 TPMIsStarted() */ +/* Indicates if the TPM has been initialized (a TPM2_Startup() has completed successfully after a + _TPM_Init()). */ +/* Return Values Meaning */ +/* TRUE TPM has been initialized */ +/* FALSE TPM has not been initialized */ + +BOOL +TPMIsStarted( + void + ) +{ + return g_initialized; +} + diff --git a/src/tpm2/PowerPlat.c b/src/tpm2/PowerPlat.c new file mode 100644 index 0000000..9077a33 --- /dev/null +++ b/src/tpm2/PowerPlat.c @@ -0,0 +1,128 @@ +/********************************************************************************/ +/* */ +/* Platform Power Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PowerPlat.c 1529 2019-11-21 23:29:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* C.7 PowerPlat.c */ +/* C.7.1. Includes and Function Prototypes */ +#include "Platform.h" +#include "PlatformACT_fp.h" /* added kgold */ +#include "_TPM_Init_fp.h" +/* C.7.2. Functions */ +/* C.7.2.1. _plat__Signal_PowerOn() */ +/* Signal platform power on */ +LIB_EXPORT int +_plat__Signal_PowerOn( + void + ) +{ + // Reset the timer + _plat__TimerReset(); + // Need to indicate that we lost power + s_powerLost = TRUE; + return 0; +} +/* C.7.2.2. _plat__WasPowerLost() */ +/* Test whether power was lost before a _TPM_Init(). */ +/* This function will clear the hardware indication of power loss before return. This means that + there can only be one spot in the TPM code where this value gets read. This method is used here + as it is the most difficult to manage in the TPM code and, if the hardware actually works this + way, it is hard to make it look like anything else. So, the burden is placed on the TPM code + rather than the platform code */ +/* Return Values Meaning */ +/* TRUE(1) power was lost */ +/* FALSE(0) power was not lost */ +LIB_EXPORT int +_plat__WasPowerLost( + void + ) +{ + int retVal = s_powerLost; + s_powerLost = FALSE; + return retVal; +} +/* C.7.2.3. _plat_Signal_Reset() */ +/* This a TPM reset without a power loss. */ +LIB_EXPORT int +_plat__Signal_Reset( + void + ) +{ + // Initialize locality + s_locality = 0; + // Command cancel + s_isCanceled = FALSE; + _TPM_Init(); + // if we are doing reset but did not have a power failure, then we should + // not need to reload NV ... + return 0; +} +/* C.7.2.4. _plat__Signal_PowerOff() */ +/* Signal platform power off */ +LIB_EXPORT void +_plat__Signal_PowerOff( + void + ) +{ + // Prepare NV memory for power off + _plat__NVDisable(0); + // Disable tick ACT tick processing + _plat__ACT_EnableTicks(FALSE); + return; +} diff --git a/src/tpm2/Power_fp.h b/src/tpm2/Power_fp.h new file mode 100644 index 0000000..7c99543 --- /dev/null +++ b/src/tpm2/Power_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* Functions That Receive the Simulated Power State Transitions of the TPM */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Power_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef POWER_FP_H +#define POWER_FP_H + +void +TPMInit( + void + ); +BOOL +TPMRegisterStartup( + void + ); +BOOL +TPMIsStarted( + void + ); + + +#endif diff --git a/src/tpm2/PrimeData.c b/src/tpm2/PrimeData.c new file mode 100644 index 0000000..9ef684d --- /dev/null +++ b/src/tpm2/PrimeData.c @@ -0,0 +1,441 @@ +/********************************************************************************/ +/* */ +/* Product of all of the Primes up to 1000 */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PrimeData.c 1311 2018-08-23 21:39:29Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +/* This table is the product of all of the primes up to 1000. Checking to see if there is a GCD + between a prime candidate and this number will eliminate many prime candidates from consideration + before running Miller-Rabin on the result. */ +const BN_STRUCT(43 * RADIX_BITS) s_CompositeOfSmallPrimes_ = +{44, 44, + { 0x2ED42696, 0x2BBFA177, 0x4820594F, 0xF73F4841, + 0xBFAC313A, 0xCAC3EB81, 0xF6F26BF8, 0x7FAB5061, + 0x59746FB7, 0xF71377F6, 0x3B19855B, 0xCBD03132, + 0xBB92EF1B, 0x3AC3152C, 0xE87C8273, 0xC0AE0E69, + 0x74A9E295, 0x448CCE86, 0x63CA1907, 0x8A0BF944, + 0xF8CC3BE0, 0xC26F0AF5, 0xC501C02F, 0x6579441A, + 0xD1099CDA, 0x6BC76A00, 0xC81A3228, 0xBFB1AB25, + 0x70FA3841, 0x51B3D076, 0xCC2359ED, 0xD9EE0769, + 0x75E47AF0, 0xD45FF31E, 0x52CCE4F6, 0x04DBC891, + 0x96658ED2, 0x1753EFE5, 0x3AE4A5A6, 0x8FD4A97F, + 0x8B15E7EB, 0x0243C3E1, 0xE0F0C31D, 0x0000000B } +}; +bigConst s_CompositeOfSmallPrimes = (const bigNum)&s_CompositeOfSmallPrimes_; +/* This table contains a bit for each of the odd values between 1 and 2^16 + 1. This table allows + fast checking of the primes in that range. Don't change the size of this table unless you are + prepared to do redo IsPrimeInt(). */ +const uint32_t s_LastPrimeInTable = 65537; +const uint32_t s_PrimeTableSize = 4097; +const uint32_t s_PrimesInTable = 6542; +const unsigned char s_PrimeTable[] = { + 0x6e, 0xcb, 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x81, 0x32, 0x4c, 0x4a, 0x86, + 0x0d, 0x82, 0x96, 0x21, 0xc9, 0x34, 0x04, 0x5a, 0x20, 0x61, 0x89, 0xa4, + 0x44, 0x11, 0x86, 0x29, 0xd1, 0x82, 0x28, 0x4a, 0x30, 0x40, 0x42, 0x32, + 0x21, 0x99, 0x34, 0x08, 0x4b, 0x06, 0x25, 0x42, 0x84, 0x48, 0x8a, 0x14, + 0x05, 0x42, 0x30, 0x6c, 0x08, 0xb4, 0x40, 0x0b, 0xa0, 0x08, 0x51, 0x12, + 0x28, 0x89, 0x04, 0x65, 0x98, 0x30, 0x4c, 0x80, 0x96, 0x44, 0x12, 0x80, + 0x21, 0x42, 0x12, 0x41, 0xc9, 0x04, 0x21, 0xc0, 0x32, 0x2d, 0x98, 0x00, + 0x00, 0x49, 0x04, 0x08, 0x81, 0x96, 0x68, 0x82, 0xb0, 0x25, 0x08, 0x22, + 0x48, 0x89, 0xa2, 0x40, 0x59, 0x26, 0x04, 0x90, 0x06, 0x40, 0x43, 0x30, + 0x44, 0x92, 0x00, 0x69, 0x10, 0x82, 0x08, 0x08, 0xa4, 0x0d, 0x41, 0x12, + 0x60, 0xc0, 0x00, 0x24, 0xd2, 0x22, 0x61, 0x08, 0x84, 0x04, 0x1b, 0x82, + 0x01, 0xd3, 0x10, 0x01, 0x02, 0xa0, 0x44, 0xc0, 0x22, 0x60, 0x91, 0x14, + 0x0c, 0x40, 0xa6, 0x04, 0xd2, 0x94, 0x20, 0x09, 0x94, 0x20, 0x52, 0x00, + 0x08, 0x10, 0xa2, 0x4c, 0x00, 0x82, 0x01, 0x51, 0x10, 0x08, 0x8b, 0xa4, + 0x25, 0x9a, 0x30, 0x44, 0x81, 0x10, 0x4c, 0x03, 0x02, 0x25, 0x52, 0x80, + 0x08, 0x49, 0x84, 0x20, 0x50, 0x32, 0x00, 0x18, 0xa2, 0x40, 0x11, 0x24, + 0x28, 0x01, 0x84, 0x01, 0x01, 0xa0, 0x41, 0x0a, 0x12, 0x45, 0x00, 0x36, + 0x08, 0x00, 0x26, 0x29, 0x83, 0x82, 0x61, 0xc0, 0x80, 0x04, 0x10, 0x10, + 0x6d, 0x00, 0x22, 0x48, 0x58, 0x26, 0x0c, 0xc2, 0x10, 0x48, 0x89, 0x24, + 0x20, 0x58, 0x20, 0x45, 0x88, 0x24, 0x00, 0x19, 0x02, 0x25, 0xc0, 0x10, + 0x68, 0x08, 0x14, 0x01, 0xca, 0x32, 0x28, 0x80, 0x00, 0x04, 0x4b, 0x26, + 0x00, 0x13, 0x90, 0x60, 0x82, 0x80, 0x25, 0xd0, 0x00, 0x01, 0x10, 0x32, + 0x0c, 0x43, 0x86, 0x21, 0x11, 0x00, 0x08, 0x43, 0x24, 0x04, 0x48, 0x10, + 0x0c, 0x90, 0x92, 0x00, 0x43, 0x20, 0x2d, 0x00, 0x06, 0x09, 0x88, 0x24, + 0x40, 0xc0, 0x32, 0x09, 0x09, 0x82, 0x00, 0x53, 0x80, 0x08, 0x80, 0x96, + 0x41, 0x81, 0x00, 0x40, 0x48, 0x10, 0x48, 0x08, 0x96, 0x48, 0x58, 0x20, + 0x29, 0xc3, 0x80, 0x20, 0x02, 0x94, 0x60, 0x92, 0x00, 0x20, 0x81, 0x22, + 0x44, 0x10, 0xa0, 0x05, 0x40, 0x90, 0x01, 0x49, 0x20, 0x04, 0x0a, 0x00, + 0x24, 0x89, 0x34, 0x48, 0x13, 0x80, 0x2c, 0xc0, 0x82, 0x29, 0x00, 0x24, + 0x45, 0x08, 0x00, 0x08, 0x98, 0x36, 0x04, 0x52, 0x84, 0x04, 0xd0, 0x04, + 0x00, 0x8a, 0x90, 0x44, 0x82, 0x32, 0x65, 0x18, 0x90, 0x00, 0x0a, 0x02, + 0x01, 0x40, 0x02, 0x28, 0x40, 0xa4, 0x04, 0x92, 0x30, 0x04, 0x11, 0x86, + 0x08, 0x42, 0x00, 0x2c, 0x52, 0x04, 0x08, 0xc9, 0x84, 0x60, 0x48, 0x12, + 0x09, 0x99, 0x24, 0x44, 0x00, 0x24, 0x00, 0x03, 0x14, 0x21, 0x00, 0x10, + 0x01, 0x1a, 0x32, 0x05, 0x88, 0x20, 0x40, 0x40, 0x06, 0x09, 0xc3, 0x84, + 0x40, 0x01, 0x30, 0x60, 0x18, 0x02, 0x68, 0x11, 0x90, 0x0c, 0x02, 0xa2, + 0x04, 0x00, 0x86, 0x29, 0x89, 0x14, 0x24, 0x82, 0x02, 0x41, 0x08, 0x80, + 0x04, 0x19, 0x80, 0x08, 0x10, 0x12, 0x68, 0x42, 0xa4, 0x04, 0x00, 0x02, + 0x61, 0x10, 0x06, 0x0c, 0x10, 0x00, 0x01, 0x12, 0x10, 0x20, 0x03, 0x94, + 0x21, 0x42, 0x12, 0x65, 0x18, 0x94, 0x0c, 0x0a, 0x04, 0x28, 0x01, 0x14, + 0x29, 0x0a, 0xa4, 0x40, 0xd0, 0x00, 0x40, 0x01, 0x90, 0x04, 0x41, 0x20, + 0x2d, 0x40, 0x82, 0x48, 0xc1, 0x20, 0x00, 0x10, 0x30, 0x01, 0x08, 0x24, + 0x04, 0x59, 0x84, 0x24, 0x00, 0x02, 0x29, 0x82, 0x00, 0x61, 0x58, 0x02, + 0x48, 0x81, 0x16, 0x48, 0x10, 0x00, 0x21, 0x11, 0x06, 0x00, 0xca, 0xa0, + 0x40, 0x02, 0x00, 0x04, 0x91, 0xb0, 0x00, 0x42, 0x04, 0x0c, 0x81, 0x06, + 0x09, 0x48, 0x14, 0x25, 0x92, 0x20, 0x25, 0x11, 0xa0, 0x00, 0x0a, 0x86, + 0x0c, 0xc1, 0x02, 0x48, 0x00, 0x20, 0x45, 0x08, 0x32, 0x00, 0x98, 0x06, + 0x04, 0x13, 0x22, 0x00, 0x82, 0x04, 0x48, 0x81, 0x14, 0x44, 0x82, 0x12, + 0x24, 0x18, 0x10, 0x40, 0x43, 0x80, 0x28, 0xd0, 0x04, 0x20, 0x81, 0x24, + 0x64, 0xd8, 0x00, 0x2c, 0x09, 0x12, 0x08, 0x41, 0xa2, 0x00, 0x00, 0x02, + 0x41, 0xca, 0x20, 0x41, 0xc0, 0x10, 0x01, 0x18, 0xa4, 0x04, 0x18, 0xa4, + 0x20, 0x12, 0x94, 0x20, 0x83, 0xa0, 0x40, 0x02, 0x32, 0x44, 0x80, 0x04, + 0x00, 0x18, 0x00, 0x0c, 0x40, 0x86, 0x60, 0x8a, 0x00, 0x64, 0x88, 0x12, + 0x05, 0x01, 0x82, 0x00, 0x4a, 0xa2, 0x01, 0xc1, 0x10, 0x61, 0x09, 0x04, + 0x01, 0x88, 0x00, 0x60, 0x01, 0xb4, 0x40, 0x08, 0x06, 0x01, 0x03, 0x80, + 0x08, 0x40, 0x94, 0x04, 0x8a, 0x20, 0x29, 0x80, 0x02, 0x0c, 0x52, 0x02, + 0x01, 0x42, 0x84, 0x00, 0x80, 0x84, 0x64, 0x02, 0x32, 0x48, 0x00, 0x30, + 0x44, 0x40, 0x22, 0x21, 0x00, 0x02, 0x08, 0xc3, 0xa0, 0x04, 0xd0, 0x20, + 0x40, 0x18, 0x16, 0x40, 0x40, 0x00, 0x28, 0x52, 0x90, 0x08, 0x82, 0x14, + 0x01, 0x18, 0x10, 0x08, 0x09, 0x82, 0x40, 0x0a, 0xa0, 0x20, 0x93, 0x80, + 0x08, 0xc0, 0x00, 0x20, 0x52, 0x00, 0x05, 0x01, 0x10, 0x40, 0x11, 0x06, + 0x0c, 0x82, 0x00, 0x00, 0x4b, 0x90, 0x44, 0x9a, 0x00, 0x28, 0x80, 0x90, + 0x04, 0x4a, 0x06, 0x09, 0x43, 0x02, 0x28, 0x00, 0x34, 0x01, 0x18, 0x00, + 0x65, 0x09, 0x80, 0x44, 0x03, 0x00, 0x24, 0x02, 0x82, 0x61, 0x48, 0x14, + 0x41, 0x00, 0x12, 0x28, 0x00, 0x34, 0x08, 0x51, 0x04, 0x05, 0x12, 0x90, + 0x28, 0x89, 0x84, 0x60, 0x12, 0x10, 0x49, 0x10, 0x26, 0x40, 0x49, 0x82, + 0x00, 0x91, 0x10, 0x01, 0x0a, 0x24, 0x40, 0x88, 0x10, 0x4c, 0x10, 0x04, + 0x00, 0x50, 0xa2, 0x2c, 0x40, 0x90, 0x48, 0x0a, 0xb0, 0x01, 0x50, 0x12, + 0x08, 0x00, 0xa4, 0x04, 0x09, 0xa0, 0x28, 0x92, 0x02, 0x00, 0x43, 0x10, + 0x21, 0x02, 0x20, 0x41, 0x81, 0x32, 0x00, 0x08, 0x04, 0x0c, 0x52, 0x00, + 0x21, 0x49, 0x84, 0x20, 0x10, 0x02, 0x01, 0x81, 0x10, 0x48, 0x40, 0x22, + 0x01, 0x01, 0x84, 0x69, 0xc1, 0x30, 0x01, 0xc8, 0x02, 0x44, 0x88, 0x00, + 0x0c, 0x01, 0x02, 0x2d, 0xc0, 0x12, 0x61, 0x00, 0xa0, 0x00, 0xc0, 0x30, + 0x40, 0x01, 0x12, 0x08, 0x0b, 0x20, 0x00, 0x80, 0x94, 0x40, 0x01, 0x84, + 0x40, 0x00, 0x32, 0x00, 0x10, 0x84, 0x00, 0x0b, 0x24, 0x00, 0x01, 0x06, + 0x29, 0x8a, 0x84, 0x41, 0x80, 0x10, 0x08, 0x08, 0x94, 0x4c, 0x03, 0x80, + 0x01, 0x40, 0x96, 0x40, 0x41, 0x20, 0x20, 0x50, 0x22, 0x25, 0x89, 0xa2, + 0x40, 0x40, 0xa4, 0x20, 0x02, 0x86, 0x28, 0x01, 0x20, 0x21, 0x4a, 0x10, + 0x08, 0x00, 0x14, 0x08, 0x40, 0x04, 0x25, 0x42, 0x02, 0x21, 0x43, 0x10, + 0x04, 0x92, 0x00, 0x21, 0x11, 0xa0, 0x4c, 0x18, 0x22, 0x09, 0x03, 0x84, + 0x41, 0x89, 0x10, 0x04, 0x82, 0x22, 0x24, 0x01, 0x14, 0x08, 0x08, 0x84, + 0x08, 0xc1, 0x00, 0x09, 0x42, 0xb0, 0x41, 0x8a, 0x02, 0x00, 0x80, 0x36, + 0x04, 0x49, 0xa0, 0x24, 0x91, 0x00, 0x00, 0x02, 0x94, 0x41, 0x92, 0x02, + 0x01, 0x08, 0x06, 0x08, 0x09, 0x00, 0x01, 0xd0, 0x16, 0x28, 0x89, 0x80, + 0x60, 0x00, 0x00, 0x68, 0x01, 0x90, 0x0c, 0x50, 0x20, 0x01, 0x40, 0x80, + 0x40, 0x42, 0x30, 0x41, 0x00, 0x20, 0x25, 0x81, 0x06, 0x40, 0x49, 0x00, + 0x08, 0x01, 0x12, 0x49, 0x00, 0xa0, 0x20, 0x18, 0x30, 0x05, 0x01, 0xa6, + 0x00, 0x10, 0x24, 0x28, 0x00, 0x02, 0x20, 0xc8, 0x20, 0x00, 0x88, 0x12, + 0x0c, 0x90, 0x92, 0x00, 0x02, 0x26, 0x01, 0x42, 0x16, 0x49, 0x00, 0x04, + 0x24, 0x42, 0x02, 0x01, 0x88, 0x80, 0x0c, 0x1a, 0x80, 0x08, 0x10, 0x00, + 0x60, 0x02, 0x94, 0x44, 0x88, 0x00, 0x69, 0x11, 0x30, 0x08, 0x12, 0xa0, + 0x24, 0x13, 0x84, 0x00, 0x82, 0x00, 0x65, 0xc0, 0x10, 0x28, 0x00, 0x30, + 0x04, 0x03, 0x20, 0x01, 0x11, 0x06, 0x01, 0xc8, 0x80, 0x00, 0xc2, 0x20, + 0x08, 0x10, 0x82, 0x0c, 0x13, 0x02, 0x0c, 0x52, 0x06, 0x40, 0x00, 0xb0, + 0x61, 0x40, 0x10, 0x01, 0x98, 0x86, 0x04, 0x10, 0x84, 0x08, 0x92, 0x14, + 0x60, 0x41, 0x80, 0x41, 0x1a, 0x10, 0x04, 0x81, 0x22, 0x40, 0x41, 0x20, + 0x29, 0x52, 0x00, 0x41, 0x08, 0x34, 0x60, 0x10, 0x00, 0x28, 0x01, 0x10, + 0x40, 0x00, 0x84, 0x08, 0x42, 0x90, 0x20, 0x48, 0x04, 0x04, 0x52, 0x02, + 0x00, 0x08, 0x20, 0x04, 0x00, 0x82, 0x0d, 0x00, 0x82, 0x40, 0x02, 0x10, + 0x05, 0x48, 0x20, 0x40, 0x99, 0x00, 0x00, 0x01, 0x06, 0x24, 0xc0, 0x00, + 0x68, 0x82, 0x04, 0x21, 0x12, 0x10, 0x44, 0x08, 0x04, 0x00, 0x40, 0xa6, + 0x20, 0xd0, 0x16, 0x09, 0xc9, 0x24, 0x41, 0x02, 0x20, 0x0c, 0x09, 0x92, + 0x40, 0x12, 0x00, 0x00, 0x40, 0x00, 0x09, 0x43, 0x84, 0x20, 0x98, 0x02, + 0x01, 0x11, 0x24, 0x00, 0x43, 0x24, 0x00, 0x03, 0x90, 0x08, 0x41, 0x30, + 0x24, 0x58, 0x20, 0x4c, 0x80, 0x82, 0x08, 0x10, 0x24, 0x25, 0x81, 0x06, + 0x41, 0x09, 0x10, 0x20, 0x18, 0x10, 0x44, 0x80, 0x10, 0x00, 0x4a, 0x24, + 0x0d, 0x01, 0x94, 0x28, 0x80, 0x30, 0x00, 0xc0, 0x02, 0x60, 0x10, 0x84, + 0x0c, 0x02, 0x00, 0x09, 0x02, 0x82, 0x01, 0x08, 0x10, 0x04, 0xc2, 0x20, + 0x68, 0x09, 0x06, 0x04, 0x18, 0x00, 0x00, 0x11, 0x90, 0x08, 0x0b, 0x10, + 0x21, 0x82, 0x02, 0x0c, 0x10, 0xb6, 0x08, 0x00, 0x26, 0x00, 0x41, 0x02, + 0x01, 0x4a, 0x24, 0x21, 0x1a, 0x20, 0x24, 0x80, 0x00, 0x44, 0x02, 0x00, + 0x2d, 0x40, 0x02, 0x00, 0x8b, 0x94, 0x20, 0x10, 0x00, 0x20, 0x90, 0xa6, + 0x40, 0x13, 0x00, 0x2c, 0x11, 0x86, 0x61, 0x01, 0x80, 0x41, 0x10, 0x02, + 0x04, 0x81, 0x30, 0x48, 0x48, 0x20, 0x28, 0x50, 0x80, 0x21, 0x8a, 0x10, + 0x04, 0x08, 0x10, 0x09, 0x10, 0x10, 0x48, 0x42, 0xa0, 0x0c, 0x82, 0x92, + 0x60, 0xc0, 0x20, 0x05, 0xd2, 0x20, 0x40, 0x01, 0x00, 0x04, 0x08, 0x82, + 0x2d, 0x82, 0x02, 0x00, 0x48, 0x80, 0x41, 0x48, 0x10, 0x00, 0x91, 0x04, + 0x04, 0x03, 0x84, 0x00, 0xc2, 0x04, 0x68, 0x00, 0x00, 0x64, 0xc0, 0x22, + 0x40, 0x08, 0x32, 0x44, 0x09, 0x86, 0x00, 0x91, 0x02, 0x28, 0x01, 0x00, + 0x64, 0x48, 0x00, 0x24, 0x10, 0x90, 0x00, 0x43, 0x00, 0x21, 0x52, 0x86, + 0x41, 0x8b, 0x90, 0x20, 0x40, 0x20, 0x08, 0x88, 0x04, 0x44, 0x13, 0x20, + 0x00, 0x02, 0x84, 0x60, 0x81, 0x90, 0x24, 0x40, 0x30, 0x00, 0x08, 0x10, + 0x08, 0x08, 0x02, 0x01, 0x10, 0x04, 0x20, 0x43, 0xb4, 0x40, 0x90, 0x12, + 0x68, 0x01, 0x80, 0x4c, 0x18, 0x00, 0x08, 0xc0, 0x12, 0x49, 0x40, 0x10, + 0x24, 0x1a, 0x00, 0x41, 0x89, 0x24, 0x4c, 0x10, 0x00, 0x04, 0x52, 0x10, + 0x09, 0x4a, 0x20, 0x41, 0x48, 0x22, 0x69, 0x11, 0x14, 0x08, 0x10, 0x06, + 0x24, 0x80, 0x84, 0x28, 0x00, 0x10, 0x00, 0x40, 0x10, 0x01, 0x08, 0x26, + 0x08, 0x48, 0x06, 0x28, 0x00, 0x14, 0x01, 0x42, 0x84, 0x04, 0x0a, 0x20, + 0x00, 0x01, 0x82, 0x08, 0x00, 0x82, 0x24, 0x12, 0x04, 0x40, 0x40, 0xa0, + 0x40, 0x90, 0x10, 0x04, 0x90, 0x22, 0x40, 0x10, 0x20, 0x2c, 0x80, 0x10, + 0x28, 0x43, 0x00, 0x04, 0x58, 0x00, 0x01, 0x81, 0x10, 0x48, 0x09, 0x20, + 0x21, 0x83, 0x04, 0x00, 0x42, 0xa4, 0x44, 0x00, 0x00, 0x6c, 0x10, 0xa0, + 0x44, 0x48, 0x80, 0x00, 0x83, 0x80, 0x48, 0xc9, 0x00, 0x00, 0x00, 0x02, + 0x05, 0x10, 0xb0, 0x04, 0x13, 0x04, 0x29, 0x10, 0x92, 0x40, 0x08, 0x04, + 0x44, 0x82, 0x22, 0x00, 0x19, 0x20, 0x00, 0x19, 0x20, 0x01, 0x81, 0x90, + 0x60, 0x8a, 0x00, 0x41, 0xc0, 0x02, 0x45, 0x10, 0x04, 0x00, 0x02, 0xa2, + 0x09, 0x40, 0x10, 0x21, 0x49, 0x20, 0x01, 0x42, 0x30, 0x2c, 0x00, 0x14, + 0x44, 0x01, 0x22, 0x04, 0x02, 0x92, 0x08, 0x89, 0x04, 0x21, 0x80, 0x10, + 0x05, 0x01, 0x20, 0x40, 0x41, 0x80, 0x04, 0x00, 0x12, 0x09, 0x40, 0xb0, + 0x64, 0x58, 0x32, 0x01, 0x08, 0x90, 0x00, 0x41, 0x04, 0x09, 0xc1, 0x80, + 0x61, 0x08, 0x90, 0x00, 0x9a, 0x00, 0x24, 0x01, 0x12, 0x08, 0x02, 0x26, + 0x05, 0x82, 0x06, 0x08, 0x08, 0x00, 0x20, 0x48, 0x20, 0x00, 0x18, 0x24, + 0x48, 0x03, 0x02, 0x00, 0x11, 0x00, 0x09, 0x00, 0x84, 0x01, 0x4a, 0x10, + 0x01, 0x98, 0x00, 0x04, 0x18, 0x86, 0x00, 0xc0, 0x00, 0x20, 0x81, 0x80, + 0x04, 0x10, 0x30, 0x05, 0x00, 0xb4, 0x0c, 0x4a, 0x82, 0x29, 0x91, 0x02, + 0x28, 0x00, 0x20, 0x44, 0xc0, 0x00, 0x2c, 0x91, 0x80, 0x40, 0x01, 0xa2, + 0x00, 0x12, 0x04, 0x09, 0xc3, 0x20, 0x00, 0x08, 0x02, 0x0c, 0x10, 0x22, + 0x04, 0x00, 0x00, 0x2c, 0x11, 0x86, 0x00, 0xc0, 0x00, 0x00, 0x12, 0x32, + 0x40, 0x89, 0x80, 0x40, 0x40, 0x02, 0x05, 0x50, 0x86, 0x60, 0x82, 0xa4, + 0x60, 0x0a, 0x12, 0x4d, 0x80, 0x90, 0x08, 0x12, 0x80, 0x09, 0x02, 0x14, + 0x48, 0x01, 0x24, 0x20, 0x8a, 0x00, 0x44, 0x90, 0x04, 0x04, 0x01, 0x02, + 0x00, 0xd1, 0x12, 0x00, 0x0a, 0x04, 0x40, 0x00, 0x32, 0x21, 0x81, 0x24, + 0x08, 0x19, 0x84, 0x20, 0x02, 0x04, 0x08, 0x89, 0x80, 0x24, 0x02, 0x02, + 0x68, 0x18, 0x82, 0x44, 0x42, 0x00, 0x21, 0x40, 0x00, 0x28, 0x01, 0x80, + 0x45, 0x82, 0x20, 0x40, 0x11, 0x80, 0x0c, 0x02, 0x00, 0x24, 0x40, 0x90, + 0x01, 0x40, 0x20, 0x20, 0x50, 0x20, 0x28, 0x19, 0x00, 0x40, 0x09, 0x20, + 0x08, 0x80, 0x04, 0x60, 0x40, 0x80, 0x20, 0x08, 0x30, 0x49, 0x09, 0x34, + 0x00, 0x11, 0x24, 0x24, 0x82, 0x00, 0x41, 0xc2, 0x00, 0x04, 0x92, 0x02, + 0x24, 0x80, 0x00, 0x0c, 0x02, 0xa0, 0x00, 0x01, 0x06, 0x60, 0x41, 0x04, + 0x21, 0xd0, 0x00, 0x01, 0x01, 0x00, 0x48, 0x12, 0x84, 0x04, 0x91, 0x12, + 0x08, 0x00, 0x24, 0x44, 0x00, 0x12, 0x41, 0x18, 0x26, 0x0c, 0x41, 0x80, + 0x00, 0x52, 0x04, 0x20, 0x09, 0x00, 0x24, 0x90, 0x20, 0x48, 0x18, 0x02, + 0x00, 0x03, 0xa2, 0x09, 0xd0, 0x14, 0x00, 0x8a, 0x84, 0x25, 0x4a, 0x00, + 0x20, 0x98, 0x14, 0x40, 0x00, 0xa2, 0x05, 0x00, 0x00, 0x00, 0x40, 0x14, + 0x01, 0x58, 0x20, 0x2c, 0x80, 0x84, 0x00, 0x09, 0x20, 0x20, 0x91, 0x02, + 0x08, 0x02, 0xb0, 0x41, 0x08, 0x30, 0x00, 0x09, 0x10, 0x00, 0x18, 0x02, + 0x21, 0x02, 0x02, 0x00, 0x00, 0x24, 0x44, 0x08, 0x12, 0x60, 0x00, 0xb2, + 0x44, 0x12, 0x02, 0x0c, 0xc0, 0x80, 0x40, 0xc8, 0x20, 0x04, 0x50, 0x20, + 0x05, 0x00, 0xb0, 0x04, 0x0b, 0x04, 0x29, 0x53, 0x00, 0x61, 0x48, 0x30, + 0x00, 0x82, 0x20, 0x29, 0x00, 0x16, 0x00, 0x53, 0x22, 0x20, 0x43, 0x10, + 0x48, 0x00, 0x80, 0x04, 0xd2, 0x00, 0x40, 0x00, 0xa2, 0x44, 0x03, 0x80, + 0x29, 0x00, 0x04, 0x08, 0xc0, 0x04, 0x64, 0x40, 0x30, 0x28, 0x09, 0x84, + 0x44, 0x50, 0x80, 0x21, 0x02, 0x92, 0x00, 0xc0, 0x10, 0x60, 0x88, 0x22, + 0x08, 0x80, 0x00, 0x00, 0x18, 0x84, 0x04, 0x83, 0x96, 0x00, 0x81, 0x20, + 0x05, 0x02, 0x00, 0x45, 0x88, 0x84, 0x00, 0x51, 0x20, 0x20, 0x51, 0x86, + 0x41, 0x4b, 0x94, 0x00, 0x80, 0x00, 0x08, 0x11, 0x20, 0x4c, 0x58, 0x80, + 0x04, 0x03, 0x06, 0x20, 0x89, 0x00, 0x05, 0x08, 0x22, 0x05, 0x90, 0x00, + 0x40, 0x00, 0x82, 0x09, 0x50, 0x00, 0x00, 0x00, 0xa0, 0x41, 0xc2, 0x20, + 0x08, 0x00, 0x16, 0x08, 0x40, 0x26, 0x21, 0xd0, 0x90, 0x08, 0x81, 0x90, + 0x41, 0x00, 0x02, 0x44, 0x08, 0x10, 0x0c, 0x0a, 0x86, 0x09, 0x90, 0x04, + 0x00, 0xc8, 0xa0, 0x04, 0x08, 0x30, 0x20, 0x89, 0x84, 0x00, 0x11, 0x22, + 0x2c, 0x40, 0x00, 0x08, 0x02, 0xb0, 0x01, 0x48, 0x02, 0x01, 0x09, 0x20, + 0x04, 0x03, 0x04, 0x00, 0x80, 0x02, 0x60, 0x42, 0x30, 0x21, 0x4a, 0x10, + 0x44, 0x09, 0x02, 0x00, 0x01, 0x24, 0x00, 0x12, 0x82, 0x21, 0x80, 0xa4, + 0x20, 0x10, 0x02, 0x04, 0x91, 0xa0, 0x40, 0x18, 0x04, 0x00, 0x02, 0x06, + 0x69, 0x09, 0x00, 0x05, 0x58, 0x02, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00, + 0x00, 0x03, 0x92, 0x20, 0x00, 0x34, 0x01, 0xc8, 0x20, 0x48, 0x08, 0x30, + 0x08, 0x42, 0x80, 0x20, 0x91, 0x90, 0x68, 0x01, 0x04, 0x40, 0x12, 0x02, + 0x61, 0x00, 0x12, 0x08, 0x01, 0xa0, 0x00, 0x11, 0x04, 0x21, 0x48, 0x04, + 0x24, 0x92, 0x00, 0x0c, 0x01, 0x84, 0x04, 0x00, 0x00, 0x01, 0x12, 0x96, + 0x40, 0x01, 0xa0, 0x41, 0x88, 0x22, 0x28, 0x88, 0x00, 0x44, 0x42, 0x80, + 0x24, 0x12, 0x14, 0x01, 0x42, 0x90, 0x60, 0x1a, 0x10, 0x04, 0x81, 0x10, + 0x48, 0x08, 0x06, 0x29, 0x83, 0x02, 0x40, 0x02, 0x24, 0x64, 0x80, 0x10, + 0x05, 0x80, 0x10, 0x40, 0x02, 0x02, 0x08, 0x42, 0x84, 0x01, 0x09, 0x20, + 0x04, 0x50, 0x00, 0x60, 0x11, 0x30, 0x40, 0x13, 0x02, 0x04, 0x81, 0x00, + 0x09, 0x08, 0x20, 0x45, 0x4a, 0x10, 0x61, 0x90, 0x26, 0x0c, 0x08, 0x02, + 0x21, 0x91, 0x00, 0x60, 0x02, 0x04, 0x00, 0x02, 0x00, 0x0c, 0x08, 0x06, + 0x08, 0x48, 0x84, 0x08, 0x11, 0x02, 0x00, 0x80, 0xa4, 0x00, 0x5a, 0x20, + 0x00, 0x88, 0x04, 0x04, 0x02, 0x00, 0x09, 0x00, 0x14, 0x08, 0x49, 0x14, + 0x20, 0xc8, 0x00, 0x04, 0x91, 0xa0, 0x40, 0x59, 0x80, 0x00, 0x12, 0x10, + 0x00, 0x80, 0x80, 0x65, 0x00, 0x00, 0x04, 0x00, 0x80, 0x40, 0x19, 0x00, + 0x21, 0x03, 0x84, 0x60, 0xc0, 0x04, 0x24, 0x1a, 0x12, 0x61, 0x80, 0x80, + 0x08, 0x02, 0x04, 0x09, 0x42, 0x12, 0x20, 0x08, 0x34, 0x04, 0x90, 0x20, + 0x01, 0x01, 0xa0, 0x00, 0x0b, 0x00, 0x08, 0x91, 0x92, 0x40, 0x02, 0x34, + 0x40, 0x88, 0x10, 0x61, 0x19, 0x02, 0x00, 0x40, 0x04, 0x25, 0xc0, 0x80, + 0x68, 0x08, 0x04, 0x21, 0x80, 0x22, 0x04, 0x00, 0xa0, 0x0c, 0x01, 0x84, + 0x20, 0x41, 0x00, 0x08, 0x8a, 0x00, 0x20, 0x8a, 0x00, 0x48, 0x88, 0x04, + 0x04, 0x11, 0x82, 0x08, 0x40, 0x86, 0x09, 0x49, 0xa4, 0x40, 0x00, 0x10, + 0x01, 0x01, 0xa2, 0x04, 0x50, 0x80, 0x0c, 0x80, 0x00, 0x48, 0x82, 0xa0, + 0x01, 0x18, 0x12, 0x41, 0x01, 0x04, 0x48, 0x41, 0x00, 0x24, 0x01, 0x00, + 0x00, 0x88, 0x14, 0x00, 0x02, 0x00, 0x68, 0x01, 0x20, 0x08, 0x4a, 0x22, + 0x08, 0x83, 0x80, 0x00, 0x89, 0x04, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x34, + 0x04, 0x00, 0x82, 0x28, 0x02, 0x02, 0x41, 0x4a, 0x90, 0x05, 0x82, 0x02, + 0x09, 0x80, 0x24, 0x04, 0x41, 0x00, 0x01, 0x92, 0x80, 0x28, 0x01, 0x14, + 0x00, 0x50, 0x20, 0x4c, 0x10, 0xb0, 0x04, 0x43, 0xa4, 0x21, 0x90, 0x04, + 0x01, 0x02, 0x00, 0x44, 0x48, 0x00, 0x64, 0x08, 0x06, 0x00, 0x42, 0x20, + 0x08, 0x02, 0x92, 0x01, 0x4a, 0x00, 0x20, 0x50, 0x32, 0x25, 0x90, 0x22, + 0x04, 0x09, 0x00, 0x08, 0x11, 0x80, 0x21, 0x01, 0x10, 0x05, 0x00, 0x32, + 0x08, 0x88, 0x94, 0x08, 0x08, 0x24, 0x0d, 0xc1, 0x80, 0x40, 0x0b, 0x20, + 0x40, 0x18, 0x12, 0x04, 0x00, 0x22, 0x40, 0x10, 0x26, 0x05, 0xc1, 0x82, + 0x00, 0x01, 0x30, 0x24, 0x02, 0x22, 0x41, 0x08, 0x24, 0x48, 0x1a, 0x00, + 0x25, 0xd2, 0x12, 0x28, 0x42, 0x00, 0x04, 0x40, 0x30, 0x41, 0x00, 0x02, + 0x00, 0x13, 0x20, 0x24, 0xd1, 0x84, 0x08, 0x89, 0x80, 0x04, 0x52, 0x00, + 0x44, 0x18, 0xa4, 0x00, 0x00, 0x06, 0x20, 0x91, 0x10, 0x09, 0x42, 0x20, + 0x24, 0x40, 0x30, 0x28, 0x00, 0x84, 0x40, 0x40, 0x80, 0x08, 0x10, 0x04, + 0x09, 0x08, 0x04, 0x40, 0x08, 0x22, 0x00, 0x19, 0x02, 0x00, 0x00, 0x80, + 0x2c, 0x02, 0x02, 0x21, 0x01, 0x90, 0x20, 0x40, 0x00, 0x0c, 0x00, 0x34, + 0x48, 0x58, 0x20, 0x01, 0x43, 0x04, 0x20, 0x80, 0x14, 0x00, 0x90, 0x00, + 0x6d, 0x11, 0x00, 0x00, 0x40, 0x20, 0x00, 0x03, 0x10, 0x40, 0x88, 0x30, + 0x05, 0x4a, 0x00, 0x65, 0x10, 0x24, 0x08, 0x18, 0x84, 0x28, 0x03, 0x80, + 0x20, 0x42, 0xb0, 0x40, 0x00, 0x10, 0x69, 0x19, 0x04, 0x00, 0x00, 0x80, + 0x04, 0xc2, 0x04, 0x00, 0x01, 0x00, 0x05, 0x00, 0x22, 0x25, 0x08, 0x96, + 0x04, 0x02, 0x22, 0x00, 0xd0, 0x10, 0x29, 0x01, 0xa0, 0x60, 0x08, 0x10, + 0x04, 0x01, 0x16, 0x44, 0x10, 0x02, 0x28, 0x02, 0x82, 0x48, 0x40, 0x84, + 0x20, 0x90, 0x22, 0x28, 0x80, 0x04, 0x00, 0x40, 0x04, 0x24, 0x00, 0x80, + 0x29, 0x03, 0x10, 0x60, 0x48, 0x00, 0x00, 0x81, 0xa0, 0x00, 0x51, 0x20, + 0x0c, 0xd1, 0x00, 0x01, 0x41, 0x20, 0x04, 0x92, 0x00, 0x00, 0x10, 0x92, + 0x00, 0x42, 0x04, 0x05, 0x01, 0x86, 0x40, 0x80, 0x10, 0x20, 0x52, 0x20, + 0x21, 0x00, 0x10, 0x48, 0x0a, 0x02, 0x00, 0xd0, 0x12, 0x41, 0x48, 0x80, + 0x04, 0x00, 0x00, 0x48, 0x09, 0x22, 0x04, 0x00, 0x24, 0x00, 0x43, 0x10, + 0x60, 0x0a, 0x00, 0x44, 0x12, 0x20, 0x2c, 0x08, 0x20, 0x44, 0x00, 0x84, + 0x09, 0x40, 0x06, 0x08, 0xc1, 0x00, 0x40, 0x80, 0x20, 0x00, 0x98, 0x12, + 0x48, 0x10, 0xa2, 0x20, 0x00, 0x84, 0x48, 0xc0, 0x10, 0x20, 0x90, 0x12, + 0x08, 0x98, 0x82, 0x00, 0x0a, 0xa0, 0x04, 0x03, 0x00, 0x28, 0xc3, 0x00, + 0x44, 0x42, 0x10, 0x04, 0x08, 0x04, 0x40, 0x00, 0x00, 0x05, 0x10, 0x00, + 0x21, 0x03, 0x80, 0x04, 0x88, 0x12, 0x69, 0x10, 0x00, 0x04, 0x08, 0x04, + 0x04, 0x02, 0x84, 0x48, 0x49, 0x04, 0x20, 0x18, 0x02, 0x64, 0x80, 0x30, + 0x08, 0x01, 0x02, 0x00, 0x52, 0x12, 0x49, 0x08, 0x20, 0x41, 0x88, 0x10, + 0x48, 0x08, 0x34, 0x00, 0x01, 0x86, 0x05, 0xd0, 0x00, 0x00, 0x83, 0x84, + 0x21, 0x40, 0x02, 0x41, 0x10, 0x80, 0x48, 0x40, 0xa2, 0x20, 0x51, 0x00, + 0x00, 0x49, 0x00, 0x01, 0x90, 0x20, 0x40, 0x18, 0x02, 0x40, 0x02, 0x22, + 0x05, 0x40, 0x80, 0x08, 0x82, 0x10, 0x20, 0x18, 0x00, 0x05, 0x01, 0x82, + 0x40, 0x58, 0x00, 0x04, 0x81, 0x90, 0x29, 0x01, 0xa0, 0x64, 0x00, 0x22, + 0x40, 0x01, 0xa2, 0x00, 0x18, 0x04, 0x0d, 0x00, 0x00, 0x60, 0x80, 0x94, + 0x60, 0x82, 0x10, 0x0d, 0x80, 0x30, 0x0c, 0x12, 0x20, 0x00, 0x00, 0x12, + 0x40, 0xc0, 0x20, 0x21, 0x58, 0x02, 0x41, 0x10, 0x80, 0x44, 0x03, 0x02, + 0x04, 0x13, 0x90, 0x29, 0x08, 0x00, 0x44, 0xc0, 0x00, 0x21, 0x00, 0x26, + 0x00, 0x1a, 0x80, 0x01, 0x13, 0x14, 0x20, 0x0a, 0x14, 0x20, 0x00, 0x32, + 0x61, 0x08, 0x00, 0x40, 0x42, 0x20, 0x09, 0x80, 0x06, 0x01, 0x81, 0x80, + 0x60, 0x42, 0x00, 0x68, 0x90, 0x82, 0x08, 0x42, 0x80, 0x04, 0x02, 0x80, + 0x09, 0x0b, 0x04, 0x00, 0x98, 0x00, 0x0c, 0x81, 0x06, 0x44, 0x48, 0x84, + 0x28, 0x03, 0x92, 0x00, 0x01, 0x80, 0x40, 0x0a, 0x00, 0x0c, 0x81, 0x02, + 0x08, 0x51, 0x04, 0x28, 0x90, 0x02, 0x20, 0x09, 0x10, 0x60, 0x00, 0x00, + 0x09, 0x81, 0xa0, 0x0c, 0x00, 0xa4, 0x09, 0x00, 0x02, 0x28, 0x80, 0x20, + 0x00, 0x02, 0x02, 0x04, 0x81, 0x14, 0x04, 0x00, 0x04, 0x09, 0x11, 0x12, + 0x60, 0x40, 0x20, 0x01, 0x48, 0x30, 0x40, 0x11, 0x00, 0x08, 0x0a, 0x86, + 0x00, 0x00, 0x04, 0x60, 0x81, 0x04, 0x01, 0xd0, 0x02, 0x41, 0x18, 0x90, + 0x00, 0x0a, 0x20, 0x00, 0xc1, 0x06, 0x01, 0x08, 0x80, 0x64, 0xca, 0x10, + 0x04, 0x99, 0x80, 0x48, 0x01, 0x82, 0x20, 0x50, 0x90, 0x48, 0x80, 0x84, + 0x20, 0x90, 0x22, 0x00, 0x19, 0x00, 0x04, 0x18, 0x20, 0x24, 0x10, 0x86, + 0x40, 0xc2, 0x00, 0x24, 0x12, 0x10, 0x44, 0x00, 0x16, 0x08, 0x10, 0x24, + 0x00, 0x12, 0x06, 0x01, 0x08, 0x90, 0x00, 0x12, 0x02, 0x4d, 0x10, 0x80, + 0x40, 0x50, 0x22, 0x00, 0x43, 0x10, 0x01, 0x00, 0x30, 0x21, 0x0a, 0x00, + 0x00, 0x01, 0x14, 0x00, 0x10, 0x84, 0x04, 0xc1, 0x10, 0x29, 0x0a, 0x00, + 0x01, 0x8a, 0x00, 0x20, 0x01, 0x12, 0x0c, 0x49, 0x20, 0x04, 0x81, 0x00, + 0x48, 0x01, 0x04, 0x60, 0x80, 0x12, 0x0c, 0x08, 0x10, 0x48, 0x4a, 0x04, + 0x28, 0x10, 0x00, 0x28, 0x40, 0x84, 0x45, 0x50, 0x10, 0x60, 0x10, 0x06, + 0x44, 0x01, 0x80, 0x09, 0x00, 0x86, 0x01, 0x42, 0xa0, 0x00, 0x90, 0x00, + 0x05, 0x90, 0x22, 0x40, 0x41, 0x00, 0x08, 0x80, 0x02, 0x08, 0xc0, 0x00, + 0x01, 0x58, 0x30, 0x49, 0x09, 0x14, 0x00, 0x41, 0x02, 0x0c, 0x02, 0x80, + 0x40, 0x89, 0x00, 0x24, 0x08, 0x10, 0x05, 0x90, 0x32, 0x40, 0x0a, 0x82, + 0x08, 0x00, 0x12, 0x61, 0x00, 0x04, 0x21, 0x00, 0x22, 0x04, 0x10, 0x24, + 0x08, 0x0a, 0x04, 0x01, 0x10, 0x00, 0x20, 0x40, 0x84, 0x04, 0x88, 0x22, + 0x20, 0x90, 0x12, 0x00, 0x53, 0x06, 0x24, 0x01, 0x04, 0x40, 0x0b, 0x14, + 0x60, 0x82, 0x02, 0x0d, 0x10, 0x90, 0x0c, 0x08, 0x20, 0x09, 0x00, 0x14, + 0x09, 0x80, 0x80, 0x24, 0x82, 0x00, 0x40, 0x01, 0x02, 0x44, 0x01, 0x20, + 0x0c, 0x40, 0x84, 0x40, 0x0a, 0x10, 0x41, 0x00, 0x30, 0x05, 0x09, 0x80, + 0x44, 0x08, 0x20, 0x20, 0x02, 0x00, 0x49, 0x43, 0x20, 0x21, 0x00, 0x20, + 0x00, 0x01, 0xb6, 0x08, 0x40, 0x04, 0x08, 0x02, 0x80, 0x01, 0x41, 0x80, + 0x40, 0x08, 0x10, 0x24, 0x00, 0x20, 0x04, 0x12, 0x86, 0x09, 0xc0, 0x12, + 0x21, 0x81, 0x14, 0x04, 0x00, 0x02, 0x20, 0x89, 0xb4, 0x44, 0x12, 0x80, + 0x00, 0xd1, 0x00, 0x69, 0x40, 0x80, 0x00, 0x42, 0x12, 0x00, 0x18, 0x04, + 0x00, 0x49, 0x06, 0x21, 0x02, 0x04, 0x28, 0x02, 0x84, 0x01, 0xc0, 0x10, + 0x68, 0x00, 0x20, 0x08, 0x40, 0x00, 0x08, 0x91, 0x10, 0x01, 0x81, 0x24, + 0x04, 0xd2, 0x10, 0x4c, 0x88, 0x86, 0x00, 0x10, 0x80, 0x0c, 0x02, 0x14, + 0x00, 0x8a, 0x90, 0x40, 0x18, 0x20, 0x21, 0x80, 0xa4, 0x00, 0x58, 0x24, + 0x20, 0x10, 0x10, 0x60, 0xc1, 0x30, 0x41, 0x48, 0x02, 0x48, 0x09, 0x00, + 0x40, 0x09, 0x02, 0x05, 0x11, 0x82, 0x20, 0x4a, 0x20, 0x24, 0x18, 0x02, + 0x0c, 0x10, 0x22, 0x0c, 0x0a, 0x04, 0x00, 0x03, 0x06, 0x48, 0x48, 0x04, + 0x04, 0x02, 0x00, 0x21, 0x80, 0x84, 0x00, 0x18, 0x00, 0x0c, 0x02, 0x12, + 0x01, 0x00, 0x14, 0x05, 0x82, 0x10, 0x41, 0x89, 0x12, 0x08, 0x40, 0xa4, + 0x21, 0x01, 0x84, 0x48, 0x02, 0x10, 0x60, 0x40, 0x02, 0x28, 0x00, 0x14, + 0x08, 0x40, 0xa0, 0x20, 0x51, 0x12, 0x00, 0xc2, 0x00, 0x01, 0x1a, 0x30, + 0x40, 0x89, 0x12, 0x4c, 0x02, 0x80, 0x00, 0x00, 0x14, 0x01, 0x01, 0xa0, + 0x21, 0x18, 0x22, 0x21, 0x18, 0x06, 0x40, 0x01, 0x80, 0x00, 0x90, 0x04, + 0x48, 0x02, 0x30, 0x04, 0x08, 0x00, 0x05, 0x88, 0x24, 0x08, 0x48, 0x04, + 0x24, 0x02, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0x65, 0x11, 0x90, + 0x00, 0x0a, 0x82, 0x04, 0xc3, 0x04, 0x60, 0x48, 0x24, 0x04, 0x92, 0x02, + 0x44, 0x88, 0x80, 0x40, 0x18, 0x06, 0x29, 0x80, 0x10, 0x01, 0x00, 0x00, + 0x44, 0xc8, 0x10, 0x21, 0x89, 0x30, 0x00, 0x4b, 0xa0, 0x01, 0x10, 0x14, + 0x00, 0x02, 0x94, 0x40, 0x00, 0x20, 0x65, 0x00, 0xa2, 0x0c, 0x40, 0x22, + 0x20, 0x81, 0x12, 0x20, 0x82, 0x04, 0x01, 0x10, 0x00, 0x08, 0x88, 0x00, + 0x00, 0x11, 0x80, 0x04, 0x42, 0x80, 0x40, 0x41, 0x14, 0x00, 0x40, 0x32, + 0x2c, 0x80, 0x24, 0x04, 0x19, 0x00, 0x00, 0x91, 0x00, 0x20, 0x83, 0x00, + 0x05, 0x40, 0x20, 0x09, 0x01, 0x84, 0x40, 0x40, 0x20, 0x20, 0x11, 0x00, + 0x40, 0x41, 0x90, 0x20, 0x00, 0x00, 0x40, 0x90, 0x92, 0x48, 0x18, 0x06, + 0x08, 0x81, 0x80, 0x48, 0x01, 0x34, 0x24, 0x10, 0x20, 0x04, 0x00, 0x20, + 0x04, 0x18, 0x06, 0x2d, 0x90, 0x10, 0x01, 0x00, 0x90, 0x00, 0x0a, 0x22, + 0x01, 0x00, 0x22, 0x00, 0x11, 0x84, 0x01, 0x01, 0x00, 0x20, 0x88, 0x00, + 0x44, 0x00, 0x22, 0x01, 0x00, 0xa6, 0x40, 0x02, 0x06, 0x20, 0x11, 0x00, + 0x01, 0xc8, 0xa0, 0x04, 0x8a, 0x00, 0x28, 0x19, 0x80, 0x00, 0x52, 0xa0, + 0x24, 0x12, 0x12, 0x09, 0x08, 0x24, 0x01, 0x48, 0x00, 0x04, 0x00, 0x24, + 0x40, 0x02, 0x84, 0x08, 0x00, 0x04, 0x48, 0x40, 0x90, 0x60, 0x0a, 0x22, + 0x01, 0x88, 0x14, 0x08, 0x01, 0x02, 0x08, 0xd3, 0x00, 0x20, 0xc0, 0x90, + 0x24, 0x10, 0x00, 0x00, 0x01, 0xb0, 0x08, 0x0a, 0xa0, 0x00, 0x80, 0x00, + 0x01, 0x09, 0x00, 0x20, 0x52, 0x02, 0x25, 0x00, 0x24, 0x04, 0x02, 0x84, + 0x24, 0x10, 0x92, 0x40, 0x02, 0xa0, 0x40, 0x00, 0x22, 0x08, 0x11, 0x04, + 0x08, 0x01, 0x22, 0x00, 0x42, 0x14, 0x00, 0x09, 0x90, 0x21, 0x00, 0x30, + 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x22, 0x09, 0x90, 0x10, 0x28, 0x40, 0x00, + 0x20, 0xc0, 0x20, 0x00, 0x90, 0x00, 0x40, 0x01, 0x82, 0x05, 0x12, 0x12, + 0x09, 0xc1, 0x04, 0x61, 0x80, 0x02, 0x28, 0x81, 0x24, 0x00, 0x49, 0x04, + 0x08, 0x10, 0x86, 0x29, 0x41, 0x80, 0x21, 0x0a, 0x30, 0x49, 0x88, 0x90, + 0x00, 0x41, 0x04, 0x29, 0x81, 0x80, 0x41, 0x09, 0x00, 0x40, 0x12, 0x10, + 0x40, 0x00, 0x10, 0x40, 0x48, 0x02, 0x05, 0x80, 0x02, 0x21, 0x40, 0x20, + 0x00, 0x58, 0x20, 0x60, 0x00, 0x90, 0x48, 0x00, 0x80, 0x28, 0xc0, 0x80, + 0x48, 0x00, 0x00, 0x44, 0x80, 0x02, 0x00, 0x09, 0x06, 0x00, 0x12, 0x02, + 0x01, 0x00, 0x10, 0x08, 0x83, 0x10, 0x45, 0x12, 0x00, 0x2c, 0x08, 0x04, + 0x44, 0x00, 0x20, 0x20, 0xc0, 0x10, 0x20, 0x01, 0x00, 0x05, 0xc8, 0x20, + 0x04, 0x98, 0x10, 0x08, 0x10, 0x00, 0x24, 0x02, 0x16, 0x40, 0x88, 0x00, + 0x61, 0x88, 0x12, 0x24, 0x80, 0xa6, 0x00, 0x42, 0x00, 0x08, 0x10, 0x06, + 0x48, 0x40, 0xa0, 0x00, 0x50, 0x20, 0x04, 0x81, 0xa4, 0x40, 0x18, 0x00, + 0x08, 0x10, 0x80, 0x01, 0x01}; +#if RSA_KEY_SIEVE && SIMULATION && RSA_INSTRUMENT +UINT32 PrimeIndex = 0; +UINT32 failedAtIteration[10] = {0}; +UINT32 PrimeCounts[3] = {0}; +UINT32 MillerRabinTrials[3] = {0}; +UINT32 totalFieldsSieved[3] = {0}; +UINT32 bitsInFieldAfterSieve[3] = {0}; +UINT32 emptyFieldsSieved[3] = {0}; +UINT32 noPrimeFields[3] = {0}; +UINT32 primesChecked[3] = {0}; +UINT16 lastSievePrime = 0; +#endif diff --git a/src/tpm2/PropertyCap.c b/src/tpm2/PropertyCap.c new file mode 100644 index 0000000..db7d679 --- /dev/null +++ b/src/tpm2/PropertyCap.c @@ -0,0 +1,610 @@ +/********************************************************************************/ +/* */ +/* For accessing the TPM_CAP_TPM_PROPERTY values */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PropertyCap.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 9.14 PropertyCap.c */ +/* 9.14.1 Description */ +/* This file contains the functions that are used for accessing the TPM_CAP_TPM_PROPERTY values. */ +/* 9.14.2 Includes */ +#include "Tpm.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" // libtpms added +/* 9.14.3 Functions */ +/* 9.14.3.1 TPMPropertyIsDefined() */ +/* This function accepts a property selection and, if so, sets value to the value of the + property. */ +/* All the fixed values are vendor dependent or determined by a platform-specific specification. The + values in the table below are examples and should be changed by the vendor. */ +/* Return Values Meaning */ +/* TRUE referenced property exists and value set */ +/* FALSE referenced property does not exist */ +static BOOL +TPMPropertyIsDefined( + TPM_PT property, // IN: property + UINT32 *value // OUT: property value + ) +{ + switch(property) + { + case TPM_PT_FAMILY_INDICATOR: + // from the title page of the specification + // For this specification, the value is "2.0". + *value = TPM_SPEC_FAMILY; + break; + case TPM_PT_LEVEL: + // from the title page of the specification + *value = TPM_SPEC_LEVEL; + break; + case TPM_PT_REVISION: + // from the title page of the specification + *value = TPM_SPEC_VERSION; + break; + case TPM_PT_DAY_OF_YEAR: + // computed from the date value on the title page of the specification + *value = TPM_SPEC_DAY_OF_YEAR; + break; + case TPM_PT_YEAR: + // from the title page of the specification + *value = TPM_SPEC_YEAR; + break; + case TPM_PT_MANUFACTURER: + // vendor ID unique to each TPM manufacturer + *value = BYTE_ARRAY_TO_UINT32(MANUFACTURER); + break; + case TPM_PT_VENDOR_STRING_1: + // first four characters of the vendor ID string + *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_1); + break; + case TPM_PT_VENDOR_STRING_2: + // second four characters of the vendor ID string +#ifdef VENDOR_STRING_2 + *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_2); +#else + *value = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_3: + // third four characters of the vendor ID string +#ifdef VENDOR_STRING_3 + *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_3); +#else + *value = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_4: + // fourth four characters of the vendor ID string +#ifdef VENDOR_STRING_4 + *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_4); +#else + *value = 0; +#endif + break; + case TPM_PT_VENDOR_TPM_TYPE: + // vendor-defined value indicating the TPM model + *value = 1; + break; + case TPM_PT_FIRMWARE_VERSION_1: + // more significant 32-bits of a vendor-specific value + *value = gp.firmwareV1; + break; + case TPM_PT_FIRMWARE_VERSION_2: + // less significant 32-bits of a vendor-specific value + *value = gp.firmwareV2; + break; + case TPM_PT_INPUT_BUFFER: + // maximum size of TPM2B_MAX_BUFFER + *value = MAX_DIGEST_BUFFER; + break; + case TPM_PT_HR_TRANSIENT_MIN: + // minimum number of transient objects that can be held in TPM + // RAM + *value = MAX_LOADED_OBJECTS; + break; + case TPM_PT_HR_PERSISTENT_MIN: + // minimum number of persistent objects that can be held in + // TPM NV memory + // In this implementation, there is no minimum number of + // persistent objects. + *value = MIN_EVICT_OBJECTS; + break; + case TPM_PT_HR_LOADED_MIN: + // minimum number of authorization sessions that can be held in + // TPM RAM + *value = MAX_LOADED_SESSIONS; + break; + case TPM_PT_ACTIVE_SESSIONS_MAX: + // number of authorization sessions that may be active at a time + *value = MAX_ACTIVE_SESSIONS; + break; + case TPM_PT_PCR_COUNT: + // number of PCR implemented + *value = IMPLEMENTATION_PCR; + break; + case TPM_PT_PCR_SELECT_MIN: + // minimum number of bytes in a TPMS_PCR_SELECT.sizeOfSelect + *value = PCR_SELECT_MIN; + break; + case TPM_PT_CONTEXT_GAP_MAX: + // maximum allowed difference (unsigned) between the contextID + // values of two saved session contexts +#if 0 + *value = ((UINT32)1 << (sizeof(CONTEXT_SLOT) * 8)) - 1; +#endif + *value = s_ContextSlotMask; // libtpms added; the mask is either 0xff (old state) or 0xffff + break; + case TPM_PT_NV_COUNTERS_MAX: + // maximum number of NV indexes that are allowed to have the + // TPMA_NV_COUNTER attribute SET + // In this implementation, there is no limitation on the number + // of counters, except for the size of the NV Index memory. + *value = 0; + break; + case TPM_PT_NV_INDEX_MAX: + // maximum size of an NV index data area + *value = MAX_NV_INDEX_SIZE; + break; + case TPM_PT_MEMORY: + // a TPMA_MEMORY indicating the memory management method for the TPM + { + union + { + TPMA_MEMORY att; + UINT32 u32; + } attributes = { TPMA_ZERO_INITIALIZER() }; + SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, sharedNV); + SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, objectCopiedToRam); + // Note: For a LSb0 machine, the bits in a bit field are in the correct + // order even if the machine is MSB0. For a MSb0 machine, a TPMA will + // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will + // NO) so the bits are manipulated correctly. + *value = attributes.u32; + break; + } + case TPM_PT_CLOCK_UPDATE: + // interval, in seconds, between updates to the copy of + // TPMS_TIME_INFO .clock in NV + *value = (1 << NV_CLOCK_UPDATE_INTERVAL); + break; + case TPM_PT_CONTEXT_HASH: + // algorithm used for the integrity hash on saved contexts and + // for digesting the fuData of TPM2_FirmwareRead() + *value = CONTEXT_INTEGRITY_HASH_ALG; + break; + case TPM_PT_CONTEXT_SYM: + // algorithm used for encryption of saved contexts + *value = CONTEXT_ENCRYPT_ALG; + break; + case TPM_PT_CONTEXT_SYM_SIZE: + // size of the key used for encryption of saved contexts + *value = CONTEXT_ENCRYPT_KEY_BITS; + break; + case TPM_PT_ORDERLY_COUNT: + // maximum difference between the volatile and non-volatile + // versions of TPMA_NV_COUNTER that have TPMA_NV_ORDERLY SET + *value = MAX_ORDERLY_COUNT; + break; + case TPM_PT_MAX_COMMAND_SIZE: + // maximum value for 'commandSize' + *value = MAX_COMMAND_SIZE; + break; + case TPM_PT_MAX_RESPONSE_SIZE: + // maximum value for 'responseSize' + *value = MAX_RESPONSE_SIZE; + break; + case TPM_PT_MAX_DIGEST: + // maximum size of a digest that can be produced by the TPM + *value = sizeof(TPMU_HA); + break; + case TPM_PT_MAX_OBJECT_CONTEXT: + // Header has 'sequence', 'handle' and 'hierarchy' +#define SIZE_OF_CONTEXT_HEADER \ + sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + sizeof(TPMI_RH_HIERARCHY) +#define SIZE_OF_CONTEXT_INTEGRITY (sizeof(UINT16) + CONTEXT_INTEGRITY_HASH_SIZE) +#define SIZE_OF_FINGERPRINT sizeof(UINT64) +#define SIZE_OF_CONTEXT_BLOB_OVERHEAD \ + (sizeof(UINT16) + SIZE_OF_CONTEXT_INTEGRITY + SIZE_OF_FINGERPRINT) +#define SIZE_OF_CONTEXT_OVERHEAD \ + (SIZE_OF_CONTEXT_HEADER + SIZE_OF_CONTEXT_BLOB_OVERHEAD) +#if 0 + // maximum size of a TPMS_CONTEXT that will be returned by + // TPM2_ContextSave for object context + *value = 0; + // adding sequence, saved handle and hierarchy + *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + + sizeof(TPMI_RH_HIERARCHY); + // add size field in TPM2B_CONTEXT + *value += sizeof(UINT16); + // add integrity hash size + *value += sizeof(UINT16) + + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); + // Add fingerprint size, which is the same as sequence size + *value += sizeof(UINT64); + // Add OBJECT structure size + *value += sizeof(OBJECT); +#else + // the maximum size of a TPMS_CONTEXT that will be returned by + // TPM2_ContextSave for object context + *value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(OBJECT); +#endif + break; + case TPM_PT_MAX_SESSION_CONTEXT: +#if 0 + // the maximum size of a TPMS_CONTEXT that will be returned by + // TPM2_ContextSave for object context + *value = 0; + // adding sequence, saved handle and hierarchy + *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + + sizeof(TPMI_RH_HIERARCHY); + // Add size field in TPM2B_CONTEXT + *value += sizeof(UINT16); + // Add integrity hash size + *value += sizeof(UINT16) + + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); + // Add fingerprint size, which is the same as sequence size + *value += sizeof(UINT64); + // Add SESSION structure size + *value += sizeof(SESSION); +#else + // the maximum size of a TPMS_CONTEXT that will be returned by + // TPM2_ContextSave for object context + *value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(SESSION); +#endif + break; + case TPM_PT_PS_FAMILY_INDICATOR: + // platform specific values for the TPM_PT_PS parameters from + // the relevant platform-specific specification + // In this reference implementation, all of these values are 0. + *value = PLATFORM_FAMILY; + break; + case TPM_PT_PS_LEVEL: + // level of the platform-specific specification + *value = PLATFORM_LEVEL; + break; + case TPM_PT_PS_REVISION: + // specification Revision times 100 for the platform-specific + // specification + *value = PLATFORM_VERSION; + break; + case TPM_PT_PS_DAY_OF_YEAR: + // platform-specific specification day of year using TCG calendar + *value = PLATFORM_DAY_OF_YEAR; + break; + case TPM_PT_PS_YEAR: + // platform-specific specification year using the CE + *value = PLATFORM_YEAR; + break; + case TPM_PT_SPLIT_MAX: + // number of split signing operations supported by the TPM + *value = 0; +#if ALG_ECC + *value = sizeof(gr.commitArray) * 8; +#endif + break; + case TPM_PT_TOTAL_COMMANDS: + // total number of commands implemented in the TPM + // Since the reference implementation does not have any + // vendor-defined commands, this will be the same as the + // number of library commands. + { +#if COMPRESSED_LISTS + (*value) = COMMAND_COUNT; +#else + COMMAND_INDEX commandIndex; + *value = 0; + // scan all implemented commands + for(commandIndex = GetClosestCommandIndex(0); + commandIndex != UNIMPLEMENTED_COMMAND_INDEX; + commandIndex = GetNextCommandIndex(commandIndex)) + { + (*value)++; // count of all implemented + } +#endif + break; + } + case TPM_PT_LIBRARY_COMMANDS: + // number of commands from the TPM library that are implemented + { +#if COMPRESSED_LISTS + *value = LIBRARY_COMMAND_ARRAY_SIZE; +#else + COMMAND_INDEX commandIndex; + *value = 0; + // scan all implemented commands + for(commandIndex = GetClosestCommandIndex(0); + commandIndex < LIBRARY_COMMAND_ARRAY_SIZE; + commandIndex = GetNextCommandIndex(commandIndex)) + { + (*value)++; + } +#endif + break; + } + case TPM_PT_VENDOR_COMMANDS: + // number of vendor commands that are implemented + *value = VENDOR_COMMAND_ARRAY_SIZE; + break; + case TPM_PT_NV_BUFFER_MAX: + // Maximum data size in an NV write command + *value = MAX_NV_BUFFER_SIZE; + break; + case TPM_PT_MODES: +#if FIPS_COMPLIANT + *value = 1; +#else + *value = 0; +#endif + break; + case TPM_PT_MAX_CAP_BUFFER: + *value = MAX_CAP_BUFFER; + break; + // Start of variable commands + case TPM_PT_PERMANENT: + // TPMA_PERMANENT + { + union { + TPMA_PERMANENT attr; + UINT32 u32; + } flags = { TPMA_ZERO_INITIALIZER() }; + if(gp.ownerAuth.t.size != 0) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, ownerAuthSet); + if(gp.endorsementAuth.t.size != 0) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, endorsementAuthSet); + if(gp.lockoutAuth.t.size != 0) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, lockoutAuthSet); + if(gp.disableClear) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, disableClear); + if(gp.failedTries >= gp.maxTries) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, inLockout); + // In this implementation, EPS is always generated by TPM + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, tpmGeneratedEPS); + // Note: For a LSb0 machine, the bits in a bit field are in the correct + // order even if the machine is MSB0. For a MSb0 machine, a TPMA will + // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will + // be NO ) so the bits are manipulate correctly. + *value = flags.u32; + break; + } + case TPM_PT_STARTUP_CLEAR: + // TPMA_STARTUP_CLEAR + { + union { + TPMA_STARTUP_CLEAR attr; + UINT32 u32; + } flags = { TPMA_ZERO_INITIALIZER() }; + // + if(g_phEnable) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnable); + if(gc.shEnable) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, shEnable); + if(gc.ehEnable) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, ehEnable); + if(gc.phEnableNV) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnableNV); + if(g_prevOrderlyState != SU_NONE_VALUE) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, orderly); + // Note: For a LSb0 machine, the bits in a bit field are in the correct + // order even if the machine is MSB0. For a MSb0 machine, a TPMA will + // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will + // be NO) so the bits are manipulate correctly. + *value = flags.u32; + break; + } + case TPM_PT_HR_NV_INDEX: + // number of NV indexes currently defined + *value = NvCapGetIndexNumber(); + break; + case TPM_PT_HR_LOADED: + // number of authorization sessions currently loaded into TPM + // RAM + *value = SessionCapGetLoadedNumber(); + break; + case TPM_PT_HR_LOADED_AVAIL: + // number of additional authorization sessions, of any type, + // that could be loaded into TPM RAM + *value = SessionCapGetLoadedAvail(); + break; + case TPM_PT_HR_ACTIVE: + // number of active authorization sessions currently being + // tracked by the TPM + *value = SessionCapGetActiveNumber(); + break; + case TPM_PT_HR_ACTIVE_AVAIL: + // number of additional authorization sessions, of any type, + // that could be created + *value = SessionCapGetActiveAvail(); + break; + case TPM_PT_HR_TRANSIENT_AVAIL: + // estimate of the number of additional transient objects that + // could be loaded into TPM RAM + *value = ObjectCapGetTransientAvail(); + break; + case TPM_PT_HR_PERSISTENT: + // number of persistent objects currently loaded into TPM + // NV memory + *value = NvCapGetPersistentNumber(); + break; + case TPM_PT_HR_PERSISTENT_AVAIL: + // number of additional persistent objects that could be loaded + // into NV memory + *value = NvCapGetPersistentAvail(); + break; + case TPM_PT_NV_COUNTERS: + // number of defined NV indexes that have NV TPMA_NV_COUNTER + // attribute SET + *value = NvCapGetCounterNumber(); + break; + case TPM_PT_NV_COUNTERS_AVAIL: + // number of additional NV indexes that can be defined with their + // TPMA_NV_COUNTER attribute SET + *value = NvCapGetCounterAvail(); + break; + case TPM_PT_ALGORITHM_SET: + // region code for the TPM + *value = gp.algorithmSet; + break; + case TPM_PT_LOADED_CURVES: +#if ALG_ECC + // number of loaded ECC curves + *value = ECC_CURVE_COUNT; +#else // ALG_ECC + *value = 0; +#endif // ALG_ECC + break; + case TPM_PT_LOCKOUT_COUNTER: + // current value of the lockout counter + *value = gp.failedTries; + break; + case TPM_PT_MAX_AUTH_FAIL: + // number of authorization failures before DA lockout is invoked + *value = gp.maxTries; + break; + case TPM_PT_LOCKOUT_INTERVAL: + // number of seconds before the value reported by + // TPM_PT_LOCKOUT_COUNTER is decremented + *value = gp.recoveryTime; + break; + case TPM_PT_LOCKOUT_RECOVERY: + // number of seconds after a lockoutAuth failure before use of + // lockoutAuth may be attempted again + *value = gp.lockoutRecovery; + break; + case TPM_PT_NV_WRITE_RECOVERY: + // number of milliseconds before the TPM will accept another command + // that will modify NV. + // This should make a call to the platform code that is doing rate + // limiting of NV. Rate limiting is not implemented in the reference + // code so no call is made. + *value = 0; + break; + case TPM_PT_AUDIT_COUNTER_0: + // high-order 32 bits of the command audit counter + *value = (UINT32)(gp.auditCounter >> 32); + break; + case TPM_PT_AUDIT_COUNTER_1: + // low-order 32 bits of the command audit counter + *value = (UINT32)(gp.auditCounter); + break; + default: + // property is not defined + return FALSE; + break; + } + return TRUE; +} +/* 9.14.3.2 TPMCapGetProperties() */ +/* This function is used to get the TPM_PT values. The search of properties will start at property + and continue until propertyList has as many values as will fit, or the last property has been + reported, or the list has as many values as requested in count. */ +/* Return Values Meaning */ +/* YES more properties are available */ +/* NO no more properties to be reported */ +TPMI_YES_NO +TPMCapGetProperties( + TPM_PT property, // IN: the starting TPM property + UINT32 count, // IN: maximum number of returned + // properties + TPML_TAGGED_TPM_PROPERTY *propertyList // OUT: property list + ) +{ + TPMI_YES_NO more = NO; + UINT32 i; + UINT32 nextGroup; + // initialize output property list + propertyList->count = 0; + // maximum count of properties we may return is MAX_PCR_PROPERTIES + if(count > MAX_TPM_PROPERTIES) count = MAX_TPM_PROPERTIES; + // if property is less than PT_FIXED, start from PT_FIXED + if(property < PT_FIXED) + property = PT_FIXED; + // There is only the fixed and variable groups with the variable group coming + // last + if(property >= (PT_VAR + PT_GROUP)) + return more; + // Don't read past the end of the selected group + nextGroup = ((property / PT_GROUP) * PT_GROUP) + PT_GROUP; + // Scan through the TPM properties of the requested group. + for(i = property; i < nextGroup; i++) + { + UINT32 value; + // if we have hit the end of the group, quit + if(i != property && ((i % PT_GROUP) == 0)) + break; + if(TPMPropertyIsDefined((TPM_PT)i, &value)) + { + if(propertyList->count < count) + { + // If the list is not full, add this property + propertyList->tpmProperty[propertyList->count].property = + (TPM_PT)i; + propertyList->tpmProperty[propertyList->count].value = value; + propertyList->count++; + } + else + { + // If the return list is full but there are more properties + // available, set the indication and exit the loop. + more = YES; + break; + } + } + } + return more; +} diff --git a/src/tpm2/PropertyCap_fp.h b/src/tpm2/PropertyCap_fp.h new file mode 100644 index 0000000..b827963 --- /dev/null +++ b/src/tpm2/PropertyCap_fp.h @@ -0,0 +1,74 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: PropertyCap_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef PROPERTYCAP_FP_H +#define PROPERTYCAP_FP_H + +TPMI_YES_NO +TPMCapGetProperties( + TPM_PT property, // IN: the starting TPM property + UINT32 count, // IN: maximum number of returned + // properties + TPML_TAGGED_TPM_PROPERTY *propertyList // OUT: property list + ); + + +#endif diff --git a/src/tpm2/Quote_fp.h b/src/tpm2/Quote_fp.h new file mode 100644 index 0000000..b347f2f --- /dev/null +++ b/src/tpm2/Quote_fp.h @@ -0,0 +1,91 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Quote_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef QUOTE_FP_H +#define QUOTE_FP_H + +typedef struct { + TPMI_DH_OBJECT signHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; + TPML_PCR_SELECTION PCRselect; +} Quote_In; + +#define RC_Quote_signHandle (TPM_RC_H + TPM_RC_1) +#define RC_Quote_qualifyingData (TPM_RC_P + TPM_RC_1) +#define RC_Quote_inScheme (TPM_RC_P + TPM_RC_2) +#define RC_Quote_PCRselect (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPM2B_ATTEST quoted; + TPMT_SIGNATURE signature; +} Quote_Out; + +TPM_RC +TPM2_Quote( + Quote_In *in, // IN: input parameter list + Quote_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/RSA_Decrypt_fp.h b/src/tpm2/RSA_Decrypt_fp.h new file mode 100644 index 0000000..1f58395 --- /dev/null +++ b/src/tpm2/RSA_Decrypt_fp.h @@ -0,0 +1,90 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: RSA_Decrypt_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef RSA_DECRYPT_FP_H +#define RSA_DECRYPT_FP_H + +typedef struct { + TPMI_DH_OBJECT keyHandle; + TPM2B_PUBLIC_KEY_RSA cipherText; + TPMT_RSA_DECRYPT inScheme; + TPM2B_DATA label; +} RSA_Decrypt_In; + +#define RC_RSA_Decrypt_keyHandle (TPM_RC_H + TPM_RC_1) +#define RC_RSA_Decrypt_cipherText (TPM_RC_P + TPM_RC_1) +#define RC_RSA_Decrypt_inScheme (TPM_RC_P + TPM_RC_2) +#define RC_RSA_Decrypt_label (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPM2B_PUBLIC_KEY_RSA message; +} RSA_Decrypt_Out; + +TPM_RC +TPM2_RSA_Decrypt( + RSA_Decrypt_In *in, // IN: input parameter list + RSA_Decrypt_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/RSA_Encrypt_fp.h b/src/tpm2/RSA_Encrypt_fp.h new file mode 100644 index 0000000..a1f0373 --- /dev/null +++ b/src/tpm2/RSA_Encrypt_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: RSA_Encrypt_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef RSA_ENCRYPT_FP_H +#define RSA_ENCRYPT_FP_H + +typedef struct { + TPMI_DH_OBJECT keyHandle; + TPM2B_PUBLIC_KEY_RSA message; + TPMT_RSA_DECRYPT inScheme; + TPM2B_DATA label; +} RSA_Encrypt_In; + +#define RC_RSA_Encrypt_keyHandle (TPM_RC_H + TPM_RC_1) +#define RC_RSA_Encrypt_message (TPM_RC_P + TPM_RC_1) +#define RC_RSA_Encrypt_inScheme (TPM_RC_P + TPM_RC_2) +#define RC_RSA_Encrypt_label (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPM2B_PUBLIC_KEY_RSA outData; +} RSA_Encrypt_Out; + +TPM_RC +TPM2_RSA_Encrypt( + RSA_Encrypt_In *in, // IN: input parameter list + RSA_Encrypt_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/RandomCommands.c b/src/tpm2/RandomCommands.c new file mode 100644 index 0000000..b6573a5 --- /dev/null +++ b/src/tpm2/RandomCommands.c @@ -0,0 +1,94 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: RandomCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "GetRandom_fp.h" +#if CC_GetRandom // Conditional expansion of this file +TPM_RC +TPM2_GetRandom( + GetRandom_In *in, // IN: input parameter list + GetRandom_Out *out // OUT: output parameter list + ) +{ + // Command Output + // if the requested bytes exceed the output buffer size, generates the + // maximum bytes that the output buffer allows + if(in->bytesRequested > sizeof(TPMU_HA)) + out->randomBytes.t.size = sizeof(TPMU_HA); + else + out->randomBytes.t.size = in->bytesRequested; + CryptRandomGenerate(out->randomBytes.t.size, out->randomBytes.t.buffer); + return TPM_RC_SUCCESS; +} +#endif // CC_GetRandom +#include "Tpm.h" +#include "StirRandom_fp.h" +#if CC_StirRandom // Conditional expansion of this file +TPM_RC +TPM2_StirRandom( + StirRandom_In *in // IN: input parameter list + ) +{ + // Internal Data Update + CryptRandomStir(in->inData.t.size, in->inData.t.buffer); + return TPM_RC_SUCCESS; +} +#endif // CC_StirRandom diff --git a/src/tpm2/ReadClock_fp.h b/src/tpm2/ReadClock_fp.h new file mode 100644 index 0000000..3d01b54 --- /dev/null +++ b/src/tpm2/ReadClock_fp.h @@ -0,0 +1,77 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ReadClock_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef READCLOCK_FP_H +#define READCLOCK_FP_H + +typedef struct { + TPMS_TIME_INFO currentTime; +} ReadClock_Out; + +TPM_RC +TPM2_ReadClock( + ReadClock_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/ReadPublic_fp.h b/src/tpm2/ReadPublic_fp.h new file mode 100644 index 0000000..1365f87 --- /dev/null +++ b/src/tpm2/ReadPublic_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ReadPublic_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef READPUBLIC_FP_H +#define READPUBLIC_FP_H + +typedef struct { + TPMI_DH_OBJECT objectHandle; +} ReadPublic_In; + +#define RC_ReadPublic_objectHandle (TPM_RC_H + TPM_RC_1) + +typedef struct { + TPM2B_PUBLIC outPublic; + TPM2B_NAME name; + TPM2B_NAME qualifiedName; +} ReadPublic_Out; + +TPM_RC +TPM2_ReadPublic( + ReadPublic_In *in, // IN: input parameter list + ReadPublic_Out *out // OUT: output parameter list + ); +#endif diff --git a/src/tpm2/Response.c b/src/tpm2/Response.c new file mode 100644 index 0000000..40d62ce --- /dev/null +++ b/src/tpm2/Response.c @@ -0,0 +1,105 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Response.c 1259 2018-07-10 19:11:09Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +/* 9.15 Response.c */ +/* 9.15.1 Description */ +/* This file contains the common code for building a response header, including setting the size of + the structure. command may be NULL if result is not TPM_RC_SUCCESS. */ +/* 9.15.2 Includes and Defines */ +#include "Tpm.h" +/* 9.15.3 BuildResponseHeader() */ +/* Adds the response header to the response. It will update command->parameterSize to indicate the + total size of the response. */ +void +BuildResponseHeader( + COMMAND *command, // IN: main control structure + BYTE *buffer, // OUT: the output buffer + TPM_RC result // IN: the response code + ) +{ + TPM_ST tag; + UINT32 size; + if(result != TPM_RC_SUCCESS) + { + tag = TPM_ST_NO_SESSIONS; + size = 10; + } + else + { + tag = command->tag; + // Compute the overall size of the response + size = STD_RESPONSE_HEADER + command->handleNum * sizeof(TPM_HANDLE); + size += command->parameterSize; + size += (command->tag == TPM_ST_SESSIONS) ? + command->authSize + sizeof(UINT32) : 0; + } + TPM_ST_Marshal(&tag, &buffer, NULL); + UINT32_Marshal(&size, &buffer, NULL); + TPM_RC_Marshal(&result, &buffer, NULL); + if(result == TPM_RC_SUCCESS) + { + if(command->handleNum > 0) + TPM_HANDLE_Marshal(&command->handles[0], &buffer, NULL); + if(tag == TPM_ST_SESSIONS) + UINT32_Marshal((UINT32 *)&command->parameterSize, &buffer, NULL); + } + command->parameterSize = size; +} diff --git a/src/tpm2/ResponseCodeProcessing.c b/src/tpm2/ResponseCodeProcessing.c new file mode 100644 index 0000000..3fa00ef --- /dev/null +++ b/src/tpm2/ResponseCodeProcessing.c @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* Miscellaneous Functions For Processing Response Codes */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ResponseCodeProcessing.c 1259 2018-07-10 19:11:09Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +/* 9.16 ResponseCodeProcessing.c */ +/* 9.16.1 Description */ +/* This file contains the miscellaneous functions for processing response codes. */ +/* NOTE: Currently, there is only one. */ +/* 9.16.2 Includes and Defines */ +#include "Tpm.h" +/* 9.16.3 RcSafeAddToResult() */ +/* Adds a modifier to a response code as long as the response code allows a modifier and no modifier + has already been added. */ +TPM_RC +RcSafeAddToResult( + TPM_RC responseCode, + TPM_RC modifier + ) +{ + if((responseCode & RC_FMT1) && !(responseCode & 0xf40)) + return responseCode + modifier; + else + return responseCode; +} diff --git a/src/tpm2/ResponseCodeProcessing_fp.h b/src/tpm2/ResponseCodeProcessing_fp.h new file mode 100644 index 0000000..da50c52 --- /dev/null +++ b/src/tpm2/ResponseCodeProcessing_fp.h @@ -0,0 +1,71 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ResponseCodeProcessing_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef RESPONSECODEPROCESSING_FP_H +#define RESPONSECODEPROCESSING_FP_H + +TPM_RC +RcSafeAddToResult( + TPM_RC responseCode, + TPM_RC modifier + ); + +#endif diff --git a/src/tpm2/Response_fp.h b/src/tpm2/Response_fp.h new file mode 100644 index 0000000..5460531 --- /dev/null +++ b/src/tpm2/Response_fp.h @@ -0,0 +1,73 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Response_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef RESPONSE_FP_H +#define RESPONSE_FP_H + +void +BuildResponseHeader( + COMMAND *command, // IN: main control structure + BYTE *buffer, // OUT: the output buffer + TPM_RC result // IN: the response code + ); + + +#endif diff --git a/src/tpm2/Rewrap_fp.h b/src/tpm2/Rewrap_fp.h new file mode 100644 index 0000000..6a29a5c --- /dev/null +++ b/src/tpm2/Rewrap_fp.h @@ -0,0 +1,92 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Rewrap_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef REWRAP_FP_H +#define REWRAP_FP_H + +typedef struct { + TPMI_DH_OBJECT oldParent; + TPMI_DH_OBJECT newParent; + TPM2B_PRIVATE inDuplicate; + TPM2B_NAME name; + TPM2B_ENCRYPTED_SECRET inSymSeed; +} Rewrap_In; + +#define RC_Rewrap_oldParent (TPM_RC_H + TPM_RC_1) +#define RC_Rewrap_newParent (TPM_RC_H + TPM_RC_2) +#define RC_Rewrap_inDuplicate (TPM_RC_P + TPM_RC_1) +#define RC_Rewrap_name (TPM_RC_P + TPM_RC_2) +#define RC_Rewrap_inSymSeed (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPM2B_PRIVATE outDuplicate; + TPM2B_ENCRYPTED_SECRET outSymSeed; +} Rewrap_Out; + +TPM_RC +TPM2_Rewrap( + Rewrap_In *in, // IN: input parameter list + Rewrap_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/RsaTestData.h b/src/tpm2/RsaTestData.h new file mode 100644 index 0000000..abbaa8d --- /dev/null +++ b/src/tpm2/RsaTestData.h @@ -0,0 +1,425 @@ +/********************************************************************************/ +/* */ +/* RSA Test Vectors */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: RsaTestData.h 1259 2018-07-10 19:11:09Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#ifndef RSATESTDATA_H +#define RSATESTDATA_H + + +/* 10.1.9 RsaTestData.h */ +/* RSA Test Vectors */ +#define RSA_TEST_KEY_SIZE 256 +typedef struct +{ + UINT16 size; + BYTE buffer[RSA_TEST_KEY_SIZE]; +} TPM2B_RSA_TEST_KEY; +typedef TPM2B_RSA_TEST_KEY TPM2B_RSA_TEST_VALUE; +typedef struct +{ + UINT16 size; + BYTE buffer[RSA_TEST_KEY_SIZE / 2]; +} TPM2B_RSA_TEST_PRIME; +const TPM2B_RSA_TEST_KEY c_rsaPublicModulus = {256, { + 0x91,0x12,0xf5,0x07,0x9d,0x5f,0x6b,0x1c,0x90,0xf6,0xcc,0x87,0xde,0x3a,0x7a,0x15, + 0xdc,0x54,0x07,0x6c,0x26,0x8f,0x25,0xef,0x7e,0x66,0xc0,0xe3,0x82,0x12,0x2f,0xab, + 0x52,0x82,0x1e,0x85,0xbc,0x53,0xba,0x2b,0x01,0xad,0x01,0xc7,0x8d,0x46,0x4f,0x7d, + 0xdd,0x7e,0xdc,0xb0,0xad,0xf6,0x0c,0xa1,0x62,0x92,0x97,0x8a,0x3e,0x6f,0x7e,0x3e, + 0xf6,0x9a,0xcc,0xf9,0xa9,0x86,0x77,0xb6,0x85,0x43,0x42,0x04,0x13,0x65,0xe2,0xad, + 0x36,0xc9,0xbf,0xc1,0x97,0x84,0x6f,0xee,0x7c,0xda,0x58,0xd2,0xae,0x07,0x00,0xaf, + 0xc5,0x5f,0x4d,0x3a,0x98,0xb0,0xed,0x27,0x7c,0xc2,0xce,0x26,0x5d,0x87,0xe1,0xe3, + 0xa9,0x69,0x88,0x4f,0x8c,0x08,0x31,0x18,0xae,0x93,0x16,0xe3,0x74,0xde,0xd3,0xf6, + 0x16,0xaf,0xa3,0xac,0x37,0x91,0x8d,0x10,0xc6,0x6b,0x64,0x14,0x3a,0xd9,0xfc,0xe4, + 0xa0,0xf2,0xd1,0x01,0x37,0x4f,0x4a,0xeb,0xe5,0xec,0x98,0xc5,0xd9,0x4b,0x30,0xd2, + 0x80,0x2a,0x5a,0x18,0x5a,0x7d,0xd4,0x3d,0xb7,0x62,0x98,0xce,0x6d,0xa2,0x02,0x6e, + 0x45,0xaa,0x95,0x73,0xe0,0xaa,0x75,0x57,0xb1,0x3d,0x1b,0x05,0x75,0x23,0x6b,0x20, + 0x69,0x9e,0x14,0xb0,0x7f,0xac,0xae,0xd2,0xc7,0x48,0x3b,0xe4,0x56,0x11,0x34,0x1e, + 0x05,0x1a,0x30,0x20,0xef,0x68,0x93,0x6b,0x9d,0x7e,0xdd,0xba,0x96,0x50,0xcc,0x1c, + 0x81,0xb4,0x59,0xb9,0x74,0x36,0xd9,0x97,0xdc,0x8f,0x17,0x82,0x72,0xb3,0x59,0xf6, + 0x23,0xfa,0x84,0xf7,0x6d,0xf2,0x05,0xff,0xf1,0xb9,0xcc,0xe9,0xa2,0x82,0x01,0xfb}}; +const TPM2B_RSA_TEST_PRIME c_rsaPrivatePrime = {RSA_TEST_KEY_SIZE / 2, { + 0xb7,0xa0,0x90,0xc7,0x92,0x09,0xde,0x71,0x03,0x37,0x4a,0xb5,0x2f,0xda,0x61,0xb8, + 0x09,0x1b,0xba,0x99,0x70,0x45,0xc1,0x0b,0x15,0x12,0x71,0x8a,0xb3,0x2a,0x4d,0x5a, + 0x41,0x9b,0x73,0x89,0x80,0x0a,0x8f,0x18,0x4c,0x8b,0xa2,0x5b,0xda,0xbd,0x43,0xbe, + 0xdc,0x76,0x4d,0x71,0x0f,0xb9,0xfc,0x7a,0x09,0xfe,0x4f,0xac,0x63,0xd9,0x2e,0x50, + 0x3a,0xa1,0x37,0xc6,0xf2,0xa1,0x89,0x12,0xe7,0x72,0x64,0x2b,0xba,0xc1,0x1f,0xca, + 0x9d,0xb7,0xaa,0x3a,0xa9,0xd3,0xa6,0x6f,0x73,0x02,0xbb,0x85,0x5d,0x9a,0xb9,0x5c, + 0x08,0x83,0x22,0x20,0x49,0x91,0x5f,0x4b,0x86,0xbc,0x3f,0x76,0x43,0x08,0x97,0xbf, + 0x82,0x55,0x36,0x2d,0x8b,0x6e,0x9e,0xfb,0xc1,0x67,0x6a,0x43,0xa2,0x46,0x81,0x71}}; +const BYTE c_RsaTestValue[RSA_TEST_KEY_SIZE] = { + 0x2a,0x24,0x3a,0xbb,0x50,0x1d,0xd4,0x2a,0xf9,0x18,0x32,0x34,0xa2,0x0f,0xea,0x5c, + 0x91,0x77,0xe9,0xe1,0x09,0x83,0xdc,0x5f,0x71,0x64,0x5b,0xeb,0x57,0x79,0xa0,0x41, + 0xc9,0xe4,0x5a,0x0b,0xf4,0x9f,0xdb,0x84,0x04,0xa6,0x48,0x24,0xf6,0x3f,0x66,0x1f, + 0xa8,0x04,0x5c,0xf0,0x7a,0x6b,0x4a,0x9c,0x7e,0x21,0xb6,0xda,0x6b,0x65,0x9c,0x3a, + 0x68,0x50,0x13,0x1e,0xa4,0xb7,0xca,0xec,0xd3,0xcc,0xb2,0x9b,0x8c,0x87,0xa4,0x6a, + 0xba,0xc2,0x06,0x3f,0x40,0x48,0x7b,0xa8,0xb8,0x2c,0x03,0x14,0x33,0xf3,0x1d,0xe9, + 0xbd,0x6f,0x54,0x66,0xb4,0x69,0x5e,0xbc,0x80,0x7c,0xe9,0x6a,0x43,0x7f,0xb8,0x6a, + 0xa0,0x5f,0x5d,0x7a,0x20,0xfd,0x7a,0x39,0xe1,0xea,0x0e,0x94,0x91,0x28,0x63,0x7a, + 0xac,0xc9,0xa5,0x3a,0x6d,0x31,0x7b,0x7c,0x54,0x56,0x99,0x56,0xbb,0xb7,0xa1,0x2d, + 0xd2,0x5c,0x91,0x5f,0x1c,0xd3,0x06,0x7f,0x34,0x53,0x2f,0x4c,0xd1,0x8b,0xd2,0x9e, + 0xdc,0xc3,0x94,0x0a,0xe1,0x0f,0xa5,0x15,0x46,0x2a,0x8e,0x10,0xc2,0xfe,0xb7,0x5e, + 0x2d,0x0d,0xd1,0x25,0xfc,0xe4,0xf7,0x02,0x19,0xfe,0xb6,0xe4,0x95,0x9c,0x17,0x4a, + 0x9b,0xdb,0xab,0xc7,0x79,0xe3,0x5e,0x40,0xd0,0x56,0x6d,0x25,0x0a,0x72,0x65,0x80, + 0x92,0x9a,0xa8,0x07,0x70,0x32,0x14,0xfb,0xfe,0x08,0xeb,0x13,0xb4,0x07,0x68,0xb4, + 0x58,0x39,0xbe,0x8e,0x78,0x3a,0x59,0x3f,0x9c,0x4c,0xe9,0xa8,0x64,0x68,0xf7,0xb9, + 0x6e,0x20,0xf5,0xcb,0xca,0x47,0xf2,0x17,0xaa,0x8b,0xbc,0x13,0x14,0x84,0xf6,0xab}; +const TPM2B_RSA_TEST_VALUE c_RsaepKvt = {RSA_TEST_KEY_SIZE, { + 0x73,0xbd,0x65,0x49,0xda,0x7b,0xb8,0x50,0x9e,0x87,0xf0,0x0a,0x8a,0x9a,0x07,0xb6, + 0x00,0x82,0x10,0x14,0x60,0xd8,0x01,0xfc,0xc5,0x18,0xea,0x49,0x5f,0x13,0xcf,0x65, + 0x66,0x30,0x6c,0x60,0x3f,0x24,0x3c,0xfb,0xe2,0x31,0x16,0x99,0x7e,0x31,0x98,0xab, + 0x93,0xb8,0x07,0x53,0xcc,0xdb,0x7f,0x44,0xd9,0xee,0x5d,0xe8,0x5f,0x97,0x5f,0xe8, + 0x1f,0x88,0x52,0x24,0x7b,0xac,0x62,0x95,0xb7,0x7d,0xf5,0xf8,0x9f,0x5a,0xa8,0x24, + 0x9a,0x76,0x71,0x2a,0x35,0x2a,0xa1,0x08,0xbb,0x95,0xe3,0x64,0xdc,0xdb,0xc2,0x33, + 0xa9,0x5f,0xbe,0x4c,0xc4,0xcc,0x28,0xc9,0x25,0xff,0xee,0x17,0x15,0x9a,0x50,0x90, + 0x0e,0x15,0xb4,0xea,0x6a,0x09,0xe6,0xff,0xa4,0xee,0xc7,0x7e,0xce,0xa9,0x73,0xe4, + 0xa0,0x56,0xbd,0x53,0x2a,0xe4,0xc0,0x2b,0xa8,0x9b,0x09,0x30,0x72,0x62,0x0f,0xf9, + 0xf6,0xa1,0x52,0xd2,0x8a,0x37,0xee,0xa5,0xc8,0x47,0xe1,0x99,0x21,0x47,0xeb,0xdd, + 0x37,0xaa,0xe4,0xbd,0x55,0x46,0x5a,0x5a,0x5d,0xfb,0x7b,0xfc,0xff,0xbf,0x26,0x71, + 0xf6,0x1e,0xad,0xbc,0xbf,0x33,0xca,0xe1,0x92,0x8f,0x2a,0x89,0x6c,0x45,0x24,0xd1, + 0xa6,0x52,0x56,0x24,0x5e,0x90,0x47,0xe5,0xcb,0x12,0xb0,0x32,0xf9,0xa6,0xbb,0xea, + 0x37,0xa9,0xbd,0xef,0x23,0xef,0x63,0x07,0x6c,0xc4,0x4e,0x64,0x3c,0xc6,0x11,0x84, + 0x7d,0x65,0xd6,0x5d,0x7a,0x17,0x58,0xa5,0xf7,0x74,0x3b,0x42,0xe3,0xd2,0xda,0x5f, + 0x6f,0xe0,0x1e,0x4b,0xcf,0x46,0xe2,0xdf,0x3e,0x41,0x8e,0x0e,0xb0,0x3f,0x8b,0x65}}; + +#define OAEP_TEST_LABEL "OAEP Test Value" + +#if ALG_SHA1_VALUE == DEFAULT_TEST_HASH + +const TPM2B_RSA_TEST_VALUE c_OaepKvt = {RSA_TEST_KEY_SIZE, { + 0x32,0x68,0x84,0x0b,0x9c,0xc9,0x25,0x26,0xd9,0xc0,0xd0,0xb1,0xde,0x60,0x55,0xae, + 0x33,0xe5,0xcf,0x6c,0x85,0xbe,0x0d,0x71,0x11,0xe1,0x45,0x60,0xbb,0x42,0x3d,0xf3, + 0xb1,0x18,0x84,0x7b,0xc6,0x5d,0xce,0x1d,0x5f,0x9a,0x97,0xcf,0xb1,0x97,0x9a,0x85, + 0x7c,0xa7,0xa1,0x63,0x23,0xb6,0x74,0x0f,0x1a,0xee,0x29,0x51,0xeb,0x50,0x8f,0x3c, + 0x8e,0x4e,0x31,0x38,0xdc,0x11,0xfc,0x9a,0x4e,0xaf,0x93,0xc9,0x7f,0x6e,0x35,0xf3, + 0xc9,0xe4,0x89,0x14,0x53,0xe2,0xc2,0x1a,0xf7,0x6b,0x9b,0xf0,0x7a,0xa4,0x69,0x52, + 0xe0,0x24,0x8f,0xea,0x31,0xa7,0x5c,0x43,0xb0,0x65,0xc9,0xfe,0xba,0xfe,0x80,0x9e, + 0xa5,0xc0,0xf5,0x8d,0xce,0x41,0xf9,0x83,0x0d,0x8e,0x0f,0xef,0x3d,0x1f,0x6a,0xcc, + 0x8a,0x3d,0x3b,0xdf,0x22,0x38,0xd7,0x34,0x58,0x7b,0x55,0xc9,0xf6,0xbc,0x7c,0x4c, + 0x3f,0xd7,0xde,0x4e,0x30,0xa9,0x69,0xf3,0x5f,0x56,0x8f,0xc2,0xe7,0x75,0x79,0xb8, + 0xa5,0xc8,0x0d,0xc0,0xcd,0xb6,0xc9,0x63,0xad,0x7c,0xe4,0x8f,0x39,0x60,0x4d,0x7d, + 0xdb,0x34,0x49,0x2a,0x47,0xde,0xc0,0x42,0x4a,0x19,0x94,0x2e,0x50,0x21,0x03,0x47, + 0xff,0x73,0xb3,0xb7,0x89,0xcc,0x7b,0x2c,0xeb,0x03,0xa7,0x9a,0x06,0xfd,0xed,0x19, + 0xbb,0x82,0xa0,0x13,0xe9,0xfa,0xac,0x06,0x5f,0xc5,0xa9,0x2b,0xda,0x88,0x23,0xa2, + 0x5d,0xc2,0x7f,0xda,0xc8,0x5a,0x94,0x31,0xc1,0x21,0xd7,0x1e,0x6b,0xd7,0x89,0xb1, + 0x93,0x80,0xab,0xd1,0x37,0xf2,0x6f,0x50,0xcd,0x2a,0xea,0xb1,0xc4,0xcd,0xcb,0xb5}}; +const TPM2B_RSA_TEST_VALUE c_RsaesKvt = {RSA_TEST_KEY_SIZE, { + 0x29,0xa4,0x2f,0xbb,0x8a,0x14,0x05,0x1e,0x3c,0x72,0x76,0x77,0x38,0xe7,0x73,0xe3, + 0x6e,0x24,0x4b,0x38,0xd2,0x1a,0xcf,0x23,0x58,0x78,0x36,0x82,0x23,0x6e,0x6b,0xef, + 0x2c,0x3d,0xf2,0xe8,0xd6,0xc6,0x87,0x8e,0x78,0x9b,0x27,0x39,0xc0,0xd6,0xef,0x4d, + 0x0b,0xfc,0x51,0x27,0x18,0xf3,0x51,0x5e,0x4d,0x96,0x3a,0xe2,0x15,0xe2,0x7e,0x42, + 0xf4,0x16,0xd5,0xc6,0x52,0x5d,0x17,0x44,0x76,0x09,0x7a,0xcf,0xe3,0x30,0xe3,0x84, + 0xf6,0x6f,0x3a,0x33,0xfb,0x32,0x0d,0x1d,0xe7,0x7c,0x80,0x82,0x4f,0xed,0xda,0x87, + 0x11,0x9c,0xc3,0x7e,0x85,0xbd,0x18,0x58,0x08,0x2b,0x23,0x37,0xe7,0x9d,0xd0,0xd1, + 0x79,0xe2,0x05,0xbd,0xf5,0x4f,0x0e,0x0f,0xdb,0x4a,0x74,0xeb,0x09,0x01,0xb3,0xca, + 0xbd,0xa6,0x7b,0x09,0xb1,0x13,0x77,0x30,0x4d,0x87,0x41,0x06,0x57,0x2e,0x5f,0x36, + 0x6e,0xfc,0x35,0x69,0xfe,0x0a,0x24,0x6c,0x98,0x8c,0xda,0x97,0xf4,0xfb,0xc7,0x83, + 0x2d,0x3e,0x7d,0xc0,0x5c,0x34,0xfd,0x11,0x2a,0x12,0xa7,0xae,0x4a,0xde,0xc8,0x4e, + 0xcf,0xf4,0x85,0x63,0x77,0xc6,0x33,0x34,0xe0,0x27,0xe4,0x9e,0x91,0x0b,0x4b,0x85, + 0xf0,0xb0,0x79,0xaa,0x7c,0xc6,0xff,0x3b,0xbc,0x04,0x73,0xb8,0x95,0xd7,0x31,0x54, + 0x3b,0x56,0xec,0x52,0x15,0xd7,0x3e,0x62,0xf5,0x82,0x99,0x3e,0x2a,0xc0,0x4b,0x2e, + 0x06,0x57,0x6d,0x3f,0x3e,0x77,0x1f,0x2b,0x2d,0xc5,0xb9,0x3b,0x68,0x56,0x73,0x70, + 0x32,0x6b,0x6b,0x65,0x25,0x76,0x45,0x6c,0x45,0xf1,0x6c,0x59,0xfc,0x94,0xa7,0x15}}; +const TPM2B_RSA_TEST_VALUE c_RsapssKvt = {RSA_TEST_KEY_SIZE, { + 0x01,0xfe,0xd5,0x83,0x0b,0x15,0xba,0x90,0x2c,0xdf,0xf7,0x26,0xb7,0x8f,0xb1,0xd7, + 0x0b,0xfd,0x83,0xf9,0x95,0xd5,0xd7,0xb5,0xc5,0xc5,0x4a,0xde,0xd5,0xe6,0x20,0x78, + 0xca,0x73,0x77,0x3d,0x61,0x36,0x48,0xae,0x3e,0x8f,0xee,0x43,0x29,0x96,0xdf,0x3f, + 0x1c,0x97,0x5a,0xbe,0xe5,0xa2,0x7e,0x5b,0xd0,0xc0,0x29,0x39,0x83,0x81,0x77,0x24, + 0x43,0xdb,0x3c,0x64,0x4d,0xf0,0x23,0xe4,0xae,0x0f,0x78,0x31,0x8c,0xda,0x0c,0xec, + 0xf1,0xdf,0x09,0xf2,0x14,0x6a,0x4d,0xaf,0x36,0x81,0x6e,0xbd,0xbe,0x36,0x79,0x88, + 0x98,0xb6,0x6f,0x5a,0xad,0xcf,0x7c,0xee,0xe0,0xdd,0x00,0xbe,0x59,0x97,0x88,0x00, + 0x34,0xc0,0x8b,0x48,0x42,0x05,0x04,0x5a,0xb7,0x85,0x38,0xa0,0x35,0xd7,0x3b,0x51, + 0xb8,0x7b,0x81,0x83,0xee,0xff,0x76,0x6f,0x50,0x39,0x4d,0xab,0x89,0x63,0x07,0x6d, + 0xf5,0xe5,0x01,0x10,0x56,0xfe,0x93,0x06,0x8f,0xd3,0xc9,0x41,0xab,0xc9,0xdf,0x6e, + 0x59,0xa8,0xc3,0x1d,0xbf,0x96,0x4a,0x59,0x80,0x3c,0x90,0x3a,0x59,0x56,0x4c,0x6d, + 0x44,0x6d,0xeb,0xdc,0x73,0xcd,0xc1,0xec,0xb8,0x41,0xbf,0x89,0x8c,0x03,0x69,0x4c, + 0xaf,0x3f,0xc1,0xc5,0xc7,0xe7,0x7d,0xa7,0x83,0x39,0x70,0xa2,0x6b,0x83,0xbc,0xbe, + 0xf5,0xbf,0x1c,0xee,0x6e,0xa3,0x22,0x1e,0x25,0x2f,0x16,0x68,0x69,0x5a,0x1d,0xfa, + 0x2c,0x3a,0x0f,0x67,0xe1,0x77,0x12,0xe8,0x3d,0xba,0xaa,0xef,0x96,0x9c,0x1f,0x64, + 0x32,0xf4,0xa7,0xb3,0x3f,0x7d,0x61,0xbb,0x9a,0x27,0xad,0xfb,0x2f,0x33,0xc4,0x70}}; +const TPM2B_RSA_TEST_VALUE c_RsassaKvt = {RSA_TEST_KEY_SIZE, { + 0x67,0x4e,0xdd,0xc2,0xd2,0x6d,0xe0,0x03,0xc4,0xc2,0x41,0xd3,0xd4,0x61,0x30,0xd0, + 0xe1,0x68,0x31,0x4a,0xda,0xd9,0xc2,0x5d,0xaa,0xa2,0x7b,0xfb,0x44,0x02,0xf5,0xd6, + 0xd8,0x2e,0xcd,0x13,0x36,0xc9,0x4b,0xdb,0x1a,0x4b,0x66,0x1b,0x4f,0x9c,0xb7,0x17, + 0xac,0x53,0x37,0x4f,0x21,0xbd,0x0c,0x66,0xac,0x06,0x65,0x52,0x9f,0x04,0xf6,0xa5, + 0x22,0x5b,0xf7,0xe6,0x0d,0x3c,0x9f,0x41,0x19,0x09,0x88,0x7c,0x41,0x4c,0x2f,0x9c, + 0x8b,0x3c,0xdd,0x7c,0x28,0x78,0x24,0xd2,0x09,0xa6,0x5b,0xf7,0x3c,0x88,0x7e,0x73, + 0x5a,0x2d,0x36,0x02,0x4f,0x65,0xb0,0xcb,0xc8,0xdc,0xac,0xa2,0xda,0x8b,0x84,0x91, + 0x71,0xe4,0x30,0x8b,0xb6,0x12,0xf2,0xf0,0xd0,0xa0,0x38,0xcf,0x75,0xb7,0x20,0xcb, + 0x35,0x51,0x52,0x6b,0xc4,0xf4,0x21,0x95,0xc2,0xf7,0x9a,0x13,0xc1,0x1a,0x7b,0x8f, + 0x77,0xda,0x19,0x48,0xbb,0x6d,0x14,0x5d,0xba,0x65,0xb4,0x9e,0x43,0x42,0x58,0x98, + 0x0b,0x91,0x46,0xd8,0x4c,0xf3,0x4c,0xaf,0x2e,0x02,0xa6,0xb2,0x49,0x12,0x62,0x43, + 0x4e,0xa8,0xac,0xbf,0xfd,0xfa,0x37,0x24,0xea,0x69,0x1c,0xf5,0xae,0xfa,0x08,0x82, + 0x30,0xc3,0xc0,0xf8,0x9a,0x89,0x33,0xe1,0x40,0x6d,0x18,0x5c,0x7b,0x90,0x48,0xbf, + 0x37,0xdb,0xea,0xfb,0x0e,0xd4,0x2e,0x11,0xfa,0xa9,0x86,0xff,0x00,0x0b,0x7b,0xca, + 0x09,0x64,0x6a,0x8f,0x0c,0x0e,0x09,0x14,0x36,0x4a,0x74,0x31,0x18,0x5b,0x18,0xeb, + 0xea,0x83,0xc3,0x66,0x68,0xa6,0x7d,0x43,0x06,0x0f,0x99,0x60,0xce,0x65,0x08,0xf6}}; +#endif // SHA1 +#if ALG_SHA256_VALUE == DEFAULT_TEST_HASH +const TPM2B_RSA_TEST_VALUE c_OaepKvt = {RSA_TEST_KEY_SIZE, { + 0x33,0x20,0x6e,0x21,0xc3,0xf6,0xcd,0xf8,0xd7,0x5d,0x9f,0xe9,0x05,0x14,0x8c,0x7c, + 0xbb,0x69,0x24,0x9e,0x52,0x8f,0xaf,0x84,0x73,0x21,0x2c,0x85,0xa5,0x30,0x4d,0xb6, + 0xb8,0xfa,0x15,0x9b,0xc7,0x8f,0xc9,0x7a,0x72,0x4b,0x85,0xa4,0x1c,0xc5,0xd8,0xe4, + 0x92,0xb3,0xec,0xd9,0xa8,0xca,0x5e,0x74,0x73,0x89,0x7f,0xb4,0xac,0x7e,0x68,0x12, + 0xb2,0x53,0x27,0x4b,0xbf,0xd0,0x71,0x69,0x46,0x9f,0xef,0xf4,0x70,0x60,0xf8,0xd7, + 0xae,0xc7,0x5a,0x27,0x38,0x25,0x2d,0x25,0xab,0x96,0x56,0x66,0x3a,0x23,0x40,0xa8, + 0xdb,0xbc,0x86,0xe8,0xf3,0xd2,0x58,0x0b,0x44,0xfc,0x94,0x1e,0xb7,0x5d,0xb4,0x57, + 0xb5,0xf3,0x56,0xee,0x9b,0xcf,0x97,0x91,0x29,0x36,0xe3,0x06,0x13,0xa2,0xea,0xd6, + 0xd6,0x0b,0x86,0x0b,0x1a,0x27,0xe6,0x22,0xc4,0x7b,0xff,0xde,0x0f,0xbf,0x79,0xc8, + 0x1b,0xed,0xf1,0x27,0x62,0xb5,0x8b,0xf9,0xd9,0x76,0x90,0xf6,0xcc,0x83,0x0f,0xce, + 0xce,0x2e,0x63,0x7a,0x9b,0xf4,0x48,0x5b,0xd7,0x81,0x2c,0x3a,0xdb,0x59,0x0d,0x4d, + 0x9e,0x46,0xe9,0x9e,0x92,0x22,0x27,0x1c,0xb0,0x67,0x8a,0xe6,0x8a,0x16,0x8a,0xdf, + 0x95,0x76,0x24,0x82,0xad,0xf1,0xbc,0x97,0xbf,0xd3,0x5e,0x6e,0x14,0x0c,0x5b,0x25, + 0xfe,0x58,0xfa,0x64,0xe5,0x14,0x46,0xb7,0x58,0xc6,0x3f,0x7f,0x42,0xd2,0x8e,0x45, + 0x13,0x41,0x85,0x12,0x2e,0x96,0x19,0xd0,0x5e,0x7d,0x34,0x06,0x32,0x2b,0xc8,0xd9, + 0x0d,0x6c,0x06,0x36,0xa0,0xff,0x47,0x57,0x2c,0x25,0xbc,0x8a,0xa5,0xe2,0xc7,0xe3}}; +const TPM2B_RSA_TEST_VALUE c_RsaesKvt = {RSA_TEST_KEY_SIZE, { + 0x39,0xfc,0x10,0x5d,0xf4,0x45,0x3d,0x94,0x53,0x06,0x89,0x24,0xe7,0xe8,0xfd,0x03, + 0xac,0xfd,0xbd,0xb2,0x28,0xd3,0x4a,0x52,0xc5,0xd4,0xdb,0x17,0xd4,0x24,0x05,0xc4, + 0xeb,0x6a,0xce,0x1d,0xbb,0x37,0xcb,0x09,0xd8,0x6c,0x83,0x19,0x93,0xd4,0xe2,0x88, + 0x88,0x9b,0xaf,0x92,0x16,0xc4,0x15,0xbd,0x49,0x13,0x22,0xb7,0x84,0xcf,0x23,0xf2, + 0x6f,0x0c,0x3e,0x8f,0xde,0x04,0x09,0x31,0x2d,0x99,0xdf,0xe6,0x74,0x70,0x30,0xde, + 0x8c,0xad,0x32,0x86,0xe2,0x7c,0x12,0x90,0x21,0xf3,0x86,0xb7,0xe2,0x64,0xca,0x98, + 0xcc,0x64,0x4b,0xef,0x57,0x4f,0x5a,0x16,0x6e,0xd7,0x2f,0x5b,0xf6,0x07,0xad,0x33, + 0xb4,0x8f,0x3b,0x3a,0x8b,0xd9,0x06,0x2b,0xed,0x3c,0x3c,0x76,0xf6,0x21,0x31,0xe3, + 0xfb,0x2c,0x45,0x61,0x42,0xba,0xe0,0xc3,0x72,0x63,0xd0,0x6b,0x8f,0x36,0x26,0xfb, + 0x9e,0x89,0x0e,0x44,0x9a,0xc1,0x84,0x5e,0x84,0x8d,0xb6,0xea,0xf1,0x0d,0x66,0xc7, + 0xdb,0x44,0xbd,0x19,0x7c,0x05,0xbe,0xc4,0xab,0x88,0x32,0xbe,0xc7,0x63,0x31,0xe6, + 0x38,0xd4,0xe5,0xb8,0x4b,0xf5,0x0e,0x55,0x9a,0x3a,0xe6,0x0a,0xec,0xee,0xe2,0xa8, + 0x88,0x04,0xf2,0xb8,0xaa,0x5a,0xd8,0x97,0x5d,0xa0,0xa8,0x42,0xfb,0xd9,0xde,0x80, + 0xae,0x4c,0xb3,0xa1,0x90,0x47,0x57,0x03,0x10,0x78,0xa6,0x8f,0x11,0xba,0x4b,0xce, + 0x2d,0x56,0xa4,0xe1,0xbd,0xf8,0xa0,0xa4,0xd5,0x48,0x3c,0x63,0x20,0x00,0x38,0xa0, + 0xd1,0xe6,0x12,0xe9,0x1d,0xd8,0x49,0xe3,0xd5,0x24,0xb5,0xc5,0x3a,0x1f,0xb0,0xd4}}; +const TPM2B_RSA_TEST_VALUE c_RsapssKvt = {RSA_TEST_KEY_SIZE, { + 0x74,0x89,0x29,0x3e,0x1b,0xac,0xc6,0x85,0xca,0xf0,0x63,0x43,0x30,0x7d,0x1c,0x9b, + 0x2f,0xbd,0x4d,0x69,0x39,0x5e,0x85,0xe2,0xef,0x86,0x0a,0xc6,0x6b,0xa6,0x08,0x19, + 0x6c,0x56,0x38,0x24,0x55,0x92,0x84,0x9b,0x1b,0x8b,0x04,0xcf,0x24,0x14,0x24,0x13, + 0x0e,0x8b,0x82,0x6f,0x96,0xc8,0x9a,0x68,0xfc,0x4c,0x02,0xf0,0xdc,0xcd,0x36,0x25, + 0x31,0xd5,0x82,0xcf,0xc9,0x69,0x72,0xf6,0x1d,0xab,0x68,0x20,0x2e,0x2d,0x19,0x49, + 0xf0,0x2e,0xad,0xd2,0xda,0xaf,0xff,0xb6,0x92,0x83,0x5b,0x8a,0x06,0x2d,0x0c,0x32, + 0x11,0x32,0x3b,0x77,0x17,0xf6,0x50,0xfb,0xf8,0x57,0xc9,0xc7,0x9b,0x9e,0xc6,0xd1, + 0xa9,0x55,0xf0,0x22,0x35,0xda,0xca,0x3c,0x8e,0xc6,0x9a,0xd8,0x25,0xc8,0x5e,0x93, + 0x0d,0xaa,0xa7,0x06,0xaf,0x11,0x29,0x99,0xe7,0x7c,0xee,0x49,0x82,0x30,0xba,0x2c, + 0xe2,0x40,0x8f,0x0a,0xa6,0x7b,0x24,0x75,0xc5,0xcd,0x03,0x12,0xf4,0xb2,0x4b,0x3a, + 0xd1,0x91,0x3c,0x20,0x0e,0x58,0x2b,0x31,0xf8,0x8b,0xee,0xbc,0x1f,0x95,0x35,0x58, + 0x6a,0x73,0xee,0x99,0xb0,0x01,0x42,0x4f,0x66,0xc0,0x66,0xbb,0x35,0x86,0xeb,0xd9, + 0x7b,0x55,0x77,0x2d,0x54,0x78,0x19,0x49,0xe8,0xcc,0xfd,0xb1,0xcb,0x49,0xc9,0xea, + 0x20,0xab,0xed,0xb5,0xed,0xfe,0xb2,0xb5,0xa8,0xcf,0x05,0x06,0xd5,0x7d,0x2b,0xbb, + 0x0b,0x65,0x6b,0x2b,0x6d,0x55,0x95,0x85,0x44,0x8b,0x12,0x05,0xf3,0x4b,0xd4,0x8e, + 0x3d,0x68,0x2d,0x29,0x9c,0x05,0x79,0xd6,0xfc,0x72,0x90,0x6a,0xab,0x46,0x38,0x81}}; +const TPM2B_RSA_TEST_VALUE c_RsassaKvt = {RSA_TEST_KEY_SIZE, { + 0x8a,0xb1,0x0a,0xb5,0xe4,0x02,0xf7,0xdd,0x45,0x2a,0xcc,0x2b,0x6b,0x8c,0x0e,0x9a, + 0x92,0x4f,0x9b,0xc5,0xe4,0x8b,0x82,0xb9,0xb0,0xd9,0x87,0x8c,0xcb,0xf0,0xb0,0x59, + 0xa5,0x92,0x21,0xa0,0xa7,0x61,0x5c,0xed,0xa8,0x6e,0x22,0x29,0x46,0xc7,0x86,0x37, + 0x4b,0x1b,0x1e,0x94,0x93,0xc8,0x4c,0x17,0x7a,0xae,0x59,0x91,0xf8,0x83,0x84,0xc4, + 0x8c,0x38,0xc2,0x35,0x0e,0x7e,0x50,0x67,0x76,0xe7,0xd3,0xec,0x6f,0x0d,0xa0,0x5c, + 0x2f,0x0a,0x80,0x28,0xd3,0xc5,0x7d,0x2d,0x1a,0x0b,0x96,0xd6,0xe5,0x98,0x05,0x8c, + 0x4d,0xa0,0x1f,0x8c,0xb6,0xfb,0xb1,0xcf,0xe9,0xcb,0x38,0x27,0x60,0x64,0x17,0xca, + 0xf4,0x8b,0x61,0xb7,0x1d,0xb6,0x20,0x9d,0x40,0x2a,0x1c,0xfd,0x55,0x40,0x4b,0x95, + 0x39,0x52,0x18,0x3b,0xab,0x44,0xe8,0x83,0x4b,0x7c,0x47,0xfb,0xed,0x06,0x9c,0xcd, + 0x4f,0xba,0x81,0xd6,0xb7,0x31,0xcf,0x5c,0x23,0xf8,0x25,0xab,0x95,0x77,0x0a,0x8f, + 0x46,0xef,0xfb,0x59,0xb8,0x04,0xd7,0x1e,0xf5,0xaf,0x6a,0x1a,0x26,0x9b,0xae,0xf4, + 0xf5,0x7f,0x84,0x6f,0x3c,0xed,0xf8,0x24,0x0b,0x43,0xd1,0xba,0x74,0x89,0x4e,0x39, + 0xfe,0xab,0xa5,0x16,0xa5,0x28,0xee,0x96,0x84,0x3e,0x16,0x6d,0x5f,0x4e,0x0b,0x7d, + 0x94,0x16,0x1b,0x8c,0xf9,0xaa,0x9b,0xc0,0x49,0x02,0x4c,0x3e,0x62,0xff,0xfe,0xa2, + 0x20,0x33,0x5e,0xa6,0xdd,0xda,0x15,0x2d,0xb7,0xcd,0xda,0xff,0xb1,0x0b,0x45,0x7b, + 0xd3,0xa0,0x42,0x29,0xab,0xa9,0x73,0xe9,0xa4,0xd9,0x8d,0xac,0xa1,0x88,0x2c,0x2d}}; +#endif // SHA256 +#if ALG_SHA384_VALUE == DEFAULT_TEST_HASH +const TPM2B_RSA_TEST_VALUE c_OaepKvt = {RSA_TEST_KEY_SIZE, { + 0x0f,0x3c,0x42,0x4d,0x8c,0x91,0x96,0x05,0x3c,0xfd,0x59,0x3b,0x7f,0x29,0xbc,0x03, + 0x67,0xc1,0xff,0x74,0xe7,0x09,0xf4,0x13,0x45,0xbe,0x13,0x1d,0xc9,0x86,0x94,0xfe, + 0xed,0xa6,0xe8,0x3a,0xcb,0x89,0x4d,0xec,0x86,0x63,0x4c,0xdb,0xf1,0x95,0xee,0xc1, + 0x46,0xc5,0x3b,0xd8,0xf8,0xa2,0x41,0x6a,0x60,0x8b,0x9e,0x5e,0x7f,0x20,0x16,0xe3, + 0x69,0xb6,0x2d,0x92,0xfc,0x60,0xa2,0x74,0x88,0xd5,0xc7,0xa6,0xd1,0xff,0xe3,0x45, + 0x02,0x51,0x39,0xd9,0xf3,0x56,0x0b,0x91,0x80,0xe0,0x6c,0xa8,0xc3,0x78,0xef,0x34, + 0x22,0x8c,0xf5,0xfb,0x47,0x98,0x5d,0x57,0x8e,0x3a,0xb9,0xff,0x92,0x04,0xc7,0xc2, + 0x6e,0xfa,0x14,0xc1,0xb9,0x68,0x15,0x5c,0x12,0xe8,0xa8,0xbe,0xea,0xe8,0x8d,0x9b, + 0x48,0x28,0x35,0xdb,0x4b,0x52,0xc1,0x2d,0x85,0x47,0x83,0xd0,0xe9,0xae,0x90,0x6e, + 0x65,0xd4,0x34,0x7f,0x81,0xce,0x69,0xf0,0x96,0x62,0xf7,0xec,0x41,0xd5,0xc2,0xe3, + 0x4b,0xba,0x9c,0x8a,0x02,0xce,0xf0,0x5d,0x14,0xf7,0x09,0x42,0x8e,0x4a,0x27,0xfe, + 0x3e,0x66,0x42,0x99,0x03,0xe1,0x69,0xbd,0xdb,0x7f,0x9b,0x70,0xeb,0x4e,0x9c,0xac, + 0x45,0x67,0x91,0x9f,0x75,0x10,0xc6,0xfc,0x14,0xe1,0x28,0xc1,0x0e,0xe0,0x7e,0xc0, + 0x5c,0x1d,0xee,0xe8,0xff,0x45,0x79,0x51,0x86,0x08,0xe6,0x39,0xac,0xb5,0xfd,0xb8, + 0xf1,0xdd,0x2e,0xf4,0xb2,0x1a,0x69,0x0d,0xd9,0x98,0x8e,0xdb,0x85,0x61,0x70,0x20, + 0x82,0x91,0x26,0x87,0x80,0xc4,0x6a,0xd8,0x3b,0x91,0x4d,0xd3,0x33,0x84,0xad,0xb7}}; +const TPM2B_RSA_TEST_VALUE c_RsaesKvt = {RSA_TEST_KEY_SIZE, { + 0x44,0xd5,0x9f,0xbc,0x48,0x03,0x3d,0x9f,0x22,0x91,0x2a,0xab,0x3c,0x31,0x71,0xab, + 0x86,0x3f,0x0f,0x6f,0x59,0x5b,0x93,0x27,0xbc,0xbc,0xcd,0x29,0x38,0x43,0x2a,0x3b, + 0x3b,0xd2,0xb3,0x45,0x40,0xba,0x15,0xb4,0x45,0xe3,0x56,0xab,0xff,0xb3,0x20,0x26, + 0x39,0xcc,0x48,0xc5,0x5d,0x41,0x0d,0x2f,0x57,0x7f,0x9d,0x16,0x2e,0x26,0x57,0xc7, + 0x6b,0xf3,0x36,0x54,0xbd,0xb6,0x1d,0x46,0x4e,0x13,0x50,0xd7,0x61,0x9d,0x8d,0x7b, + 0xeb,0x21,0x9f,0x79,0xf3,0xfd,0xe0,0x1b,0xa8,0xed,0x6d,0x29,0x33,0x0d,0x65,0x94, + 0x24,0x1e,0x62,0x88,0x6b,0x2b,0x4e,0x39,0xf5,0x80,0x39,0xca,0x76,0x95,0xbc,0x7c, + 0x27,0x1d,0xdd,0x3a,0x11,0xf1,0x3e,0x54,0x03,0xb7,0x43,0x91,0x99,0x33,0xfe,0x9d, + 0x14,0x2c,0x87,0x9a,0x95,0x18,0x1f,0x02,0x04,0x6a,0xe2,0xb7,0x81,0x14,0x13,0x45, + 0x16,0xfb,0xe4,0xb7,0x8f,0xab,0x2b,0xd7,0x60,0x34,0x8a,0x55,0xbc,0x01,0x8c,0x49, + 0x02,0x29,0xf1,0x9c,0x94,0x98,0x44,0xd0,0x94,0xcb,0xd4,0x85,0x4c,0x3b,0x77,0x72, + 0x99,0xd5,0x4b,0xc6,0x3b,0xe4,0xd2,0xc8,0xe9,0x6a,0x23,0x18,0x3b,0x3b,0x5e,0x32, + 0xec,0x70,0x84,0x5d,0xbb,0x6a,0x8f,0x0c,0x5f,0x55,0xa5,0x30,0x34,0x48,0xbb,0xc2, + 0xdf,0x12,0xb9,0x81,0xad,0x36,0x3f,0xf0,0x24,0x16,0x48,0x04,0x4a,0x7f,0xfd,0x9f, + 0x4c,0xea,0xfe,0x1d,0x83,0xd0,0x81,0xad,0x25,0x6c,0x5f,0x45,0x36,0x91,0xf0,0xd5, + 0x8b,0x53,0x0a,0xdf,0xec,0x9f,0x04,0x58,0xc4,0x35,0xa0,0x78,0x1f,0x68,0xe0,0x22}}; +const TPM2B_RSA_TEST_VALUE c_RsapssKvt = {RSA_TEST_KEY_SIZE, { + 0x3f,0x3a,0x82,0x6d,0x42,0xe3,0x8b,0x4f,0x45,0x9c,0xda,0x6c,0xbe,0xbe,0xcd,0x00, + 0x98,0xfb,0xbe,0x59,0x30,0xc6,0x3c,0xaa,0xb3,0x06,0x27,0xb5,0xda,0xfa,0xb2,0xc3, + 0x43,0xb7,0xbd,0xe9,0xd3,0x23,0xed,0x80,0xce,0x74,0xb3,0xb8,0x77,0x8d,0xe6,0x8d, + 0x3c,0xe5,0xf5,0xd7,0x80,0xcf,0x38,0x55,0x76,0xd7,0x87,0xa8,0xd6,0x3a,0xcf,0xfd, + 0xd8,0x91,0x65,0xab,0x43,0x66,0x50,0xb7,0x9a,0x13,0x6b,0x45,0x80,0x76,0x86,0x22, + 0x27,0x72,0xf7,0xbb,0x65,0x22,0x5c,0x55,0x60,0xd8,0x84,0x9f,0xf2,0x61,0x52,0xac, + 0xf2,0x4f,0x5b,0x7b,0x21,0xe1,0xf5,0x4b,0x8f,0x01,0xf2,0x4b,0xcf,0xd3,0xfb,0x74, + 0x5e,0x6e,0x96,0xb4,0xa8,0x0f,0x01,0x9b,0x26,0x54,0x0a,0x70,0x55,0x26,0xb7,0x0b, + 0xe8,0x01,0x68,0x66,0x0d,0x6f,0xb5,0xfc,0x66,0xbd,0x9e,0x44,0xed,0x6a,0x1e,0x3c, + 0x3b,0x61,0x5d,0xe8,0xdb,0x99,0x5b,0x67,0xbf,0x94,0xfb,0xe6,0x8c,0x4b,0x07,0xcb, + 0x43,0x3a,0x0d,0xb1,0x1b,0x10,0x66,0x81,0xe2,0x0d,0xe7,0xd1,0xca,0x85,0xa7,0x50, + 0x82,0x2d,0xbf,0xed,0xcf,0x43,0x6d,0xdb,0x2c,0x7b,0x73,0x20,0xfe,0x73,0x3f,0x19, + 0xc6,0xdb,0x69,0xb8,0xc3,0xd3,0xf4,0xe5,0x64,0xf8,0x36,0x8e,0xd5,0xd8,0x09,0x2a, + 0x5f,0x26,0x70,0xa1,0xd9,0x5b,0x14,0xf8,0x22,0xe9,0x9d,0x22,0x51,0xf4,0x52,0xc1, + 0x6f,0x53,0xf5,0xca,0x0d,0xda,0x39,0x8c,0x29,0x42,0xe8,0x58,0x89,0xbb,0xd1,0x2e, + 0xc5,0xdb,0x86,0x8d,0xaf,0xec,0x58,0x36,0x8d,0x8d,0x57,0x23,0xd5,0xdd,0xb9,0x24}}; +const TPM2B_RSA_TEST_VALUE c_RsassaKvt = {RSA_TEST_KEY_SIZE, { + 0x39,0x10,0x58,0x7d,0x6d,0xa8,0xd5,0x90,0x07,0xd6,0x2b,0x13,0xe9,0xd8,0x93,0x7e, + 0xf3,0x5d,0x71,0xe0,0xf0,0x33,0x3a,0x4a,0x22,0xf3,0xe6,0x95,0xd3,0x8e,0x8c,0x41, + 0xe7,0xb3,0x13,0xde,0x4a,0x45,0xd3,0xd1,0xfb,0xb1,0x3f,0x9b,0x39,0xa5,0x50,0x58, + 0xef,0xb6,0x3a,0x43,0xdd,0x54,0xab,0xda,0x9d,0x32,0x49,0xe4,0x57,0x96,0xe5,0x1b, + 0x1d,0x8f,0x33,0x8e,0x07,0x67,0x56,0x14,0xc1,0x18,0x78,0xa2,0x52,0xe6,0x2e,0x07, + 0x81,0xbe,0xd8,0xca,0x76,0x63,0x68,0xc5,0x47,0xa2,0x92,0x5e,0x4c,0xfd,0x14,0xc7, + 0x46,0x14,0xbe,0xc7,0x85,0xef,0xe6,0xb8,0x46,0xcb,0x3a,0x67,0x66,0x89,0xc6,0xee, + 0x9d,0x64,0xf5,0x0d,0x09,0x80,0x9a,0x6f,0x0e,0xeb,0xe4,0xb9,0xe9,0xab,0x90,0x4f, + 0xe7,0x5a,0xc8,0xca,0xf6,0x16,0x0a,0x82,0xbd,0xb7,0x76,0x59,0x08,0x2d,0xd9,0x40, + 0x5d,0xaa,0xa5,0xef,0xfb,0xe3,0x81,0x2c,0x2c,0x5c,0xa8,0x16,0xbd,0x63,0x20,0xc2, + 0x4d,0x3b,0x51,0xaa,0x62,0x1f,0x06,0xe5,0xbb,0x78,0x44,0x04,0x0c,0x5c,0xe1,0x1b, + 0x6b,0x9d,0x21,0x10,0xaf,0x48,0x48,0x98,0x97,0x77,0xc2,0x73,0xb4,0x98,0x64,0xcc, + 0x94,0x2c,0x29,0x28,0x45,0x36,0xd1,0xc5,0xd0,0x2f,0x97,0x27,0x92,0x65,0x22,0xbb, + 0x63,0x79,0xea,0xf5,0xff,0x77,0x0f,0x4b,0x56,0x8a,0x9f,0xad,0x1a,0x97,0x67,0x39, + 0x69,0xb8,0x4c,0x6c,0xc2,0x56,0xc5,0x7a,0xa8,0x14,0x5a,0x24,0x7a,0xa4,0x6e,0x55, + 0xb2,0x86,0x1d,0xf4,0x62,0x5a,0x2d,0x87,0x6d,0xde,0x99,0x78,0x2d,0xef,0xd7,0xdc}}; +#endif // SHA384 +#if ALG_SHA512_VALUE == DEFAULT_TEST_HASH +const TPM2B_RSA_TEST_VALUE c_OaepKvt = {RSA_TEST_KEY_SIZE, { + 0x48,0x45,0xa7,0x70,0xb2,0x41,0xb7,0x48,0x5e,0x79,0x8c,0xdf,0x1c,0xc6,0x7e,0xbb, + 0x11,0x80,0x82,0x52,0xbf,0x40,0x3d,0x90,0x03,0x6e,0x20,0x3a,0xb9,0x65,0xc8,0x51, + 0x4c,0xbd,0x9c,0xa9,0x43,0x89,0xd0,0x57,0x0c,0xa3,0x69,0x22,0x7e,0x82,0x2a,0x1c, + 0x1d,0x5a,0x80,0x84,0x81,0xbb,0x5e,0x5e,0xd0,0xc1,0x66,0x9a,0xac,0x00,0xba,0x14, + 0xa2,0xe9,0xd0,0x3a,0x89,0x5a,0x63,0xe2,0xec,0x92,0x05,0xf4,0x47,0x66,0x12,0x7f, + 0xdb,0xa7,0x3c,0x5b,0x67,0xe1,0x55,0xca,0x0a,0x27,0xbf,0x39,0x89,0x11,0x05,0xba, + 0x9b,0x5a,0x9b,0x65,0x44,0xad,0x78,0xcf,0x8f,0x94,0xf6,0x9a,0xb4,0x52,0x39,0x0e, + 0x00,0xba,0xbc,0xe0,0xbd,0x6f,0x81,0x2d,0x76,0x42,0x66,0x70,0x07,0x77,0xbf,0x09, + 0x88,0x2a,0x0c,0xb1,0x56,0x3e,0xee,0xfd,0xdc,0xb6,0x3c,0x0d,0xc5,0xa4,0x0d,0x10, + 0x32,0x80,0x3e,0x1e,0xfe,0x36,0x8f,0xb5,0x42,0xc1,0x21,0x7b,0xdf,0xdf,0x4a,0xd2, + 0x68,0x0c,0x01,0x9f,0x4a,0xfd,0xd4,0xec,0xf7,0x49,0x06,0xab,0xed,0xc6,0xd5,0x1b, + 0x63,0x76,0x38,0xc8,0x6c,0xc7,0x4f,0xcb,0x29,0x8a,0x0e,0x6f,0x33,0xaf,0x69,0x31, + 0x8e,0xa7,0xdd,0x9a,0x36,0xde,0x9b,0xf1,0x0b,0xfb,0x20,0xa0,0x6d,0x33,0x31,0xc9, + 0x9e,0xb4,0x2e,0xc5,0x40,0x0e,0x60,0x71,0x36,0x75,0x05,0xf9,0x37,0xe0,0xca,0x8e, + 0x8f,0x56,0xe0,0xea,0x9b,0xeb,0x17,0xf3,0xca,0x40,0xc3,0x48,0x01,0xba,0xdc,0xc6, + 0x4b,0x2b,0x5b,0x7b,0x5c,0x81,0xa6,0xbb,0xc7,0x43,0xc0,0xbe,0xc0,0x30,0x7b,0x55}}; +const TPM2B_RSA_TEST_VALUE c_RsaesKvt = {RSA_TEST_KEY_SIZE, { + 0x74,0x83,0xfa,0x52,0x65,0x50,0x68,0xd0,0x82,0x05,0x72,0x70,0x78,0x1c,0xac,0x10, + 0x23,0xc5,0x07,0xf8,0x93,0xd2,0xeb,0x65,0x87,0xbb,0x47,0xc2,0xfb,0x30,0x9e,0x61, + 0x4c,0xac,0x04,0x57,0x5a,0x7c,0xeb,0x29,0x08,0x84,0x86,0x89,0x1e,0x8f,0x07,0x32, + 0xa3,0x8b,0x70,0xe7,0xa2,0x9f,0x9c,0x42,0x71,0x3d,0x23,0x59,0x82,0x5e,0x8a,0xde, + 0xd6,0xfb,0xd8,0xc5,0x8b,0xc0,0xdb,0x10,0x38,0x87,0xd3,0xbf,0x04,0xb0,0x66,0xb9, + 0x85,0x81,0x54,0x4c,0x69,0xdc,0xba,0x78,0xf3,0x4a,0xdb,0x25,0xa2,0xf2,0x34,0x55, + 0xdd,0xaa,0xa5,0xc4,0xed,0x55,0x06,0x0e,0x2a,0x30,0x77,0xab,0x82,0x79,0xf0,0xcd, + 0x9d,0x6f,0x09,0xa0,0xc8,0x82,0xc9,0xe0,0x61,0xda,0x40,0xcd,0x17,0x59,0xc0,0xef, + 0x95,0x6d,0xa3,0x6d,0x1c,0x2b,0xee,0x24,0xef,0xd8,0x4a,0x55,0x6c,0xd6,0x26,0x42, + 0x32,0x17,0xfd,0x6a,0xb3,0x4f,0xde,0x07,0x2f,0x10,0xd4,0xac,0x14,0xea,0x89,0x68, + 0xcc,0xd3,0x07,0xb7,0xcf,0xba,0x39,0x20,0x63,0x20,0x7b,0x44,0x8b,0x48,0x60,0x5d, + 0x3a,0x2a,0x0a,0xe9,0x68,0xab,0x15,0x46,0x27,0x64,0xb5,0x82,0x06,0x29,0xe7,0x25, + 0xca,0x46,0x48,0x6e,0x2a,0x34,0x57,0x4b,0x81,0x75,0xae,0xb6,0xfd,0x6f,0x51,0x5f, + 0x04,0x59,0xc7,0x15,0x1f,0xe0,0x68,0xf7,0x36,0x2d,0xdf,0xc8,0x9d,0x05,0x27,0x2d, + 0x3f,0x2b,0x59,0x5d,0xcb,0xf3,0xc4,0x92,0x6e,0x00,0xa8,0x8d,0xd0,0x69,0xe5,0x59, + 0xda,0xba,0x4f,0x38,0xf5,0xa0,0x8b,0xf1,0x73,0xe9,0x0d,0xee,0x64,0xe5,0xa2,0xd8}}; +const TPM2B_RSA_TEST_VALUE c_RsapssKvt = {RSA_TEST_KEY_SIZE, { + 0x1b,0xca,0x8b,0x18,0x15,0x3b,0x95,0x5b,0x0a,0x89,0x10,0x03,0x7f,0x7c,0xa0,0xc9, + 0x66,0x57,0x86,0x6a,0xc9,0xeb,0x82,0x71,0xf3,0x8d,0x6f,0xa9,0xa4,0x2d,0xd0,0x22, + 0xdf,0xe9,0xc6,0x71,0x5b,0xf4,0x27,0x38,0x5b,0x2c,0x8a,0x54,0xcc,0x85,0x11,0x69, + 0x6d,0x6f,0x42,0xe7,0x22,0xcb,0xd6,0xad,0x1a,0xc5,0xab,0x6a,0xa5,0xfc,0xa5,0x70, + 0x72,0x4a,0x62,0x25,0xd0,0xa2,0x16,0x61,0xab,0xac,0x31,0xa0,0x46,0x24,0x4f,0xdd, + 0x9a,0x36,0x55,0xb6,0x00,0x9e,0x23,0x50,0x0d,0x53,0x01,0xb3,0x46,0x56,0xb2,0x1d, + 0x33,0x5b,0xca,0x41,0x7f,0x65,0x7e,0x00,0x5c,0x12,0xff,0x0a,0x70,0x5d,0x8c,0x69, + 0x4a,0x02,0xee,0x72,0x30,0xa7,0x5c,0xa4,0xbb,0xbe,0x03,0x0c,0xe4,0x5f,0x33,0xb6, + 0x78,0x91,0x9d,0xd8,0xec,0x34,0x03,0x2e,0x63,0x32,0xc7,0x2a,0x36,0x50,0xd5,0x8b, + 0x0e,0x7f,0x54,0x4e,0xf4,0x29,0x11,0x1b,0xcd,0x0f,0x37,0xa5,0xbc,0x61,0x83,0x50, + 0xfa,0x18,0x75,0xd9,0xfe,0xa7,0xe8,0x9b,0xc1,0x4f,0x96,0x37,0x81,0x71,0xdf,0x71, + 0x8b,0x89,0x81,0xf4,0x95,0xb5,0x29,0x66,0x41,0x0c,0x73,0xd7,0x0b,0x21,0xb4,0xfb, + 0xf9,0x63,0x2f,0xe9,0x7b,0x38,0xaa,0x20,0xc3,0x96,0xcc,0xb7,0xb2,0x24,0xa1,0xe0, + 0x59,0x9c,0x10,0x9e,0x5a,0xf7,0xe3,0x02,0xe6,0x23,0xe2,0x44,0x21,0x3f,0x6e,0x5e, + 0x79,0xb2,0x93,0x7d,0xce,0xed,0xe2,0xe1,0xab,0x98,0x07,0xa7,0xbd,0xbc,0xd8,0xf7, + 0x06,0xeb,0xc5,0xa6,0x37,0x18,0x11,0x88,0xf7,0x63,0x39,0xb9,0x57,0x29,0xdc,0x03}}; +const TPM2B_RSA_TEST_VALUE c_RsassaKvt = {RSA_TEST_KEY_SIZE, { + 0x05,0x55,0x00,0x62,0x01,0xc6,0x04,0x31,0x55,0x73,0x3f,0x2a,0xf9,0xd4,0x0f,0xc1, + 0x2b,0xeb,0xd8,0xc8,0xdb,0xb2,0xab,0x6c,0x26,0xde,0x2d,0x89,0xc2,0x2d,0x36,0x62, + 0xc8,0x22,0x5d,0x58,0x03,0xb1,0x46,0x14,0xa5,0xd4,0xbc,0x25,0x6b,0x7f,0x8f,0x14, + 0x7e,0x03,0x2f,0x3d,0xb8,0x39,0xa5,0x79,0x13,0x7e,0x22,0x2a,0xb9,0x3e,0x8f,0xaa, + 0x01,0x7c,0x03,0x12,0x21,0x6c,0x2a,0xb4,0x39,0x98,0x6d,0xff,0x08,0x6c,0x59,0x2d, + 0xdc,0xc6,0xf1,0x77,0x62,0x10,0xa6,0xcc,0xe2,0x71,0x8e,0x97,0x00,0x87,0x5b,0x0e, + 0x20,0x00,0x3f,0x18,0x63,0x83,0xf0,0xe4,0x0a,0x64,0x8c,0xe9,0x8c,0x91,0xe7,0x89, + 0x04,0x64,0x2c,0x8b,0x41,0xc8,0xac,0xf6,0x5a,0x75,0xe6,0xa5,0x76,0x43,0xcb,0xa5, + 0x33,0x8b,0x07,0xc9,0x73,0x0f,0x45,0xa4,0xc3,0xac,0xc1,0xc3,0xe6,0xe7,0x21,0x66, + 0x1c,0xba,0xbf,0xea,0x3e,0x39,0xfa,0xb2,0xe2,0x8f,0xfe,0x9c,0xb4,0x85,0x89,0x33, + 0x2a,0x0c,0xc8,0x5d,0x58,0xe1,0x89,0x12,0xe9,0x4d,0x42,0xb3,0x1f,0x99,0x0c,0x3e, + 0xd8,0xb2,0xeb,0xf5,0x88,0xfb,0xe1,0x4b,0x8e,0xdc,0xd3,0xa8,0xda,0xbe,0x04,0x45, + 0xbf,0x56,0xc6,0x54,0x70,0x00,0xb8,0x66,0x46,0x3a,0xa3,0x1e,0xb6,0xeb,0x1a,0xa0, + 0x0b,0xd3,0x9a,0x9a,0x52,0xda,0x60,0x69,0xb7,0xef,0x93,0x47,0x38,0xab,0x1a,0xa0, + 0x22,0x6e,0x76,0x06,0xb6,0x74,0xaf,0x74,0x8f,0x51,0xc0,0x89,0x5a,0x4b,0xbe,0x6a, + 0x91,0x18,0x25,0x7d,0xa6,0x77,0xe6,0xfd,0xc2,0x62,0x36,0x07,0xc6,0xef,0x79,0xc9}}; +#endif // SHA512 + +#endif diff --git a/src/tpm2/RunCommand.c b/src/tpm2/RunCommand.c new file mode 100644 index 0000000..06465b7 --- /dev/null +++ b/src/tpm2/RunCommand.c @@ -0,0 +1,105 @@ +/********************************************************************************/ +/* */ +/* Platform specific entry and fail processing */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: RunCommand.c 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* C.11 RunCommand.c */ +/* C.11.1. Introduction */ +/* This module provides the platform specific entry and fail processing. The _plat__RunCommand() + function is used to call to ExecuteCommand() in the TPM code. This function does whatever + processing is necessary to set up the platform in anticipation of the call to the TPM including + setup for error processing. */ +/* The _plat__Fail() function is called when there is a failure in the TPM. The TPM code will have + set the flag to indicate that the TPM is in failure mode. This call will then recursively call + ExecuteCommand() in order to build the failure mode response. When ExecuteCommand() returns to + _plat__Fail(), the platform will do some platform specif operation to return to the environment + in which the TPM is executing. For a simulator, setjmp/longjmp is used. For an OS, a system exit + to the OS would be appropriate. */ +/* C.11.2. Includes and locals */ +#include "Platform.h" +#include +#include "ExecCommand_fp.h" +jmp_buf s_jumpBuffer; +/* C.11.3. Functions */ +/* C.11.3.1. _plat__RunCommand() */ +/* This version of RunCommand() will set up a jum_buf and call ExecuteCommand(). If the command + executes without failing, it will return and RunCommand() will return. If there is a failure in + the command, then _plat__Fail() is called and it will longjump back to RunCommand() which will + call ExecuteCommand() again. However, this time, the TPM will be in failure mode so + ExecuteCommand() will simply build a failure response and return. */ +LIB_EXPORT void +_plat__RunCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + uint32_t *responseSize, // IN/OUT: response buffer size + unsigned char **response // IN/OUT: response buffer + ) +{ + setjmp(s_jumpBuffer); + ExecuteCommand(requestSize, request, responseSize, response); +} +/* C.11.3.2. _plat__Fail() */ +/* This is the platform depended failure exit for the TPM. */ +LIB_EXPORT NORETURN void +_plat__Fail( + void + ) +{ + longjmp(&s_jumpBuffer[0], 1); +} diff --git a/src/tpm2/SelfTest.h b/src/tpm2/SelfTest.h new file mode 100644 index 0000000..1973721 --- /dev/null +++ b/src/tpm2/SelfTest.h @@ -0,0 +1,130 @@ +/********************************************************************************/ +/* */ +/* Structure definitions for the self-test */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SelfTest.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +#ifndef SELFTEST_H +#define SELFTEST_H + +/* 10.1.10 SelfTest.h */ +/* 10.1.10.1 Introduction */ + +/* This file contains the structure definitions for the self-test. It also contains macros for use + when the self-test is implemented. */ + +#define SELF_TEST_FAILURE FAIL(FATAL_ERROR_SELF_TEST) + +// Use the definition of key sizes to set algorithm values for key size. + +#define AES_ENTRIES (AES_128 + AES_192 + AES_256) +#define SM4_ENTRIES (SM4_128) +#define CAMELLIA_ENTRIES (CAMELLIA_128 + CAMELLIA_192 + CAMELLIA_256) +#define TDES_ENTRIES (TDES_128 * 2 + TDES_192 * 2) /* libtpms changed */ +#define NUM_SYMS (AES_ENTRIES + SM4_ENTRIES + CAMELLIA_ENTRIES + TDES_ENTRIES) +typedef UINT32 SYM_INDEX; + +/* These two defines deal with the fact that the TPM_ALG_ID table does not delimit the symmetric + mode values with a SYM_MODE_FIRST and SYM_MODE_LAST */ + +#define SYM_MODE_FIRST ALG_CTR_VALUE +#define SYM_MODE_LAST ALG_ECB_VALUE + +#define NUM_SYM_MODES (SYM_MODE_LAST - SYM_MODE_FIRST + 1) + +/* Define a type to hold a bit vector for the modes. */ +#if NUM_SYM_MODES <= 0 +#error "No symmetric modes implemented" +#elif NUM_SYM_MODES <= 8 +typedef BYTE SYM_MODES; +#elif NUM_SYM_MODES <= 16 +typedef UINT16 SYM_MODES; +#elif NUM_SYM_MODES <= 32 +typedef UINT32 SYM_MODES; +#else +#error "Too many symmetric modes" +#endif +typedef struct SYMMETRIC_TEST_VECTOR { + const TPM_ALG_ID alg; // the algorithm + const UINT16 keyBits; // bits in the key + const BYTE *key; // The test key + const UINT32 ivSize; // block size of the algorithm + const UINT32 dataInOutSize; // size to encrypt/decrypt + const BYTE *dataIn; // data to encrypt + const BYTE *dataOut[NUM_SYM_MODES];// data to decrypt +} SYMMETRIC_TEST_VECTOR; +#if ALG_SHA512 +# define DEFAULT_TEST_HASH ALG_SHA512_VALUE +# define DEFAULT_TEST_DIGEST_SIZE SHA512_DIGEST_SIZE +# define DEFAULT_TEST_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE +#elif ALG_SHA384 +# define DEFAULT_TEST_HASH ALG_SHA384_VALUE +# define DEFAULT_TEST_DIGEST_SIZE SHA384_DIGEST_SIZE +# define DEFAULT_TEST_HASH_BLOCK_SIZE SHA384_BLOCK_SIZE +#elif ALG_SHA256 +# define DEFAULT_TEST_HASH ALG_SHA256_VALUE +# define DEFAULT_TEST_DIGEST_SIZE SHA256_DIGEST_SIZE +# define DEFAULT_TEST_HASH_BLOCK_SIZE SHA256_BLOCK_SIZE +#elif ALG_SHA1 +# define DEFAULT_TEST_HASH ALG_SHA1_VALUE +# define DEFAULT_TEST_DIGEST_SIZE SHA1_DIGEST_SIZE +# define DEFAULT_TEST_HASH_BLOCK_SIZE SHA1_BLOCK_SIZE +#endif + + +#endif diff --git a/src/tpm2/SelfTest_fp.h b/src/tpm2/SelfTest_fp.h new file mode 100644 index 0000000..63ecb2c --- /dev/null +++ b/src/tpm2/SelfTest_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SelfTest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef SELFTEST_FP_H +#define SELFTEST_FP_H + +typedef struct{ + TPMI_YES_NO fullTest; +} SelfTest_In; + +#define RC_SelfTest_fullTest (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_SelfTest( + SelfTest_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/SequenceComplete_fp.h b/src/tpm2/SequenceComplete_fp.h new file mode 100644 index 0000000..efe5965 --- /dev/null +++ b/src/tpm2/SequenceComplete_fp.h @@ -0,0 +1,92 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SequenceComplete_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef SEQUENCECOMPLETE_FP_H +#define SEQUENCECOMPLETE_FP_H + +typedef struct { + TPMI_DH_OBJECT sequenceHandle; + TPM2B_MAX_BUFFER buffer; + TPMI_RH_HIERARCHY hierarchy; +} SequenceComplete_In; + +#define RC_SequenceComplete_sequenceHandle (TPM_RC_H + TPM_RC_1) +#define RC_SequenceComplete_buffer (TPM_RC_P + TPM_RC_1) +#define RC_SequenceComplete_hierarchy (TPM_RC_P + TPM_RC_2) + + +typedef struct { + TPM2B_DIGEST result; + TPMT_TK_HASHCHECK validation; +} SequenceComplete_Out; + + + +TPM_RC +TPM2_SequenceComplete( + SequenceComplete_In *in, // IN: input parameter list + SequenceComplete_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/SequenceUpdate_fp.h b/src/tpm2/SequenceUpdate_fp.h new file mode 100644 index 0000000..bedff79 --- /dev/null +++ b/src/tpm2/SequenceUpdate_fp.h @@ -0,0 +1,82 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SequenceUpdate_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef SEQUENCEUPDATE_FP_H +#define SEQUENCEUPDATE_FP_H + + +typedef struct { + TPMI_DH_OBJECT sequenceHandle; + TPM2B_MAX_BUFFER buffer; +} SequenceUpdate_In; + +#define RC_SequenceUpdate_sequenceHandle (TPM_RC_P + TPM_RC_1) +#define RC_SequenceUpdate_buffer (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_SequenceUpdate( + SequenceUpdate_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/Session.c b/src/tpm2/Session.c new file mode 100644 index 0000000..991a146 --- /dev/null +++ b/src/tpm2/Session.c @@ -0,0 +1,835 @@ +/********************************************************************************/ +/* */ +/* Manage the session context counter */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Session.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + + +/* 8.9.2 Includes, Defines, and Local Variables */ +#define SESSION_C +#include "Tpm.h" + +/* 8.9.3 File Scope Function -- ContextIdSetOldest() */ + +static void +ContextIdSetOldest( + void + ) +{ + CONTEXT_SLOT lowBits; + CONTEXT_SLOT entry; + CONTEXT_SLOT smallest = CONTEXT_SLOT_MASKED(~0); // libtpms changed + UINT32 i; + pAssert(s_ContextSlotMask == 0xff || s_ContextSlotMask == 0xffff); // libtpms added + // Set oldestSaveContext to a value indicating none assigned + s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; + lowBits = CONTEXT_SLOT_MASKED(gr.contextCounter); // libtpms changed + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + { + entry = gr.contextArray[i]; + // only look at entries that are saved contexts + if(entry > MAX_LOADED_SESSIONS) + { + // Use a less than or equal in case the oldest + // is brand new (= lowBits-1) and equal to our initial + // value for smallest. + if(CONTEXT_SLOT_MASKED(entry - lowBits) <= smallest) // libtpms changed + { + smallest = CONTEXT_SLOT_MASKED(entry - lowBits); // libtpms changed + s_oldestSavedSession = i; + } + } + } + // When we finish, either the s_oldestSavedSession still has its initial + // value, or it has the index of the oldest saved context. +} +/* 8.9.4 Startup Function -- SessionStartup() */ +/* This function initializes the session subsystem on TPM2_Startup(). */ +BOOL +SessionStartup( + STARTUP_TYPE type + ) +{ + UINT32 i; + // Initialize session slots. At startup, all the in-memory session slots + // are cleared and marked as not occupied + for(i = 0; i < MAX_LOADED_SESSIONS; i++) + s_sessions[i].occupied = FALSE; // session slot is not occupied + // The free session slots the number of maximum allowed loaded sessions + s_freeSessionSlots = MAX_LOADED_SESSIONS; + // Initialize context ID data. On a ST_SAVE or hibernate sequence, it will + // scan the saved array of session context counts, and clear any entry that + // references a session that was in memory during the state save since that + // memory was not preserved over the ST_SAVE. + if(type == SU_RESUME || type == SU_RESTART) + { + // On ST_SAVE we preserve the contexts that were saved but not the ones + // in memory + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + { + // If the array value is unused or references a loaded session then + // that loaded session context is lost and the array entry is + // reclaimed. + if(gr.contextArray[i] <= MAX_LOADED_SESSIONS) + gr.contextArray[i] = 0; + } + // Find the oldest session in context ID data and set it in + // s_oldestSavedSession + ContextIdSetOldest(); + } + else + { + // For STARTUP_CLEAR, clear out the contextArray + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + gr.contextArray[i] = 0; + // reset the context counter + gr.contextCounter = MAX_LOADED_SESSIONS + 1; + // Initialize oldest saved session + s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; + + // Initialize the context slot mask for UINT16 + s_ContextSlotMask = 0xffff; // libtpms added + } + return TRUE; +} +/* 8.9.5 Access Functions */ +/* 8.9.5.1 SessionIsLoaded() */ +/* This function test a session handle references a loaded session. The handle must have previously + been checked to make sure that it is a valid handle for an authorization session. */ +/* NOTE: A PWAP authorization does not have a session. */ +/* Return Values Meaning */ +/* TRUE if session is loaded */ +/* FALSE if it is not loaded */ +BOOL +SessionIsLoaded( + TPM_HANDLE handle // IN: session handle + ) +{ + pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION + || HandleGetType(handle) == TPM_HT_HMAC_SESSION); + handle = handle & HR_HANDLE_MASK; + // if out of range of possible active session, or not assigned to a loaded + // session return false + if(handle >= MAX_ACTIVE_SESSIONS + || gr.contextArray[handle] == 0 + || gr.contextArray[handle] > MAX_LOADED_SESSIONS) + return FALSE; + return TRUE; +} +/* 8.9.5.2 SessionIsSaved() */ +/* This function test a session handle references a saved session. The handle must have previously + been checked to make sure that it is a valid handle for an authorization session. */ +/* NOTE: A password authorization does not have a session. */ +/* This function requires that the handle be a valid session handle. */ +/* Return Values Meaning */ +/* TRUE if session is saved */ +/* FALSE if it is not saved */ +BOOL +SessionIsSaved( + TPM_HANDLE handle // IN: session handle + ) +{ + pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION + || HandleGetType(handle) == TPM_HT_HMAC_SESSION); + handle = handle & HR_HANDLE_MASK; + // if out of range of possible active session, or not assigned, or + // assigned to a loaded session, return false + if(handle >= MAX_ACTIVE_SESSIONS + || gr.contextArray[handle] == 0 + || gr.contextArray[handle] <= MAX_LOADED_SESSIONS + ) + return FALSE; + return TRUE; +} +/* 8.9.5.3 SequenceNumberForSavedContextIsValid() */ +BOOL +SequenceNumberForSavedContextIsValid( + TPMS_CONTEXT *context // IN: pointer to a context + // structure to be validated + ) +{ +#define MAX_CONTEXT_GAP ((UINT64)(CONTEXT_SLOT_MASKED(~0) + 1)) /* libtpms changed */ + pAssert(s_ContextSlotMask == 0xff || s_ContextSlotMask == 0xffff); // libtpms added + + TPM_HANDLE handle = context->savedHandle & HR_HANDLE_MASK; + if(// Handle must be with the range of active sessions + handle >= MAX_ACTIVE_SESSIONS + // the array entry must be for a saved context + || gr.contextArray[handle] <= MAX_LOADED_SESSIONS + // the array entry must agree with the sequence number + || gr.contextArray[handle] != CONTEXT_SLOT_MASKED(context->sequence) // libtpms changed + // the provided sequence number has to be less than the current counter + || context->sequence > gr.contextCounter + // but not so much that it could not be a valid sequence number + || gr.contextCounter - context->sequence > MAX_CONTEXT_GAP) + return FALSE; + return TRUE; +} +/* 8.9.5.4 SessionPCRValueIsCurrent() */ +/* This function is used to check if PCR values have been updated since the last time they were + checked in a policy session. */ +/* This function requires the session is loaded. */ +/* Return Values Meaning */ +/* TRUE if PCR value is current */ +/* FALSE if PCR value is not current */ +BOOL +SessionPCRValueIsCurrent( + SESSION *session // IN: session structure + ) +{ + if(session->pcrCounter != 0 + && session->pcrCounter != gr.pcrCounter + ) + return FALSE; + else + return TRUE; +} +/* 8.9.5.5 SessionGet() */ +/* This function returns a pointer to the session object associated with a session handle. */ +/* The function requires that the session is loaded. */ +SESSION * +SessionGet( + TPM_HANDLE handle // IN: session handle + ) +{ + size_t slotIndex; + CONTEXT_SLOT sessionIndex; + pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION + || HandleGetType(handle) == TPM_HT_HMAC_SESSION + ); + slotIndex = handle & HR_HANDLE_MASK; + pAssert(slotIndex < MAX_ACTIVE_SESSIONS); + // get the contents of the session array. Because session is loaded, we + // should always get a valid sessionIndex + sessionIndex = gr.contextArray[slotIndex] - 1; + pAssert(sessionIndex < MAX_LOADED_SESSIONS); + return &s_sessions[sessionIndex].session; +} +/* 8.9.6 Utility Functions */ +/* 8.9.6.1 ContextIdSessionCreate() */ +/* This function is called when a session is created. It will check to see if the current gap would + prevent a context from being saved. If so it will return TPM_RC_CONTEXT_GAP. Otherwise, it will + try to find an open slot in contextArray, set contextArray to the slot. This routine requires + that the caller has determined the session array index for the session. */ +/* TPM_RC_CONTEXT_GAP can't assign a new contextID until the oldest saved session context is + recycled */ +/* TPM_RC_SESSION_HANDLE there is no slot available in the context array for tracking of this + session context */ +static TPM_RC +ContextIdSessionCreate( + TPM_HANDLE *handle, /* OUT: receives the assigned handle. This will be + an index that must be adjusted by the caller + according to the type of the session created */ + UINT32 sessionIndex /* IN: The session context array entry that + will be occupied by the created session */ + ) +{ + pAssert(sessionIndex < MAX_LOADED_SESSIONS); + // check to see if creating the context is safe + // Is this going to be an assignment for the last session context + // array entry? If so, then there will be no room to recycle the + // oldest context if needed. If the gap is not at maximum, then + // it will be possible to save a context if it becomes necessary. + if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS + && s_freeSessionSlots == 1) + { + // See if the gap is at maximum + // The current value of the contextCounter will be assigned to the next + // saved context. If the value to be assigned would make the same as an + // existing context, then we can't use it because of the ambiguity it would + // create. + if(CONTEXT_SLOT_MASKED(gr.contextCounter) // libtpms changed + == gr.contextArray[s_oldestSavedSession]) + return TPM_RC_CONTEXT_GAP; + } + // Find an unoccupied entry in the contextArray + for(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++) + { + if(gr.contextArray[*handle] == 0) + { + // indicate that the session associated with this handle + // references a loaded session + gr.contextArray[*handle] = CONTEXT_SLOT_MASKED(sessionIndex + 1); // libtpms changed + return TPM_RC_SUCCESS; + } + } + return TPM_RC_SESSION_HANDLES; +} +/* 8.9.6.2 SessionCreate() */ +/* This function does the detailed work for starting an authorization session. This is done in a + support routine rather than in the action code because the session management may differ in + implementations. This implementation uses a fixed memory allocation to hold sessions and a fixed + allocation to hold the contextID for the saved contexts. */ +/* Error Returns Meaning */ +/* TPM_RC_CONTEXT_GAP need to recycle sessions */ +/* TPM_RC_SESSION_HANDLE active session space is full */ +/* TPM_RC_SESSION_MEMORY loaded session space is full */ +TPM_RC +SessionCreate( + TPM_SE sessionType, // IN: the session type + TPMI_ALG_HASH authHash, // IN: the hash algorithm + TPM2B_NONCE *nonceCaller, // IN: initial nonceCaller + TPMT_SYM_DEF *symmetric, // IN: the symmetric algorithm + TPMI_DH_ENTITY bind, // IN: the bind object + TPM2B_DATA *seed, // IN: seed data + TPM_HANDLE *sessionHandle, // OUT: the session handle + TPM2B_NONCE *nonceTpm // OUT: the session nonce + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + CONTEXT_SLOT slotIndex; + SESSION *session = NULL; + pAssert(sessionType == TPM_SE_HMAC + || sessionType == TPM_SE_POLICY + || sessionType == TPM_SE_TRIAL); + // If there are no open spots in the session array, then no point in searching + if(s_freeSessionSlots == 0) + return TPM_RC_SESSION_MEMORY; + // Find a space for loading a session + for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) + { + // Is this available? + if(s_sessions[slotIndex].occupied == FALSE) + { + session = &s_sessions[slotIndex].session; + break; + } + } + // if no spot found, then this is an internal error + if(slotIndex >= MAX_LOADED_SESSIONS) { // libtpms changed + FAIL(FATAL_ERROR_INTERNAL); + // should never get here due to longjmp in FAIL() libtpms added begin; cppcheck + return TPM_RC_FAILURE; + } // libtpms added end + // Call context ID function to get a handle. TPM_RC_SESSION_HANDLE may be + // returned from ContextIdHandelAssign() + result = ContextIdSessionCreate(sessionHandle, slotIndex); + if(result != TPM_RC_SUCCESS) + return result; + //*** Only return from this point on is TPM_RC_SUCCESS + // Can now indicate that the session array entry is occupied. + s_freeSessionSlots--; + s_sessions[slotIndex].occupied = TRUE; + // Initialize the session data + MemorySet(session, 0, sizeof(SESSION)); + // Initialize internal session data + session->authHashAlg = authHash; + // Initialize session type + if(sessionType == TPM_SE_HMAC) + { + *sessionHandle += HMAC_SESSION_FIRST; + } + else + { + *sessionHandle += POLICY_SESSION_FIRST; + // For TPM_SE_POLICY or TPM_SE_TRIAL + session->attributes.isPolicy = SET; + if(sessionType == TPM_SE_TRIAL) + session->attributes.isTrialPolicy = SET; + SessionSetStartTime(session); + // Initialize policyDigest. policyDigest is initialized with a string of 0 + // of session algorithm digest size. Since the session is already clear. + // Just need to set the size + session->u2.policyDigest.t.size = + CryptHashGetDigestSize(session->authHashAlg); + } + // Create initial session nonce + session->nonceTPM.t.size = nonceCaller->t.size; + CryptRandomGenerate(session->nonceTPM.t.size, session->nonceTPM.t.buffer); + MemoryCopy2B(&nonceTpm->b, &session->nonceTPM.b, + sizeof(nonceTpm->t.buffer)); + // Set up session parameter encryption algorithm + session->symmetric = *symmetric; + // If there is a bind object or a session secret, then need to compute + // a sessionKey. + if(bind != TPM_RH_NULL || seed->t.size != 0) + { + // sessionKey = KDFa(hash, (authValue || seed), "ATH", nonceTPM, + // nonceCaller, bits) + // The HMAC key for generating the sessionSecret can be the concatenation + // of an authorization value and a seed value + TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer))); + TPM2B_KEY key; + // Get hash size, which is also the length of sessionKey + session->sessionKey.t.size = CryptHashGetDigestSize(session->authHashAlg); + // Get authValue of associated entity + EntityGetAuthValue(bind, (TPM2B_AUTH *)&key); + pAssert(key.t.size + seed->t.size <= sizeof(key.t.buffer)); + // Concatenate authValue and seed + MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer)); + // Compute the session key + CryptKDFa(session->authHashAlg, &key.b, SESSION_KEY, &session->nonceTPM.b, + &nonceCaller->b, + session->sessionKey.t.size * 8, session->sessionKey.t.buffer, + NULL, FALSE); + } + // Copy the name of the entity that the HMAC session is bound to + // Policy session is not bound to an entity + if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC) + { + session->attributes.isBound = SET; + SessionComputeBoundEntity(bind, &session->u1.boundEntity); + } + // If there is a bind object and it is subject to DA, then use of this session + // is subject to DA regardless of how it is used. + session->attributes.isDaBound = (bind != TPM_RH_NULL) + && (IsDAExempted(bind) == FALSE); + // If the session is bound, then check to see if it is bound to lockoutAuth + session->attributes.isLockoutBound = (session->attributes.isDaBound == SET) + && (bind == TPM_RH_LOCKOUT); + return TPM_RC_SUCCESS; +} +/* 8.9.6.3 SessionContextSave() */ +/* This function is called when a session context is to be saved. The contextID of the saved + session is returned. If no contextID can be assigned, then the routine returns + TPM_RC_CONTEXT_GAP. If the function completes normally, the session slot will be freed. */ +/* This function requires that handle references a loaded session. Otherwise, it should not be + called at the first place. */ +/* Error Returns Meaning */ +/* TPM_RC_CONTEXT_GAP a contextID could not be assigned. */ +/* TPM_RC_TOO_MANY_CONTEXTS the counter maxed out */ +TPM_RC +SessionContextSave( + TPM_HANDLE handle, // IN: session handle + CONTEXT_COUNTER *contextID // OUT: assigned contextID + ) +{ + UINT32 contextIndex; + CONTEXT_SLOT slotIndex; + pAssert(SessionIsLoaded(handle)); + pAssert(s_ContextSlotMask == 0xff || s_ContextSlotMask == 0xffff); // libtpms added + // check to see if the gap is already maxed out + // Need to have a saved session + if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS + // if the oldest saved session has the same value as the low bits + // of the contextCounter, then the GAP is maxed out. + && gr.contextArray[s_oldestSavedSession] == CONTEXT_SLOT_MASKED(gr.contextCounter)) // libtpms changed + return TPM_RC_CONTEXT_GAP; + // if the caller wants the context counter, set it + if(contextID != NULL) + *contextID = gr.contextCounter; + contextIndex = handle & HR_HANDLE_MASK; + pAssert(contextIndex < MAX_ACTIVE_SESSIONS); + // Extract the session slot number referenced by the contextArray + // because we are going to overwrite this with the low order + // contextID value. + slotIndex = gr.contextArray[contextIndex] - 1; + // Set the contextID for the contextArray + gr.contextArray[contextIndex] = CONTEXT_SLOT_MASKED(gr.contextCounter); // libtpms changed + // Increment the counter + gr.contextCounter++; + // In the unlikely event that the 64-bit context counter rolls over... + if(gr.contextCounter == 0) + { + // back it up + gr.contextCounter--; + // return an error + return TPM_RC_TOO_MANY_CONTEXTS; + } + // if the low-order bits wrapped, need to advance the value to skip over + // the values used to indicate that a session is loaded + if(CONTEXT_SLOT_MASKED(gr.contextCounter) == 0) // libtpms changed + gr.contextCounter += MAX_LOADED_SESSIONS + 1; + // If no other sessions are saved, this is now the oldest. + if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS) + s_oldestSavedSession = contextIndex; + // Mark the session slot as unoccupied + s_sessions[slotIndex].occupied = FALSE; + // and indicate that there is an additional open slot + s_freeSessionSlots++; + return TPM_RC_SUCCESS; +} +/* 8.9.6.4 SessionContextLoad() */ +/* This function is used to load a session from saved context. The session handle must be for a + saved context. */ +/* If the gap is at a maximum, then the only session that can be loaded is the oldest session, + otherwise TPM_RC_CONTEXT_GAP is returned. */ +/* This function requires that handle references a valid saved session. */ +/* Error Returns Meaning */ +/* TPM_RC_SESSION_MEMORY no free session slots */ +/* TPM_RC_CONTEXT_GAP the gap count is maximum and this is not the oldest saved context */ +TPM_RC +SessionContextLoad( + SESSION_BUF *session, // IN: session structure from saved context + TPM_HANDLE *handle // IN/OUT: session handle + ) +{ + UINT32 contextIndex; + CONTEXT_SLOT slotIndex; + pAssert(s_ContextSlotMask == 0xff || s_ContextSlotMask == 0xffff); // libtpms added + pAssert(HandleGetType(*handle) == TPM_HT_POLICY_SESSION + || HandleGetType(*handle) == TPM_HT_HMAC_SESSION); + // Don't bother looking if no openings + if(s_freeSessionSlots == 0) + return TPM_RC_SESSION_MEMORY; + // Find a free session slot to load the session + for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) + if(s_sessions[slotIndex].occupied == FALSE) break; + // if no spot found, then this is an internal error + pAssert(slotIndex < MAX_LOADED_SESSIONS); + // libtpms: besides the s_freeSessionSlots guard add another array index guard + if (slotIndex >= MAX_LOADED_SESSIONS) { // libtpms added begin; cppcheck + FAIL(FATAL_ERROR_INTERNAL); + // should never get here due to longjmp in FAIL() + return TPM_RC_FAILURE; + } // libtpms added end + contextIndex = *handle & HR_HANDLE_MASK; // extract the index + // If there is only one slot left, and the gap is at maximum, the only session + // context that we can safely load is the oldest one. + if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS + && s_freeSessionSlots == 1 + && CONTEXT_SLOT_MASKED(gr.contextCounter) == gr.contextArray[s_oldestSavedSession] // libtpms changed + && contextIndex != s_oldestSavedSession) + return TPM_RC_CONTEXT_GAP; + pAssert(contextIndex < MAX_ACTIVE_SESSIONS); + // set the contextArray value to point to the session slot where + // the context is loaded + gr.contextArray[contextIndex] = slotIndex + 1; + // if this was the oldest context, find the new oldest + if(contextIndex == s_oldestSavedSession) + ContextIdSetOldest(); + // Copy session data to session slot + MemoryCopy(&s_sessions[slotIndex].session, session, sizeof(SESSION)); + // Set session slot as occupied + s_sessions[slotIndex].occupied = TRUE; + // Reduce the number of open spots + s_freeSessionSlots--; + return TPM_RC_SUCCESS; +} +/* 8.9.6.5 SessionFlush() */ +/* This function is used to flush a session referenced by its handle. If the session associated + with handle is loaded, the session array entry is marked as available. */ +/* This function requires that handle be a valid active session. */ +void +SessionFlush( + TPM_HANDLE handle // IN: loaded or saved session handle + ) +{ + CONTEXT_SLOT slotIndex; + UINT32 contextIndex; // Index into contextArray + pAssert((HandleGetType(handle) == TPM_HT_POLICY_SESSION + || HandleGetType(handle) == TPM_HT_HMAC_SESSION + ) + && (SessionIsLoaded(handle) || SessionIsSaved(handle)) + ); + // Flush context ID of this session + // Convert handle to an index into the contextArray + contextIndex = handle & HR_HANDLE_MASK; + pAssert(contextIndex < sizeof(gr.contextArray) / sizeof(gr.contextArray[0])); + // Get the current contents of the array + slotIndex = gr.contextArray[contextIndex]; + // Mark context array entry as available + gr.contextArray[contextIndex] = 0; + // Is this a saved session being flushed + if(slotIndex > MAX_LOADED_SESSIONS) + { + // Flushing the oldest session? + if(contextIndex == s_oldestSavedSession) + // If so, find a new value for oldest. + ContextIdSetOldest(); + } + else + { + // Adjust slot index to point to session array index + slotIndex -= 1; + // Free session array index + s_sessions[slotIndex].occupied = FALSE; + s_freeSessionSlots++; + } + return; +} +/* 8.9.6.6 SessionComputeBoundEntity() */ +/* This function computes the binding value for a session. The binding value for a reserved handle + is the handle itself. For all the other entities, the authValue at the time of binding is + included to prevent squatting. For those values, the Name and the authValue are concatenated into + the bind buffer. If they will not both fit, the will be overlapped by XORing() bytes. If XOR is + required, the bind value will be full. */ +void +SessionComputeBoundEntity( + TPMI_DH_ENTITY entityHandle, // IN: handle of entity + TPM2B_NAME *bind // OUT: binding value + ) +{ + TPM2B_AUTH auth; + BYTE *pAuth = auth.t.buffer; + UINT16 i; + // Get name + EntityGetName(entityHandle, bind); + // // The bound value of a reserved handle is the handle itself + // if(bind->t.size == sizeof(TPM_HANDLE)) return; + // For all the other entities, concatenate the authorization value to the name. + // Get a local copy of the authorization value because some overlapping + // may be necessary. + EntityGetAuthValue(entityHandle, &auth); + // Make sure that the extra space is zeroed + MemorySet(&bind->t.name[bind->t.size], 0, sizeof(bind->t.name) - bind->t.size); + // XOR the authValue at the end of the name + for(i = sizeof(bind->t.name) - auth.t.size; i < sizeof(bind->t.name); i++) + bind->t.name[i] ^= *pAuth++; + // Set the bind value to the maximum size + bind->t.size = sizeof(bind->t.name); + return; +} +/* 8.9.6.7 SessionSetStartTime() */ +/* This function is used to initialize the session timing */ +void +SessionSetStartTime( + SESSION *session // IN: the session to update + ) +{ + session->startTime = g_time; + session->epoch = g_timeEpoch; + session->timeout = 0; +} +/* 8.9.6.8 SessionResetPolicyData() */ +/* This function is used to reset the policy data without changing the nonce or the start time of + the session. */ +void +SessionResetPolicyData( + SESSION *session // IN: the session to reset + ) +{ + SESSION_ATTRIBUTES oldAttributes; + pAssert(session != NULL); + // Will need later + oldAttributes = session->attributes; + // No command + session->commandCode = 0; + // No locality selected + MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality)); + // The cpHash size to zero + session->u1.cpHash.b.size = 0; + // No timeout + session->timeout = 0; + // Reset the pcrCounter + session->pcrCounter = 0; + // Reset the policy hash + MemorySet(&session->u2.policyDigest.t.buffer, 0, + session->u2.policyDigest.t.size); + // Reset the session attributes + MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES)); + // Restore the policy attributes + session->attributes.isPolicy = SET; + session->attributes.isTrialPolicy = oldAttributes.isTrialPolicy; + // Restore the bind attributes + session->attributes.isDaBound = oldAttributes.isDaBound; + session->attributes.isLockoutBound = oldAttributes.isLockoutBound; +} +/* 8.9.6.9 SessionCapGetLoaded() */ +/* This function returns a list of handles of loaded session, started from input handle */ +/* Handle must be in valid loaded session handle range, but does not have to point to a loaded + session. */ +/* Return Values Meaning */ +/* YES if there are more handles available */ +/* NO all the available handles has been returned */ +TPMI_YES_NO +SessionCapGetLoaded( + TPMI_SH_POLICY handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ) +{ + TPMI_YES_NO more = NO; + UINT32 i; + pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION); + // Initialize output handle list + handleList->count = 0; + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; + // Iterate session context ID slots to get loaded session handles + for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) + { + // If session is active + if(gr.contextArray[i] != 0) + { + // If session is loaded + if(gr.contextArray[i] <= MAX_LOADED_SESSIONS) + { + if(handleList->count < count) + { + SESSION *session; + // If we have not filled up the return list, add this + // session handle to it + // assume that this is going to be an HMAC session + handle = i + HMAC_SESSION_FIRST; + session = SessionGet(handle); + if(session->attributes.isPolicy) + handle = i + POLICY_SESSION_FIRST; + handleList->handle[handleList->count] = handle; + handleList->count++; + } + else + { + // If the return list is full but we still have loaded object + // available, report this and stop iterating + more = YES; + break; + } + } + } + } + return more; +} +/* 8.9.6.10 SessionCapGetSaved() */ +/* This function returns a list of handles for saved session, starting at handle. */ +/* Handle must be in a valid handle range, but does not have to point to a saved session */ +/* Return Values Meaning */ +/* YES if there are more handles available */ +/* NO all the available handles has been returned */ +TPMI_YES_NO +SessionCapGetSaved( + TPMI_SH_HMAC handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ) +{ + TPMI_YES_NO more = NO; + UINT32 i; +#ifdef TPM_HT_SAVED_SESSION + pAssert(HandleGetType(handle) == TPM_HT_SAVED_SESSION); +#else + pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION); +#endif + // Initialize output handle list + handleList->count = 0; + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; + // Iterate session context ID slots to get loaded session handles + for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) + { + // If session is active + if(gr.contextArray[i] != 0) + { + // If session is saved + if(gr.contextArray[i] > MAX_LOADED_SESSIONS) + { + if(handleList->count < count) + { + // If we have not filled up the return list, add this + // session handle to it + handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST; + handleList->count++; + } + else + { + // If the return list is full but we still have loaded object + // available, report this and stop iterating + more = YES; + break; + } + } + } + } + return more; +} +/* 8.9.6.11 SessionCapGetLoadedNumber() */ +/* This function return the number of authorization sessions currently loaded into TPM RAM. */ +UINT32 +SessionCapGetLoadedNumber( + void + ) +{ + return MAX_LOADED_SESSIONS - s_freeSessionSlots; +} +/* 8.9.6.12 SessionCapGetLoadedAvail() */ +/* This function returns the number of additional authorization sessions, of any type, that could be + loaded into TPM RAM. */ +/* NOTE: In other implementations, this number may just be an estimate. The only requirement for the + estimate is, if it is one or more, then at least one session must be loadable. */ +UINT32 +SessionCapGetLoadedAvail( + void + ) +{ + return s_freeSessionSlots; +} +/* 8.9.6.13 SessionCapGetActiveNumber() */ +/* This function returns the number of active authorization sessions currently being tracked by the + TPM. */ +UINT32 +SessionCapGetActiveNumber( + void + ) +{ + UINT32 i; + UINT32 num = 0; + // Iterate the context array to find the number of non-zero slots + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + { + if(gr.contextArray[i] != 0) num++; + } + return num; +} +/* 8.9.6.14 SessionCapGetActiveAvail() */ +/* This function returns the number of additional authorization sessions, of any type, that could be + created. This not the number of slots for sessions, but the number of additional sessions that + the TPM is capable of tracking. */ +UINT32 +SessionCapGetActiveAvail( + void + ) +{ + UINT32 i; + UINT32 num = 0; + // Iterate the context array to find the number of zero slots + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + { + if(gr.contextArray[i] == 0) num++; + } + return num; +} diff --git a/src/tpm2/SessionCommands.c b/src/tpm2/SessionCommands.c new file mode 100644 index 0000000..d2f3f96 --- /dev/null +++ b/src/tpm2/SessionCommands.c @@ -0,0 +1,175 @@ +/********************************************************************************/ +/* */ +/* Session Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SessionCommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "StartAuthSession_fp.h" +#if CC_StartAuthSession // Conditional expansion of this file +TPM_RC +TPM2_StartAuthSession( + StartAuthSession_In *in, // IN: input parameter buffer + StartAuthSession_Out *out // OUT: output parameter buffer + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT *tpmKey; // TPM key for decrypt salt + TPM2B_DATA salt; + // Input Validation + // Check input nonce size. IT should be at least 16 bytes but not larger + // than the digest size of session hash. + if(in->nonceCaller.t.size < 16 + || in->nonceCaller.t.size > CryptHashGetDigestSize(in->authHash)) + return TPM_RCS_SIZE + RC_StartAuthSession_nonceCaller; + // If an decrypt key is passed in, check its validation + if(in->tpmKey != TPM_RH_NULL) + { + // Get pointer to loaded decrypt key + tpmKey = HandleToObject(in->tpmKey); + // key must be asymmetric with its sensitive area loaded. Since this + // command does not require authorization, the presence of the sensitive + // area was not already checked as it is with most other commands that + // use the sensitive are so check it here + if(!CryptIsAsymAlgorithm(tpmKey->publicArea.type)) + return TPM_RCS_KEY + RC_StartAuthSession_tpmKey; + // secret size cannot be 0 + if(in->encryptedSalt.t.size == 0) + return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; + // Decrypting salt requires accessing the private portion of a key. + // Therefore, tmpKey can not be a key with only public portion loaded + if(tpmKey->attributes.publicOnly) + return TPM_RCS_HANDLE + RC_StartAuthSession_tpmKey; + // HMAC session input handle check. + // tpmKey should be a decryption key + if(!IS_ATTRIBUTE(tpmKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_StartAuthSession_tpmKey; + // Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors + // may be returned at this point + result = CryptSecretDecrypt(tpmKey, &in->nonceCaller, SECRET_KEY, + &in->encryptedSalt, &salt); + if(result != TPM_RC_SUCCESS) + return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; + } + else + { + // secret size must be 0 + if(in->encryptedSalt.t.size != 0) + return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; + salt.t.size = 0; + } + switch(HandleGetType(in->bind)) + { + case TPM_HT_TRANSIENT: + { + OBJECT *object = HandleToObject(in->bind); + // If the bind handle references a transient object, make sure that we + // can get to the authorization value. Also, make sure that the object + // has a proper Name (nameAlg != TPM_ALG_NULL). If it doesn't, then + // it might be possible to bind to an object where the authValue is + // known. This does not create a real issue in that, if you know the + // authorization value, you can actually bind to the object. However, + // there is a potential + if(object->attributes.publicOnly == SET) + return TPM_RCS_HANDLE + RC_StartAuthSession_bind; + break; + } + case TPM_HT_NV_INDEX: + // a PIN index can't be a bind object + { + NV_INDEX *nvIndex = NvGetIndexInfo(in->bind, NULL); + if(IsNvPinPassIndex(nvIndex->publicArea.attributes) + || IsNvPinFailIndex(nvIndex->publicArea.attributes)) + return TPM_RCS_HANDLE + RC_StartAuthSession_bind; + break; + } + default: + break; + } + // If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR) + // then the mode must be CFB. + if(in->symmetric.algorithm != TPM_ALG_NULL + && in->symmetric.algorithm != TPM_ALG_XOR + && in->symmetric.mode.sym != TPM_ALG_CFB) + return TPM_RCS_MODE + RC_StartAuthSession_symmetric; + // Internal Data Update and command output + // Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES + // or TPM_RC_SESSION_MEMORY errors may be returned at this point. + // + // The detailed actions for creating the session context are not shown here + // as the details are implementation dependent + // SessionCreate sets the output handle and nonceTPM + result = SessionCreate(in->sessionType, in->authHash, &in->nonceCaller, + &in->symmetric, in->bind, &salt, &out->sessionHandle, + &out->nonceTPM); + return result; +} +#endif // CC_StartAuthSession +#include "Tpm.h" +#include "PolicyRestart_fp.h" +#if CC_PolicyRestart // Conditional expansion of this file +TPM_RC +TPM2_PolicyRestart( + PolicyRestart_In *in // IN: input parameter list + ) +{ + // Initialize policy session data + SessionResetPolicyData(SessionGet(in->sessionHandle)); + return TPM_RC_SUCCESS; +} +#endif // CC_PolicyRestart diff --git a/src/tpm2/SessionProcess.c b/src/tpm2/SessionProcess.c new file mode 100644 index 0000000..f8efc68 --- /dev/null +++ b/src/tpm2/SessionProcess.c @@ -0,0 +1,1990 @@ +/********************************************************************************/ +/* */ +/* Process the Authorization Sessions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SessionProcess.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 6.4 SessionProcess.c */ +/* 6.4.1 Introduction */ +/* This file contains the subsystem that process the authorization sessions including implementation + of the Dictionary Attack logic. ExecCommand() uses ParseSessionBuffer() to process the + authorization session area of a command and BuildResponseSession() to create the authorization + session area of a response */ +#define SESSION_PROCESS_C +#include "Tpm.h" +#include "ACT.h" +/* 6.4.3.1 IsDAExempted() */ +/* This function indicates if a handle is exempted from DA logic. A handle is exempted if it is */ +/* a) a primary seed handle, */ +/* b) an object with noDA bit SET, */ +/* c) an NV Index with TPMA_NV_NO_DA bit SET, or */ +/* d) a PCR handle. */ +BOOL +IsDAExempted( + TPM_HANDLE handle // IN: entity handle + ) +{ + BOOL result = FALSE; + // + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + // All permanent handles, other than TPM_RH_LOCKOUT, are exempt from + // DA protection. + result = (handle != TPM_RH_LOCKOUT); + break; + // When this function is called, a persistent object will have been loaded + // into an object slot and assigned a transient handle. + case TPM_HT_TRANSIENT: + { + TPMA_OBJECT attributes = ObjectGetPublicAttributes(handle); + result = IS_ATTRIBUTE(attributes, TPMA_OBJECT, noDA); + break; + } + case TPM_HT_NV_INDEX: + { + NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); + result = IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, NO_DA); + break; + } + case TPM_HT_PCR: + // PCRs are always exempted from DA. + result = TRUE; + break; + default: + break; + } + return result; +} +/* 6.4.3.2 IncrementLockout() */ +/* This function is called after an authorization failure that involves use of an authValue. If the + entity referenced by the handle is not exempt from DA protection, then the failedTries counter + will be incremented. */ +static TPM_RC +IncrementLockout( + UINT32 sessionIndex + ) +{ + TPM_HANDLE handle = s_associatedHandles[sessionIndex]; + TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; + SESSION *session = NULL; + // + // Don't increment lockout unless the handle associated with the session + // is DA protected or the session is bound to a DA protected entity. + if(sessionHandle == TPM_RS_PW) + { + if(IsDAExempted(handle)) + return TPM_RC_BAD_AUTH; + } + else + { + session = SessionGet(sessionHandle); + // If the session is bound to lockout, then use that as the relevant + // handle. This means that an authorization failure with a bound session + // bound to lockoutAuth will take precedence over any other + // lockout check + if(session->attributes.isLockoutBound == SET) + handle = TPM_RH_LOCKOUT; + if(session->attributes.isDaBound == CLEAR + && (IsDAExempted(handle) || session->attributes.includeAuth == CLEAR)) + // If the handle was changed to TPM_RH_LOCKOUT, this will not return + // TPM_RC_BAD_AUTH + return TPM_RC_BAD_AUTH; + } + if(handle == TPM_RH_LOCKOUT) + { + pAssert(gp.lockOutAuthEnabled == TRUE); + // lockout is no longer enabled + gp.lockOutAuthEnabled = FALSE; + // For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since + // the lockout authorization will be reset at startup. + if(gp.lockoutRecovery != 0) + { + if(NV_IS_AVAILABLE) + // Update NV. + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + else + // No NV access for now. Put the TPM in pending mode. + s_DAPendingOnNV = TRUE; + } + } + else + { + if(gp.recoveryTime != 0) + { + gp.failedTries++; + if(NV_IS_AVAILABLE) + // Record changes to NV. NvWrite will SET g_updateNV + NV_SYNC_PERSISTENT(failedTries); + else + // No NV access for now. Put the TPM in pending mode. + s_DAPendingOnNV = TRUE; + } + } + // Register a DA failure and reset the timers. + DARegisterFailure(handle); + return TPM_RC_AUTH_FAIL; +} +/* 6.4.3.3 IsSessionBindEntity() */ +/* This function indicates if the entity associated with the handle is the entity, to which this + session is bound. The binding would occur by making the bind parameter in TPM2_StartAuthSession() + not equal to TPM_RH_NULL. The binding only occurs if the session is an HMAC session. The bind + value is a combination of the Name and the authValue of the entity. */ +static BOOL +IsSessionBindEntity( + TPM_HANDLE associatedHandle, // IN: handle to be authorized + SESSION *session // IN: associated session + ) +{ + TPM2B_NAME entity; // The bind value for the entity + // If the session is not bound, return FALSE. + if(session->attributes.isBound) + { + // Compute the bind value for the entity. + SessionComputeBoundEntity(associatedHandle, &entity); + // Compare to the bind value in the session. + return MemoryEqual2B(&entity.b, &session->u1.boundEntity.b); + } + return FALSE; +} +/* 6.4.3.4 IsPolicySessionRequired() */ +/* Checks if a policy session is required for a command. If a command requires DUP or ADMIN role + authorization, then the handle that requires that role is the first handle in the command. This + simplifies this checking. If a new command is created that requires multiple ADMIN role + authorizations, then it will have to be special-cased in this function. A policy session is + required if: */ +/* a) the command requires the DUP role, */ +/* b) the command requires the ADMIN role and the authorized entity is an object and its + adminWithPolicy bit is SET, or */ +/* c) the command requires the ADMIN role and the authorized entity is a permanent handle or an NV + Index. */ +/* d) The authorized entity is a PCR belonging to a policy group, and has its policy initialized */ +/* Return Values Meaning */ +/* TRUE policy session is required */ +/* FALSE policy session is not required */ +static BOOL +IsPolicySessionRequired( + COMMAND_INDEX commandIndex, // IN: command index + UINT32 sessionIndex // IN: session index + ) +{ + AUTH_ROLE role = CommandAuthRole(commandIndex, sessionIndex); + TPM_HT type = HandleGetType(s_associatedHandles[sessionIndex]); + if(role == AUTH_DUP) + return TRUE; + if(role == AUTH_ADMIN) + { + // We allow an exception for ADMIN role in a transient object. If the object + // allows ADMIN role actions with authorization, then policy is not + // required. For all other cases, there is no way to override the command + // requirement that a policy be used + if(type == TPM_HT_TRANSIENT) + { + OBJECT *object = HandleToObject(s_associatedHandles[sessionIndex]); + if(!IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, + adminWithPolicy)) + return FALSE; + } + return TRUE; + } + if(type == TPM_HT_PCR) + { + if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex])) + { + TPM2B_DIGEST policy; + TPMI_ALG_HASH policyAlg; + policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex], + &policy); + if(policyAlg != TPM_ALG_NULL) + return TRUE; + } + } + return FALSE; +} +/* 6.4.3.5 IsAuthValueAvailable() */ +/* This function indicates if authValue is available and allowed for USER role authorization of an + entity. */ +/* This function is similar to IsAuthPolicyAvailable() except that it does not check the size of the + authValue as IsAuthPolicyAvailable() does (a null authValue is a valid authorization, but a null + policy is not a valid policy). */ +/* This function does not check that the handle reference is valid or if the entity is in an + enabled hierarchy. Those checks are assumed to have been performed during the handle + unmarshaling. */ +static BOOL +IsAuthValueAvailable( + TPM_HANDLE handle, // IN: handle of entity + COMMAND_INDEX commandIndex, // IN: command index + UINT32 sessionIndex // IN: session index + ) +{ + BOOL result = FALSE; + // + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + switch(handle) + { + // At this point hierarchy availability has already been + // checked so primary seed handles are always available here + case TPM_RH_OWNER: + case TPM_RH_ENDORSEMENT: + case TPM_RH_PLATFORM: +#ifdef VENDOR_PERMANENT + // This vendor defined handle associated with the + // manufacturer's shared secret + case VENDOR_PERMANENT: +#endif + // The DA checking has been performed on LockoutAuth but we + // bypass the DA logic if we are using lockout policy. The + // policy would allow execution to continue an lockoutAuth + // could be used, even if direct use of lockoutAuth is disabled + case TPM_RH_LOCKOUT: + // NullAuth is always available. + case TPM_RH_NULL: + result = TRUE; + break; +#ifndef __ACT_DISABLED // libtpms added begin + FOR_EACH_ACT(CASE_ACT_HANDLE) + { + // The ACT auth value is not available if the platform is disabled + result = g_phEnable == SET; + break; + } +#endif // libtpms added end + default: + // Otherwise authValue is not available. + break; + } + break; + case TPM_HT_TRANSIENT: + // A persistent object has already been loaded and the internal + // handle changed. + { + OBJECT *object; + TPMA_OBJECT attributes; + // + object = HandleToObject(handle); + attributes = object->publicArea.objectAttributes; + // authValue is always available for a sequence object. + // An alternative for this is to + // SET_ATTRIBUTE(object->publicArea, TPMA_OBJECT, userWithAuth) when the + // sequence is started. + if(ObjectIsSequence(object)) + { + result = TRUE; + break; + } + // authValue is available for an object if it has its sensitive + // portion loaded and + // 1. userWithAuth bit is SET, or + // 2. ADMIN role is required + if(object->attributes.publicOnly == CLEAR + && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, userWithAuth) + || (CommandAuthRole(commandIndex, sessionIndex) == AUTH_ADMIN + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, adminWithPolicy)))) + result = TRUE; + } + break; + case TPM_HT_NV_INDEX: + // NV Index. + { + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(handle, &locator); + TPMA_NV nvAttributes; + // + pAssert(nvIndex != 0); + nvAttributes = nvIndex->publicArea.attributes; + if(IsWriteOperation(commandIndex)) + { + // AuthWrite can't be set for a PIN index + if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHWRITE)) + result = TRUE; + } + else + { + // A "read" operation + // For a PIN Index, the authValue is available as long as the + // Index has been written and the pinCount is less than pinLimit + if(IsNvPinFailIndex(nvAttributes) + || IsNvPinPassIndex(nvAttributes)) + { + NV_PIN pin; + if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)) + break; // return false + // get the index values + pin.intVal = NvGetUINT64Data(nvIndex, locator); + if(pin.pin.pinCount < pin.pin.pinLimit) + result = TRUE; + } + // For non-PIN Indexes, need to allow use of the authValue + else if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHREAD)) + result = TRUE; + } + } + break; + case TPM_HT_PCR: + // PCR handle. + // authValue is always allowed for PCR + result = TRUE; + break; + default: + // Otherwise, authValue is not available + break; + } + return result; +} + +/* 6.4.3.6 IsAuthPolicyAvailable() */ +/* This function indicates if an authPolicy is available and allowed. */ +/* This function does not check that the handle reference is valid or if the entity is in an enabled + hierarchy. Those checks are assumed to have been performed during the handle unmarshaling. */ +/* Return Values Meaning */ +/* TRUE authPolicy is available */ +/* FALSE authPolicy is not available */ +static BOOL +IsAuthPolicyAvailable( + TPM_HANDLE handle, // IN: handle of entity + COMMAND_INDEX commandIndex, // IN: command index + UINT32 sessionIndex // IN: session index + ) +{ + BOOL result = FALSE; + // + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + switch(handle) + { + // At this point hierarchy availability has already been checked. + case TPM_RH_OWNER: + if(gp.ownerPolicy.t.size != 0) + result = TRUE; + break; + case TPM_RH_ENDORSEMENT: + if(gp.endorsementPolicy.t.size != 0) + result = TRUE; + break; + case TPM_RH_PLATFORM: + if(gc.platformPolicy.t.size != 0) + result = TRUE; + break; +#define ACT_GET_POLICY(N) \ + case TPM_RH_ACT_##N: \ + if(go.ACT_##N.authPolicy.t.size != 0) \ + result = TRUE; \ + break; + + FOR_EACH_ACT(ACT_GET_POLICY) + + case TPM_RH_LOCKOUT: + if(gp.lockoutPolicy.t.size != 0) + result = TRUE; + break; + default: + break; + } + break; + case TPM_HT_TRANSIENT: + { + // Object handle. + // An evict object would already have been loaded and given a + // transient object handle by this point. + OBJECT *object = HandleToObject(handle); + // Policy authorization is not available for an object with only + // public portion loaded. + if(object->attributes.publicOnly == CLEAR) + { + // Policy authorization is always available for an object but + // is never available for a sequence. + if(!ObjectIsSequence(object)) + result = TRUE; + } + break; + } + case TPM_HT_NV_INDEX: + // An NV Index. + { + NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); + TPMA_NV nvAttributes = nvIndex->publicArea.attributes; + // + // If the policy size is not zero, check if policy can be used. + if(nvIndex->publicArea.authPolicy.t.size != 0) + { + // If policy session is required for this handle, always + // uses policy regardless of the attributes bit setting + if(IsPolicySessionRequired(commandIndex, sessionIndex)) + result = TRUE; + // Otherwise, the presence of the policy depends on the NV + // attributes. + else if(IsWriteOperation(commandIndex)) + { + if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYWRITE)) + result = TRUE; + } + else + { + if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYREAD)) + result = TRUE; + } + } + } + break; + case TPM_HT_PCR: + // PCR handle. + if(PCRPolicyIsAvailable(handle)) + result = TRUE; + break; + default: + break; + } + return result; +} +/* 6.4.4 Session Parsing Functions */ +/* 6.4.4.1 ClearCpRpHashes() */ + +void +ClearCpRpHashes( + COMMAND *command + ) +{ + // The macros expand according to the implemented hash algorithms. An IDE may + // complain that COMMAND does not contain SHA1CpHash or SHA1RpHash because of the + // complexity of the macro expansion where the data space is defined; but, if SHA1 + // is implemented, it actually does and the compiler is happy. +#define CLEAR_CP_HASH(HASH, Hash) command->Hash##CpHash.b.size = 0; + FOR_EACH_HASH(CLEAR_CP_HASH) +#define CLEAR_RP_HASH(HASH, Hash) command->Hash##RpHash.b.size = 0; + FOR_EACH_HASH(CLEAR_RP_HASH) +} + +/* 6.4.4.2 GetCpHashPointer() */ +/* Function to get a pointer to the cpHash of the command */ +static TPM2B_DIGEST * +GetCpHashPointer( + COMMAND *command, + TPMI_ALG_HASH hashAlg + ) +{ + TPM2B_DIGEST *retVal; + // + // Define the macro that will expand for each implemented algorithm in the switch + // statement below. +#define GET_CP_HASH_POINTER(HASH, Hash) \ + case ALG_##HASH##_VALUE: \ + retVal = (TPM2B_DIGEST *)&command->Hash##CpHash; \ + break; + + switch(hashAlg) + { + // For each implemented hash, this will expand as defined above + // by GET_CP_HASH_POINTER. Your IDE may complain that + // 'struct "COMMAND" has no field "SHA1CpHash"' but the compiler says + // it does, so... + FOR_EACH_HASH(GET_CP_HASH_POINTER) + default: + retVal = NULL; + break; + } + return retVal; +} + +/* 6.4.4.3 GetRpHashPointer() */ +/* Function to get a pointer to the RpHash() of the command */ +static TPM2B_DIGEST * +GetRpHashPointer( + COMMAND *command, + TPMI_ALG_HASH hashAlg + ) +{ + TPM2B_DIGEST *retVal; + // + // Define the macro that will expand for each implemented algorithm in the switch + // statement below. +#define GET_RP_HASH_POINTER(HASH, Hash) \ + case ALG_##HASH##_VALUE: \ + retVal = (TPM2B_DIGEST *)&command->Hash##RpHash; \ + break; + + switch(hashAlg) + { + // For each implemented hash, this will expand as defined above + // by GET_RP_HASH_POINTER. Your IDE may complain that + // 'struct "COMMAND" has no field 'SHA1RpHash'" but the compiler says + // it does, so... + FOR_EACH_HASH(GET_RP_HASH_POINTER) + default: + retVal = NULL; + break; + } + return retVal; +} + +/* 6.4.4.4 ComputeCpHash() */ +/* This function computes the cpHash as defined in Part 2 and described in Part 1. */ +static TPM2B_DIGEST * +ComputeCpHash( + COMMAND *command, // IN: command parsing structure + TPMI_ALG_HASH hashAlg // IN: hash algorithm + ) +{ + UINT32 i; + HASH_STATE hashState; + TPM2B_NAME name; + TPM2B_DIGEST *cpHash; + // cpHash = hash(commandCode [ || authName1 + // [ || authName2 + // [ || authName 3 ]]] + // [ || parameters]) + // A cpHash can contain just a commandCode only if the lone session is + // an audit session. + // Get pointer to the hash value + cpHash = GetCpHashPointer(command, hashAlg); + if(cpHash->t.size == 0) + { + cpHash->t.size = CryptHashStart(&hashState, hashAlg); + // Add commandCode. + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code); + // Add authNames for each of the handles. + for(i = 0; i < command->handleNum; i++) + CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i], + &name)->b); + // Add the parameters. + CryptDigestUpdate(&hashState, command->parameterSize, + command->parameterBuffer); + // Complete the hash. + CryptHashEnd2B(&hashState, &cpHash->b); + } + return cpHash; +} +/* 6.4.4.5 GetCpHash() */ +/* This function is used to access a precomputed cpHash. */ +static TPM2B_DIGEST * +GetCpHash( + COMMAND *command, + TPMI_ALG_HASH hashAlg + ) +{ + TPM2B_DIGEST *cpHash = GetCpHashPointer(command, hashAlg); + // + pAssert(cpHash->t.size != 0); + return cpHash; +} +/* 6.4.4.6 CompareTemplateHash() */ +/* This function computes the template hash and compares it to the session templateHash. It is the + hash of the second parameter assuming that the command is TPM2_Create(), TPM2_CreatePrimary(), or + TPM2_CreateLoaded() */ +static BOOL +CompareTemplateHash( + COMMAND *command, // IN: parsing structure + SESSION *session // IN: session data + ) +{ + BYTE *pBuffer = command->parameterBuffer; + INT32 pSize = command->parameterSize; + TPM2B_DIGEST tHash; + UINT16 size; + // + // Only try this for the three commands for which it is intended + if(command->code != TPM_CC_Create + && command->code != TPM_CC_CreatePrimary +#if CC_CreateLoaded + && command->code != TPM_CC_CreateLoaded +#endif + ) + return FALSE; + // Assume that the first parameter is a TPM2B and unmarshal the size field + // Note: this will not affect the parameter buffer and size in the calling + // function. + if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS) + return FALSE; + // reduce the space in the buffer. + // NOTE: this could make pSize go negative if the parameters are not correct but + // the unmarshaling code does not try to unmarshal if the remaining size is + // negative. + pSize -= size; + // Advance the pointer + pBuffer += size; + // Get the size of what should be the template + if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS) + return FALSE; + // See if this is reasonable + if(size > pSize) + return FALSE; + // Hash the template data + tHash.t.size = CryptHashBlock(session->authHashAlg, size, pBuffer, + sizeof(tHash.t.buffer), tHash.t.buffer); + return(MemoryEqual2B(&session->u1.templateHash.b, &tHash.b)); +} +/* 6.4.4.7 CompareNameHash() */ +/* This function computes the name hash and compares it to the nameHash in the session data. */ +BOOL +CompareNameHash( + COMMAND *command, // IN: main parsing structure + SESSION *session // IN: session structure with nameHash + ) +{ + HASH_STATE hashState; + TPM2B_DIGEST nameHash; + UINT32 i; + TPM2B_NAME name; + // + nameHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + // Add names. + for(i = 0; i < command->handleNum; i++) + CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i], + &name)->b); + // Complete hash. + CryptHashEnd2B(&hashState, &nameHash.b); + // and compare + return MemoryEqual(session->u1.nameHash.t.buffer, nameHash.t.buffer, + nameHash.t.size); +} +/* 6.4.4.8 CheckPWAuthSession() */ +/* This function validates the authorization provided in a PWAP session. It compares the input value + to authValue of the authorized entity. Argument sessionIndex is used to get handles handle of the + referenced entities from s_inputAuthValues[] and s_associatedHandles[]. */ +/* Error Returns Meaning */ +/* TPM_RC_AUTH_FAIL authorization fails and increments DA failure count */ +/* TPM_RC_BAD_AUTH authorization fails but DA does not apply */ +static TPM_RC +CheckPWAuthSession( + UINT32 sessionIndex // IN: index of session to be processed + ) +{ + TPM2B_AUTH authValue; + TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; + // Strip trailing zeros from the password. + MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]); + // Get the authValue with trailing zeros removed + EntityGetAuthValue(associatedHandle, &authValue); + // Success if the values are identical. + if(MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &authValue.b)) + { + return TPM_RC_SUCCESS; + } + else // if the digests are not identical + { + // Invoke DA protection if applicable. + return IncrementLockout(sessionIndex); + } +} +/* 6.4.4.9 ComputeCommandHMAC() */ +/* This function computes the HMAC for an authorization session in a command. */ +static TPM2B_DIGEST * +ComputeCommandHMAC( + COMMAND *command, // IN: primary control structure + UINT32 sessionIndex, // IN: index of session to be processed + TPM2B_DIGEST *hmac // OUT: authorization HMAC + ) +{ + TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); + TPM2B_KEY key; + BYTE marshalBuffer[sizeof(TPMA_SESSION)]; + BYTE *buffer; + UINT32 marshalSize; + HMAC_STATE hmacState; + TPM2B_NONCE *nonceDecrypt; + TPM2B_NONCE *nonceEncrypt; + SESSION *session; + nonceDecrypt = NULL; + nonceEncrypt = NULL; + // Determine if extra nonceTPM values are going to be required. + // If this is the first session (sessionIndex = 0) and it is an authorization + // session that uses an HMAC, then check if additional session nonces are to be + // included. + if(sessionIndex == 0 + && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) + { + // If there is a decrypt session and if this is not the decrypt session, + // then an extra nonce may be needed. + if(s_decryptSessionIndex != UNDEFINED_INDEX + && s_decryptSessionIndex != sessionIndex) + { + // Will add the nonce for the decrypt session. + SESSION *decryptSession + = SessionGet(s_sessionHandles[s_decryptSessionIndex]); + nonceDecrypt = &decryptSession->nonceTPM; + } + // Now repeat for the encrypt session. + if(s_encryptSessionIndex != UNDEFINED_INDEX + && s_encryptSessionIndex != sessionIndex + && s_encryptSessionIndex != s_decryptSessionIndex) + { + // Have to have the nonce for the encrypt session. + SESSION *encryptSession + = SessionGet(s_sessionHandles[s_encryptSessionIndex]); + nonceEncrypt = &encryptSession->nonceTPM; + } + } + // Continue with the HMAC processing. + session = SessionGet(s_sessionHandles[sessionIndex]); + // Generate HMAC key. + MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); + // Check if the session has an associated handle and if the associated entity + // is the one to which the session is bound. If not, add the authValue of + // this entity to the HMAC key. + // If the session is bound to the object or the session is a policy session + // with no authValue required, do not include the authValue in the HMAC key. + // Note: For a policy session, its isBound attribute is CLEARED. + // Include the entity authValue if it is needed + if(session->attributes.includeAuth == SET) + { + TPM2B_AUTH authValue; + // Get the entity authValue with trailing zeros removed + EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue); + // add the authValue to the HMAC key + MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer)); + } + // if the HMAC key size is 0, a NULL string HMAC is allowed + if(key.t.size == 0 + && s_inputAuthValues[sessionIndex].t.size == 0) + { + hmac->t.size = 0; + return hmac; + } + // Start HMAC + hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b); + // Add cpHash + CryptDigestUpdate2B(&hmacState.hashState, + &ComputeCpHash(command, session->authHashAlg)->b); + // Add nonces as required + CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b); + CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b); + if(nonceDecrypt != NULL) + CryptDigestUpdate2B(&hmacState.hashState, &nonceDecrypt->b); + if(nonceEncrypt != NULL) + CryptDigestUpdate2B(&hmacState.hashState, &nonceEncrypt->b); + // Add sessionAttributes + buffer = marshalBuffer; + marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]), + &buffer, NULL); + CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer); + // Complete the HMAC computation + CryptHmacEnd2B(&hmacState, &hmac->b); + return hmac; +} +/* 6.4.4.10 CheckSessionHMAC() */ +/* This function checks the HMAC of in a session. It uses ComputeCommandHMAC() to compute the + expected HMAC value and then compares the result with the HMAC in the authorization session. The + authorization is successful if they are the same. */ +/* If the authorizations are not the same, IncrementLockout() is called. It will return + TPM_RC_AUTH_FAIL if the failure caused the failureCount to increment. Otherwise, it will return + TPM_RC_BAD_AUTH. */ +/* Error Returns Meaning */ +/* TPM_RC_AUTH_FAIL authorization failure caused failureCount increment */ +/* TPM_RC_BAD_AUTH authorization failure did not cause failureCount increment */ +static TPM_RC +CheckSessionHMAC( + COMMAND *command, // IN: primary control structure + UINT32 sessionIndex // IN: index of session to be processed + ) +{ + TPM2B_DIGEST hmac; // authHMAC for comparing + // Compute authHMAC + ComputeCommandHMAC(command, sessionIndex, &hmac); + // Compare the input HMAC with the authHMAC computed above. + if(!MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &hmac.b)) + { + // If an HMAC session has a failure, invoke the anti-hammering + // if it applies to the authorized entity or the session. + // Otherwise, just indicate that the authorization is bad. + return IncrementLockout(sessionIndex); + } + return TPM_RC_SUCCESS; +} +/* 6.4.4.11 CheckPolicyAuthSession() */ +/* This function is used to validate the authorization in a policy session. This function performs + the following comparisons to see if a policy authorization is properly provided. The check + are: */ +/* a) compare policyDigest in session with authPolicy associated with the entity to be + authorized; */ +/* b) compare timeout if applicable; */ +/* c) compare commandCode if applicable; */ +/* d) compare cpHash if applicable; and */ +/* e) see if PCR values have changed since computed. */ +/* If all the above checks succeed, the handle is authorized. The order of these comparisons is not + important because any failure will result in the same error code. */ +/* Error Returns Meaning */ +/* TPM_RC_PCR_CHANGED PCR value is not current */ +/* TPM_RC_POLICY_FAIL policy session fails */ +/* TPM_RC_LOCALITY command locality is not allowed */ +/* TPM_RC_POLICY_CC CC doesn't match */ +/* TPM_RC_EXPIRED policy session has expired */ +/* TPM_RC_PP PP is required but not asserted */ +/* TPM_RC_NV_UNAVAILABLE NV is not available for write */ +/* TPM_RC_NV_RATE NV is rate limiting */ +static TPM_RC +CheckPolicyAuthSession( + COMMAND *command, // IN: primary parsing structure + UINT32 sessionIndex // IN: index of session to be processed + ) +{ + SESSION *session; + TPM2B_DIGEST authPolicy; + TPMI_ALG_HASH policyAlg; + UINT8 locality; + // Initialize pointer to the authorization session. + session = SessionGet(s_sessionHandles[sessionIndex]); + // If the command is TPM2_PolicySecret(), make sure that + // either password or authValue is required + if(command->code == TPM_CC_PolicySecret + && session->attributes.isPasswordNeeded == CLEAR + && session->attributes.isAuthValueNeeded == CLEAR) + return TPM_RC_MODE; + // See if the PCR counter for the session is still valid. + if(!SessionPCRValueIsCurrent(session)) + return TPM_RC_PCR_CHANGED; + // Get authPolicy. + policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex], + &authPolicy); + // Compare authPolicy. + if(!MemoryEqual2B(&session->u2.policyDigest.b, &authPolicy.b)) + return TPM_RC_POLICY_FAIL; + // Policy is OK so check if the other factors are correct + // Compare policy hash algorithm. + if(policyAlg != session->authHashAlg) + return TPM_RC_POLICY_FAIL; + // Compare timeout. + if(session->timeout != 0) + { + // Cannot compare time if clock stop advancing. An TPM_RC_NV_UNAVAILABLE + // or TPM_RC_NV_RATE error may be returned here. This doesn't mean that + // a new nonce will be created just that, because TPM time can't advance + // we can't do time-based operations. + RETURN_IF_NV_IS_NOT_AVAILABLE; + if((session->timeout < g_time) + || (session->epoch != g_timeEpoch)) + return TPM_RC_EXPIRED; + } + // If command code is provided it must match + if(session->commandCode != 0) + { + if(session->commandCode != command->code) + return TPM_RC_POLICY_CC; + } + else + { + // If command requires a DUP or ADMIN authorization, the session must have + // command code set. + AUTH_ROLE role = CommandAuthRole(command->index, sessionIndex); + if(role == AUTH_ADMIN || role == AUTH_DUP) + return TPM_RC_POLICY_FAIL; + } + // Check command locality. + { + BYTE sessionLocality[sizeof(TPMA_LOCALITY)]; + BYTE *buffer = sessionLocality; + // Get existing locality setting in canonical form + sessionLocality[0] = 0; + TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL); + // See if the locality has been set + if(sessionLocality[0] != 0) + { + // If so, get the current locality + locality = _plat__LocalityGet(); + if(locality < 5) + { + if(((sessionLocality[0] & (1 << locality)) == 0) + || sessionLocality[0] > 31) + return TPM_RC_LOCALITY; + } + else if(locality > 31) + { + if(sessionLocality[0] != locality) + return TPM_RC_LOCALITY; + } + else + { + // Could throw an assert here but a locality error is just + // as good. It just means that, whatever the locality is, it isn't + // the locality requested so... + return TPM_RC_LOCALITY; + } + } + } // end of locality check + // Check physical presence. + if(session->attributes.isPPRequired == SET + && !_plat__PhysicalPresenceAsserted()) + return TPM_RC_PP; + // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or + // DUP role for this handle. + if(session->u1.cpHash.b.size != 0) + { + BOOL OK; + if(session->attributes.isCpHashDefined) + // Compare cpHash. + OK = MemoryEqual2B(&session->u1.cpHash.b, + &ComputeCpHash(command, session->authHashAlg)->b); + else if(session->attributes.isTemplateSet) + OK = CompareTemplateHash(command, session); + else + OK = CompareNameHash(command, session); + if(!OK) + return TPM_RCS_POLICY_FAIL; + } + if(session->attributes.checkNvWritten) + { + NV_REF locator; + NV_INDEX *nvIndex; + // If this is not an NV index, the policy makes no sense so fail it. + if(HandleGetType(s_associatedHandles[sessionIndex]) != TPM_HT_NV_INDEX) + return TPM_RC_POLICY_FAIL; + // Get the index data + nvIndex = NvGetIndexInfo(s_associatedHandles[sessionIndex], &locator); + // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state + if((IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + != (session->attributes.nvWrittenState == SET)) + return TPM_RC_POLICY_FAIL; + } + return TPM_RC_SUCCESS; +} +/* 6.4.4.12 RetrieveSessionData() */ +/* This function will unmarshal the sessions in the session area of a command. The values are placed + in the arrays that are defined at the beginning of this file. The normal unmarshaling errors are + possible. */ +/* Error Returns Meaning */ +/* TPM_RC_SUCCSS unmarshaled without error */ +/* TPM_RC_SIZE the number of bytes unmarshaled is not the same as the value for authorizationSize in + the command */ +static TPM_RC +RetrieveSessionData( + COMMAND *command // IN: main parsing structure for command + ) +{ + int i; + TPM_RC result; + SESSION *session; + TPMA_SESSION sessionAttributes; + TPM_HT sessionType; + INT32 sessionIndex; + TPM_RC errorIndex; + s_decryptSessionIndex = UNDEFINED_INDEX; + s_encryptSessionIndex = UNDEFINED_INDEX; + s_auditSessionIndex = UNDEFINED_INDEX; + for(sessionIndex = 0; command->authSize > 0; sessionIndex++) + { + errorIndex = TPM_RC_S + g_rcIndex[sessionIndex]; + // If maximum allowed number of sessions has been parsed, return a size + // error with a session number that is larger than the number of allowed + // sessions + if(sessionIndex == MAX_SESSION_NUM) + return TPM_RCS_SIZE + errorIndex; + // make sure that the associated handle for each session starts out + // unassigned + s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; + // First parameter: Session handle. + result = TPMI_SH_AUTH_SESSION_Unmarshal( + &s_sessionHandles[sessionIndex], + &command->parameterBuffer, + &command->authSize, TRUE); + if(result != TPM_RC_SUCCESS) + return result + TPM_RC_S + g_rcIndex[sessionIndex]; + // Second parameter: Nonce. + result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex], + &command->parameterBuffer, + &command->authSize); + if(result != TPM_RC_SUCCESS) + return result + TPM_RC_S + g_rcIndex[sessionIndex]; + // Third parameter: sessionAttributes. + result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex], + &command->parameterBuffer, + &command->authSize); + if(result != TPM_RC_SUCCESS) + return result + TPM_RC_S + g_rcIndex[sessionIndex]; + // Fourth parameter: authValue (PW or HMAC). + result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex], + &command->parameterBuffer, + &command->authSize); + if(result != TPM_RC_SUCCESS) + return result + errorIndex; + sessionAttributes = s_attributes[sessionIndex]; + if(s_sessionHandles[sessionIndex] == TPM_RS_PW) + { + // A PWAP session needs additional processing. + // Can't have any attributes set other than continueSession bit + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt) + || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt) + || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit) + || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive) + || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset)) + return TPM_RCS_ATTRIBUTES + errorIndex; + // The nonce size must be zero. + if(s_nonceCaller[sessionIndex].t.size != 0) + return TPM_RCS_NONCE + errorIndex; + continue; + } + // For not password sessions... + // Find out if the session is loaded. + if(!SessionIsLoaded(s_sessionHandles[sessionIndex])) + return TPM_RC_REFERENCE_S0 + sessionIndex; + sessionType = HandleGetType(s_sessionHandles[sessionIndex]); + session = SessionGet(s_sessionHandles[sessionIndex]); + // Check if the session is an HMAC/policy session. + if((session->attributes.isPolicy == SET + && sessionType == TPM_HT_HMAC_SESSION) + || (session->attributes.isPolicy == CLEAR + && sessionType == TPM_HT_POLICY_SESSION)) + return TPM_RCS_HANDLE + errorIndex; + // Check that this handle has not previously been used. + for(i = 0; i < sessionIndex; i++) + { + if(s_sessionHandles[i] == s_sessionHandles[sessionIndex]) + return TPM_RCS_HANDLE + errorIndex; + } + // If the session is used for parameter encryption or audit as well, set + // the corresponding Indexes. + // First process decrypt. + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)) + { + // Check if the commandCode allows command parameter encryption. + if(DecryptSize(command->index) == 0) + return TPM_RCS_ATTRIBUTES + errorIndex; + // Encrypt attribute can only appear in one session + if(s_decryptSessionIndex != UNDEFINED_INDEX) + return TPM_RCS_ATTRIBUTES + errorIndex; + // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL + if(session->symmetric.algorithm == TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC + errorIndex; + // All checks passed, so set the index for the session used to decrypt + // a command parameter. + s_decryptSessionIndex = sessionIndex; + } + // Now process encrypt. + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)) + { + // Check if the commandCode allows response parameter encryption. + if(EncryptSize(command->index) == 0) + return TPM_RCS_ATTRIBUTES + errorIndex; + // Encrypt attribute can only appear in one session. + if(s_encryptSessionIndex != UNDEFINED_INDEX) + return TPM_RCS_ATTRIBUTES + errorIndex; + // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL + if(session->symmetric.algorithm == TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC + errorIndex; + // All checks passed, so set the index for the session used to encrypt + // a response parameter. + s_encryptSessionIndex = sessionIndex; + } + // At last process audit. + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)) + { + // Audit attribute can only appear in one session. + if(s_auditSessionIndex != UNDEFINED_INDEX) + return TPM_RCS_ATTRIBUTES + errorIndex; + // An audit session can not be policy session. + if(HandleGetType(s_sessionHandles[sessionIndex]) + == TPM_HT_POLICY_SESSION) + return TPM_RCS_ATTRIBUTES + errorIndex; + // If this is a reset of the audit session, or the first use + // of the session as an audit session, it doesn't matter what + // the exclusive state is. The session will become exclusive. + if(!IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset) + && session->attributes.isAudit == SET) + { + // Not first use or reset. If auditExlusive is SET, then this + // session must be the current exclusive session. + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive) + && g_exclusiveAuditSession != s_sessionHandles[sessionIndex]) + return TPM_RC_EXCLUSIVE; + } + s_auditSessionIndex = sessionIndex; + } + // Initialize associated handle as undefined. This will be changed when + // the handles are processed. + s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; + } + command->sessionNum = sessionIndex; + return TPM_RC_SUCCESS; +} +/* 6.4.4.13 CheckLockedOut() */ +/* This function checks to see if the TPM is in lockout. This function should only be called if the + entity being checked is subject to DA protection. The TPM is in lockout if the NV is not + available and a DA write is pending. Otherwise the TPM is locked out if checking for lockoutAuth + (lockoutAuthCheck == TRUE) and use of lockoutAuth is disabled, or failedTries >= maxTries */ +/* Error Returns Meaning */ +/* TPM_RC_NV_RATE NV is rate limiting */ +/* TPM_RC_NV_UNAVAILABLE NV is not available at this time */ +/* TPM_RC_LOCKOUT TPM is in lockout */ +static TPM_RC +CheckLockedOut( + BOOL lockoutAuthCheck // IN: TRUE if checking is for lockoutAuth + ) +{ + // If NV is unavailable, and current cycle state recorded in NV is not + // SU_NONE_VALUE, refuse to check any authorization because we would + // not be able to handle a DA failure. + if(!NV_IS_AVAILABLE && NV_IS_ORDERLY) + return g_NvStatus; + // Check if DA info needs to be updated in NV. + if(s_DAPendingOnNV) + { + // If NV is accessible, + RETURN_IF_NV_IS_NOT_AVAILABLE; + // ... write the pending DA data and proceed. + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + NV_SYNC_PERSISTENT(failedTries); + s_DAPendingOnNV = FALSE; + } + // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth + // is disabled... + if(lockoutAuthCheck) + { + if(gp.lockOutAuthEnabled == FALSE) + return TPM_RC_LOCKOUT; + } + else + { + // ... or if the number of failed tries has been maxed out. + if(gp.failedTries >= gp.maxTries) + return TPM_RC_LOCKOUT; +#if USE_DA_USED + // If the daUsed flag is not SET, then no DA validation until the + // daUsed state is written to NV + if(!g_daUsed) + { + RETURN_IF_NV_IS_NOT_AVAILABLE; + g_daUsed = TRUE; + gp.orderlyState = SU_DA_USED_VALUE; + NV_SYNC_PERSISTENT(orderlyState); + return TPM_RC_RETRY; + } +#endif + } + return TPM_RC_SUCCESS; +} +/* 6.4.4.14 CheckAuthSession() */ +/* This function checks that the authorization session properly authorizes the use of the associated + handle. */ +/* Error Returns Meaning */ +/* TPM_RC_LOCKOUT entity is protected by DA and TPM is in lockout, or TPM is locked out on NV update + pending on DA parameters */ +/* TPM_RC_PP Physical Presence is required but not provided */ +/* TPM_RC_AUTH_FAIL HMAC or PW authorization failed with DA side-effects (can be a policy + session) */ +/* TPM_RC_BAD_AUTH HMAC or PW authorization failed without DA side-effects (can be a policy + session) */ +/* TPM_RC_POLICY_FAIL if policy session fails */ +/* TPM_RC_POLICY_CC command code of policy was wrong */ +/* TPM_RC_EXPIRED the policy session has expired */ +/* TPM_RC_PCR ??? */ +/* TPM_RC_AUTH_UNAVAILABLE authValue or authPolicy unavailable */ +static TPM_RC +CheckAuthSession( + COMMAND *command, // IN: primary parsing structure + UINT32 sessionIndex // IN: index of session to be processed + ) +{ + TPM_RC result = TPM_RC_SUCCESS; + SESSION *session = NULL; + TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; + TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; + TPM_HT sessionHandleType = HandleGetType(sessionHandle); + BOOL authUsed; + + pAssert(sessionHandle != TPM_RH_UNASSIGNED); + + // Take care of physical presence + if(associatedHandle == TPM_RH_PLATFORM) + { + // If the physical presence is required for this command, check for PP + // assertion. If it isn't asserted, no point going any further. + if(PhysicalPresenceIsRequired(command->index) + && !_plat__PhysicalPresenceAsserted()) + return TPM_RC_PP; + } + if(sessionHandle != TPM_RS_PW) + { + session = SessionGet(sessionHandle); + // Set includeAuth to indicate if DA checking will be required and if the + // authValue will be included in any HMAC. + if(sessionHandleType == TPM_HT_POLICY_SESSION) + { + // For a policy session, will check the DA status of the entity if either + // isAuthValueNeeded or isPasswordNeeded is SET. + session->attributes.includeAuth = + session->attributes.isAuthValueNeeded + || session->attributes.isPasswordNeeded; + } + else + { + // For an HMAC session, need to check unless the session + // is bound. + session->attributes.includeAuth = + !IsSessionBindEntity(s_associatedHandles[sessionIndex], session); + } + authUsed = session->attributes.includeAuth; + } + else + // Password session + authUsed = TRUE; + // If the authorization session is going to use an authValue, then make sure + // that access to that authValue isn't locked out. + if(authUsed) + { + // See if entity is subject to lockout. + if(!IsDAExempted(associatedHandle)) + { + // See if in lockout + result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT); + if(result != TPM_RC_SUCCESS) + return result; + } + } + // Policy or HMAC+PW? + if(sessionHandleType != TPM_HT_POLICY_SESSION) + { + // for non-policy session make sure that a policy session is not required + if(IsPolicySessionRequired(command->index, sessionIndex)) + return TPM_RC_AUTH_TYPE; + // The authValue must be available. + // Note: The authValue is going to be "used" even if it is an EmptyAuth. + // and the session is bound. + if(!IsAuthValueAvailable(associatedHandle, command->index, sessionIndex)) + return TPM_RC_AUTH_UNAVAILABLE; + } + else + { + // ... see if the entity has a policy, ... + // Note: IsAuthPolicyAvailable will return FALSE if the sensitive area of the + // object is not loaded + if(!IsAuthPolicyAvailable(associatedHandle, command->index, sessionIndex)) + return TPM_RC_AUTH_UNAVAILABLE; + // ... and check the policy session. + result = CheckPolicyAuthSession(command, sessionIndex); + if(result != TPM_RC_SUCCESS) + return result; + } + // Check authorization according to the type + if((TPM_RS_PW == sessionHandle) || (session->attributes.isPasswordNeeded == SET)) + result = CheckPWAuthSession(sessionIndex); + else + result = CheckSessionHMAC(command, sessionIndex); + // Do processing for PIN Indexes are only three possibilities for 'result' at + // this point: TPM_RC_SUCCESS, TPM_RC_AUTH_FAIL, TPM_RC_BAD_AUTH + // For all these cases, we would have to process a PIN index if the + // authValue of the index was used for authorization. + if((TPM_HT_NV_INDEX == HandleGetType(associatedHandle)) && authUsed) + { + NV_REF locator; + NV_INDEX *nvIndex = NvGetIndexInfo(associatedHandle, &locator); + NV_PIN pinData; + TPMA_NV nvAttributes; + + pAssert(nvIndex != NULL); + nvAttributes = nvIndex->publicArea.attributes; + // If this is a PIN FAIL index and the value has been written + // then we can update the counter (increment or clear) + if(IsNvPinFailIndex(nvAttributes) + && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)) + { + pinData.intVal = NvGetUINT64Data(nvIndex, locator); + if(result != TPM_RC_SUCCESS) + pinData.pin.pinCount++; + else + pinData.pin.pinCount = 0; + NvWriteUINT64Data(nvIndex, pinData.intVal); + } + // If this is a PIN PASS Index, increment if we have used the + // authorization value. + // NOTE: If the counter has already hit the limit, then we + // would not get here because the authorization value would not + // be available and the TPM would have returned before it gets here + else if(IsNvPinPassIndex(nvAttributes) + && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN) + && result == TPM_RC_SUCCESS) + { + // If the access is valid, then increment the use counter + pinData.intVal = NvGetUINT64Data(nvIndex, locator); + pinData.pin.pinCount++; + NvWriteUINT64Data(nvIndex, pinData.intVal); + } + } + return result; +} +#if CC_GetCommandAuditDigest +/* 6.4.4.15 CheckCommandAudit() */ +/* This function is called before the command is processed if audit is enabled for the command. It + will check to see if the audit can be performed and will ensure that the cpHash is available for + the audit. */ +/* Error Returns Meaning */ +/* TPM_RC_NV_UNAVAILABLE NV is not available for write */ +/* TPM_RC_NV_RATE NV is rate limiting */ +static TPM_RC +CheckCommandAudit( + COMMAND *command + ) +{ + // If the audit digest is clear and command audit is required, NV must be + // available so that TPM2_GetCommandAuditDigest() is able to increment + // audit counter. If NV is not available, the function bails out to prevent + // the TPM from attempting an operation that would fail anyway. + if(gr.commandAuditDigest.t.size == 0 + || GetCommandCode(command->index) == TPM_CC_GetCommandAuditDigest) + { + RETURN_IF_NV_IS_NOT_AVAILABLE; + } + // Make sure that the cpHash is computed for the algorithm + ComputeCpHash(command, gp.auditHashAlg); + return TPM_RC_SUCCESS; +} +#endif +/* 6.4.4.16 ParseSessionBuffer() */ +/* This function is the entry function for command session processing. It iterates sessions in + session area and reports if the required authorization has been properly provided. It also + processes audit session and passes the information of encryption sessions to parameter encryption + module. */ +/* Error Returns Meaning */ +/* various parsing failure or authorization failure */ +TPM_RC +ParseSessionBuffer( + COMMAND *command // IN: the structure that contains + ) +{ + TPM_RC result; + UINT32 i; + INT32 size = 0; + TPM2B_AUTH extraKey; + UINT32 sessionIndex; + TPM_RC errorIndex; + SESSION *session = NULL; + // Check if a command allows any session in its session area. + if(!IsSessionAllowed(command->index)) + return TPM_RC_AUTH_CONTEXT; + // Default-initialization. + command->sessionNum = 0; + result = RetrieveSessionData(command); + if(result != TPM_RC_SUCCESS) + return result; + // There is no command in the TPM spec that has more handles than + // MAX_SESSION_NUM. + pAssert(command->handleNum <= MAX_SESSION_NUM); + // Associate the session with an authorization handle. + for(i = 0; i < command->handleNum; i++) + { + if(CommandAuthRole(command->index, i) != AUTH_NONE) + { + // If the received session number is less than the number of handles + // that requires authorization, an error should be returned. + // Note: for all the TPM 2.0 commands, handles requiring + // authorization come first in a command input and there are only ever + // two values requiring authorization + if(i > (command->sessionNum - 1)) + return TPM_RC_AUTH_MISSING; + // Record the handle associated with the authorization session + s_associatedHandles[i] = command->handles[i]; + } + } + // Consistency checks are done first to avoid authorization failure when the + // command will not be executed anyway. + for(sessionIndex = 0; sessionIndex < command->sessionNum; sessionIndex++) + { + errorIndex = TPM_RC_S + g_rcIndex[sessionIndex]; + // PW session must be an authorization session + if(s_sessionHandles[sessionIndex] == TPM_RS_PW) + { + if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED) + return TPM_RCS_HANDLE + errorIndex; + // a password session can't be audit, encrypt or decrypt + if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit) + || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt) + || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt)) + return TPM_RCS_ATTRIBUTES + errorIndex; + session = NULL; + } + else + { + session = SessionGet(s_sessionHandles[sessionIndex]); + // A trial session can not appear in session area, because it cannot + // be used for authorization, audit or encrypt/decrypt. + if(session->attributes.isTrialPolicy == SET) + return TPM_RCS_ATTRIBUTES + errorIndex; + // See if the session is bound to a DA protected entity + // NOTE: Since a policy session is never bound, a policy is still + // usable even if the object is DA protected and the TPM is in + // lockout. + if(session->attributes.isDaBound == SET) + { + result = CheckLockedOut(session->attributes.isLockoutBound == SET); + if(result != TPM_RC_SUCCESS) + return result; + } + // If this session is for auditing, make sure the cpHash is computed. + if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)) + ComputeCpHash(command, session->authHashAlg); + } + // if the session has an associated handle, check the authorization + if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) + { + result = CheckAuthSession(command, sessionIndex); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, errorIndex); + } + else + { + // a session that is not for authorization must either be encrypt, + // decrypt, or audit + if(!IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit) + && !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt) + && !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt)) + return TPM_RCS_ATTRIBUTES + errorIndex; + // no authValue included in any of the HMAC computations + pAssert(session != NULL); + session->attributes.includeAuth = CLEAR; + // check HMAC for encrypt/decrypt/audit only sessions + result = CheckSessionHMAC(command, sessionIndex); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, errorIndex); + } + } +#if CC_GetCommandAuditDigest + // Check if the command should be audited. Need to do this before any parameter + // encryption so that the cpHash for the audit is correct + if(CommandAuditIsRequired(command->index)) + { + result = CheckCommandAudit(command); + if(result != TPM_RC_SUCCESS) + return result; // No session number to reference + } +#endif + // Decrypt the first parameter if applicable. This should be the last operation + // in session processing. + // If the encrypt session is associated with a handle and the handle's + // authValue is available, then authValue is concatenated with sessionKey to + // generate encryption key, no matter if the handle is the session bound entity + // or not. + if(s_decryptSessionIndex != UNDEFINED_INDEX) + { + // If this is an authorization session, include the authValue in the + // generation of the decryption key + if(s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED) + { + EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex], + &extraKey); + } + else + { + extraKey.b.size = 0; + } + size = DecryptSize(command->index); + result = CryptParameterDecryption(s_sessionHandles[s_decryptSessionIndex], + &s_nonceCaller[s_decryptSessionIndex].b, + command->parameterSize, (UINT16)size, + &extraKey, + command->parameterBuffer); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, + TPM_RC_S + g_rcIndex[s_decryptSessionIndex]); + } + return TPM_RC_SUCCESS; +} +/* 6.4.4.17 CheckAuthNoSession() */ +/* Function to process a command with no session associated. The function makes sure all the handles + in the command require no authorization. */ +/* Error Returns Meaning */ +/* TPM_RC_AUTH_MISSING failure - one or more handles require authorization */ +TPM_RC +CheckAuthNoSession( + COMMAND *command // IN: command parsing structure + ) +{ + UINT32 i; + TPM_RC result = TPM_RC_SUCCESS; + // Check if the command requires authorization + for(i = 0; i < command->handleNum; i++) + { + if(CommandAuthRole(command->index, i) != AUTH_NONE) + return TPM_RC_AUTH_MISSING; + } +#if CC_GetCommandAuditDigest + // Check if the command should be audited. + if(CommandAuditIsRequired(command->index)) + { + result = CheckCommandAudit(command); + if(result != TPM_RC_SUCCESS) + return result; + } +#endif + // Initialize number of sessions to be 0 + command->sessionNum = 0; + return TPM_RC_SUCCESS; +} +/* 6.4.5 Response Session Processing */ +/* 6.4.5.1 Introduction */ +/* The following functions build the session area in a response and handle the audit sessions (if + present). */ +/* 6.4.5.2 ComputeRpHash() */ +/* Function to compute rpHash (Response Parameter Hash). The rpHash is only computed if there is an + HMAC authorization session and the return code is TPM_RC_SUCCESS. */ +static TPM2B_DIGEST * +ComputeRpHash( + COMMAND *command, // IN: command structure + TPM_ALG_ID hashAlg // IN: hash algorithm to compute rpHash + ) +{ + TPM2B_DIGEST *rpHash = GetRpHashPointer(command, hashAlg); + HASH_STATE hashState; + if(rpHash->t.size == 0) + { + // rpHash := hash(responseCode || commandCode || parameters) + // Initiate hash creation. + rpHash->t.size = CryptHashStart(&hashState, hashAlg); + // Add hash constituents. + CryptDigestUpdateInt(&hashState, sizeof(TPM_RC), TPM_RC_SUCCESS); + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code); + CryptDigestUpdate(&hashState, command->parameterSize, + command->parameterBuffer); + // Complete hash computation. + CryptHashEnd2B(&hashState, &rpHash->b); + } + return rpHash; +} +/* 6.4.5.3 InitAuditSession() */ +/* This function initializes the audit data in an audit session. */ +static void +InitAuditSession( + SESSION *session // session to be initialized + ) +{ + // Mark session as an audit session. + session->attributes.isAudit = SET; + // Audit session can not be bound. + session->attributes.isBound = CLEAR; + // Size of the audit log is the size of session hash algorithm digest. + session->u2.auditDigest.t.size = CryptHashGetDigestSize(session->authHashAlg); + // Set the original digest value to be 0. + MemorySet(&session->u2.auditDigest.t.buffer, + 0, + session->u2.auditDigest.t.size); + return; +} +/* 6.4.5.4 UpdateAuditDigest */ +/* Function to update an audit digest */ +static void +UpdateAuditDigest( + COMMAND *command, + TPMI_ALG_HASH hashAlg, + TPM2B_DIGEST *digest + ) +{ + HASH_STATE hashState; + TPM2B_DIGEST *cpHash = GetCpHash(command, hashAlg); + TPM2B_DIGEST *rpHash = ComputeRpHash(command, hashAlg); + // + pAssert(cpHash != NULL); + // digestNew := hash (digestOld || cpHash || rpHash) + // Start hash computation. + digest->t.size = CryptHashStart(&hashState, hashAlg); + // Add old digest. + CryptDigestUpdate2B(&hashState, &digest->b); + // Add cpHash + CryptDigestUpdate2B(&hashState, &cpHash->b); + // Add rpHash + CryptDigestUpdate2B(&hashState, &rpHash->b); + // Finalize the hash. + CryptHashEnd2B(&hashState, &digest->b); +} +/* 6.4.5.5 Audit() */ +/* This function updates the audit digest in an audit session. */ +static void +Audit( + COMMAND *command, // IN: primary control structure + SESSION *auditSession // IN: loaded audit session + ) +{ + UpdateAuditDigest(command, auditSession->authHashAlg, + &auditSession->u2.auditDigest); + return; +} +#if CC_GetCommandAuditDigest +/* 6.4.5.6 CommandAudit() */ +/* This function updates the command audit digest. */ +static void +CommandAudit( + COMMAND *command // IN: + ) +{ + // If the digest.size is one, it indicates the special case of changing + // the audit hash algorithm. For this case, no audit is done on exit. + // NOTE: When the hash algorithm is changed, g_updateNV is set in order to + // force an update to the NV on exit so that the change in digest will + // be recorded. So, it is safe to exit here without setting any flags + // because the digest change will be written to NV when this code exits. + if(gr.commandAuditDigest.t.size == 1) + { + gr.commandAuditDigest.t.size = 0; + return; + } + // If the digest size is zero, need to start a new digest and increment + // the audit counter. + if(gr.commandAuditDigest.t.size == 0) + { + gr.commandAuditDigest.t.size = CryptHashGetDigestSize(gp.auditHashAlg); + MemorySet(gr.commandAuditDigest.t.buffer, + 0, + gr.commandAuditDigest.t.size); + // Bump the counter and save its value to NV. + gp.auditCounter++; + NV_SYNC_PERSISTENT(auditCounter); + } + UpdateAuditDigest(command, gp.auditHashAlg, &gr.commandAuditDigest); + return; +} +#endif +/* 6.4.5.7 UpdateAuditSessionStatus() */ +/* Function to update the internal audit related states of a session. It */ +/* a) initializes the session as audit session and sets it to be exclusive if this is the first time + it is used for audit or audit reset was requested; */ +/* b) reports exclusive audit session; */ +/* c) extends audit log; and */ +/* d) clears exclusive audit session if no audit session found in the command. */ +static void +UpdateAuditSessionStatus( + COMMAND *command // IN: primary control structure + ) +{ + UINT32 i; + TPM_HANDLE auditSession = TPM_RH_UNASSIGNED; + // Iterate through sessions + for(i = 0; i < command->sessionNum; i++) + { + SESSION *session; + // PW session do not have a loaded session and can not be an audit + // session either. Skip it. + if(s_sessionHandles[i] == TPM_RS_PW) + continue; + session = SessionGet(s_sessionHandles[i]); + // If a session is used for audit + if(IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, audit)) + { + // An audit session has been found + auditSession = s_sessionHandles[i]; + // If the session has not been an audit session yet, or + // the auditSetting bits indicate a reset, initialize it and set + // it to be the exclusive session + if(session->attributes.isAudit == CLEAR + || IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditReset)) + { + InitAuditSession(session); + g_exclusiveAuditSession = auditSession; + } + else + { + // Check if the audit session is the current exclusive audit + // session and, if not, clear previous exclusive audit session. + if(g_exclusiveAuditSession != auditSession) + g_exclusiveAuditSession = TPM_RH_UNASSIGNED; + } + // Report audit session exclusivity. + if(g_exclusiveAuditSession == auditSession) + { + SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive); + } + else + { + CLEAR_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive); + } + // Extend audit log. + Audit(command, session); + } + } + // If no audit session is found in the command, and the command allows + // a session then, clear the current exclusive + // audit session. + if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(command->index)) + { + g_exclusiveAuditSession = TPM_RH_UNASSIGNED; + } + return; +} +/* 6.4.5.8 ComputeResponseHMAC() */ +/* Function to compute HMAC for authorization session in a response. */ +static void +ComputeResponseHMAC( + COMMAND *command, // IN: command structure + UINT32 sessionIndex, // IN: session index to be processed + SESSION *session, // IN: loaded session + TPM2B_DIGEST *hmac // OUT: authHMAC + ) +{ + TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); + TPM2B_KEY key; // HMAC key + BYTE marshalBuffer[sizeof(TPMA_SESSION)]; + BYTE *buffer; + UINT32 marshalSize; + HMAC_STATE hmacState; + TPM2B_DIGEST *rpHash = ComputeRpHash(command, session->authHashAlg); + // Generate HMAC key + MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); + // Add the object authValue if required + if(session->attributes.includeAuth == SET) + { + // Note: includeAuth may be SET for a policy that is used in + // UndefineSpaceSpecial(). At this point, the Index has been deleted + // so the includeAuth will have no meaning. However, the + // s_associatedHandles[] value for the session is now set to TPM_RH_NULL so + // this will return the authValue associated with TPM_RH_NULL and that is + // and empty buffer. + TPM2B_AUTH authValue; + // Get the authValue with trailing zeros removed + EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue); + // Add it to the key + MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer)); + } + // if the HMAC key size is 0, the response HMAC is computed according to the + // input HMAC + if(key.t.size == 0 + && s_inputAuthValues[sessionIndex].t.size == 0) + { + hmac->t.size = 0; + return; + } + // Start HMAC computation. + hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b); + // Add hash components. + CryptDigestUpdate2B(&hmacState.hashState, &rpHash->b); + CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b); + CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b); + // Add session attributes. + buffer = marshalBuffer; + marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, NULL); + CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer); + // Finalize HMAC. + CryptHmacEnd2B(&hmacState, &hmac->b); + return; +} +/* 6.4.5.9 UpdateInternalSession() */ +/* Updates internal sessions: */ +/* a) Restarts session time. */ +/* b) Clears a policy session since nonce is rolling. */ +static void +UpdateInternalSession( + SESSION *session, // IN: the session structure + UINT32 i // IN: session number + ) +{ + // If nonce is rolling in a policy session, the policy related data + // will be re-initialized. + if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION + && IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession)) + { + // When the nonce rolls it starts a new timing interval for the + // policy session. + SessionResetPolicyData(session); + SessionSetStartTime(session); + } + return; +} +/* 6.4.5.10 BuildSingleResponseAuth() */ +/* Function to compute response HMAC value for a policy or HMAC session. */ +static TPM2B_NONCE * +BuildSingleResponseAuth( + COMMAND *command, // IN: command structure + UINT32 sessionIndex, // IN: session index to be processed + TPM2B_AUTH *auth // OUT: authHMAC + ) +{ + // Fill in policy/HMAC based session response. + SESSION *session = SessionGet(s_sessionHandles[sessionIndex]); + // If the session is a policy session with isPasswordNeeded SET, the + // authorization field is empty. + if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION + && session->attributes.isPasswordNeeded == SET) + auth->t.size = 0; + else + // Compute response HMAC. + ComputeResponseHMAC(command, sessionIndex, session, auth); + UpdateInternalSession(session, sessionIndex); + return &session->nonceTPM; +} +/* 6.4.5.11 UpdateAllNonceTPM() */ +/* Updates TPM nonce for all sessions in command. */ +static void +UpdateAllNonceTPM( + COMMAND *command // IN: controlling structure + ) +{ + UINT32 i; + SESSION *session; + for(i = 0; i < command->sessionNum; i++) + { + // If not a PW session, compute the new nonceTPM. + if(s_sessionHandles[i] != TPM_RS_PW) + { + session = SessionGet(s_sessionHandles[i]); + // Update nonceTPM in both internal session and response. + CryptRandomGenerate(session->nonceTPM.t.size, + session->nonceTPM.t.buffer); + } + } + return; +} +/* 6.4.5.12 BuildResponseSession() */ +/* Function to build Session buffer in a response. The authorization data is added to the end of + command->responseBuffer. The size of the authorization area is accumulated in + command->authSize. When this is called, command->responseBuffer is pointing at the next location + in the response buffer to be filled. This is where the authorization sessions will go, if + any. command->parameterSize is the number of bytes that have been marshaled as parameters in the + output buffer. */ +void +BuildResponseSession( + COMMAND *command // IN: structure that has relevant command + // information + ) +{ + pAssert(command->authSize == 0); + // Reset the parameter buffer to point to the start of the parameters so that + // there is a starting point for any rpHash that might be generated and so there + // is a place where parameter encryption would start + command->parameterBuffer = command->responseBuffer - command->parameterSize; + // Session nonces should be updated before parameter encryption + if(command->tag == TPM_ST_SESSIONS) + { + UpdateAllNonceTPM(command); + // Encrypt first parameter if applicable. Parameter encryption should + // happen after nonce update and before any rpHash is computed. + // If the encrypt session is associated with a handle, the authValue of + // this handle will be concatenated with sessionKey to generate + // encryption key, no matter if the handle is the session bound entity + // or not. The authValue is added to sessionKey only when the authValue + // is available. + if(s_encryptSessionIndex != UNDEFINED_INDEX) + { + UINT32 size; + TPM2B_AUTH extraKey; + extraKey.b.size = 0; + // If this is an authorization session, include the authValue in the + // generation of the encryption key + if(s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED) + { + EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex], + &extraKey); + } + size = EncryptSize(command->index); + CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex], + &s_nonceCaller[s_encryptSessionIndex].b, + (UINT16)size, + &extraKey, + command->parameterBuffer); + } + } + // Audit sessions should be processed regardless of the tag because + // a command with no session may cause a change of the exclusivity state. + UpdateAuditSessionStatus(command); +#if CC_GetCommandAuditDigest + // Command Audit + if(CommandAuditIsRequired(command->index)) + CommandAudit(command); +#endif + // Process command with sessions. + if(command->tag == TPM_ST_SESSIONS) + { + UINT32 i; + pAssert(command->sessionNum > 0); + // Iterate over each session in the command session area, and create + // corresponding sessions for response. + for(i = 0; i < command->sessionNum; i++) + { + TPM2B_NONCE *nonceTPM; + TPM2B_DIGEST responseAuth; + // Make sure that continueSession is SET on any Password session. + // This makes it marginally easier for the management software + // to keep track of the closed sessions. + if(s_sessionHandles[i] == TPM_RS_PW) + { + SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession); + responseAuth.t.size = 0; + nonceTPM = (TPM2B_NONCE *)&responseAuth; + } + else + { + // Compute the response HMAC and get a pointer to the nonce used. + // This function will also update the values if needed. Note, the + nonceTPM = BuildSingleResponseAuth(command, i, &responseAuth); + } + command->authSize += TPM2B_NONCE_Marshal(nonceTPM, + &command->responseBuffer, + NULL); + command->authSize += TPMA_SESSION_Marshal(&s_attributes[i], + &command->responseBuffer, + NULL); + command->authSize += TPM2B_DIGEST_Marshal(&responseAuth, + &command->responseBuffer, + NULL); + if(!IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession)) + SessionFlush(s_sessionHandles[i]); + } + } + return; +} +/* 6.4.5.13 SessionRemoveAssociationToHandle() */ +/* This function deals with the case where an entity associated with an authorization is deleted + during command processing. The primary use of this is to support UndefineSpaceSpecial(). */ +void +SessionRemoveAssociationToHandle( + TPM_HANDLE handle + ) +{ + UINT32 i; + for(i = 0; i < MAX_SESSION_NUM; i++) + { + if(s_associatedHandles[i] == handle) + { + s_associatedHandles[i] = TPM_RH_NULL; + } + } +} diff --git a/src/tpm2/SessionProcess_fp.h b/src/tpm2/SessionProcess_fp.h new file mode 100644 index 0000000..cfc7b76 --- /dev/null +++ b/src/tpm2/SessionProcess_fp.h @@ -0,0 +1,97 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SessionProcess_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef SESSIONPROCESS_FP_H +#define SESSIONPROCESS_FP_H + +BOOL +IsDAExempted( + TPM_HANDLE handle // IN: entity handle + ); +void +ClearCpRpHashes( + COMMAND *command + ); +BOOL +CompareNameHash( + COMMAND *command, // IN: main parsing structure + SESSION *session // IN: session structure with nameHash + ); +TPM_RC +ParseSessionBuffer( + COMMAND *command // IN: the structure that contains + ); +TPM_RC +CheckAuthNoSession( + COMMAND *command // IN: command parsing structure + ); +void +BuildResponseSession( + COMMAND *command // IN: structure that has relevant command + // information + ); +void +SessionRemoveAssociationToHandle( + TPM_HANDLE handle + ); + + +#endif diff --git a/src/tpm2/Session_fp.h b/src/tpm2/Session_fp.h new file mode 100644 index 0000000..10a670e --- /dev/null +++ b/src/tpm2/Session_fp.h @@ -0,0 +1,158 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Session_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef SESSION_FP_H +#define SESSION_FP_H + +BOOL +SessionStartup( + STARTUP_TYPE type + ); +BOOL +SessionIsLoaded( + TPM_HANDLE handle // IN: session handle + ); +BOOL +SessionIsSaved( + TPM_HANDLE handle // IN: session handle + ); +BOOL +SequenceNumberForSavedContextIsValid( + TPMS_CONTEXT *context // IN: pointer to a context structure to be + // validated + ); +BOOL +SessionPCRValueIsCurrent( + SESSION *session // IN: session structure + ); +SESSION * +SessionGet( + TPM_HANDLE handle // IN: session handle + ); +TPM_RC +SessionCreate( + TPM_SE sessionType, // IN: the session type + TPMI_ALG_HASH authHash, // IN: the hash algorithm + TPM2B_NONCE *nonceCaller, // IN: initial nonceCaller + TPMT_SYM_DEF *symmetric, // IN: the symmetric algorithm + TPMI_DH_ENTITY bind, // IN: the bind object + TPM2B_DATA *seed, // IN: seed data + TPM_HANDLE *sessionHandle, // OUT: the session handle + TPM2B_NONCE *nonceTpm // OUT: the session nonce + ); +TPM_RC +SessionContextSave( + TPM_HANDLE handle, // IN: session handle + CONTEXT_COUNTER *contextID // OUT: assigned contextID + ); +TPM_RC +SessionContextLoad( + SESSION_BUF *session, // IN: session structure from saved context + TPM_HANDLE *handle // IN/OUT: session handle + ); +void +SessionFlush( + TPM_HANDLE handle // IN: loaded or saved session handle + ); +void +SessionComputeBoundEntity( + TPMI_DH_ENTITY entityHandle, // IN: handle of entity + TPM2B_NAME *bind // OUT: binding value + ); +void +SessionSetStartTime( + SESSION *session // IN: the session to update + ); +void +SessionResetPolicyData( + SESSION *session // IN: the session to reset + ); +TPMI_YES_NO +SessionCapGetLoaded( + TPMI_SH_POLICY handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ); +TPMI_YES_NO +SessionCapGetSaved( + TPMI_SH_HMAC handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE *handleList // OUT: list of handle + ); +UINT32 +SessionCapGetLoadedNumber( + void + ); +UINT32 +SessionCapGetLoadedAvail( + void + ); +UINT32 +SessionCapGetActiveNumber( + void + ); +UINT32 +SessionCapGetActiveAvail( + void + ); + + +#endif diff --git a/src/tpm2/SetAlgorithmSet_fp.h b/src/tpm2/SetAlgorithmSet_fp.h new file mode 100644 index 0000000..dab38ff --- /dev/null +++ b/src/tpm2/SetAlgorithmSet_fp.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SetAlgorithmSet_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef SETALGORITHMSET_FP_H +#define SETALGORITHMSET_FP_H + +typedef struct { + TPMI_RH_PLATFORM authHandle; + UINT32 algorithmSet; +} SetAlgorithmSet_In; + +#define RC_SetAlgorithmSet_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_SetAlgorithmSet_algorithmSet (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_SetAlgorithmSet( + SetAlgorithmSet_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/SetCommandCodeAuditStatus_fp.h b/src/tpm2/SetCommandCodeAuditStatus_fp.h new file mode 100644 index 0000000..af6cfc3 --- /dev/null +++ b/src/tpm2/SetCommandCodeAuditStatus_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SetCommandCodeAuditStatus_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef SETCOMMANDCODEAUDITSTATUS_FP_H +#define SETCOMMANDCODEAUDITSTATUS_FP_H + +typedef struct { + TPMI_RH_PROVISION auth; + TPMI_ALG_HASH auditAlg; + TPML_CC setList; + TPML_CC clearList; +} SetCommandCodeAuditStatus_In; + +#define RC_SetCommandCodeAuditStatus_auth (TPM_RC_H + TPM_RC_1) +#define RC_SetCommandCodeAuditStatus_auditAlg (TPM_RC_P + TPM_RC_1) +#define RC_SetCommandCodeAuditStatus_setList (TPM_RC_P + TPM_RC_2) +#define RC_SetCommandCodeAuditStatus_clearList (TPM_RC_P + TPM_RC_3) + +TPM_RC +TPM2_SetCommandCodeAuditStatus( + SetCommandCodeAuditStatus_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/SetPrimaryPolicy_fp.h b/src/tpm2/SetPrimaryPolicy_fp.h new file mode 100644 index 0000000..3c4d374 --- /dev/null +++ b/src/tpm2/SetPrimaryPolicy_fp.h @@ -0,0 +1,80 @@ +/********************************************************************************/ +/* */ +/* TPM2_SetPrimaryPolicy Command Header */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SetPrimaryPolicy_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef SETPRIMARYPOLICY_FP_H +#define SETPRIMARYPOLICY_FP_H + +typedef struct { + TPMI_RH_HIERARCHY_POLICY authHandle; + TPM2B_DIGEST authPolicy; + TPMI_ALG_HASH hashAlg; +} SetPrimaryPolicy_In; + +#define RC_SetPrimaryPolicy_authHandle (TPM_RC_H + TPM_RC_1) +#define RC_SetPrimaryPolicy_authPolicy (TPM_RC_P + TPM_RC_1) +#define RC_SetPrimaryPolicy_hashAlg (TPM_RC_P + TPM_RC_2) + +TPM_RC +TPM2_SetPrimaryPolicy( + SetPrimaryPolicy_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/Shutdown_fp.h b/src/tpm2/Shutdown_fp.h new file mode 100644 index 0000000..ceb6a8e --- /dev/null +++ b/src/tpm2/Shutdown_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Shutdown_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef SHUTDOWN_FP_H +#define SHUTDOWN_FP_H + +typedef struct{ + TPM_SU shutdownType; +} Shutdown_In; + +#define RC_Shutdown_shutdownType (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_Shutdown( + Shutdown_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/Sign_fp.h b/src/tpm2/Sign_fp.h new file mode 100644 index 0000000..16a8ba7 --- /dev/null +++ b/src/tpm2/Sign_fp.h @@ -0,0 +1,89 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Sign_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef SIGN_FP_H +#define SIGN_FP_H + +typedef struct { + TPMI_DH_OBJECT keyHandle; + TPM2B_DIGEST digest; + TPMT_SIG_SCHEME inScheme; + TPMT_TK_HASHCHECK validation; +} Sign_In; + +#define RC_Sign_keyHandle (TPM_RC_H + TPM_RC_1) +#define RC_Sign_digest (TPM_RC_P + TPM_RC_1) +#define RC_Sign_inScheme (TPM_RC_P + TPM_RC_2) +#define RC_Sign_validation (TPM_RC_P + TPM_RC_3) + +typedef struct { + TPMT_SIGNATURE signature; +} Sign_Out; + +TPM_RC +TPM2_Sign( + Sign_In *in, // IN: input parameter list + Sign_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/SigningCommands.c b/src/tpm2/SigningCommands.c new file mode 100644 index 0000000..529c40c --- /dev/null +++ b/src/tpm2/SigningCommands.c @@ -0,0 +1,156 @@ +/********************************************************************************/ +/* */ +/* Signing and Signature Verification */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SigningCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "VerifySignature_fp.h" +#if CC_VerifySignature // Conditional expansion of this file +TPM_RC +TPM2_VerifySignature( + VerifySignature_In *in, // IN: input parameter list + VerifySignature_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *signObject = HandleToObject(in->keyHandle); + TPMI_RH_HIERARCHY hierarchy; + // Input Validation + // The object to validate the signature must be a signing key. + if(!IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_ATTRIBUTES + RC_VerifySignature_keyHandle; + // Validate Signature. TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE + // error may be returned by CryptCVerifySignatrue() + result = CryptValidateSignature(in->keyHandle, &in->digest, &in->signature); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_VerifySignature_signature); + // Command Output + hierarchy = GetHieriarchy(in->keyHandle); + if(hierarchy == TPM_RH_NULL + || signObject->publicArea.nameAlg == TPM_ALG_NULL) + { + // produce empty ticket if hierarchy is TPM_RH_NULL or nameAlg is + // TPM_ALG_NULL + out->validation.tag = TPM_ST_VERIFIED; + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + else + { + // Compute ticket + TicketComputeVerified(hierarchy, &in->digest, &signObject->name, + &out->validation); + } + return TPM_RC_SUCCESS; +} +#endif // CC_VerifySignature +#include "Tpm.h" +#include "Sign_fp.h" +#if CC_Sign // Conditional expansion of this file +#include "Attest_spt_fp.h" +TPM_RC +TPM2_Sign( + Sign_In *in, // IN: input parameter list + Sign_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + TPMT_TK_HASHCHECK ticket; + OBJECT *signObject = HandleToObject(in->keyHandle); + // + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_Sign_keyHandle; + + // A key that will be used for x.509 signatures can't be used in TPM2_Sign(). + if(IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, x509sign)) + return TPM_RCS_ATTRIBUTES + RC_Sign_keyHandle; + + // pick a scheme for sign. If the input sign scheme is not compatible with + // the default scheme, return an error. + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_Sign_inScheme; + // If validation is provided, or the key is restricted, check the ticket + if(in->validation.digest.t.size != 0 + || IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, restricted)) + { + // Compute and compare ticket + TicketComputeHashCheck(in->validation.hierarchy, + in->inScheme.details.any.hashAlg, + &in->digest, &ticket); + if(!MemoryEqual2B(&in->validation.digest.b, &ticket.digest.b)) + return TPM_RCS_TICKET + RC_Sign_validation; + } + else + // If we don't have a ticket, at least verify that the provided 'digest' + // is the size of the scheme hashAlg digest. + // NOTE: this does not guarantee that the 'digest' is actually produced using + // the indicated hash algorithm, but at least it might be. + { + if(in->digest.t.size + != CryptHashGetDigestSize(in->inScheme.details.any.hashAlg)) + return TPM_RCS_SIZE + RC_Sign_digest; + } + // Command Output + // Sign the hash. A TPM_RC_VALUE or TPM_RC_SCHEME + // error may be returned at this point + result = CryptSign(signObject, &in->inScheme, &in->digest, &out->signature); + return result; +} +#endif // CC_Sign diff --git a/src/tpm2/Simulator_fp.h b/src/tpm2/Simulator_fp.h new file mode 100644 index 0000000..aedcc91 --- /dev/null +++ b/src/tpm2/Simulator_fp.h @@ -0,0 +1,212 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Simulator_fp.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* D.2 Simulator_fp.h */ +#ifndef _SIMULATOR_FP_H_ +#define _SIMULATOR_FP_H_ + +#include + +#ifdef TPM_WINDOWS +#include +#include +#endif + +#ifdef TPM_POSIX +#include +#include +#include +#include +#include +#endif + +/* D.2.1. From TcpServer.c */ +/* D.2.1.1. PlatformServer() */ +/* Moved to TpmServer_fp.h because it's different for Windows and Unix */ + +/* D.2.2. From TPMCmdp.c */ +/* D.2.2.1. Signal_PowerOn() */ +/* This function processes a power-on indication. Among other things, it calls the _TPM_Init() + handler. */ +void +_rpc__Signal_PowerOn( + bool isReset + ); +/* D.2.2.2. Signal_Restart() */ +/* This function processes the clock restart indication. All it does is call the platform + function. */ +void +_rpc__Signal_Restart( + void + ); +/* D.2.2.3. Signal_PowerOff() */ +/* This function processes the power off indication. Its primary function is to set a flag + indicating that the next power on indication should cause _TPM_Init() to be called. */ +void +_rpc__Signal_PowerOff( + void + ); +#if 0 /* libtpms added */ +/* D.2.2.4. _rpc__ForceFailureMode() */ +/* This function is used to debug the Failure Mode logic of the TPM. It will set a flag in the TPM + code such that the next call to TPM2_SelfTest() will result in a failure, putting the TPM into + Failure Mode. */ +void +_rpc__ForceFailureMode( + void + ); +/* D.2.2.5. _rpc__Signal_PhysicalPresenceOn() */ +/* This function is called to simulate activation of the physical presence pin. */ +void +_rpc__Signal_PhysicalPresenceOn( + void + ); +/* D.2.2.6. _rpc__Signal_PhysicalPresenceOff() */ +/* This function is called to simulate deactivation of the physical presence pin. */ +void +_rpc__Signal_PhysicalPresenceOff( + void + ); +/* D.2.2.7. _rpc__Signal_Hash_Start() */ +/* This function is called to simulate a _TPM_Hash_Start() event. It will call */ +void +_rpc__Signal_Hash_Start( + void + ); +/* D.2.2.8. _rpc__Signal_Hash_Data() */ +/* This function is called to simulate a _TPM_Hash_Data() event. */ +void +_rpc__Signal_Hash_Data( + _IN_BUFFER input + ); +/* D.2.2.9. _rpc__Signal_HashEnd() */ +/* This function is called to simulate a _TPM_Hash_End() event. */ +void +_rpc__Signal_HashEnd( + void + ); +#endif /* libtpms added */ +/* rpc__Send_Command() This is the interface to the TPM code. */ +void +_rpc__Send_Command( + unsigned char locality, + _IN_BUFFER request, + _OUT_BUFFER *response + ); + +/* D.2.2.10. _rpc__Signal_CancelOn() */ +/* This function is used to turn on the indication to cancel a command in process. An executing + command is not interrupted. The command code may periodically check this indication to see if it + should abort the current command processing and returned TPM_RC_CANCELLED. */ +void +_rpc__Signal_CancelOn( + void + ); +/* D.2.2.11. _rpc__Signal_CancelOff() */ +/* This function is used to turn off the indication to cancel a command in process. */ +void +_rpc__Signal_CancelOff( + void + ); +/* D.2.2.12. _rpc__Signal_NvOn() */ +/* In a system where the NV memory used by the TPM is not within the TPM, the NV may not always be + available. This function turns on the indicator that indicates that NV is available. */ +void +_rpc__Signal_NvOn( + void + ); +#if 0 /* libtpms added */ +/* D.2.2.13. _rpc__Signal_NvOff() */ +/* This function is used to set the indication that NV memory is no longer available. */ +void +_rpc__Signal_NvOff( + void + ); +/* D.2.2.14. _rpc__RsaKeyCacheControl() */ +/* This function is used to enable/disable the use of the RSA key cache during simulation. */ +void +_rpc__RsaKeyCacheControl( + int state + ); +/* D.4.2.15. _rpc__ACT_GetSignaled() */ +bool +_rpc__ACT_GetSignaled( + uint32_t actHandle + ); + +/* D.2.3. From TPMCmds.c */ +/* D.2.3.1. main() */ +/* This is the main entry point for the simulator. */ +int +main( + int argc, + char *argv[] + ); +#endif /* libtpms added */ +/* libtpms added begin */ +void _rpc__Signal_SetTPMEstablished(void); +bool _rpc__Signal_GetTPMEstablished(void); +void _rpc__Signal_ResetTPMEstablished(void); +bool _rpc__Signal_IsPowerOn(void); +/* libtpms added end */ + +#endif // _SIMULATOR_FP_H_ + diff --git a/src/tpm2/StartAuthSession_fp.h b/src/tpm2/StartAuthSession_fp.h new file mode 100644 index 0000000..c284864 --- /dev/null +++ b/src/tpm2/StartAuthSession_fp.h @@ -0,0 +1,97 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: StartAuthSession_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef STARTAUTHSESSION_FP_H +#define STARTAUTHSESSION_FP_H + +typedef struct { + TPMI_DH_OBJECT tpmKey; + TPMI_DH_ENTITY bind; + TPM2B_NONCE nonceCaller; + TPM2B_ENCRYPTED_SECRET encryptedSalt; + TPM_SE sessionType; + TPMT_SYM_DEF symmetric; + TPMI_ALG_HASH authHash; +} StartAuthSession_In; + +typedef struct { + TPMI_SH_AUTH_SESSION sessionHandle; + TPM2B_NONCE nonceTPM; +} StartAuthSession_Out; + +#define RC_StartAuthSession_tpmKey (TPM_RC_H + TPM_RC_1) +#define RC_StartAuthSession_bind (TPM_RC_H + TPM_RC_2) +#define RC_StartAuthSession_nonceCaller (TPM_RC_P + TPM_RC_1) +#define RC_StartAuthSession_encryptedSalt (TPM_RC_P + TPM_RC_2) +#define RC_StartAuthSession_sessionType (TPM_RC_P + TPM_RC_3) +#define RC_StartAuthSession_symmetric (TPM_RC_P + TPM_RC_4) +#define RC_StartAuthSession_authHash (TPM_RC_P + TPM_RC_5) + +TPM_RC +TPM2_StartAuthSession( + StartAuthSession_In *in, // IN: input parameter buffer + StartAuthSession_Out *out // OUT: output parameter buffer + ); + + +#endif diff --git a/src/tpm2/StartupCommands.c b/src/tpm2/StartupCommands.c new file mode 100644 index 0000000..1212b46 --- /dev/null +++ b/src/tpm2/StartupCommands.c @@ -0,0 +1,349 @@ +/********************************************************************************/ +/* */ +/* Startup Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: StartupCommands.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 9.2 _TPM_Init */ +#include "Tpm.h" +#include "PlatformACT_fp.h" /* added kgold */ +#include "_TPM_Init_fp.h" +#include "StateMarshal.h" /* libtpms added */ +// This function is used to process a _TPM_Init indication. +LIB_EXPORT void +_TPM_Init( + void + ) +{ + BOOL restored = FALSE; /* libtpms added */ + + g_powerWasLost = g_powerWasLost | _plat__WasPowerLost(); +#if SIMULATION && !defined NDEBUG /* libtpms changed */ + // If power was lost and this was a simulation, put canary in RAM used by NV + // so that uninitialized memory can be detected more easily + if(g_powerWasLost) + { + memset(&gc, 0xbb, sizeof(gc)); + memset(&gr, 0xbb, sizeof(gr)); + memset(&gp, 0xbb, sizeof(gp)); + memset(&go, 0xbb, sizeof(go)); + } +#endif +#if SIMULATION + // Clear the flag that forces failure on self-test + g_forceFailureMode = FALSE; +#endif + // Disable the tick processing + _plat__ACT_EnableTicks(FALSE); + // Set initialization state + TPMInit(); + // Set g_DRTMHandle as unassigned + g_DRTMHandle = TPM_RH_UNASSIGNED; + // No H-CRTM, yet. + g_DrtmPreStartup = FALSE; + // Initialize the NvEnvironment. + g_nvOk = NvPowerOn(); + // Initialize cryptographic functions + g_inFailureMode |= (CryptInit() == FALSE); /* libtpms changed */ + if(!g_inFailureMode) + { + // Load the persistent data + NvReadPersistent(); + // Load the orderly data (clock and DRBG state). + // If this is not done here, things break + NvRead(&go, NV_ORDERLY_DATA, sizeof(go)); + // Start clock. Need to do this after NV has been restored. + TimePowerOn(); + + /* libtpms added begin */ + VolatileLoad(&restored); + if (restored) + NVShadowRestore(); + /* libtpms added end */ + } + return; +} +#include "Tpm.h" +#include "Startup_fp.h" +#if CC_Startup // Conditional expansion of this file +TPM_RC +TPM2_Startup( + Startup_In *in // IN: input parameter list + ) +{ + STARTUP_TYPE startup; + BYTE locality = _plat__LocalityGet(); + BOOL OK = TRUE; // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Get the flags for the current startup locality and the H-CRTM. + // Rather than generalizing the locality setting, this code takes advantage + // of the fact that the PC Client specification only allows Startup() + // from locality 0 and 3. To generalize this probably would require a + // redo of the NV space and since this is a feature that is hardly ever used + // outside of the PC Client, this code just support the PC Client needs. + // Input Validation + // Check that the locality is a supported value + if(locality != 0 && locality != 3) + return TPM_RC_LOCALITY; + // If there was a H-CRTM, then treat the locality as being 3 + // regardless of what the Startup() was. This is done to preserve the + // H-CRTM PCR so that they don't get overwritten with the normal + // PCR startup initialization. This basically means that g_StartupLocality3 + // and g_DrtmPreStartup can't both be SET at the same time. + if(g_DrtmPreStartup) + locality = 0; + g_StartupLocality3 = (locality == 3); +#if USE_DA_USED + // If there was no orderly shutdown, then there might have been a write to + // failedTries that didn't get recorded but only if g_daUsed was SET in the + // shutdown state + g_daUsed = (gp.orderlyState == SU_DA_USED_VALUE); + if(g_daUsed) + gp.orderlyState = SU_NONE_VALUE; +#endif + g_prevOrderlyState = gp.orderlyState; + // If there was a proper shutdown, then the startup modifiers are in the + // orderlyState. Turn them off in the copy. + if(IS_ORDERLY(g_prevOrderlyState)) + g_prevOrderlyState &= ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3); + // If this is a Resume, + if(in->startupType == TPM_SU_STATE) + { + // then there must have been a prior TPM2_ShutdownState(STATE) + if(g_prevOrderlyState != TPM_SU_STATE) + return TPM_RCS_VALUE + RC_Startup_startupType; + // and the part of NV used for state save must have been recovered + // correctly. + // NOTE: if this fails, then the caller will need to do Startup(CLEAR). The + // code for Startup(Clear) cannot fail if the NV can't be read correctly + // because that would prevent the TPM from ever getting unstuck. + if(g_nvOk == FALSE) + return TPM_RC_NV_UNINITIALIZED; + // For Resume, the H-CRTM has to be the same as the previous boot + if(g_DrtmPreStartup != ((gp.orderlyState & PRE_STARTUP_FLAG) != 0)) + return TPM_RCS_VALUE + RC_Startup_startupType; + if(g_StartupLocality3 != ((gp.orderlyState & STARTUP_LOCALITY_3) != 0)) + return TPM_RC_LOCALITY; + } + // Clean up the gp state + gp.orderlyState = g_prevOrderlyState; + + // Internal Date Update + if((gp.orderlyState == TPM_SU_STATE) && (g_nvOk == TRUE)) + { + // Always read the data that is only cleared on a Reset because this is not + // a reset + NvRead(&gr, NV_STATE_RESET_DATA, sizeof(gr)); + if(in->startupType == TPM_SU_STATE) + { + // If this is a startup STATE (a Resume) need to read the data + // that is cleared on a startup CLEAR because this is not a Reset + // or Restart. + NvRead(&gc, NV_STATE_CLEAR_DATA, sizeof(gc)); + startup = SU_RESUME; + } + else + startup = SU_RESTART; + } + else + // Will do a TPM reset if Shutdown(CLEAR) and Startup(CLEAR) or no shutdown + // or there was a failure reading the NV data. + startup = SU_RESET; + // Startup for cryptographic library. Don't do this until after the orderly + // state has been read in from NV. + OK = OK && CryptStartup(startup); + // When the cryptographic library has been started, indicate that a TPM2_Startup + // command has been received. + OK = OK && TPMRegisterStartup(); + // Read the platform unique value that is used as VENDOR_PERMANENT + // authorization value + g_platformUniqueDetails.t.size + = (UINT16)_plat__GetUnique(1, sizeof(g_platformUniqueDetails.t.buffer), + g_platformUniqueDetails.t.buffer); + // Start up subsystems + // Start set the safe flag + OK = OK && TimeStartup(startup); + // Start dictionary attack subsystem + OK = OK && DAStartup(startup); + // Enable hierarchies + OK = OK && HierarchyStartup(startup); + // Restore/Initialize PCR + OK = OK && PCRStartup(startup, locality); + // Restore/Initialize command audit information + OK = OK && CommandAuditStartup(startup); + // Restore the ACT + OK = OK && ActStartup(startup); + //// The following code was moved from Time.c where it made no sense + if (OK) + { + switch (startup) + { + case SU_RESUME: + // Resume sequence + gr.restartCount++; + break; + case SU_RESTART: + // Hibernate sequence + gr.clearCount++; + gr.restartCount++; + break; + default: + // Reset object context ID to 0 + gr.objectContextID = 0; + // Reset clearCount to 0 + gr.clearCount = 0; + // Reset sequence + // Increase resetCount + gp.resetCount++; + // Write resetCount to NV + NV_SYNC_PERSISTENT(resetCount); + gp.totalResetCount++; + // We do not expect the total reset counter overflow during the life + // time of TPM. if it ever happens, TPM will be put to failure mode + // and there is no way to recover it. + // The reason that there is no recovery is that we don't increment + // the NV totalResetCount when incrementing would make it 0. When the + // TPM starts up again, the old value of totalResetCount will be read + // and we will get right back to here with the increment failing. +#if 0 // libtpms added + if(gp.totalResetCount == 0) + FAIL(FATAL_ERROR_INTERNAL); +#endif // libtpms added + // Write total reset counter to NV + NV_SYNC_PERSISTENT(totalResetCount); + // Reset restartCount + gr.restartCount = 0; + break; + } + } + // Initialize session table + OK = OK && SessionStartup(startup); + // Initialize object table + OK = OK && ObjectStartup(); + // Initialize index/evict data. This function clears read/write locks + // in NV index + OK = OK && NvEntityStartup(startup); + // Initialize the orderly shut down flag for this cycle to SU_NONE_VALUE. + gp.orderlyState = SU_NONE_VALUE; + OK = OK && NV_SYNC_PERSISTENT(orderlyState); + // This can be reset after the first completion of a TPM2_Startup() after + // a power loss. It can probably be reset earlier but this is an OK place. + if (OK) + g_powerWasLost = FALSE; + return (OK) ? TPM_RC_SUCCESS : TPM_RC_FAILURE; +} +#endif // CC_Startup +#include "Tpm.h" +#include "Shutdown_fp.h" +#if CC_Shutdown // Conditional expansion of this file +TPM_RC +TPM2_Shutdown( + Shutdown_In *in // IN: input parameter list + ) +{ + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + // Input Validation + // If PCR bank has been reconfigured, a CLEAR state save is required + if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE) + return TPM_RCS_TYPE + RC_Shutdown_shutdownType; + // Internal Data Update + gp.orderlyState = in->shutdownType; +#if USE_DA_USED + // CLEAR g_daUsed so that any future DA-protected access will cause the + // shutdown to become non-orderly. It is not sufficient to invalidate the + // shutdown state after a DA failure because an attacker can inhibit access + // to NV and use the fact that an update of failedTries was attempted as an + // indication of an authorization failure. By making sure that the orderly state + // is CLEAR before any DA attempt, this prevents the possibility of this 'attack.' + g_daUsed = FALSE; +#endif + // PCR private date state save + PCRStateSave(in->shutdownType); + // Save the ACT state + ActShutdown(in->shutdownType); + // Save RAM backed NV index data + NvUpdateIndexOrderlyData(); +#if ACCUMULATE_SELF_HEAL_TIMER + // Save the current time value + go.time = g_time; +#endif + // Save all orderly data + NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); + if(in->shutdownType == TPM_SU_STATE) + { + // Save STATE_RESET and STATE_CLEAR data + NvWrite(NV_STATE_CLEAR_DATA, sizeof(STATE_CLEAR_DATA), &gc); + NvWrite(NV_STATE_RESET_DATA, sizeof(STATE_RESET_DATA), &gr); + // Save the startup flags for resume + if(g_DrtmPreStartup) + gp.orderlyState = TPM_SU_STATE | PRE_STARTUP_FLAG; + else if(g_StartupLocality3) + gp.orderlyState = TPM_SU_STATE | STARTUP_LOCALITY_3; + } + // only two shutdown options + else if(in->shutdownType != TPM_SU_CLEAR) + { + return TPM_RCS_VALUE + RC_Shutdown_shutdownType; + } + NV_SYNC_PERSISTENT(orderlyState); + return TPM_RC_SUCCESS; +} +#endif // CC_Shutdown diff --git a/src/tpm2/Startup_fp.h b/src/tpm2/Startup_fp.h new file mode 100644 index 0000000..1aaad54 --- /dev/null +++ b/src/tpm2/Startup_fp.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Startup_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef STARTUP_FP_H +#define STARTUP_FP_H + +void +_TPM_Init( + void + ); + + +typedef struct { + TPM_SU startupType; +} Startup_In; + +#define RC_Startup_startupType (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_Startup( + Startup_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/StateMarshal.c b/src/tpm2/StateMarshal.c new file mode 100644 index 0000000..fbb2662 --- /dev/null +++ b/src/tpm2/StateMarshal.c @@ -0,0 +1,98 @@ +/********************************************************************************/ +/* */ +/* Marshalling and unmarshalling of state */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#include "config.h" + +#include "StateMarshal.h" +#include "Volatile.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" +#include "tpm_nvfilename.h" +#include "tpm_error.h" +#include "tpm_memory.h" + +UINT16 +VolatileSave(BYTE **buffer, INT32 *size) +{ + return VolatileState_Save(buffer, size); +} + +TPM_RC +VolatileLoad(BOOL *restored) +{ + TPM_RC rc = TPM_RC_SUCCESS; + +#ifdef TPM_LIBTPMS_CALLBACKS + unsigned char *data = NULL; + uint32_t length = 0; + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + TPM_RESULT ret = TPM_SUCCESS; + bool is_empty_state; + + *restored = FALSE; + + /* try to get state blob set via TPMLIB_SetState() */ + GetCachedState(TPMLIB_STATE_VOLATILE, &data, &length, &is_empty_state); + if (is_empty_state) + return rc; + + if (!data && cbs->tpm_nvram_loaddata) { + uint32_t tpm_number = 0; + const char *name = TPM_VOLATILESTATE_NAME; + + ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name); + } + + if (data && ret == TPM_SUCCESS) { + unsigned char *p = data; + rc = VolatileState_Load(&data, (INT32 *)&length); + /* + * if this failed, VolatileState_Load will have started + * failure mode. + */ + free(p); + + *restored = (rc == 0); + } +#endif /* TPM_LIBTPMS_CALLBACKS */ + + return rc; +} diff --git a/src/tpm2/StateMarshal.h b/src/tpm2/StateMarshal.h new file mode 100644 index 0000000..6fc6d14 --- /dev/null +++ b/src/tpm2/StateMarshal.h @@ -0,0 +1,53 @@ +/********************************************************************************/ +/* */ +/* Marshalling and unmarshalling of state */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef STATE_MARSHAL_H +#define STATE_MARSHAL_H + +#include "Tpm.h" +#include "TpmTypes.h" + +/* + * we keep these in a separate file to avoid symbol clashes when + * included from the interface code. + */ +TPM_RC VolatileLoad(BOOL *restored); +UINT16 VolatileSave(BYTE **buffer, INT32 *size); + +#endif /* STATE_MARSHAL_H */ + diff --git a/src/tpm2/StirRandom_fp.h b/src/tpm2/StirRandom_fp.h new file mode 100644 index 0000000..40ee129 --- /dev/null +++ b/src/tpm2/StirRandom_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: StirRandom_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef STIRRANDOM_FP_H +#define STIRRANDOM_FP_H + +typedef struct { + TPM2B_SENSITIVE_DATA inData; +} StirRandom_In; + +#define RC_StirRandom_inData (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_StirRandom( + StirRandom_In *in // IN: input parameter list + ); + +#endif diff --git a/src/tpm2/SupportLibraryFunctionPrototypes_fp.h b/src/tpm2/SupportLibraryFunctionPrototypes_fp.h new file mode 100644 index 0000000..3b1e1a9 --- /dev/null +++ b/src/tpm2/SupportLibraryFunctionPrototypes_fp.h @@ -0,0 +1,156 @@ +/********************************************************************************/ +/* */ +/* For Selected Math Library */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SupportLibraryFunctionPrototypes_fp.h 1529 2019-11-21 23:29:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H +#define SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H + +/* 10.1.11 SupportLibraryFunctionPrototypes_fp.h */ +/* 10.1.11.1 Introduction */ + +/* This file contains the function prototypes for the functions that need to be present in the + selected math library. For each function listed, there should be a small stub function. That + stub provides the interface between the TPM code and the support library. In most cases, the stub + function will only need to do a format conversion between the TPM big number and the support + library big number. The TPM big number format was chosen to make this relatively simple and + fast. */ + + +/* 10.1.11.2 SupportLibInit() */ +/* This function is called by CryptInit() so that necessary initializations can be performed on the + cryptographic library. */ + + +LIB_EXPORT +int SupportLibInit(void); + + +/* 10.1.11.3 MathLibraryCompatibililtyCheck() */ +/* This function is only used during development to make sure that the library that is being + referenced is using the same size of data structures as the TPM. */ + +BOOL +MathLibraryCompatibilityCheck( + void + ); +/* 10.1.1114 BnModMult() */ +/* Does multiply op1 * op2 and divide by modulus returning the remainder of the divide. */ + +LIB_EXPORT BOOL +BnModMult(bigNum result, bigConst op1, bigConst op2, bigConst modulus); + +/* 10.1.11.5 BnMult() */ +/* Multiplies two numbers and returns the result */ + +LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier); + +/* 10.1.11.6 BnDiv() */ +/* This function divides two bigNum values. The function returns FALSE if there is an error in the + operation. */ +LIB_EXPORT BOOL BnDiv(bigNum quotient, bigNum remainder, + bigConst dividend, bigConst divisor); + +/* 10.1.11.7 BnMod() */ +#define BnMod(a, b) BnDiv(NULL, (a), (a), (b)) + +/* 10.1.11.8 BnGcd() */ +/* Get the greatest common divisor of two numbers. This function is only needed when the TPM + implements RSA. */ +LIB_EXPORT BOOL BnGcd(bigNum gcd, bigConst number1, bigConst number2); + +/* 10.1.11.9 BnModExp() */ +/* Do modular exponentiation using bigNum values. This function is only needed when the TPM + implements RSA. */ +LIB_EXPORT BOOL BnModExp(bigNum result, bigConst number, + bigConst exponent, bigConst modulus); + +/* 10.1.11.10 BnModInverse() */ +/* Modular multiplicative inverse. This function is only needed when the TPM implements RSA. */ +LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, + bigConst modulus); + +/* 10.1.11.11 BnEccModMult() */ +/* This function does a point multiply of the form R = [d]S. A return of FALSE indicates that the + result was the point at infinity. This function is only needed if the TPM supports ECC. */ +LIB_EXPORT BOOL BnEccModMult(bigPoint R, pointConst S, bigConst d, bigCurve E); + +/* 10.1.11.13 BnEccModMult2() */ +/* This function does a point multiply of the form R = [d]S + [u]Q. A return of FALSE indicates that + the result was the point at infinity. This function is only needed if the TPM supports ECC */ +LIB_EXPORT BOOL BnEccModMult2(bigPoint R, pointConst S, bigConst d, + pointConst Q, bigConst u, bigCurve E); + +/* 10.1.11.14 BnEccAdd() */ +/* This function does a point add R = S + Q. A return of FALSE indicates that the result was the + point at infinity. This function is only needed if the TPM supports ECC. */ +LIB_EXPORT BOOL BnEccAdd(bigPoint R, pointConst S, pointConst Q, bigCurve E); + +/* 10.1.11.15 BnCurveInitialize() */ +/* This function is used to initialize the pointers of a bnCurve_t structure. The structure is a set + of pointers to bigNum values. The curve-dependent values are set by a different function. This + function is only needed if the TPM supports ECC.*/ +LIB_EXPORT bigCurve BnCurveInitialize(bigCurve E, TPM_ECC_CURVE curveId); + +/* 10.1.11.16 BnCurveFree() */ +/* This function will free the allocated components of the curve and end the frame in which the + curve data exists */ +LIB_EXPORT void BnCurveFree(bigCurve E); + +#endif diff --git a/src/tpm2/SymmetricCommands.c b/src/tpm2/SymmetricCommands.c new file mode 100644 index 0000000..68b6353 --- /dev/null +++ b/src/tpm2/SymmetricCommands.c @@ -0,0 +1,350 @@ +/********************************************************************************/ +/* */ +/* Symmetric Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SymmetricCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "EncryptDecrypt_fp.h" +#if CC_EncryptDecrypt2 +#include "EncryptDecrypt_spt_fp.h" +#endif +#if CC_EncryptDecrypt // Conditional expansion of this file +TPM_RC +TPM2_EncryptDecrypt( + EncryptDecrypt_In *in, // IN: input parameter list + EncryptDecrypt_Out *out // OUT: output parameter list + ) +{ +#if CC_EncryptDecrypt2 + return EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode, + &in->ivIn, &in->inData, out); +#else + OBJECT *symKey; + UINT16 keySize; + UINT16 blockSize; + BYTE *key; + TPM_ALG_ID alg; + TPM_ALG_ID mode; + TPM_RC result; + BOOL OK; + TPMA_OBJECT attributes; + // Input Validation + symKey = HandleToObject(in->keyHandle); + mode = symKey->publicArea.parameters.symDetail.sym.mode.sym; + attributes = symKey->publicArea.objectAttributes; + // The input key should be a symmetric key + if(symKey->publicArea.type != TPM_ALG_SYMCIPHER) + return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; + // The key must be unrestricted and allow the selected operation + OK = IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) + if(YES == in->decrypt) + OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt); + else + OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign); + if(!OK) + return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle; + // If the key mode is not TPM_ALG_NULL... + // or TPM_ALG_NULL + if(mode != TPM_ALG_NULL) + { + // then the input mode has to be TPM_ALG_NULL or the same as the key + if((in->mode != TPM_ALG_NULL) && (in->mode != mode)) + return TPM_RCS_MODE + RC_EncryptDecrypt_mode; + } + else + { + // if the key mode is null, then the input can't be null + if(in->mode == TPM_ALG_NULL) + return TPM_RCS_MODE + RC_EncryptDecrypt_mode; + mode = in->mode; + } + // The input iv for ECB mode should be an Empty Buffer. All the other modes + // should have an iv size same as encryption block size + keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym; + alg = symKey->publicArea.parameters.symDetail.sym.algorithm; + blockSize = CryptGetSymmetricBlockSize(alg, keySize); + // reverify the algorithm. This is mainly to keep static analysis tools happy + if(blockSize == 0) + return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; + // Note: When an algorithm is not supported by a TPM, the TPM_ALG_xxx for that + // algorithm is not defined. However, it is assumed that the TPM_ALG_xxx for + // the algorithm is always defined. Both have the same numeric value. + // TPM_ALG_xxx is used here so that the code does not get cluttered with + // #ifdef's. Having this check does not mean that the algorithm is supported. + // If it was not supported the unmarshaling code would have rejected it before + // this function were called. This means that, depending on the implementation, + // the check could be redundant but it doesn't hurt. + if(((mode == TPM_ALG_ECB) && (in->ivIn.t.size != 0)) + || ((mode != TPM_ALG_ECB) && (in->ivIn.t.size != blockSize))) + return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn; + // The input data size of CBC mode or ECB mode must be an even multiple of + // the symmetric algorithm's block size + if(((mode == TPM_ALG_CBC) || (mode == TPM_ALG_ECB)) + && ((in->inData.t.size % blockSize) != 0)) + return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; + // Copy IV + // Note: This is copied here so that the calls to the encrypt/decrypt functions + // will modify the output buffer, not the input buffer + out->ivOut = in->ivIn; + // Command Output + key = symKey->sensitive.sensitive.sym.t.buffer; + // For symmetric encryption, the cipher data size is the same as plain data + // size. + out->outData.t.size = in->inData.t.size; + if(in->decrypt == YES) + { + // Decrypt data to output + result = CryptSymmetricDecrypt(out->outData.t.buffer, alg, keySize, key, + &(out->ivOut), mode, in->inData.t.size, + in->inData.t.buffer); + } + else + { + // Encrypt data to output + result = CryptSymmetricEncrypt(out->outData.t.buffer, alg, keySize, key, + &(out->ivOut), mode, in->inData.t.size, + in->inData.t.buffer); + } + return result; +#endif // CC_EncryptDecrypt2 +} +#endif // CC_EncryptDecrypt +#include "Tpm.h" +#include "EncryptDecrypt2_fp.h" +#include "EncryptDecrypt_spt_fp.h" +#if CC_EncryptDecrypt2 // Conditional expansion of this file +TPM_RC +TPM2_EncryptDecrypt2( + EncryptDecrypt2_In *in, // IN: input parameter list + EncryptDecrypt2_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + // EncryptDecyrptShared() performs the operations as shown in + // TPM2_EncrypDecrypt + result = EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode, + &in->ivIn, &in->inData, + (EncryptDecrypt_Out *)out); + // Handle response code swizzle. + switch(result) + { + case TPM_RCS_MODE + RC_EncryptDecrypt_mode: + result = TPM_RCS_MODE + RC_EncryptDecrypt2_mode; + break; + case TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn: + result = TPM_RCS_SIZE + RC_EncryptDecrypt2_ivIn; + break; + case TPM_RCS_SIZE + RC_EncryptDecrypt_inData: + result = TPM_RCS_SIZE + RC_EncryptDecrypt2_inData; + break; + default: + break; + } + return result; +} +#endif // CC_EncryptDecrypt2 +#include "Tpm.h" +#include "Hash_fp.h" +#if CC_Hash // Conditional expansion of this file +TPM_RC +TPM2_Hash( + Hash_In *in, // IN: input parameter list + Hash_Out *out // OUT: output parameter list + ) +{ + HASH_STATE hashState; + // Command Output + // Output hash + // Start hash stack + out->outHash.t.size = CryptHashStart(&hashState, in->hashAlg); + // Adding hash data + CryptDigestUpdate2B(&hashState, &in->data.b); + // Complete hash + CryptHashEnd2B(&hashState, &out->outHash.b); + // Output ticket + out->validation.tag = TPM_ST_HASHCHECK; + out->validation.hierarchy = in->hierarchy; + if(in->hierarchy == TPM_RH_NULL) + { + // Ticket is not required + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + else if(in->data.t.size >= sizeof(TPM_GENERATED_VALUE) + && !TicketIsSafe(&in->data.b)) + { + // Ticket is not safe + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + else + { + // Compute ticket + TicketComputeHashCheck(in->hierarchy, in->hashAlg, + &out->outHash, &out->validation); + } + return TPM_RC_SUCCESS; +} +#endif // CC_Hash +#include "Tpm.h" +#include "HMAC_fp.h" +#if CC_HMAC // Conditional expansion of this file +TPM_RC +TPM2_HMAC( + HMAC_In *in, // IN: input parameter list + HMAC_Out *out // OUT: output parameter list + ) +{ + HMAC_STATE hmacState; + OBJECT *hmacObject; + TPMI_ALG_HASH hashAlg; + TPMT_PUBLIC *publicArea; + // Input Validation + // Get HMAC key object and public area pointers + hmacObject = HandleToObject(in->handle); + publicArea = &hmacObject->publicArea; + // Make sure that the key is an HMAC key + if(publicArea->type != TPM_ALG_KEYEDHASH) + return TPM_RCS_TYPE + RC_HMAC_handle; + // and that it is unrestricted + if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_HMAC_handle; + // and that it is a signing key + if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_KEY + RC_HMAC_handle; + // See if the key has a default + if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL) + // it doesn't so use the input value + hashAlg = in->hashAlg; + else + { + // key has a default so use it + hashAlg + = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg; + // and verify that the input was either the TPM_ALG_NULL or the default + if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg) + hashAlg = TPM_ALG_NULL; + } + // if we ended up without a hash algorithm then return an error + if(hashAlg == TPM_ALG_NULL) + return TPM_RCS_VALUE + RC_HMAC_hashAlg; + // Command Output + // Start HMAC stack + out->outHMAC.t.size = CryptHmacStart2B(&hmacState, hashAlg, + &hmacObject->sensitive.sensitive.bits.b); + // Adding HMAC data + CryptDigestUpdate2B(&hmacState.hashState, &in->buffer.b); + // Complete HMAC + CryptHmacEnd2B(&hmacState, &out->outHMAC.b); + return TPM_RC_SUCCESS; +} +#endif // CC_HMAC + +#include "Tpm.h" +#include "MAC_fp.h" +#if CC_MAC // Conditional expansion of this file +/* Error Returns Meaning */ +/* TPM_RC_ATTRIBUTES key referenced by handle is a restricted key */ +/* TPM_RC_KEY handle does not reference a signing key */ +/* TPM_RC_TYPE key referenced by handle is not an HMAC key */ +/* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object + referenced by handle */ +TPM_RC +TPM2_MAC( + MAC_In *in, // IN: input parameter list + MAC_Out *out // OUT: output parameter list + ) +{ + OBJECT *keyObject; + HMAC_STATE state; + TPMT_PUBLIC *publicArea; + TPM_RC result; + // Input Validation + // Get MAC key object and public area pointers + keyObject = HandleToObject(in->handle); + publicArea = &keyObject->publicArea; + // If the key is not able to do a MAC, indicate that the handle selects an + // object that can't do a MAC + result = CryptSelectMac(publicArea, &in->inScheme); + if(result == TPM_RCS_TYPE) + return TPM_RCS_TYPE + RC_MAC_handle; + // If there is another error type, indicate that the scheme and key are not + // compatible + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_MAC_inScheme); + // Make sure that the key is not restricted + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_MAC_handle; + // and that it is a signing key + if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_KEY + RC_MAC_handle; + // Command Output + out->outMAC.t.size = CryptMacStart(&state, &publicArea->parameters, + in->inScheme, + &keyObject->sensitive.sensitive.any.b); + // If the mac can't start, treat it as a fatal error + if(out->outMAC.t.size == 0) + return TPM_RC_FAILURE; + CryptDigestUpdate2B(&state.hashState, &in->buffer.b); + // If the MAC result is not what was expected, it is a fatal error + if(CryptHmacEnd2B(&state, &out->outMAC.b) != out->outMAC.t.size) + return TPM_RC_FAILURE; + return TPM_RC_SUCCESS; +} +#endif // CC_MAC diff --git a/src/tpm2/SymmetricTest.h b/src/tpm2/SymmetricTest.h new file mode 100644 index 0000000..058f50a --- /dev/null +++ b/src/tpm2/SymmetricTest.h @@ -0,0 +1,138 @@ +/********************************************************************************/ +/* */ +/* Structures and data definitions for the symmetric tests */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SymmetricTest.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.1.11 SymmetricTest.h */ + +/* 10.1.11.1 Introduction */ + +/* This file contains the structures and data definitions for the symmetric tests. This file + references the header file that contains the actual test vectors. This organization was chosen so + that the program that is used to generate the test vector values does not have to also + re-generate this data. */ + +#ifndef SELF_TEST_DATA +#error "This file may only be included in AlgorithmTests.c" +#endif +#ifndef _SYMMETRIC_TEST_H +#define _SYMMETRIC_TEST_H +#include "SymmetricTestData.h" + +/* 10.1.11.2 Symmetric Test Structures */ + +const SYMMETRIC_TEST_VECTOR c_symTestValues[NUM_SYMS + 1] = { +#if ALG_AES && AES_128 + {TPM_ALG_AES, 128, key_AES128, 16, sizeof(dataIn_AES128), dataIn_AES128, + {dataOut_AES128_CTR, dataOut_AES128_OFB, dataOut_AES128_CBC, + dataOut_AES128_CFB, dataOut_AES128_ECB}}, +#endif +#if ALG_AES && AES_192 + {TPM_ALG_AES_, 192, key_AES192, 16, sizeof(dataIn_AES192), dataIn_AES192, + {dataOut_AES192_CTR, dataOut_AES192_OFB, dataOut_AES192_CBC, + dataOut_AES192_CFB, dataOut_AES192_ECB}}, +#endif +#if ALG_AES && AES_256 + {TPM_ALG_AES, 256, key_AES256, 16, sizeof(dataIn_AES256), dataIn_AES256, + {dataOut_AES256_CTR, dataOut_AES256_OFB, dataOut_AES256_CBC, + dataOut_AES256_CFB, dataOut_AES256_ECB}}, +#endif +#if ALG_SM4 && SM4_128 // libtpms activated + {TPM_ALG_SM4, 128, key_SM4128, 16, sizeof(dataIn_SM4128), dataIn_SM4128, + {dataOut_SM4128_CTR, dataOut_SM4128_OFB, dataOut_SM4128_CBC, + dataOut_SM4128_CFB, dataOut_AES128_ECB}}, +#endif +// libtpms added begin +#if ALG_TDES && TDES_128 + {TPM_ALG_TDES, 128, key_TDES128, 8, sizeof(dataIn_TDES128), dataIn_TDES128, + {dataOut_TDES128_CTR, dataOut_TDES128_OFB, dataOut_TDES128_CBC, + dataOut_TDES128_CFB, dataOut_TDES128_ECB}}, + {TPM_ALG_TDES, 128, key_TDES128, 8, sizeof(dataInShort_TDES128), dataInShort_TDES128, + {NULL, dataOutShort_TDES128_OFB, NULL, + dataOutShort_TDES128_CFB, NULL}}, +#endif +#if ALG_TDES && TDES_192 + {TPM_ALG_TDES, 192, key_TDES192, 8, sizeof(dataIn_TDES192), dataIn_TDES192, + {dataOut_TDES192_CTR, dataOut_TDES192_OFB, dataOut_TDES192_CBC, + dataOut_TDES192_CFB, dataOut_TDES192_ECB}}, + {TPM_ALG_TDES, 192, key_TDES192, 8, sizeof(dataInShort_TDES192), dataInShort_TDES192, + {NULL, dataOutShort_TDES192_OFB, NULL, + dataOutShort_TDES192_CFB, NULL}}, +#endif +#if ALG_CAMELLIA && CAMELLIA_128 + {TPM_ALG_CAMELLIA, 128, key_CAMELLIA128, 16, sizeof(dataIn_CAMELLIA128), dataIn_CAMELLIA128, + {dataOut_CAMELLIA128_CTR, dataOut_CAMELLIA128_OFB, dataOut_CAMELLIA128_CBC, + dataOut_CAMELLIA128_CFB, dataOut_CAMELLIA128_ECB}}, +#endif +#if ALG_CAMELLIA && CAMELLIA_192 + {TPM_ALG_CAMELLIA, 192, key_CAMELLIA192, 16, sizeof(dataIn_CAMELLIA192), dataIn_CAMELLIA192, + {dataOut_CAMELLIA192_CTR, dataOut_CAMELLIA192_OFB, dataOut_CAMELLIA192_CBC, + dataOut_CAMELLIA192_CFB, dataOut_CAMELLIA192_ECB}}, +#endif +#if ALG_CAMELLIA && CAMELLIA_256 + {TPM_ALG_CAMELLIA, 256, key_CAMELLIA256, 16, sizeof(dataIn_CAMELLIA256), dataIn_CAMELLIA256, + {dataOut_CAMELLIA256_CTR, dataOut_CAMELLIA256_OFB, dataOut_CAMELLIA256_CBC, + dataOut_CAMELLIA256_CFB, dataOut_CAMELLIA256_ECB}}, +#endif +// libtpms added end + {0} +}; + +#endif // _SYMMETRIC_TEST_H + diff --git a/src/tpm2/SymmetricTestData.h b/src/tpm2/SymmetricTestData.h new file mode 100644 index 0000000..77321fa --- /dev/null +++ b/src/tpm2/SymmetricTestData.h @@ -0,0 +1,400 @@ +/********************************************************************************/ +/* */ +/* Vector for testing Either Encrypt or Decrypt */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: SymmetricTestData.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef SYMMETRICTESTDATA_H +#define SYMMETRICTESTDATA_H + +/* 10.1.10 SymmetricTestData.h */ +/* This is a vector for testing either encrypt or decrypt. The premise for decrypt is that the IV + for decryption is the same as the IV for encryption. However, the ivOut value may be different + for encryption and decryption. We will encrypt at least two blocks. This means that the chaining + value will be used for each of the schemes (if any) and that implicitly checks that the chaining + value is handled properly. */ +#if AES_128 +const BYTE key_AES128 [] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; +const BYTE dataIn_AES128 [] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; +const BYTE dataOut_AES128_ECB [] = { + 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, + 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97, + 0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d, + 0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf}; +const BYTE dataOut_AES128_CBC [] = { + 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, + 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2}; +const BYTE dataOut_AES128_CFB [] = { + 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, + 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a, + 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, + 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b}; +const BYTE dataOut_AES128_OFB [] = { + 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, + 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25}; +const BYTE dataOut_AES128_CTR [] = { + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, + 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, + 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, + 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff}; +#endif +#if AES_192 +const BYTE key_AES192 [] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b}; +const BYTE dataIn_AES192 [] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; +const BYTE dataOut_AES192_ECB [] = { + 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, + 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc, + 0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad, + 0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef}; +const BYTE dataOut_AES192_CBC [] = { + 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, + 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8, + 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, + 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a}; +const BYTE dataOut_AES192_CFB [] = { + 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, + 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74, + 0x67, 0xce, 0x7f, 0x7f, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1a, 0x2b, 0x70, 0x17, 0x1d, 0x3d, 0x7a}; +const BYTE dataOut_AES192_OFB [] = { + 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, + 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01}; +const BYTE dataOut_AES192_CTR [] = { + 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, + 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b, + 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, + 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94}; +#endif +#if AES_256 +const BYTE key_AES256 [] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; +const BYTE dataIn_AES256 [] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; +const BYTE dataOut_AES256_ECB [] = { + 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, + 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8, + 0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26, + 0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70}; +const BYTE dataOut_AES256_CBC [] = { + 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, + 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, + 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d}; +const BYTE dataOut_AES256_CFB [] = { + 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, + 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60, + 0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, + 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b}; +const BYTE dataOut_AES256_OFB [] = { + 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, + 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d}; +const BYTE dataOut_AES256_CTR [] = { + 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, + 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, + 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, + 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5}; +#endif +// libtpms added begin +#if TDES_128 +const BYTE key_TDES128 [] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; +const BYTE dataIn_TDES128 [] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; +const BYTE dataOut_TDES128_ECB [] = { + 0xdf, 0x8f, 0x88, 0x43, 0x2f, 0xea, 0x61, 0x0c, + 0xc1, 0xfa, 0xaf, 0x1a, 0xb1, 0xc0, 0xc0, 0x37, + 0x27, 0xf2, 0xe0, 0x8e, 0xda, 0x14, 0xbe, 0x79, + 0x91, 0x95, 0xd2, 0x61, 0x2b, 0x46, 0x49, 0x4e, + 0x1b, 0x10, 0xa6, 0xcc, 0x02, 0xb6, 0x5a, 0x6c}; +const BYTE dataOut_TDES128_CBC [] = { + 0x0a, 0xdd, 0xd5, 0x8a, 0x85, 0x33, 0xda, 0x86, + 0x68, 0x8f, 0xb9, 0x05, 0xe3, 0x32, 0xe1, 0x58, + 0x82, 0x33, 0x72, 0x85, 0xbc, 0x64, 0xcd, 0xd2, + 0x25, 0xa2, 0x54, 0x5e, 0x22, 0xe0, 0xde, 0x92, + 0x80, 0x69, 0x5e, 0x61, 0x77, 0xb5, 0x94, 0x1b}; +const BYTE dataOut_TDES128_CFB [] = { + 0x9c, 0xe7, 0x8f, 0x92, 0x6d, 0x37, 0xe4, 0xaa, + 0x8e, 0x12, 0x14, 0xdc, 0xb7, 0x46, 0xc3, 0x6d, + 0x3f, 0x6f, 0x17, 0x5b, 0x97, 0x9d, 0x9e, 0x8a, + 0xb5, 0xc4, 0xcd, 0x2a, 0x7a, 0x3e, 0xad, 0xec}; +const BYTE dataOut_TDES128_OFB [] = { + 0x9c, 0xe7, 0x8f, 0x92, 0x6d, 0x37, 0xe4, 0xaa, + 0x1b, 0x85, 0x9f, 0x7f, 0x80, 0x56, 0x10, 0xbc, + 0xa4, 0xaa, 0x05, 0xd0, 0xd8, 0xf1, 0xda, 0x3e, + 0x74, 0x82, 0x69, 0xb2, 0x8f, 0xf1, 0x6d, 0xde}; +const BYTE dataOut_TDES128_CTR [] = { + 0x9e, 0xf8, 0x6f, 0x66, 0x5a, 0xa7, 0x9c, 0x91, + 0xe8, 0x07, 0xf9, 0x7a, 0x96, 0xf9, 0x6a, 0x87, + 0x19, 0x22, 0x3f, 0x9d, 0x9e, 0x92, 0xc4, 0x25, + 0x4a, 0x31, 0x6d, 0x3c, 0x35, 0xa6, 0x3a, 0x03}; + +const BYTE dataInShort_TDES128 [] = { + 0x31, 0x32, 0x33, 0x34, 0x35}; +// CBC and ECB need multiple of blocksize input +const BYTE dataOutShort_TDES128_CFB[] = { + 0xc6, 0x14, 0x02, 0x44, 0x76}; +const BYTE dataOutShort_TDES128_OFB[] = { + 0xc6, 0x14, 0x02, 0x44, 0x76}; +#endif +#if TDES_192 +const BYTE key_TDES192 [] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b}; +const BYTE dataIn_TDES192 [] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; +const BYTE dataOut_TDES192_ECB [] = { + 0x37, 0x62, 0x02, 0x5d, 0xad, 0x85, 0x03, 0xe9, + 0xff, 0x0f, 0xce, 0x66, 0x28, 0x74, 0x3f, 0x94, + 0x72, 0x42, 0xbb, 0xc5, 0x14, 0xae, 0xc6, 0x2f, + 0x61, 0xd1, 0x03, 0x9c, 0xd1, 0xf7, 0xf8, 0x29, + 0x62, 0x91, 0x03, 0x74, 0xe7, 0x05, 0xb3, 0xb6}; +const BYTE dataOut_TDES192_CBC [] = { + 0x6c, 0x30, 0xbb, 0x5e, 0xbc, 0x73, 0xb1, 0x2d, + 0x40, 0x24, 0x93, 0x65, 0xd8, 0x9a, 0x27, 0x4f, + 0xdd, 0x09, 0xfc, 0x95, 0x28, 0xa3, 0xd9, 0x46, + 0xf9, 0x15, 0x43, 0x52, 0x7a, 0x0d, 0xd6, 0x3e, + 0xd1, 0xb0, 0x10, 0x64, 0x63, 0x5e, 0xa0, 0xb5}; +const BYTE dataOut_TDES192_CFB [] = { + 0x89, 0x00, 0xbb, 0xec, 0x56, 0xdc, 0x77, 0x81, + 0x59, 0xdb, 0x1d, 0xa4, 0xe2, 0x33, 0x85, 0x2d, + 0xbf, 0xfb, 0xe3, 0xe2, 0xe0, 0x46, 0x91, 0x09, + 0x15, 0xcb, 0x41, 0x7c, 0xd5, 0x84, 0x60, 0xf1}; +const BYTE dataOut_TDES192_OFB [] = { + 0x89, 0x00, 0xbb, 0xec, 0x56, 0xdc, 0x77, 0x81, + 0xf0, 0x12, 0x4b, 0xe3, 0xc5, 0x83, 0x60, 0x45, + 0xda, 0x4d, 0xba, 0x05, 0x78, 0xa3, 0x77, 0xc8, + 0x21, 0x57, 0xcd, 0x62, 0xbb, 0x93, 0xc8, 0x4e}; +const BYTE dataOut_TDES192_CTR [] = { + 0x17, 0x4d, 0xdf, 0xde, 0x7b, 0xe0, 0x2f, 0xb7, + 0x58, 0x49, 0x76, 0xe5, 0x80, 0xbd, 0x49, 0x45, + 0x64, 0x3a, 0xe4, 0x42, 0xfe, 0x4c, 0x25, 0xd4, + 0x79, 0x74, 0xf0, 0xe6, 0x0b, 0x3d, 0x20, 0xac}; + +const BYTE dataInShort_TDES192 [] = { + 0x31, 0x32, 0x33, 0x34, 0x35}; +// CBC and ECB need multiple of blocksize input +const BYTE dataOutShort_TDES192_CFB[] = { + 0xd3, 0xf3, 0x36, 0x3a, 0x4d}; +const BYTE dataOutShort_TDES192_OFB[] = { + 0xd3, 0xf3, 0x36, 0x3a, 0x4d}; +#endif +#if CAMELLIA_128 +const BYTE key_CAMELLIA128 [] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; +const BYTE dataIn_CAMELLIA128 [] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; +const BYTE dataOut_CAMELLIA128_ECB [] = { + 0x43, 0x2f, 0xc5, 0xdc, 0xd6, 0x28, 0x11, 0x5b, + 0x7c, 0x38, 0x8d, 0x77, 0x0b, 0x27, 0x0c, 0x96, + 0x0b, 0xe1, 0xf1, 0x40, 0x23, 0x78, 0x2a, 0x22, + 0xe8, 0x38, 0x4c, 0x5a, 0xbb, 0x7f, 0xab, 0x2b, + 0x7e, 0x70, 0x91, 0x4b, 0xf1, 0x6a, 0x5b, 0xf9, + 0x66, 0x36, 0x97, 0x11, 0xdf, 0xeb, 0x46, 0xef}; +const BYTE dataOut_CAMELLIA128_CBC [] = { + 0x16, 0x07, 0xcf, 0x49, 0x4b, 0x36, 0xbb, 0xf0, + 0x0d, 0xae, 0xb0, 0xb5, 0x03, 0xc8, 0x31, 0xab, + 0xa2, 0xf2, 0xcf, 0x67, 0x16, 0x29, 0xef, 0x78, + 0x40, 0xc5, 0xa5, 0xdf, 0xb5, 0x07, 0x48, 0x87, + 0xa0, 0x0a, 0xdd, 0x48, 0xf1, 0x12, 0xef, 0xa5, + 0xae, 0xc3, 0x5f, 0x22, 0x3c, 0x55, 0x84, 0xc0}; +const BYTE dataOut_CAMELLIA128_CFB [] = { + 0x14, 0xf7, 0x64, 0x61, 0x87, 0x81, 0x7e, 0xb5, + 0x86, 0x59, 0x91, 0x46, 0xb8, 0x2b, 0xd7, 0x19, + 0xa5, 0x3d, 0x28, 0xbb, 0x82, 0xdf, 0x74, 0x11, + 0x03, 0xea, 0x4f, 0x92, 0x1a, 0x44, 0x88, 0x0b}; +const BYTE dataOut_CAMELLIA128_OFB [] = { + 0x14, 0xf7, 0x64, 0x61, 0x87, 0x81, 0x7e, 0xb5, + 0x86, 0x59, 0x91, 0x46, 0xb8, 0x2b, 0xd7, 0x19, + 0x97, 0x32, 0x91, 0x71, 0x6c, 0x4d, 0x82, 0xd0, + 0x1a, 0x07, 0x9e, 0x6d, 0xf7, 0x00, 0xe6, 0xeb}; +const BYTE dataOut_CAMELLIA128_CTR [] = { + 0xb8, 0x09, 0x14, 0x08, 0x77, 0xdd, 0x16, 0xc0, + 0x76, 0x78, 0x09, 0x04, 0xf8, 0x3d, 0xed, 0x11, + 0xbb, 0x41, 0xe6, 0x4e, 0x9b, 0xf1, 0x76, 0xce, + 0x05, 0xd4, 0x18, 0x6b, 0x25, 0x86, 0xd4, 0xc9}; +#endif +#if CAMELLIA_192 +#error Missing test cases for CAMELLIA_192 +#endif +#if CAMELLIA_256 +const BYTE key_CAMELLIA256 [] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; +const BYTE dataIn_CAMELLIA256 [] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; +const BYTE dataOut_CAMELLIA256_ECB [] = { + 0xbe, 0xfd, 0x21, 0x9b, 0x11, 0x2f, 0xa0, 0x00, + 0x98, 0x91, 0x9c, 0xd1, 0x01, 0xc9, 0xcc, 0xfa, + 0xc9, 0x1d, 0x3a, 0x8f, 0x1a, 0xea, 0x08, 0xa9, + 0x38, 0x6c, 0xf4, 0xb6, 0x6c, 0x01, 0x69, 0xea, + 0x75, 0xf3, 0x8b, 0xad, 0x6b, 0x72, 0x54, 0xfa, + 0xa4, 0xb0, 0x3d, 0x32, 0x0a, 0x0d, 0xb2, 0xdc}; +const BYTE dataOut_CAMELLIA256_CBC [] = { + 0xe6, 0xcf, 0xa3, 0x5f, 0xc0, 0x2b, 0x13, 0x4a, + 0x4d, 0x2c, 0x0b, 0x67, 0x37, 0xac, 0x3e, 0xda, + 0x36, 0xcb, 0xeb, 0x73, 0xbd, 0x50, 0x4b, 0x40, + 0x70, 0xb1, 0xb7, 0xde, 0x2b, 0x21, 0xeb, 0x50, + 0x6a, 0x0c, 0xf7, 0x4b, 0xbc, 0x7f, 0xbb, 0xa3, + 0x82, 0x9c, 0x6d, 0x06, 0xcb, 0x4f, 0xb2, 0xc5}; +const BYTE dataOut_CAMELLIA256_CFB [] = { + 0xcf, 0x61, 0x07, 0xbb, 0x0c, 0xea, 0x7d, 0x7f, + 0xb1, 0xbd, 0x31, 0xf5, 0xe7, 0xb0, 0x6c, 0x93, + 0x89, 0xbe, 0xdb, 0x4c, 0xcd, 0xd8, 0x64, 0xea, + 0x11, 0xba, 0x4c, 0xbe, 0x84, 0x9b, 0x5e, 0x2b}; +const BYTE dataOut_CAMELLIA256_OFB [] = { + 0xcf, 0x61, 0x07, 0xbb, 0x0c, 0xea, 0x7d, 0x7f, + 0xb1, 0xbd, 0x31, 0xf5, 0xe7, 0xb0, 0x6c, 0x93, + 0x85, 0x52, 0x1d, 0xb2, 0xf6, 0xbb, 0x67, 0x7f, + 0x1e, 0xb2, 0x24, 0x46, 0x58, 0x41, 0x83, 0x40}; +const BYTE dataOut_CAMELLIA256_CTR [] = { + 0x47, 0xba, 0x6e, 0xea, 0x51, 0xb4, 0x38, 0xfc, + 0xf2, 0x1c, 0x3c, 0xc9, 0x88, 0x76, 0x28, 0x17, + 0x1a, 0x7b, 0xbb, 0xfc, 0x7f, 0x6e, 0x9e, 0xe5, + 0x86, 0x46, 0xc3, 0xef, 0x8d, 0xab, 0xc5, 0x40}; +#endif +#if SM4_128 +// source: https://tools.ietf.org/html/draft-ribose-cfrg-sm4-04#appendix-A.2 +const BYTE key_SM4128 [] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; +const BYTE dataIn_SM4128 [] = { + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xDD, + 0xEE, 0xEE, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB}; +const BYTE dataOut_SM4128_ECB [] = { + 0x5E, 0xC8, 0x14, 0x3D, 0xE5, 0x09, 0xCF, 0xF7, + 0xB5, 0x17, 0x9F, 0x8F, 0x47, 0x4B, 0x86, 0x19, + 0x2F, 0x1D, 0x30, 0x5A, 0x7F, 0xB1, 0x7D, 0xF9, + 0x85, 0xF8, 0x1C, 0x84, 0x82, 0x19, 0x23, 0x04, + 0x00, 0x2A, 0x8A, 0x4E, 0xFA, 0x86, 0x3C, 0xCA, + 0xD0, 0x24, 0xAC, 0x03, 0x00, 0xBB, 0x40, 0xD2} +const BYTE dataOut_SM4128_CBC [] = { + 0x78, 0xEB, 0xB1, 0x1C, 0xC4, 0x0B, 0x0A, 0x48, + 0x31, 0x2A, 0xAE, 0xB2, 0x04, 0x02, 0x44, 0xCB, + 0x4C, 0xB7, 0x01, 0x69, 0x51, 0x90, 0x92, 0x26, + 0x97, 0x9B, 0x0D, 0x15, 0xDC, 0x6A, 0x8F, 0x6D, + 0x40, 0xD8, 0x41, 0x32, 0xE9, 0x99, 0x74, 0xA4, + 0xA8, 0x80, 0x88, 0x68, 0x42, 0x07, 0x48, 0x59}; +const BYTE dataOut_SM4128_CFB [] = { + 0xAC, 0x32, 0x36, 0xCB, 0x86, 0x1D, 0xD3, 0x16, + 0xE6, 0x41, 0x3B, 0x4E, 0x3C, 0x75, 0x24, 0xB7, + 0x69, 0xD4, 0xC5, 0x4E, 0xD4, 0x33, 0xB9, 0xA0, + 0x34, 0x60, 0x09, 0xBE, 0xB3, 0x7B, 0x2B, 0x3F}; +const BYTE dataOut_SM4128_OFB [] = { + 0xAC, 0x32, 0x36, 0xCB, 0x86, 0x1D, 0xD3, 0x16, + 0xE6, 0x41, 0x3B, 0x4E, 0x3C, 0x75, 0x24, 0xB7, + 0x1D, 0x01, 0xAC, 0xA2, 0x48, 0x7C, 0xA5, 0x82, + 0xCB, 0xF5, 0x46, 0x3E, 0x66, 0x98, 0x53, 0x9B}; +/* The data are obtained by running the commands as below: + echo "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFFAAAAAAAABBBBBBBB" | xxd -p -r > plain.txt + openssl enc -sm4-ctr -in plain.txt -iv "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF" -out out.txt -K "0123456789ABCDEFFEDCBA9876543210" +*/ +const BYTE dataOut_SM4_CTR [] = { + 0xF4, 0x88, 0x4C, 0x6D, 0x39, 0x7E, 0x0B, 0x06, + 0x3D, 0xAC, 0xD9, 0x46, 0x1A, 0xA4, 0xA5, 0x6A, + 0x60, 0xDD, 0xA7, 0x5F, 0x86, 0xBC, 0xFE, 0xA4, + 0xF1, 0x5D, 0xB4, 0x6A, 0xD1, 0x4E, 0x7C, 0x7F}; +#endif +// libtpms added end + +#endif diff --git a/src/tpm2/TPMB.h b/src/tpm2/TPMB.h new file mode 100644 index 0000000..8559b17 --- /dev/null +++ b/src/tpm2/TPMB.h @@ -0,0 +1,97 @@ +/********************************************************************************/ +/* */ +/* This file contains extra TPM2B structures */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TPMB.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef TPMB_H +#define TPMB_H + +/* 5.17 TPMB.h */ +/* This file contains extra TPM2B structures */ + +/* TPM2B Types */ +typedef struct { + UINT16 size; + BYTE buffer[1]; +} TPM2B, *P2B; +typedef const TPM2B *PC2B; + +/* This macro helps avoid having to type in the structure in order to create a new TPM2B type that + is used in a function. */ + +#define TPM2B_TYPE(name, bytes) \ + typedef union { \ + struct { \ + UINT16 size; \ + BYTE buffer[(bytes)]; \ + } t; \ + TPM2B b; \ + } TPM2B_##name + +/* This macro defines a TPM2B with a constant character value. This macro sets the size of the + string to the size minus the terminating zero byte. This lets the user of the label add their + terminating 0. This method is chosen so that existing code that provides a label will continue to + work correctly. Macro to instance and initialize a TPM2B value */ +#define TPM2B_INIT(TYPE, name) \ + TPM2B_##TYPE name = {sizeof(name.t.buffer), {0}} +#define TPM2B_BYTE_VALUE(bytes) TPM2B_TYPE(bytes##_BYTE_VALUE, bytes) + +#endif + + diff --git a/src/tpm2/TPMCmdp.c b/src/tpm2/TPMCmdp.c new file mode 100644 index 0000000..041b780 --- /dev/null +++ b/src/tpm2/TPMCmdp.c @@ -0,0 +1,364 @@ +/********************************************************************************/ +/* */ +/* Process the commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TPMCmdp.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* D.4 TPMCmdp.c */ +/* D.4.1. Description */ +/* This file contains the functions that process the commands received on the control port or the + command port of the simulator. The control port is used to allow simulation of hardware events + (such as, _TPM_Hash_Start()) to test the simulated TPM's reaction to those events. This improves + code coverage of the testing. */ +/* D.4.2. Includes and Data Definitions */ +#include +#include +#include +#include +#include "TpmBuildSwitches.h" +#ifdef TPM_WINDOWS +#include +#include +#endif +#include "Platform_fp.h" +#include "PlatformACT_fp.h" +#include "ExecCommand_fp.h" +#include "Manufacture_fp.h" +#include "_TPM_Init_fp.h" +#include "_TPM_Hash_Start_fp.h" +#include "_TPM_Hash_Data_fp.h" +#include "_TPM_Hash_End_fp.h" +#include "TpmFail_fp.h" +#include "TpmTcpProtocol.h" +#include "Simulator_fp.h" +#ifdef TPM_WINDOWS +#include "TcpServer_fp.h" /* kgold */ +#endif +#ifdef TPM_POSIX +#include "TcpServerPosix_fp.h" /* kgold */ +#endif +#include "TpmProfile.h" /* kgold */ + +static bool s_isPowerOn = false; +/* D.4.3. Functions */ +/* D.4.3.1. Signal_PowerOn() */ +/* This function processes a power-on indication. Among other things, it calls the _TPM_Init() + handler. */ +void +_rpc__Signal_PowerOn( + bool isReset + ) +{ + // if power is on and this is not a call to do TPM reset then return + if(s_isPowerOn && !isReset) + return; + // If this is a reset but power is not on, then return + if(isReset && !s_isPowerOn) + return; + // Unless this is just a reset, pass power on signal to platform + if(!isReset) + _plat__Signal_PowerOn(); + // Power on and reset both lead to _TPM_Init() + _plat__Signal_Reset(); + // Set state as power on + s_isPowerOn = true; +} +#if 0 /* libtpms added */ +/* D.4.3.2. Signal_Restart() */ +/* This function processes the clock restart indication. All it does is call the platform + function. */ +void +_rpc__Signal_Restart( + void + ) +{ + _plat__TimerRestart(); +} +#endif /* libtpms added */ +/* D.4.3.3. Signal_PowerOff() */ +/* This function processes the power off indication. Its primary function is to set a flag + indicating that the next power on indication should cause _TPM_Init() to be called. */ +void +_rpc__Signal_PowerOff( + void + ) +{ + if(s_isPowerOn) + // Pass power off signal to platform + _plat__Signal_PowerOff(); + // This could be redundant, but... + s_isPowerOn = false; + return; +} +#if 0 /* libtpms added */ +/* D.4.3.4. _rpc__ForceFailureMode() */ +/* This function is used to debug the Failure Mode logic of the TPM. It will set a flag in the TPM + code such that the next call to TPM2_SelfTest() will result in a failure, putting the TPM into + Failure Mode. */ +void +_rpc__ForceFailureMode( + void + ) +{ + SetForceFailureMode(); + return; +} +/* D.4.3.5. _rpc__Signal_PhysicalPresenceOn() */ +/* This function is called to simulate activation of the physical presence pin. */ +void +_rpc__Signal_PhysicalPresenceOn( + void + ) +{ + // If TPM power is on + if(s_isPowerOn) + // Pass physical presence on to platform + _plat__Signal_PhysicalPresenceOn(); + return; +} +/* D.4.3.6. _rpc__Signal_PhysicalPresenceOff() */ +/* This function is called to simulate deactivation of the physical presence pin. */ +void +_rpc__Signal_PhysicalPresenceOff( + void + ) +{ + // If TPM power is on + if(s_isPowerOn) + // Pass physical presence off to platform + _plat__Signal_PhysicalPresenceOff(); + return; +} +/* D.4.3.7. _rpc__Signal_Hash_Start() */ +/* This function is called to simulate a _TPM_Hash_Start() event. It will call */ +void +_rpc__Signal_Hash_Start( + void + ) +{ + // If TPM power is on + if(s_isPowerOn) + // Pass _TPM_Hash_Start signal to TPM + _TPM_Hash_Start(); + return; +} +/* D.4.3.8. _rpc__Signal_Hash_Data() */ +/* This function is called to simulate a _TPM_Hash_Data() event. */ +void +_rpc__Signal_Hash_Data( + _IN_BUFFER input + ) +{ + // If TPM power is on + if(s_isPowerOn) + // Pass _TPM_Hash_Data signal to TPM + _TPM_Hash_Data(input.BufferSize, input.Buffer); + return; +} +/* D.4.3.9. _rpc__Signal_HashEnd() */ +/* This function is called to simulate a _TPM_Hash_End() event. */ +void +_rpc__Signal_HashEnd( + void + ) +{ + // If TPM power is on + if(s_isPowerOn) + // Pass _TPM_HashEnd signal to TPM + _TPM_Hash_End(); + return; +} +#endif /* libtpms added */ +/* D.4.3.10. rpc_Send_Command() */ +/* This is the interface to the TPM code. */ +void +_rpc__Send_Command( + unsigned char locality, + _IN_BUFFER request, + _OUT_BUFFER *response + ) +{ + // If TPM is power off, reject any commands. + if(!s_isPowerOn) + { + response->BufferSize = 0; + return; + } + // Set the locality of the command so that it doesn't change during the command + _plat__LocalitySet(locality); + // Do implementation-specific command dispatch + _plat__RunCommand(request.BufferSize, request.Buffer, + &response->BufferSize, &response->Buffer); + return; +} +/* D.4.3.10. _rpc__Signal_CancelOn() */ +/* This function is used to turn on the indication to cancel a command in process. An executing + command is not interrupted. The command code may periodically check this indication to see if it + should abort the current command processing and returned TPM_RC_CANCELLED. */ +void +_rpc__Signal_CancelOn( + void + ) +{ + // If TPM is power off, reject this signal + if(s_isPowerOn) + // Set the platform canceling flag. + _plat__SetCancel(); + return; +} +/* D.4.3.11. _rpc__Signal_CancelOff() */ +/* This function is used to turn off the indication to cancel a command in process. */ +void +_rpc__Signal_CancelOff( + void + ) +{ + // If TPM power is n + if(s_isPowerOn) + // Set the platform canceling flag. + _plat__ClearCancel(); + return; +} +/* D.4.3.12. _rpc__Signal_NvOn() */ +/* In a system where the NV memory used by the TPM is not within the TPM, the NV may not always be + available. This function turns on the indicator that indicates that NV is available. */ +void +_rpc__Signal_NvOn( + void + ) +{ + // If TPM power is on + if(s_isPowerOn) + // Make the NV available + _plat__SetNvAvail(); + return; +} +#if 0 /* libtpms added */ +/* D.4.3.13. _rpc__Signal_NvOff() */ +/* This function is used to set the indication that NV memory is no longer available. */ +void +_rpc__Signal_NvOff( + void + ) +{ + // If TPM power is on + if(s_isPowerOn) + // Make NV not available + _plat__ClearNvAvail(); + return; +} +void RsaKeyCacheControl(int state); +/* D.4.3.14. _rpc__RsaKeyCacheControl() */ +/* This function is used to enable/disable the use of the RSA key cache during simulation. */ +void +_rpc__RsaKeyCacheControl( + int state + ) +{ +#if USE_RSA_KEY_CACHE + RsaKeyCacheControl(state); +#else + NOT_REFERENCED(state); +#endif +} + +#define TPM_RH_ACT_0 0x40000110 + +/* D.4.2.15. _rpc__ACT_GetSignaled() */ +/* This function is used to count the ACT second tick. */ +bool +_rpc__ACT_GetSignaled( + uint32_t actHandle + ) +{ + // If TPM power is on + if (s_isPowerOn) + // Query the platform + return _plat__ACT_GetSignaled(actHandle - TPM_RH_ACT_0); + return false; +} +#endif /* libtpms added */ + +/* libtpms added begin */ +static bool tpmEstablished; + +void +_rpc__Signal_SetTPMEstablished(void) +{ + tpmEstablished = TRUE; +} + +void +_rpc__Signal_ResetTPMEstablished(void) +{ + /* check for locality 3 or 4 already done by caller */ + tpmEstablished = FALSE; +} + +bool +_rpc__Signal_GetTPMEstablished(void) +{ + return tpmEstablished; +} + +bool +_rpc__Signal_IsPowerOn(void) +{ + return s_isPowerOn; +} +/* libtpms added end */ diff --git a/src/tpm2/TcpServerPosix_fp.h b/src/tpm2/TcpServerPosix_fp.h new file mode 100644 index 0000000..d984130 --- /dev/null +++ b/src/tpm2/TcpServerPosix_fp.h @@ -0,0 +1,131 @@ +/********************************************************************************/ +/* */ +/* Socket Interface to a TPM Simulator */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TcpServerPosix_fp.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#ifndef TCPSERVERPOSIX_FP_H +#define TCPSERVERPOSIX_FP_H + +#include +#include +#include +#include +#include + +#include "CompilerDependencies.h" +#include "BaseTypes.h" + +bool +PlatformServer( + SOCKET s + ); +int +PlatformSvcRoutine( + void *port + ); +int +PlatformSignalService( + int *PortNumberPlatform + ); +int +RegularCommandService( + int *PortNumber + ); +int +StartTcpServer( + int *PortNumber, + int *PortNumberPlatform + ); +bool +ReadBytes( + SOCKET s, + char *buffer, + int NumBytes + ); +bool +WriteBytes( + SOCKET s, + char *buffer, + int NumBytes + ); +bool +WriteUINT32( + SOCKET s, + UINT32 val + ); +bool +ReadVarBytes( + SOCKET s, + char *buffer, + UINT32 *BytesReceived, + int MaxLen + ); +bool +WriteVarBytes( + SOCKET s, + char *buffer, + int BytesToSend + ); +bool +TpmServer( + SOCKET s + ); + + +#endif diff --git a/src/tpm2/TestParms_fp.h b/src/tpm2/TestParms_fp.h new file mode 100644 index 0000000..c71f67e --- /dev/null +++ b/src/tpm2/TestParms_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TestParms_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef TESTPARMS_FP_H +#define TESTPARMS_FP_H + +typedef struct { + TPMT_PUBLIC_PARMS parameters; +} TestParms_In; + +#define RC_TestParms_parameters (TPM_RC_P + TPM_RC_1) + +TPM_RC +TPM2_TestParms( + TestParms_In *in // IN: input parameter list + ); + + +#endif diff --git a/src/tpm2/TestingCommands.c b/src/tpm2/TestingCommands.c new file mode 100644 index 0000000..27a2352 --- /dev/null +++ b/src/tpm2/TestingCommands.c @@ -0,0 +1,108 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TestingCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016-2018 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "SelfTest_fp.h" +#if CC_SelfTest // Conditional expansion of this file +TPM_RC +TPM2_SelfTest( + SelfTest_In *in // IN: input parameter list + ) +{ + // Command Output + // Call self test function in crypt module + return CryptSelfTest(in->fullTest); +} +#endif // CC_SelfTest +#include "Tpm.h" +#include "IncrementalSelfTest_fp.h" +#if CC_IncrementalSelfTest // Conditional expansion of this file +TPM_RC +TPM2_IncrementalSelfTest( + IncrementalSelfTest_In *in, // IN: input parameter list + IncrementalSelfTest_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + // Command Output + // Call incremental self test function in crypt module. If this function + // returns TPM_RC_VALUE, it means that an algorithm on the 'toTest' list is + // not implemented. + result = CryptIncrementalSelfTest(&in->toTest, &out->toDoList); + if(result == TPM_RC_VALUE) + return TPM_RCS_VALUE + RC_IncrementalSelfTest_toTest; + return result; +} +#endif // CC_IncrementalSelfTest +#include "Tpm.h" +#include "GetTestResult_fp.h" +#if CC_GetTestResult // Conditional expansion of this file +TPM_RC +TPM2_GetTestResult( + GetTestResult_Out *out // OUT: output parameter list + ) +{ + // Command Output + // Call incremental self test function in crypt module + out->testResult = CryptGetTestResult(&out->outData); + return TPM_RC_SUCCESS; +} +#endif // CC_GetTestResult diff --git a/src/tpm2/Ticket.c b/src/tpm2/Ticket.c new file mode 100644 index 0000000..cceac8d --- /dev/null +++ b/src/tpm2/Ticket.c @@ -0,0 +1,236 @@ +/********************************************************************************/ +/* */ +/* Functions used for ticket computations. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Ticket.c 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 10.2.23 Ticket.c */ +/* 10.2.23.1 Introduction */ +/* This clause contains the functions used for ticket computations. */ +/* 10.2.23.2 Includes */ +#include "Tpm.h" +/* 10.2.23.3 Functions */ +/* 10.2.23.3.1 TicketIsSafe() */ +/* This function indicates if producing a ticket is safe. It checks if the leading bytes of an input + buffer is TPM_GENERATED_VALUE or its substring of canonical form. If so, it is not safe to + produce ticket for an input buffer claiming to be TPM generated buffer */ +/* Return Values Meaning */ +/* TRUE It is safe to produce ticket */ +/* FALSE It is not safe to produce ticket */ +BOOL +TicketIsSafe( + TPM2B *buffer + ) +{ + TPM_CONSTANTS32 valueToCompare = TPM_GENERATED_VALUE; + BYTE bufferToCompare[sizeof(valueToCompare)]; + BYTE *marshalBuffer; + // + // If the buffer size is less than the size of TPM_GENERATED_VALUE, assume + // it is not safe to generate a ticket + if(buffer->size < sizeof(valueToCompare)) + return FALSE; + marshalBuffer = bufferToCompare; + TPM_CONSTANTS32_Marshal(&valueToCompare, &marshalBuffer, NULL); + if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare))) + return FALSE; + else + return TRUE; +} +/* 10.2.23.3.2 TicketComputeVerified() */ +/* This function creates a TPMT_TK_VERIFIED ticket. */ +void +TicketComputeVerified( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + TPM2B_DIGEST *digest, // IN: digest + TPM2B_NAME *keyName, // IN: name of key that signed the values + TPMT_TK_VERIFIED *ticket // OUT: verified ticket + ) +{ + TPM2B_PROOF *proof; + HMAC_STATE hmacState; + // + // Fill in ticket fields + ticket->tag = TPM_ST_VERIFIED; + ticket->hierarchy = hierarchy; + proof = HierarchyGetProof(hierarchy); + // Start HMAC using the proof value of the hierarchy as the HMAC key + ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, + &proof->b); + // TPM_ST_VERIFIED + CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); + // digest + CryptDigestUpdate2B(&hmacState.hashState, &digest->b); + // key name + CryptDigestUpdate2B(&hmacState.hashState, &keyName->b); + // done + CryptHmacEnd2B(&hmacState, &ticket->digest.b); + return; +} +/* 10.2.23.3.3 TicketComputeAuth() */ +/* This function creates a TPMT_TK_AUTH ticket. */ +void +TicketComputeAuth( + TPM_ST type, // IN: the type of ticket. + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + UINT64 timeout, // IN: timeout + BOOL expiresOnReset,// IN: flag to indicate if ticket expires on + // TPM Reset + TPM2B_DIGEST *cpHashA, // IN: input cpHashA + TPM2B_NONCE *policyRef, // IN: input policyRef + TPM2B_NAME *entityName, // IN: name of entity + TPMT_TK_AUTH *ticket // OUT: Created ticket + ) +{ + TPM2B_PROOF *proof; + HMAC_STATE hmacState; + // + // Get proper proof + proof = HierarchyGetProof(hierarchy); + // Fill in ticket fields + ticket->tag = type; + ticket->hierarchy = hierarchy; + // Start HMAC with hierarchy proof as the HMAC key + ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, + &proof->b); + // TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED, + CryptDigestUpdateInt(&hmacState, sizeof(UINT16), ticket->tag); + // cpHash + CryptDigestUpdate2B(&hmacState.hashState, &cpHashA->b); + // policyRef + CryptDigestUpdate2B(&hmacState.hashState, &policyRef->b); + // keyName + CryptDigestUpdate2B(&hmacState.hashState, &entityName->b); + // timeout + CryptDigestUpdateInt(&hmacState, sizeof(timeout), timeout); + if(timeout != 0) + { + // epoch + CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE), + g_timeEpoch); + // reset count + if(expiresOnReset) + CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount), + gp.totalResetCount); + } + // done + CryptHmacEnd2B(&hmacState, &ticket->digest.b); + return; +} +/* 10.2.23.3.4 TicketComputeHashCheck() */ +/* This function creates a TPMT_TK_HASHCHECK ticket. */ +void +TicketComputeHashCheck( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + TPM_ALG_ID hashAlg, // IN: the hash algorithm for 'digest' + TPM2B_DIGEST *digest, // IN: input digest + TPMT_TK_HASHCHECK *ticket // OUT: Created ticket + ) +{ + TPM2B_PROOF *proof; + HMAC_STATE hmacState; + // + // Get proper proof + proof = HierarchyGetProof(hierarchy); + // Fill in ticket fields + ticket->tag = TPM_ST_HASHCHECK; + ticket->hierarchy = hierarchy; + // Start HMAC using hierarchy proof as HMAC key + ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, + &proof->b); + // TPM_ST_HASHCHECK + CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); + // hash algorithm + CryptDigestUpdateInt(&hmacState, sizeof(hashAlg), hashAlg); + // digest + CryptDigestUpdate2B(&hmacState.hashState, &digest->b); + // done + CryptHmacEnd2B(&hmacState, &ticket->digest.b); + return; +} +/* 10.2.23.3.5 TicketComputeCreation() */ +/* This function creates a TPMT_TK_CREATION ticket. */ +void +TicketComputeCreation( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy for ticket + TPM2B_NAME *name, // IN: object name + TPM2B_DIGEST *creation, // IN: creation hash + TPMT_TK_CREATION *ticket // OUT: created ticket + ) +{ + TPM2B_PROOF *proof; + HMAC_STATE hmacState; + // Get proper proof + proof = HierarchyGetProof(hierarchy); + // Fill in ticket fields + ticket->tag = TPM_ST_CREATION; + ticket->hierarchy = hierarchy; + // Start HMAC using hierarchy proof as HMAC key + ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, + &proof->b); + // TPM_ST_CREATION + CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); + // name if provided + if(name != NULL) + CryptDigestUpdate2B(&hmacState.hashState, &name->b); + // creation hash + CryptDigestUpdate2B(&hmacState.hashState, &creation->b); + // Done + CryptHmacEnd2B(&hmacState, &ticket->digest.b); + return; +} diff --git a/src/tpm2/Ticket_fp.h b/src/tpm2/Ticket_fp.h new file mode 100644 index 0000000..78e5eb2 --- /dev/null +++ b/src/tpm2/Ticket_fp.h @@ -0,0 +1,104 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Ticket_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef TICKET_FP_H +#define TICKET_FP_H + +BOOL +TicketIsSafe( + TPM2B *buffer + ); +void +TicketComputeVerified( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + TPM2B_DIGEST *digest, // IN: digest + TPM2B_NAME *keyName, // IN: name of key that signed the values + TPMT_TK_VERIFIED *ticket // OUT: verified ticket + ); +void +TicketComputeAuth( + TPM_ST type, // IN: the type of ticket. + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + UINT64 timeout, // IN: timeout + BOOL expiresOnReset,// IN: flag to indicate if ticket expires on + // TPM Reset + TPM2B_DIGEST *cpHashA, // IN: input cpHashA + TPM2B_NONCE *policyRef, // IN: input policyRef + TPM2B_NAME *entityName, // IN: name of entity + TPMT_TK_AUTH *ticket // OUT: Created ticket + ); +void +TicketComputeHashCheck( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + TPM_ALG_ID hashAlg, // IN: the hash algorithm for 'digest' + TPM2B_DIGEST *digest, // IN: input digest + TPMT_TK_HASHCHECK *ticket // OUT: Created ticket + ); +void +TicketComputeCreation( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy for ticket + TPM2B_NAME *name, // IN: object name + TPM2B_DIGEST *creation, // IN: creation hash + TPMT_TK_CREATION *ticket // OUT: created ticket + ); + + +#endif diff --git a/src/tpm2/Time.c b/src/tpm2/Time.c new file mode 100644 index 0000000..9ff1bb5 --- /dev/null +++ b/src/tpm2/Time.c @@ -0,0 +1,273 @@ +/********************************************************************************/ +/* */ +/* Functions relating to the TPM's time functions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Time.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 8.10.1 Introduction */ +/* This file contains the functions relating to the TPM's time functions including the interface to + the implementation-specific time functions. */ +/* 8.10.2 Includes */ +#include "Tpm.h" +#include "PlatformClock.h" +/* 8.10.3 Functions */ +/* 8.10.3.1 TimePowerOn() */ +/* This function initialize time info at _TPM_Init(). */ +/* This function is called at _TPM_Init() so that the TPM time can start counting as soon as the TPM + comes out of reset and doesn't have to wait until TPM2_Startup() in order to begin the new time + epoch. This could be significant for systems that could get powered up but not run any TPM + commands for some period of time. */ +void +TimePowerOn( + void + ) +{ + g_time = _plat__TimerRead(); +} +/* 8.10.3.2 TimeNewEpoch() */ +/* This function does the processing to generate a new time epoch nonce and set NV for update. This + function is only called when NV is known to be available and the clock is running. The epoch is + updated to persistent data. */ +static void +TimeNewEpoch( + void + ) +{ +#if CLOCK_STOPS + CryptRandomGenerate(sizeof(CLOCK_NONCE), (BYTE *)&g_timeEpoch); +#else + // if the epoch is kept in NV, update it. + gp.timeEpoch++; + NV_SYNC_PERSISTENT(timeEpoch); +#endif + // Clean out any lingering state + _plat__TimerWasStopped(); +} +/* 8.10.3.3 TimeStartup() */ +/* This function updates the resetCount and restartCount components of TPMS_CLOCK_INFO structure at + TPM2_Startup(). */ +/* This function will deal with the deferred creation of a new epoch. TimeUpdateToCurrent() will not + start a new epoch even if one is due when TPM_Startup() has not been run. This is because the + state of NV is not known until startup completes. When Startup is done, then it will create the + epoch nonce to complete the initializations by calling this function. */ +BOOL +TimeStartup( + STARTUP_TYPE type // IN: start up type + ) +{ + NOT_REFERENCED(type); + // If the previous cycle is orderly shut down, the value of the safe bit + // the same as previously saved. Otherwise, it is not safe. + if(!NV_IS_ORDERLY) + go.clockSafe = NO; + return TRUE; +} +/* 8.10.3.4 TimeClockUpdate() */ +/* This function updates go.clock. If newTime requires an update of NV, then NV is checked for + availability. If it is not available or is rate limiting, then go.clock is not updated and the + function returns an error. If newTime would not cause an NV write, then go.clock is updated. If + an NV write occurs, then go.safe is SET. */ +void +TimeClockUpdate( + UINT64 newTime // IN: New time value in mS. + ) +{ +#define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1) + // Check to see if the update will cause a need for an nvClock update + if((newTime | CLOCK_UPDATE_MASK) > (go.clock | CLOCK_UPDATE_MASK)) + { + pAssert(g_NvStatus == TPM_RC_SUCCESS); + // Going to update the NV time state so SET the safe flag + go.clockSafe = YES; + // update the time + go.clock = newTime; + + /* libtpms: Changing the clock alone does not cause the permanent + * state to be written to storage, there must be other + * reasons as well. + */ + UPDATE_TYPE old_g_updateNV = g_updateNV; // libtpms added + + NvWrite(NV_ORDERLY_DATA, sizeof(go), &go); + + g_updateNV = old_g_updateNV; // libtpms added + } + else + // No NV update needed so just update + go.clock = newTime; +} +/* 8.10.3.5 TimeUpdate() */ +/* This function is used to update the time and clock values. If the TPM has run TPM2_Startup(), + this function is called at the start of each command. If the TPM has not run TPM2_Startup(), this + is called from TPM2_Startup() to get the clock values initialized. It is not called on command + entry because, in this implementation, the go structure is not read from NV until + TPM2_Startup(). The reason for this is that the initialization code (_TPM_Init()) may run before + NV is accessible. */ +void +TimeUpdate( + void + ) +{ + UINT64 elapsed; + // + // Make sure that we consume the current _plat__TimerWasStopped() state. + if(_plat__TimerWasStopped()) + { + TimeNewEpoch(); + } + // Get the difference between this call and the last time we updated the tick + // timer. + elapsed = _plat__TimerRead() - g_time; + // Don't read + + g_time += elapsed; + // Don't need to check the result because it has to be success because have + // already checked that NV is available. + TimeClockUpdate(go.clock + elapsed); + // Call self healing logic for dictionary attack parameters + DASelfHeal(); +} +/* 8.10.3.6 TimeUpdateToCurrent() */ +/* This function updates the Time and Clock in the global TPMS_TIME_INFO structure. */ +/* In this implementation, Time and Clock are updated at the beginning of each command and the + values are unchanged for the duration of the command. */ +/* Because Clock updates may require a write to NV memory, Time and Clock are not allowed to advance + if NV is not available. When clock is not advancing, any function that uses Clock will fail and + return TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE. */ +/* This implementation does not do rate limiting. If the implementation does do rate limiting, then + the Clock update should not be inhibited even when doing rate limiting. */ +void +TimeUpdateToCurrent( + void + ) +{ + // Can't update time during the dark interval or when rate limiting so don't + // make any modifications to the internal clock value. Also, defer any clock + // processing until TPM has run TPM2_Startup() + if(!NV_IS_AVAILABLE || !TPMIsStarted()) + return; + TimeUpdate(); +} +/* 8.10.3.7 TimeSetAdjustRate() */ +/* This function is used to perform rate adjustment on Time and Clock. */ +void +TimeSetAdjustRate( + TPM_CLOCK_ADJUST adjust // IN: adjust constant + ) +{ + switch(adjust) + { + case TPM_CLOCK_COARSE_SLOWER: + _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE); + break; + case TPM_CLOCK_COARSE_FASTER: + _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE); + break; + case TPM_CLOCK_MEDIUM_SLOWER: + _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM); + break; + case TPM_CLOCK_MEDIUM_FASTER: + _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM); + break; + case TPM_CLOCK_FINE_SLOWER: + _plat__ClockAdjustRate(CLOCK_ADJUST_FINE); + break; + case TPM_CLOCK_FINE_FASTER: + _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE); + break; + case TPM_CLOCK_NO_CHANGE: + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return; +} +/* 8.10.3.8 TimeGetMarshaled() */ +/* This function is used to access TPMS_TIME_INFO in canonical form. The function collects the time + information and marshals it into dataBuffer and returns the marshaled size */ +/* Return Value Meaning */ +UINT16 +TimeGetMarshaled( + TIME_INFO *dataBuffer // OUT: result buffer + ) +{ + TPMS_TIME_INFO timeInfo; + // Fill TPMS_TIME_INFO structure + timeInfo.time = g_time; + TimeFillInfo(&timeInfo.clockInfo); + // Marshal TPMS_TIME_INFO to canonical form + return TPMS_TIME_INFO_Marshal(&timeInfo, (BYTE **)&dataBuffer, NULL); +} +/* 8.10.3.9 TimeFillInfo */ +/* This function gathers information to fill in a TPMS_CLOCK_INFO structure. */ +void +TimeFillInfo( + TPMS_CLOCK_INFO *clockInfo + ) +{ + clockInfo->clock = go.clock; + clockInfo->resetCount = gp.resetCount; + clockInfo->restartCount = gr.restartCount; + // If NV is not available, clock stopped advancing and the value reported is + // not "safe". + if(NV_IS_AVAILABLE) + clockInfo->safe = go.clockSafe; + else + clockInfo->safe = NO; + return; +} diff --git a/src/tpm2/Time_fp.h b/src/tpm2/Time_fp.h new file mode 100644 index 0000000..b4143e5 --- /dev/null +++ b/src/tpm2/Time_fp.h @@ -0,0 +1,99 @@ +/********************************************************************************/ +/* */ +/* Functions relating to the TPM's time functions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Time_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef TIME_FP_H +#define TIME_FP_H + +void +TimePowerOn( + void + ); +BOOL +TimeStartup( + STARTUP_TYPE type // IN: start up type + ); +void +TimeClockUpdate( + UINT64 newTime + ); +void +TimeUpdate( + void + ); +void +TimeUpdateToCurrent( + void + ); +void +TimeSetAdjustRate( + TPM_CLOCK_ADJUST adjust // IN: adjust constant + ); +UINT16 +TimeGetMarshaled( + TIME_INFO *dataBuffer // OUT: result buffer + ); +void +TimeFillInfo( + TPMS_CLOCK_INFO *clockInfo + ); + + +#endif diff --git a/src/tpm2/Tpm.h b/src/tpm2/Tpm.h new file mode 100644 index 0000000..e05c529 --- /dev/null +++ b/src/tpm2/Tpm.h @@ -0,0 +1,81 @@ +/********************************************************************************/ +/* */ +/* Root header file for building any TPM.lib code */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Tpm.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 5.18 Tpm.h */ +/* Root header file for building any TPM.lib code */ +#ifndef _TPM_H_ +#define _TPM_H_ + +#include "TpmBuildSwitches.h" +#include "BaseTypes.h" +#include "TPMB.h" +#include "MinMax.h" +#include "TpmProfile.h" +#include "TpmAlgorithmDefines.h" +#include "LibSupport.h" // Types from the library. These need to come before +// Global.h because some of the structures in +// that file depend on the structures used by the +// cryptographic libraries. +#include "GpMacros.h" // Define additional macros +#include "Global.h" // Define other TPM types +#include "InternalRoutines.h" // Function prototypes + +#endif // _TPM_H_ diff --git a/src/tpm2/TpmAlgorithmDefines.h b/src/tpm2/TpmAlgorithmDefines.h new file mode 100644 index 0000000..e397367 --- /dev/null +++ b/src/tpm2/TpmAlgorithmDefines.h @@ -0,0 +1,405 @@ +/********************************************************************************/ +/* */ +/* Algorithm Values from the TCG Algorithm Registry */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmAlgorithmDefines.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2021 */ +/* */ +/********************************************************************************/ + +// 10.1.18 TpmAlgorithmDefines.h +// This file contains the algorithm values from the TCG Algorithm Registry. +#ifndef _TPM_ALGORITHM_DEFINES_H_ +#define _TPM_ALGORITHM_DEFINES_H_ +// Table 2:3 - Definition of Base Types +#define ECC_CURVES \ + {TPM_ECC_BN_P256, TPM_ECC_BN_P638, TPM_ECC_NIST_P192, \ + TPM_ECC_NIST_P224, TPM_ECC_NIST_P256, TPM_ECC_NIST_P384, \ + TPM_ECC_NIST_P521, TPM_ECC_SM2_P256} +#define ECC_CURVE_COUNT \ + (ECC_BN_P256 + ECC_BN_P638 + ECC_NIST_P192 + ECC_NIST_P224 + \ + ECC_NIST_P256 + ECC_NIST_P384 + ECC_NIST_P521 + ECC_SM2_P256) +#define MAX_ECC_KEY_BITS \ + MAX(ECC_BN_P256 * 256, MAX(ECC_BN_P638 * 638, \ + MAX(ECC_NIST_P192 * 192, MAX(ECC_NIST_P224 * 224, \ + MAX(ECC_NIST_P256 * 256, MAX(ECC_NIST_P384 * 384, \ + MAX(ECC_NIST_P521 * 521, MAX(ECC_SM2_P256 * 256, \ + 0)))))))) +#define MAX_ECC_KEY_BYTES BITS_TO_BYTES(MAX_ECC_KEY_BITS) + +// Table 0:6 - Defines for PLATFORM Values +#define PLATFORM_FAMILY TPM_SPEC_FAMILY +#define PLATFORM_LEVEL TPM_SPEC_LEVEL +#define PLATFORM_VERSION TPM_SPEC_VERSION +#define PLATFORM_YEAR TPM_SPEC_YEAR +#define PLATFORM_DAY_OF_YEAR TPM_SPEC_DAY_OF_YEAR + +// Table 1:12 - Defines for SHA1 Hash Values +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 +// Table 1:13 - Defines for SHA256 Hash Values +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 +// Table 1:14 - Defines for SHA384 Hash Values +#define SHA384_DIGEST_SIZE 48 +#define SHA384_BLOCK_SIZE 128 +// Table 1:15 - Defines for SHA512 Hash Values +#define SHA512_DIGEST_SIZE 64 +#define SHA512_BLOCK_SIZE 128 +// Table 1:16 - Defines for SM3_256 Hash Values +#define SM3_256_DIGEST_SIZE 32 +#define SM3_256_BLOCK_SIZE 64 +// Table 1:16 - Defines for SHA3_256 Hash Values +#define SHA3_256_DIGEST_SIZE 32 +#define SHA3_256_BLOCK_SIZE 136 +// Table 1:16 - Defines for SHA3_384 Hash Values +#define SHA3_384_DIGEST_SIZE 48 +#define SHA3_384_BLOCK_SIZE 104 +// Table 1:16 - Defines for SHA3_512 Hash Values +#define SHA3_512_DIGEST_SIZE 64 +#define SHA3_512_BLOCK_SIZE 72 +// Table 1:00 - Defines for RSA Asymmetric Cipher Algorithm Constants +#define RSA_KEY_SIZES_BITS \ + (1024 * RSA_1024), (2048 * RSA_2048), (3072 * RSA_3072), \ + (4096 * RSA_4096), (16384 * RSA_16384) +#if RSA_16384 +# define RSA_MAX_KEY_SIZE_BITS 16384 +#elif RSA_4096 +# define RSA_MAX_KEY_SIZE_BITS 4096 +#elif RSA_3072 +# define RSA_MAX_KEY_SIZE_BITS 3072 +#elif RSA_2048 +# define RSA_MAX_KEY_SIZE_BITS 2048 +#elif RSA_1024 +# define RSA_MAX_KEY_SIZE_BITS 1024 +#else +# define RSA_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_RSA_KEY_BITS RSA_MAX_KEY_SIZE_BITS +#define MAX_RSA_KEY_BYTES ((RSA_MAX_KEY_SIZE_BITS + 7) / 8) +// Table 1:17 - Defines for AES Symmetric Cipher Algorithm Constants +#define AES_KEY_SIZES_BITS \ + (128 * AES_128), (192 * AES_192), (256 * AES_256) +#if AES_256 +# define AES_MAX_KEY_SIZE_BITS 256 +#elif AES_192 +# define AES_MAX_KEY_SIZE_BITS 192 +#elif AES_128 +# define AES_MAX_KEY_SIZE_BITS 128 +#else +# define AES_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_AES_KEY_BITS AES_MAX_KEY_SIZE_BITS +#define MAX_AES_KEY_BYTES ((AES_MAX_KEY_SIZE_BITS + 7) / 8) +#define AES_128_BLOCK_SIZE_BYTES (AES_128 * 16) +#define AES_192_BLOCK_SIZE_BYTES (AES_192 * 16) +#define AES_256_BLOCK_SIZE_BYTES (AES_256 * 16) +#define AES_BLOCK_SIZES \ + AES_128_BLOCK_SIZE_BYTES, AES_192_BLOCK_SIZE_BYTES, \ + AES_256_BLOCK_SIZE_BYTES +#if ALG_AES +# define AES_MAX_BLOCK_SIZE 16 +#else +# define AES_MAX_BLOCK_SIZE 0 +#endif +#define MAX_AES_BLOCK_SIZE_BYTES AES_MAX_BLOCK_SIZE +// 1:18 - Defines for SM4 Symmetric Cipher Algorithm Constants +#define SM4_KEY_SIZES_BITS (128 * SM4_128) +#if SM4_128 +# define SM4_MAX_KEY_SIZE_BITS 128 +#else +# define SM4_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_SM4_KEY_BITS SM4_MAX_KEY_SIZE_BITS +#define MAX_SM4_KEY_BYTES ((SM4_MAX_KEY_SIZE_BITS + 7) / 8) +#define SM4_128_BLOCK_SIZE_BYTES (SM4_128 * 16) +#define SM4_BLOCK_SIZES SM4_128_BLOCK_SIZE_BYTES +#if ALG_SM4 +# define SM4_MAX_BLOCK_SIZE 16 +#else +# define SM4_MAX_BLOCK_SIZE 0 +#endif +#define MAX_SM4_BLOCK_SIZE_BYTES SM4_MAX_BLOCK_SIZE +// 1:19 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants +#define CAMELLIA_KEY_SIZES_BITS \ + (128 * CAMELLIA_128), (192 * CAMELLIA_192), (256 * CAMELLIA_256) +#if CAMELLIA_256 +# define CAMELLIA_MAX_KEY_SIZE_BITS 256 +#elif CAMELLIA_192 +# define CAMELLIA_MAX_KEY_SIZE_BITS 192 +#elif CAMELLIA_128 +# define CAMELLIA_MAX_KEY_SIZE_BITS 128 +#else +# define CAMELLIA_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_CAMELLIA_KEY_BITS CAMELLIA_MAX_KEY_SIZE_BITS +#define MAX_CAMELLIA_KEY_BYTES ((CAMELLIA_MAX_KEY_SIZE_BITS + 7) / 8) +#define CAMELLIA_128_BLOCK_SIZE_BYTES (CAMELLIA_128 * 16) +#define CAMELLIA_192_BLOCK_SIZE_BYTES (CAMELLIA_192 * 16) +#define CAMELLIA_256_BLOCK_SIZE_BYTES (CAMELLIA_256 * 16) +#define CAMELLIA_BLOCK_SIZES \ + CAMELLIA_128_BLOCK_SIZE_BYTES, CAMELLIA_192_BLOCK_SIZE_BYTES, \ + CAMELLIA_256_BLOCK_SIZE_BYTES +#if ALG_CAMELLIA +# define CAMELLIA_MAX_BLOCK_SIZE 16 +#else +# define CAMELLIA_MAX_BLOCK_SIZE 0 +#endif +#define MAX_CAMELLIA_BLOCK_SIZE_BYTES CAMELLIA_MAX_BLOCK_SIZE +// 1:17 - Defines for TDES Symmetric Cipher Algorithm Constants +#define TDES_KEY_SIZES_BITS (128 * TDES_128), (192 * TDES_192) +#if TDES_192 +# define TDES_MAX_KEY_SIZE_BITS 192 +#elif TDES_128 +# define TDES_MAX_KEY_SIZE_BITS 128 +#else +# define TDES_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_TDES_KEY_BITS TDES_MAX_KEY_SIZE_BITS +#define MAX_TDES_KEY_BYTES ((TDES_MAX_KEY_SIZE_BITS + 7) / 8) +#define TDES_128_BLOCK_SIZE_BYTES (TDES_128 * 8) +#define TDES_192_BLOCK_SIZE_BYTES (TDES_192 * 8) +#define TDES_BLOCK_SIZES \ + TDES_128_BLOCK_SIZE_BYTES, TDES_192_BLOCK_SIZE_BYTES +#if ALG_TDES +# define TDES_MAX_BLOCK_SIZE 8 +#else +# define TDES_MAX_BLOCK_SIZE 0 +#endif +#define MAX_TDES_BLOCK_SIZE_BYTES TDES_MAX_BLOCK_SIZE +// Additional values for benefit of code +#define TPM_CC_FIRST 0x0000011F +#define TPM_CC_LAST 0x0000019A +#if COMPRESSED_LISTS +#define ADD_FILL 0 +#else +#define ADD_FILL 1 +#endif +// Size the array of library commands based on whether or not the array is packed (only defined +// commands) or dense (having entries for unimplemented commands) +#define LIBRARY_COMMAND_ARRAY_SIZE (0 \ + + (ADD_FILL || CC_NV_UndefineSpaceSpecial) /* 0x0000011F */ \ + + (ADD_FILL || CC_EvictControl) /* 0x00000120 */ \ + + (ADD_FILL || CC_HierarchyControl) /* 0x00000121 */ \ + + (ADD_FILL || CC_NV_UndefineSpace) /* 0x00000122 */ \ + + ADD_FILL /* 0x00000123 */ \ + + (ADD_FILL || CC_ChangeEPS) /* 0x00000124 */ \ + + (ADD_FILL || CC_ChangePPS) /* 0x00000125 */ \ + + (ADD_FILL || CC_Clear) /* 0x00000126 */ \ + + (ADD_FILL || CC_ClearControl) /* 0x00000127 */ \ + + (ADD_FILL || CC_ClockSet) /* 0x00000128 */ \ + + (ADD_FILL || CC_HierarchyChangeAuth) /* 0x00000129 */ \ + + (ADD_FILL || CC_NV_DefineSpace) /* 0x0000012A */ \ + + (ADD_FILL || CC_PCR_Allocate) /* 0x0000012B */ \ + + (ADD_FILL || CC_PCR_SetAuthPolicy) /* 0x0000012C */ \ + + (ADD_FILL || CC_PP_Commands) /* 0x0000012D */ \ + + (ADD_FILL || CC_SetPrimaryPolicy) /* 0x0000012E */ \ + + (ADD_FILL || CC_FieldUpgradeStart) /* 0x0000012F */ \ + + (ADD_FILL || CC_ClockRateAdjust) /* 0x00000130 */ \ + + (ADD_FILL || CC_CreatePrimary) /* 0x00000131 */ \ + + (ADD_FILL || CC_NV_GlobalWriteLock) /* 0x00000132 */ \ + + (ADD_FILL || CC_GetCommandAuditDigest) /* 0x00000133 */ \ + + (ADD_FILL || CC_NV_Increment) /* 0x00000134 */ \ + + (ADD_FILL || CC_NV_SetBits) /* 0x00000135 */ \ + + (ADD_FILL || CC_NV_Extend) /* 0x00000136 */ \ + + (ADD_FILL || CC_NV_Write) /* 0x00000137 */ \ + + (ADD_FILL || CC_NV_WriteLock) /* 0x00000138 */ \ + + (ADD_FILL || CC_DictionaryAttackLockReset) /* 0x00000139 */ \ + + (ADD_FILL || CC_DictionaryAttackParameters) /* 0x0000013A */ \ + + (ADD_FILL || CC_NV_ChangeAuth) /* 0x0000013B */ \ + + (ADD_FILL || CC_PCR_Event) /* 0x0000013C */ \ + + (ADD_FILL || CC_PCR_Reset) /* 0x0000013D */ \ + + (ADD_FILL || CC_SequenceComplete) /* 0x0000013E */ \ + + (ADD_FILL || CC_SetAlgorithmSet) /* 0x0000013F */ \ + + (ADD_FILL || CC_SetCommandCodeAuditStatus) /* 0x00000140 */ \ + + (ADD_FILL || CC_FieldUpgradeData) /* 0x00000141 */ \ + + (ADD_FILL || CC_IncrementalSelfTest) /* 0x00000142 */ \ + + (ADD_FILL || CC_SelfTest) /* 0x00000143 */ \ + + (ADD_FILL || CC_Startup) /* 0x00000144 */ \ + + (ADD_FILL || CC_Shutdown) /* 0x00000145 */ \ + + (ADD_FILL || CC_StirRandom) /* 0x00000146 */ \ + + (ADD_FILL || CC_ActivateCredential) /* 0x00000147 */ \ + + (ADD_FILL || CC_Certify) /* 0x00000148 */ \ + + (ADD_FILL || CC_PolicyNV) /* 0x00000149 */ \ + + (ADD_FILL || CC_CertifyCreation) /* 0x0000014A */ \ + + (ADD_FILL || CC_Duplicate) /* 0x0000014B */ \ + + (ADD_FILL || CC_GetTime) /* 0x0000014C */ \ + + (ADD_FILL || CC_GetSessionAuditDigest) /* 0x0000014D */ \ + + (ADD_FILL || CC_NV_Read) /* 0x0000014E */ \ + + (ADD_FILL || CC_NV_ReadLock) /* 0x0000014F */ \ + + (ADD_FILL || CC_ObjectChangeAuth) /* 0x00000150 */ \ + + (ADD_FILL || CC_PolicySecret) /* 0x00000151 */ \ + + (ADD_FILL || CC_Rewrap) /* 0x00000152 */ \ + + (ADD_FILL || CC_Create) /* 0x00000153 */ \ + + (ADD_FILL || CC_ECDH_ZGen) /* 0x00000154 */ \ + + (ADD_FILL || CC_HMAC || CC_MAC) /* 0x00000155 */ \ + + (ADD_FILL || CC_Import) /* 0x00000156 */ \ + + (ADD_FILL || CC_Load) /* 0x00000157 */ \ + + (ADD_FILL || CC_Quote) /* 0x00000158 */ \ + + (ADD_FILL || CC_RSA_Decrypt) /* 0x00000159 */ \ + + ADD_FILL /* 0x0000015A */ \ + + (ADD_FILL || CC_HMAC_Start || CC_MAC_Start) /* 0x0000015B */ \ + + (ADD_FILL || CC_SequenceUpdate) /* 0x0000015C */ \ + + (ADD_FILL || CC_Sign) /* 0x0000015D */ \ + + (ADD_FILL || CC_Unseal) /* 0x0000015E */ \ + + ADD_FILL /* 0x0000015F */ \ + + (ADD_FILL || CC_PolicySigned) /* 0x00000160 */ \ + + (ADD_FILL || CC_ContextLoad) /* 0x00000161 */ \ + + (ADD_FILL || CC_ContextSave) /* 0x00000162 */ \ + + (ADD_FILL || CC_ECDH_KeyGen) /* 0x00000163 */ \ + + (ADD_FILL || CC_EncryptDecrypt) /* 0x00000164 */ \ + + (ADD_FILL || CC_FlushContext) /* 0x00000165 */ \ + + ADD_FILL /* 0x00000166 */ \ + + (ADD_FILL || CC_LoadExternal) /* 0x00000167 */ \ + + (ADD_FILL || CC_MakeCredential) /* 0x00000168 */ \ + + (ADD_FILL || CC_NV_ReadPublic) /* 0x00000169 */ \ + + (ADD_FILL || CC_PolicyAuthorize) /* 0x0000016A */ \ + + (ADD_FILL || CC_PolicyAuthValue) /* 0x0000016B */ \ + + (ADD_FILL || CC_PolicyCommandCode) /* 0x0000016C */ \ + + (ADD_FILL || CC_PolicyCounterTimer) /* 0x0000016D */ \ + + (ADD_FILL || CC_PolicyCpHash) /* 0x0000016E */ \ + + (ADD_FILL || CC_PolicyLocality) /* 0x0000016F */ \ + + (ADD_FILL || CC_PolicyNameHash) /* 0x00000170 */ \ + + (ADD_FILL || CC_PolicyOR) /* 0x00000171 */ \ + + (ADD_FILL || CC_PolicyTicket) /* 0x00000172 */ \ + + (ADD_FILL || CC_ReadPublic) /* 0x00000173 */ \ + + (ADD_FILL || CC_RSA_Encrypt) /* 0x00000174 */ \ + + ADD_FILL /* 0x00000175 */ \ + + (ADD_FILL || CC_StartAuthSession) /* 0x00000176 */ \ + + (ADD_FILL || CC_VerifySignature) /* 0x00000177 */ \ + + (ADD_FILL || CC_ECC_Parameters) /* 0x00000178 */ \ + + (ADD_FILL || CC_FirmwareRead) /* 0x00000179 */ \ + + (ADD_FILL || CC_GetCapability) /* 0x0000017A */ \ + + (ADD_FILL || CC_GetRandom) /* 0x0000017B */ \ + + (ADD_FILL || CC_GetTestResult) /* 0x0000017C */ \ + + (ADD_FILL || CC_Hash) /* 0x0000017D */ \ + + (ADD_FILL || CC_PCR_Read) /* 0x0000017E */ \ + + (ADD_FILL || CC_PolicyPCR) /* 0x0000017F */ \ + + (ADD_FILL || CC_PolicyRestart) /* 0x00000180 */ \ + + (ADD_FILL || CC_ReadClock) /* 0x00000181 */ \ + + (ADD_FILL || CC_PCR_Extend) /* 0x00000182 */ \ + + (ADD_FILL || CC_PCR_SetAuthValue) /* 0x00000183 */ \ + + (ADD_FILL || CC_NV_Certify) /* 0x00000184 */ \ + + (ADD_FILL || CC_EventSequenceComplete) /* 0x00000185 */ \ + + (ADD_FILL || CC_HashSequenceStart) /* 0x00000186 */ \ + + (ADD_FILL || CC_PolicyPhysicalPresence) /* 0x00000187 */ \ + + (ADD_FILL || CC_PolicyDuplicationSelect) /* 0x00000188 */ \ + + (ADD_FILL || CC_PolicyGetDigest) /* 0x00000189 */ \ + + (ADD_FILL || CC_TestParms) /* 0x0000018A */ \ + + (ADD_FILL || CC_Commit) /* 0x0000018B */ \ + + (ADD_FILL || CC_PolicyPassword) /* 0x0000018C */ \ + + (ADD_FILL || CC_ZGen_2Phase) /* 0x0000018D */ \ + + (ADD_FILL || CC_EC_Ephemeral) /* 0x0000018E */ \ + + (ADD_FILL || CC_PolicyNvWritten) /* 0x0000018F */ \ + + (ADD_FILL || CC_PolicyTemplate) /* 0x00000190 */ \ + + (ADD_FILL || CC_CreateLoaded) /* 0x00000191 */ \ + + (ADD_FILL || CC_PolicyAuthorizeNV) /* 0x00000192 */ \ + + (ADD_FILL || CC_EncryptDecrypt2) /* 0x00000193 */ \ + + (ADD_FILL || CC_AC_GetCapability) /* 0x00000194 */ \ + + (ADD_FILL || CC_AC_Send) /* 0x00000195 */ \ + + (ADD_FILL || CC_Policy_AC_SendSelect) /* 0x00000196 */ \ + + (ADD_FILL || CC_CertifyX509) /* 0x00000197 */ \ + + (ADD_FILL || CC_ACT_SetTimeout) /* 0x00000198 */ \ + + (ADD_FILL || CC_ECC_Encrypt) /* 0x00000199 */ \ + + (ADD_FILL || CC_ECC_Decrypt) /* 0x0000019A */ \ + ) + +#define VENDOR_COMMAND_ARRAY_SIZE (0 + CC_Vendor_TCG_Test) + +#define COMMAND_COUNT (LIBRARY_COMMAND_ARRAY_SIZE + VENDOR_COMMAND_ARRAY_SIZE) +#define HASH_COUNT \ + (ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA3_256 + \ + ALG_SHA3_384 + ALG_SHA3_512 + ALG_SHA512 + ALG_SM3_256) +#define MAX_HASH_BLOCK_SIZE \ + (MAX(ALG_SHA1 * SHA1_BLOCK_SIZE, \ + MAX(ALG_SHA256 * SHA256_BLOCK_SIZE, \ + MAX(ALG_SHA384 * SHA384_BLOCK_SIZE, \ + MAX(ALG_SHA3_256 * SHA3_256_BLOCK_SIZE, \ + MAX(ALG_SHA3_384 * SHA3_384_BLOCK_SIZE, \ + MAX(ALG_SHA3_512 * SHA3_512_BLOCK_SIZE, \ + MAX(ALG_SHA512 * SHA512_BLOCK_SIZE, \ + MAX(ALG_SM3_256 * SM3_256_BLOCK_SIZE, \ + 0))))))))) +#define MAX_DIGEST_SIZE \ + (MAX(ALG_SHA1 * SHA1_DIGEST_SIZE, \ + MAX(ALG_SHA256 * SHA256_DIGEST_SIZE, \ + MAX(ALG_SHA384 * SHA384_DIGEST_SIZE, \ + MAX(ALG_SHA3_256 * SHA3_256_DIGEST_SIZE, \ + MAX(ALG_SHA3_384 * SHA3_384_DIGEST_SIZE, \ + MAX(ALG_SHA3_512 * SHA3_512_DIGEST_SIZE, \ + MAX(ALG_SHA512 * SHA512_DIGEST_SIZE, \ + MAX(ALG_SM3_256 * SM3_256_DIGEST_SIZE, \ + 0))))))))) +#if MAX_DIGEST_SIZE == 0 || MAX_HASH_BLOCK_SIZE == 0 +#error "Hash data not valid" +#endif +// Define the 2B structure that would hold any hash block +TPM2B_TYPE(MAX_HASH_BLOCK, MAX_HASH_BLOCK_SIZE); +// Following typedef is for some old code +typedef TPM2B_MAX_HASH_BLOCK TPM2B_HASH_BLOCK; + +#define MAX_SYM_KEY_BITS \ + (MAX(AES_MAX_KEY_SIZE_BITS, MAX(CAMELLIA_MAX_KEY_SIZE_BITS, \ + MAX(SM4_MAX_KEY_SIZE_BITS, MAX(TDES_MAX_KEY_SIZE_BITS, \ + 0))))) +#define MAX_SYM_KEY_BYTES ((MAX_SYM_KEY_BITS + 7) / 8) +#define MAX_SYM_BLOCK_SIZE \ + (MAX(AES_MAX_BLOCK_SIZE, MAX(CAMELLIA_MAX_BLOCK_SIZE, \ + MAX(SM4_MAX_BLOCK_SIZE, MAX(TDES_MAX_BLOCK_SIZE, \ + 0))))) +#if MAX_SYM_KEY_BITS == 0 || MAX_SYM_BLOCK_SIZE == 0 +# error Bad size for MAX_SYM_KEY_BITS or MAX_SYM_BLOCK +#endif +#endif // _TPM_ALGORITHM_DEFINES_H_ diff --git a/src/tpm2/TpmAsn1.c b/src/tpm2/TpmAsn1.c new file mode 100644 index 0000000..f23b2a9 --- /dev/null +++ b/src/tpm2/TpmAsn1.c @@ -0,0 +1,508 @@ +/********************************************************************************/ +/* */ +/* TPM ASN.1 */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmAsn1.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +/* 10.2.23 TpmAsn1.c */ +/* 10.2.23.1 Includes */ +#include "Tpm.h" +#define _OIDS_ +#include "OIDs.h" +#include "TpmAsn1.h" +#include "TpmAsn1_fp.h" +/* 10.2.23.2 Unmarshaling Functions */ +/* 10.2.23.2.1 ASN1UnmarshalContextInitialize() */ +/* Function does standard initialization of a context. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure */ +BOOL +ASN1UnmarshalContextInitialize( + ASN1UnmarshalContext *ctx, + INT16 size, + BYTE *buffer + ) +{ + VERIFY(buffer != NULL); + VERIFY(size > 0); + ctx->buffer = buffer; + ctx->size = size; + ctx->offset = 0; + ctx->tag = 0xFF; + return TRUE; + Error: + return FALSE; +} +/* 10.2.23.2.2 ASN1DecodeLength() */ +/* This function extracts the length of an element from buffer starting at offset. */ +/* Return Value Meaning */ +/* >=0 the extracted length */ +/* <0 an error */ +INT16 +ASN1DecodeLength( + ASN1UnmarshalContext *ctx + ) +{ + BYTE first; // Next octet in buffer + INT16 value; + // + VERIFY(ctx->offset < ctx->size); + first = NEXT_OCTET(ctx); + // If the number of octets of the entity is larger than 127, then the first octet + // is the number of octets in the length specifier. + if(first >= 0x80) + { + // Make sure that this length field is contained with the structure being + // parsed + CHECK_SIZE(ctx, (first & 0x7F)); + if(first == 0x82) + { + // Two octets of size + // get the next value + value = (INT16)NEXT_OCTET(ctx); + // Make sure that the result will fit in an INT16 + VERIFY(value < 0x0080); + // Shift up and add next octet + value = (value << 8) + NEXT_OCTET(ctx); + } + else if(first == 0x81) + value = NEXT_OCTET(ctx); + // Sizes larger than will fit in a INT16 are an error + else + goto Error; + } + else + value = first; + // Make sure that the size defined something within the current context + CHECK_SIZE(ctx, value); + return value; + Error: + ctx->size = -1; // Makes everything fail from now on. + return -1; +} +/* 10.2.23.2.3 ASN1NextTag() */ +/* This function extracts the next type from buffer starting at offset. It advances offset as it + parses the type and the length of the type. It returns the length of the type. On return, the + length octets starting at offset are the octets of the type. */ +/* Return Value Meaning */ +/* >=0 the number of octets in type */ +/* <0 an error */ +INT16 +ASN1NextTag( + ASN1UnmarshalContext *ctx + ) +{ + // A tag to get? + VERIFY(ctx->offset < ctx->size); + // Get it + ctx->tag = NEXT_OCTET(ctx); + // Make sure that it is not an extended tag + VERIFY((ctx->tag & 0x1F) != 0x1F); + // Get the length field and return that + return ASN1DecodeLength(ctx); + + Error: + // Attempt to read beyond the end of the context or an illegal tag + ctx->size = -1; // Persistent failure + ctx->tag = 0xFF; + return -1; +} +/* 10.2.23.2.4 ASN1GetBitStringValue() */ +/* Try to parse a bit string of up to 32 bits from a value that is expected to be a bit string. The + bit string is left justified so that the MSb of the input is the MSb of the returned value. If + there is a general parsing error, the context->size is set to -1. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure */ + +BOOL +ASN1GetBitStringValue( + ASN1UnmarshalContext *ctx, + UINT32 *val + ) +{ + int shift; + INT16 length; + UINT32 value = 0; + int inputBits; + // + length = ASN1NextTag(ctx); + VERIFY(length >= 1); + VERIFY(ctx->tag == ASN1_BITSTRING); + // Get the shift value for the bit field (how many bits to lop off of the end) + shift = NEXT_OCTET(ctx); + length--; + // Get the number of bits in the input + inputBits = (8 * length) - shift; + // the shift count has to make sense + VERIFY((shift < 8) && ((length > 0) || (shift == 0))); + // if there are any bytes left + for(; length > 1; length--) + { + + // for all but the last octet, just shift and add the new octet + VERIFY((value & 0xFF000000) == 0); // can't loose significant bits + value = (value << 8) + NEXT_OCTET(ctx); + + } + if(length == 1) + { + // for the last octet, just shift the accumulated value enough to + // accept the significant bits in the last octet and shift the last + // octet down + VERIFY(((value & (0xFF000000 << (8 - shift)))) == 0); + value = (value << (8 - shift)) + (NEXT_OCTET(ctx) >> shift); + + } + // 'Left justify' the result + if(inputBits > 0) + value <<= (32 - inputBits); + *val = value; + return TRUE; + Error: + ctx->size = -1; + return FALSE; +} + +/* 10.2.23.3 Marshaling Functions */ +/* 10.2.23.3.1 Introduction */ +/* Marshaling of an ASN.1 structure is accomplished from the bottom up. That is, the things that + will be at the end of the structure are added last. To manage the collecting of the relative + sizes, start a context for the outermost container, if there is one, and then placing items in + from the bottom up. If the bottom-most item is also within a structure, create a nested context + by calling ASN1StartMarshalingContext(). */ +/* The context control structure contains a buffer pointer, an offset, an end and a stack. offset is + the offset from the start of the buffer of the last added byte. When offset reaches 0, the buffer + is full. offset is a signed value so that, when it becomes negative, there is an overflow. Only + two functions are allowed to move bytes into the buffer: ASN1PushByte() and + ASN1PushBytes(). These functions make sure that no data is written beyond the end of the + buffer. */ +/* When a new context is started, the current value of end is pushed on the stack and end is set to + 'offset. As bytes are added, offset gets smaller. At any time, the count of bytes in the current + context is simply end - offset. */ +/* Since starting a new context involves setting end = offset, the number of bytes in the context + starts at 0. The nominal way of ending a context is to use end - offset to set the length value, + and then a tag is added to the buffer. Then the previous end value is popped meaning that the + context just ended becomes a member of the now current context. */ +/* The nominal strategy for building a completed ASN.1 structure is to push everything into the + buffer and then move everything to the start of the buffer. The move is simple as the size of the + move is the initial end value minus the final offset value. The destination is buffer and the + source is buffer + offset. As Skippy would say "Easy peasy, Joe." */ +/* It is not necessary to provide a buffer into which the data is placed. If no buffer is provided, + then the marshaling process will return values needed for marshaling. On strategy for filling the + buffer would be to execute the process for building the structure without using a buffer. This + would return the overall size of the structure. Then that amount of data could be allocated for + the buffer and the fill process executed again with the data going into the buffer. At the end, + the data would be in its final resting place. */ +/* 10.2.23.3.2 ASN1InitialializeMarshalContext() */ +/* This creates a structure for handling marshaling of an ASN.1 formatted data structure. */ +void +ASN1InitialializeMarshalContext( + ASN1MarshalContext *ctx, + INT16 length, + BYTE *buffer + ) +{ + ctx->buffer = buffer; + if(buffer) + ctx->offset = length; + else + ctx->offset = INT16_MAX; + ctx->end = ctx->offset; + ctx->depth = -1; +} +/* 10.2.23.3.3 ASN1StartMarshalContext() */ +/* This starts a new constructed element. It is constructed on top of the value that was previously placed in the structure. */ +void +ASN1StartMarshalContext( + ASN1MarshalContext *ctx + ) +{ + pAssert((ctx->depth + 1) < MAX_DEPTH); + ctx->depth++; + ctx->ends[ctx->depth] = ctx->end; + ctx->end = ctx->offset; +} +/* 10.2.23.3.4 ASN1EndMarshalContext() */ +/* This function restores the end pointer for an encapsulating structure. */ +/* Return Value Meaning */ +/* > 0 the size of the encapsulated structure that was just ended */ +/* <= 0 an error */ +INT16 +ASN1EndMarshalContext( + ASN1MarshalContext *ctx + ) +{ + INT16 length; + pAssert(ctx->depth >= 0); + length = ctx->end - ctx->offset; + ctx->end = ctx->ends[ctx->depth--]; + if((ctx->depth == -1) && (ctx->buffer)) + { + MemoryCopy(ctx->buffer, ctx->buffer + ctx->offset, ctx->end - ctx->offset); + } + return length; +} +/* 10.2.23.3.5 ASN1EndEncapsulation() */ +/* This function puts a tag and length in the buffer. In this function, an embedded BIT_STRING is + assumed to be a collection of octets. To indicate that all bits are used, a byte of zero is + prepended. If a raw bit-string is needed, a new function like ASN1PushInteger() would be + needed. */ +/* Return Value Meaning */ +/* > 0 number of octets in the encapsulation */ +/* == 0 failure */ +UINT16 +ASN1EndEncapsulation( + ASN1MarshalContext *ctx, + BYTE tag + ) +{ + // only add a leading zero for an encapsulated BIT STRING + if (tag == ASN1_BITSTRING) + ASN1PushByte(ctx, 0); + ASN1PushTagAndLength(ctx, tag, ctx->end - ctx->offset); + return ASN1EndMarshalContext(ctx); +} +/* 10.2.23.3.6 ASN1PushByte() */ +BOOL +ASN1PushByte( + ASN1MarshalContext *ctx, + BYTE b + ) +{ + if(ctx->offset > 0) + { + ctx->offset -= 1; + if(ctx->buffer) + ctx->buffer[ctx->offset] = b; + return TRUE; + } + ctx->offset = -1; + return FALSE; +} +/* 10.2.23.3.7 ASN1PushBytes() */ +/* Push some raw bytes onto the buffer. count cannot be zero. */ +/* Return Value Meaning */ +/* > 0 count bytes */ +/* == 0 failure unless count was zero */ +INT16 +ASN1PushBytes( + ASN1MarshalContext *ctx, + INT16 count, + const BYTE *buffer + ) +{ + // make sure that count is not negative which would mess up the math; and that + // if there is a count, there is a buffer + VERIFY((count >= 0) && ((buffer != NULL) || (count == 0))); + // back up the offset to determine where the new octets will get pushed + ctx->offset -= count; + // can't go negative + VERIFY(ctx->offset >= 0); + // if there are buffers, move the data, otherwise, assume that this is just a + // test. + if(count && buffer && ctx->buffer) + MemoryCopy(&ctx->buffer[ctx->offset], buffer, count); + return count; + Error: + ctx->offset = -1; + return 0; +} +/* 10.2.23.3.8 ASN1PushNull() */ +/* Return Value Meaning */ +/* > 0 count bytes */ +/* == 0 failure unless count was zero */ +INT16 +ASN1PushNull( + ASN1MarshalContext *ctx + ) +{ + ASN1PushByte(ctx, 0); + ASN1PushByte(ctx, ASN1_NULL); + return (ctx->offset >= 0) ? 2 : 0; +} +/* 10.2.23.3.9 ASN1PushLength() */ +/* Push a length value. This will only handle length values that fit in an INT16. */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +ASN1PushLength( + ASN1MarshalContext *ctx, + INT16 len + ) +{ + UINT16 start = ctx->offset; + VERIFY(len >= 0); + if(len <= 127) + ASN1PushByte(ctx, (BYTE)len); + else + { + ASN1PushByte(ctx, (BYTE)(len & 0xFF)); + len >>= 8; + if(len == 0) + ASN1PushByte(ctx, 0x81); + else + { + ASN1PushByte(ctx, (BYTE)(len)); + ASN1PushByte(ctx, 0x82); + } + } + goto Exit; + Error: + ctx->offset = -1; + Exit: + return (ctx->offset > 0) ? start - ctx->offset : 0; +} +/* 10.2.23.3.10 ASN1PushTagAndLength() */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +ASN1PushTagAndLength( + ASN1MarshalContext *ctx, + BYTE tag, + INT16 length + ) +{ + INT16 bytes; + bytes = ASN1PushLength(ctx, length); + bytes += (INT16)ASN1PushByte(ctx, tag); + return (ctx->offset < 0) ? 0 : bytes; +} +/* 10.2.23.3.11 ASN1PushTaggedOctetString() */ +/* This function will push a random octet string. */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +ASN1PushTaggedOctetString( + ASN1MarshalContext *ctx, + INT16 size, + const BYTE *string, + BYTE tag + ) +{ + ASN1PushBytes(ctx, size, string); + // PushTagAndLenght just tells how many octets it added so the total size of this + // element is the sum of those octets and input size. + size += ASN1PushTagAndLength(ctx, tag, size); + return size; +} +/* 10.2.23.3.12 ASN1PushUINT() */ +/* This function pushes an native-endian integer value. This just changes a native-endian integer + into a big-endian byte string and calls ASN1PushInteger(). That function will remove leading + zeros and make sure that the number is positive. */ +/* Return Value Meaning */ +/* > 0 count bytes */ +/* == 0 failure unless count was zero */ +INT16 +ASN1PushUINT( + ASN1MarshalContext *ctx, + UINT32 integer + ) +{ + BYTE marshaled[4]; + UINT32_TO_BYTE_ARRAY(integer, marshaled); + return ASN1PushInteger(ctx, 4, marshaled); +} +/* 10.2.23.3.13 ASN1PushInteger */ +/* Push a big-endian integer on the end of the buffer */ +/* Return Value Meaning */ +/* > 0 the number of bytes marshaled for the integer */ +/* == 0 failure */ +INT16 +ASN1PushInteger( + ASN1MarshalContext *ctx, // IN/OUT: buffer context + INT16 iLen, // IN: octets of the integer + BYTE *integer // IN: big-endian integer + ) +{ + // no leading 0's + while((*integer == 0) && (--iLen > 0)) + integer++; + // Move the bytes to the buffer + ASN1PushBytes(ctx, iLen, integer); + // if needed, add a leading byte of 0 to make the number positive + if(*integer & 0x80) + iLen += (INT16)ASN1PushByte(ctx, 0); + // PushTagAndLenght just tells how many octets it added so the total size of this + // element is the sum of those octets and the adjusted input size. + iLen += ASN1PushTagAndLength(ctx, ASN1_INTEGER, iLen); + return iLen; +} +/* 10.2.23.3.14 ASN1PushOID() */ +/* This function is used to add an OID. An OID is 0x06 followed by a byte of size followed by size + bytes. This is used to avoid having to do anything special in the definition of an OID. */ +/* Return Value Meaning */ +/* > 0 the number of bytes marshaled for the integer */ +/* == 0 failure */ +INT16 +ASN1PushOID( + ASN1MarshalContext *ctx, + const BYTE *OID + ) +{ + if((*OID == ASN1_OBJECT_IDENTIFIER) && ((OID[1] & 0x80) == 0)) + { + return ASN1PushBytes(ctx, OID[1] + 2, OID); + } + ctx->offset = -1; + return 0; +} diff --git a/src/tpm2/TpmAsn1.h b/src/tpm2/TpmAsn1.h new file mode 100644 index 0000000..5e57eac --- /dev/null +++ b/src/tpm2/TpmAsn1.h @@ -0,0 +1,137 @@ +/********************************************************************************/ +/* */ +/* Macro and Structure Definitions for the X509 Commands and Functions. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmAsn1.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +// 10.1.15 TpmAsn1.h +// 10.1.15.1 Introduction +// This file contains the macro and structure definitions for the X509 commands and functions. +#ifndef _TPMASN1_H_ +#define _TPMASN1_H_ +// 10.1.15.2 Includes +#include "Tpm.h" +#include "OIDs.h" +// 10.1.15.3 Defined Constants +// 10.1.15.3.1 ASN.1 Universal Types (Class 00b +#define ASN1_EOC 0x00 +#define ASN1_BOOLEAN 0x01 +#define ASN1_INTEGER 0x02 +#define ASN1_BITSTRING 0x03 +#define ASN1_OCTET_STRING 0x04 +#define ASN1_NULL 0x05 +#define ASN1_OBJECT_IDENTIFIER 0x06 +#define ASN1_OBJECT_DESCRIPTOR 0x07 +#define ASN1_EXTERNAL 0x08 +#define ASN1_REAL 0x09 +#define ASN1_ENUMERATED 0x0A +#define ASN1_EMBEDDED 0x0B +#define ASN1_UTF8String 0x0C +#define ASN1_RELATIVE_OID 0x0D +#define ASN1_SEQUENCE 0x10 // Primitive + Constructed + 0x10 +#define ASN1_SET 0x11 // Primitive + Constructed + 0x11 +#define ASN1_NumericString 0x12 +#define ASN1_PrintableString 0x13 +#define ASN1_T61String 0x14 +#define ASN1_VideoString 0x15 +#define ASN1_IA5String 0x16 +#define ASN1_UTCTime 0x17 +#define ASN1_GeneralizeTime 0x18 +#define ASN1_VisibleString 0x1A +#define ASN1_GeneralString 0x1B +#define ASN1_UniversalString 0x1C +#define ASN1_CHARACTER STRING 0x1D +#define ASN1_BMPString 0x1E +#define ASN1_CONSTRUCTED 0x20 +#define ASN1_APPLICAIION_SPECIFIC 0xA0 +#define ASN1_CONSTRUCTED_SEQUENCE (ASN1_SEQUENCE + ASN1_CONSTRUCTED) +#define MAX_DEPTH 10 // maximum push depth for marshaling context. +// 10.1.15.4 Macros +// 10.1.15.4.1 Unmarshaling Macros +#ifndef VERIFY +#define VERIFY(_X_) {if(!(_X_)) goto Error; } +#endif +// Checks the validity of the size making sure that there is no wrap around +#define CHECK_SIZE(context, length) \ + VERIFY( (((length) + (context)->offset) >= (context)->offset) \ + && (((length) + (context)->offset) <= (context)->size)) +#define NEXT_OCTET(context) ((context)->buffer[(context)->offset++]) +#define PEEK_NEXT(context) ((context)->buffer[(context)->offset]) +// 10.1.15.4.2 Marshaling Macros Marshaling works in reverse order. The offset is set to the top of +// the buffer and, as the buffer is filled, offset counts down to zero. When the full thing is +// encoded it can be moved to the top of the buffer. This happens when the last context is closed. + +#define CHECK_SPACE(context, length) VERIFY(context->offset > length) +// 10.1.15.5 Structures +typedef struct ASN1UnmarshalContext { + BYTE *buffer; // pointer to the buffer + INT16 size; // size of the buffer (a negative number indicates + // a parsing failure). + INT16 offset; // current offset into the buffer (a negative number + // indicates a parsing failure). Not used + BYTE tag; // The last unmarshaled tag +} ASN1UnmarshalContext; +typedef struct ASN1MarshalContext { + BYTE *buffer; // pointer to the start of the buffer + INT16 offset; // place on the top where the last entry was added + // items are added from the bottom up. + INT16 end; // the end offset of the current value + INT16 depth; // how many pushed end values. + INT16 ends[MAX_DEPTH]; +} ASN1MarshalContext; +#endif // _TPMASN1_H_ diff --git a/src/tpm2/TpmAsn1_fp.h b/src/tpm2/TpmAsn1_fp.h new file mode 100644 index 0000000..55f61c9 --- /dev/null +++ b/src/tpm2/TpmAsn1_fp.h @@ -0,0 +1,152 @@ +/********************************************************************************/ +/* */ +/* TPM ASN.1 */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmAsn1_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#ifndef TPMASN1_FP_H +#define TPMASN1_FP_H + +BOOL +ASN1UnmarshalContextInitialize( + ASN1UnmarshalContext *ctx, + INT16 size, + BYTE *buffer + ); +INT16 +ASN1DecodeLength( + ASN1UnmarshalContext *ctx + ); +INT16 +ASN1NextTag( + ASN1UnmarshalContext *ctx + ); +BOOL +ASN1GetBitStringValue( + ASN1UnmarshalContext *ctx, + UINT32 *val + ); +void +ASN1InitialializeMarshalContext( + ASN1MarshalContext *ctx, + INT16 length, + BYTE *buffer + ); +void +ASN1StartMarshalContext( + ASN1MarshalContext *ctx + ); +INT16 +ASN1EndMarshalContext( + ASN1MarshalContext *ctx + ); +UINT16 +ASN1EndEncapsulation( + ASN1MarshalContext *ctx, + BYTE tag + ); +BOOL +ASN1PushByte( + ASN1MarshalContext *ctx, + BYTE b + ); +INT16 +ASN1PushBytes( + ASN1MarshalContext *ctx, + INT16 count, + const BYTE *buffer + ); +INT16 +ASN1PushNull( + ASN1MarshalContext *ctx + ); +INT16 +ASN1PushLength( + ASN1MarshalContext *ctx, + INT16 len + ); +INT16 +ASN1PushTagAndLength( + ASN1MarshalContext *ctx, + BYTE tag, + INT16 length + ); +INT16 +ASN1PushTaggedOctetString( + ASN1MarshalContext *ctx, + INT16 size, + const BYTE *string, + BYTE tag + ); +INT16 +ASN1PushUINT( + ASN1MarshalContext *ctx, + UINT32 integer + ); +INT16 +ASN1PushInteger( + ASN1MarshalContext *ctx, // IN/OUT: buffer context + INT16 iLen, // IN: octets of the integer + BYTE *integer // IN: big-endian integer + ); +INT16 +ASN1PushOID( + ASN1MarshalContext *ctx, + const BYTE *OID + ); +#endif diff --git a/src/tpm2/TpmBuildSwitches.h b/src/tpm2/TpmBuildSwitches.h new file mode 100644 index 0000000..c4a7b31 --- /dev/null +++ b/src/tpm2/TpmBuildSwitches.h @@ -0,0 +1,364 @@ +/********************************************************************************/ +/* */ +/* Build Switches */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmBuildSwitches.h 1619 2020-05-19 16:51:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 5.19 TpmBuildSwitches.h */ + +/* This file contains the build switches. This contains switches for multiple versions of the + crypto-library so some may not apply to your environment. */ +/* The switches are guarded so that they can either be set on the command line or set here. If the + switch is listed on the command line (-DSOME_SWITCH) with no setting, then the switch will be set + to YES. If the switch setting is not on the command line or if the setting is other than YES or + NO, then the switch will be set to the default value. The default can either be YES or NO as + indicated on each line where the default is selected. */ +/* A caution. Do not try to test these macros by inserting #defines in this file. For some curious + reason, a variable set on the command line with no setting will have a value of 1. An #if + SOME_VARIABLE will work if the variable is not defined or is defined on the command line with no + initial setting. However, a #define SOME_VARIABLE is a null string and when used in #if + SOME_VARIABLE will not be a proper expression. If you want to test various switches, either use + the command line or change the default. */ + +#ifndef TPMBUILDSWITCHES_H +#define TPMBUILDSWITCHES_H + +#undef YES +#define YES 1 +#undef NO +#define NO 0 + +/* Allow the command line to specify a profile file */ + +#ifdef PROFILE +# define PROFILE_QUOTE(a) #a +# define PROFILE_INCLUDE(a) PROFILE_QUOTE(a) +# include PROFILE_INCLUDE(PROFILE) +#endif + +// Need an unambiguous definition for DEBUG. Don't change this +#ifndef DEBUG +# ifdef NDEBUG +# define DEBUG NO +# else +# define DEBUG YES +# endif +#elif (DEBUG != NO) && (DEBUG != YES) +# undef DEBUG +# define DEBUG YES // Default: Either YES or NO +#endif +#include "CompilerDependencies.h" + +// This definition is required for the re-factored code +#if (!defined USE_BN_ECC_DATA) || ((USE_BN_ECC_DATA != NO) && (USE_BN_ECC_DATA != YES)) +# undef USE_BN_ECC_DATA +# define USE_BN_ECC_DATA YES // Default: Either YES or NO +#endif + +/* The SIMULATION switch allows certain other macros to be enabled. The things that can be enabled + in a simulation include key caching, reproducible random sequences, instrumentation of the RSA + key generation process, and certain other debug code. SIMULATION Needs to be defined as either + YES or NO. This grouping of macros will make sure that it is set correctly. A simulated TPM would + include a Virtual TPM. The interfaces for a Virtual TPM should be modified from the standard ones + in the Simulator project. If SIMULATION is in the compile parameters without modifiers, make + SIMULATION == YES */ +#if !(defined SIMULATION) || ((SIMULATION != NO) && (SIMULATION != YES)) +# undef SIMULATION +# define SIMULATION NO // Default: Either YES or NO libtpms: NO +#endif + +// Define this to run the function that checks the compatibility between the chosen big number math +// library and the TPM code. Not all ports use this. + +#if !(defined LIBRARY_COMPATIBILITY_CHECK) \ + || (( LIBRARY_COMPATIBILITY_CHECK != NO) \ + && (LIBRARY_COMPATIBILITY_CHECK != YES)) +# undef LIBRARY_COMPATIBILITY_CHECK +# define LIBRARY_COMPATIBILITY_CHECK YES // Default: Either YES or NO libtpms: YES +#endif +#if !(defined FIPS_COMPLIANT) || ((FIPS_COMPLIANT != NO) && (FIPS_COMPLIANT != YES)) +# undef FIPS_COMPLIANT +# define FIPS_COMPLIANT NO // Default: Either YES or NO libtpms: NO +#endif + +// Definition to allow alternate behavior for non-orderly startup. If there is a chance that the TPM +// could not update failedTries + +/* Removes the behavior of automatically incrementing the failed tries counter after any non-orderly + shutdown. When YES, the failed counter is incremented on non-orderly shutdown only if an attempt + to access a DA protected object was made on the previous cycle. */ + +#if !(defined USE_DA_USED) || ((USE_DA_USED != NO) && (USE_DA_USED != YES)) +# undef USE_DA_USED +# define USE_DA_USED YES // Default: Either YES or NO +#endif + +// Define TABLE_DRIVEN_DISPATCH to use tables rather than case statements for command dispatch and +// handle unmarshaling +#if !(defined TABLE_DRIVEN_DISPATCH) \ + || ((TABLE_DRIVEN_DISPATCH != NO) && (TABLE_DRIVEN_DISPATCH != YES)) +# undef TABLE_DRIVEN_DISPATCH +# define TABLE_DRIVEN_DISPATCH YES // Default: Either YES or NO +#endif + +/* This switch is used to enable the self-test capability in AlgorithmTests.c */ +#if !(defined SELF_TEST) || ((SELF_TEST != NO) && (SELF_TEST != YES)) +# undef SELF_TEST +# define SELF_TEST YES // Default: Either YES or NO +#endif + +/* Enable the generation of RSA primes using a sieve. */ +#if !(defined RSA_KEY_SIEVE) || ((RSA_KEY_SIEVE != NO) && (RSA_KEY_SIEVE != YES)) +# undef RSA_KEY_SIEVE +# define RSA_KEY_SIEVE YES // Default: Either YES or NO +#endif + +/* Enable the instrumentation of the sieve process. This is used to tune the sieve variables.*/ +#if RSA_KEY_SIEVE && SIMULATION +# if !(defined RSA_INSTRUMENT) || ((RSA_INSTRUMENT != NO) && (RSA_INSTRUMENT != YES)) +# undef RSA_INSTRUMENT +# define RSA_INSTRUMENT NO // Default: Either YES or NO +# endif +#endif + +/* This switch enables the RNG state save and restore */ +#if !(defined _DRBG_STATE_SAVE) \ + || ((_DRBG_STATE_SAVE != NO) && (_DRBG_STATE_SAVE != YES)) +# undef _DRBG_STATE_SAVE +# define _DRBG_STATE_SAVE YES // Default: Either YES or NO +#endif + +/* Switch added to support packed lists that leave out space associated with unimplemented + commands. Comment this out to use linear lists. */ +/* NOTE: if vendor specific commands are present, the associated list is always in compressed + form. */ +#if !(defined COMPRESSED_LISTS) \ + || ((COMPRESSED_LISTS != NO) && (COMPRESSED_LISTS != YES)) +# undef COMPRESSED_LISTS +# define COMPRESSED_LISTS YES // Default: Either YES or NO +#endif + + +/* This switch indicates where clock epoch value should be stored. If this value defined, then it is + assumed that the timer will change at any time so the nonce should be a random number kept in + RAM. When it is not defined, then the timer only stops during power outages. */ +#if !(defined CLOCK_STOPS) || ((CLOCK_STOPS != NO) && (CLOCK_STOPS != YES)) +# undef CLOCK_STOPS +# define CLOCK_STOPS NO // Default: Either YES or NO +#endif + +// This switch allows use of #defines in place of pass-through marshaling or unmarshaling code. A +// pass-through function just calls another function to do the required function and does no +// parameter checking of its own. The table-driven dispatcher calls directly to the lowest level +// marshaling/unmarshaling code and by-passes any pass-through functions. +#if (defined USE_MARSHALING_DEFINES) && (USE_MARSHALING_DEFINES != NO) +# undef USE_MARSHALING_DEFINES +# define USE_MARSHALING_DEFINES YES +#else +# define USE_MARSHALING_DEFINES YES // Default: Either YES or NO +#endif + +// The switches in this group can only be enabled when doing debug during simulation +#if SIMULATION && DEBUG + +/* This forces the use of a smaller context slot size. This reduction reduces the range of the epoch + allowing the tester to force the epoch to occur faster than the normal defined in TpmProfile.h */ +# if !(defined CONTEXT_SLOT) +# define CONTEXT_SLOT UINT8 +# endif + +// Enables use of the key cache. Default is YES +# if !(defined USE_RSA_KEY_CACHE) \ + || ((USE_RSA_KEY_CACHE != NO) && (USE_RSA_KEY_CACHE != YES)) +# undef USE_RSA_KEY_CACHE +# define USE_RSA_KEY_CACHE YES // Default: Either YES or NO +# endif + +// Enables use of a file to store the key cache values so that the TPM will start faster during +// debug. Default for this is YES +# if USE_RSA_KEY_CACHE +# if !(defined USE_KEY_CACHE_FILE) \ + || ((USE_KEY_CACHE_FILE != NO) && (USE_KEY_CACHE_FILE != YES)) +# undef USE_KEY_CACHE_FILE +# define USE_KEY_CACHE_FILE YES // Default: Either YES or NO +# endif +# else +# undef USE_KEY_CACHE_FILE +# define USE_KEY_CACHE_FILE NO +# endif // USE_RSA_KEY_CACHE + +// This provides fixed seeding of the RNG when doing debug on a simulator. This should allow +// consistent results on test runs as long as the input parameters to the functions remains the +// same. There is no default value. +# if !(defined USE_DEBUG_RNG) || ((USE_DEBUG_RNG != NO) && (USE_DEBUG_RNG != YES)) +# undef USE_DEBUG_RNG +# define USE_DEBUG_RNG YES // Default: Either YES or NO +# endif + +// Don't change these. They are the settings needed when not doing a simulation and not doing +// debug. Can't use the key cache except during debug. Otherwise, all of the key values end up being +// the same +#else +# define USE_RSA_KEY_CACHE NO +# define USE_RSA_KEY_CACHE_FILE NO +# define USE_DEBUG_RNG NO +#endif // DEBUG && SIMULATION + +#if DEBUG + +// In some cases, the relationship between two values may be dependent on things that change based +// on various selections like the chosen cryptographic libraries. It is possible that these +// selections will result in incompatible settings. These are often detectable by the compiler but +// it isn't always possible to do the check in the preprocessor code. For example, when the check +// requires use of 'sizeof()' then the preprocessor can't do the comparison. For these cases, we +// include a special macro that, depending on the compiler will generate a warning to indicate if +// the check always passes or always fails because it involves fixed constants. To run these checks, +// define COMPILER_CHECKS. +# if !(defined COMPILER_CHECKS) \ + || ((COMPILER_CHECKS != NO) && (COMPILER_CHECKS != YES)) +# undef COMPILER_CHECKS +# define COMPILER_CHECKS NO // Default: Either YES or NO +# endif + +// Some of the values (such as sizes) are the result of different options set in +// TpmProfile.h. The combination might not be consistent. A function is defined +// (TpmSizeChecks()) that is used to verify the sizes at run time. To enable the function, define +// this parameter. +# if !(defined RUNTIME_SIZE_CHECKS) \ + || ((RUNTIME_SIZE_CHECKS != NO) && (RUNTIME_SIZE_CHECKS != YES)) +# undef RUNTIME_SIZE_CHECKS +# define RUNTIME_SIZE_CHECKS NO // Default: Either YES or NO libtpms: NO +# endif + +// If doing debug, can set the DRBG to print out the intermediate test values. Before enabling this, +// make sure that the dbgDumpMemBlock() function has been added someplace (preferably, somewhere in +// CryptRand.c) +# if !(defined DRBG_DEBUG_PRINT) \ + || ((DRBG_DEBUG_PRINT != NO) && (DRBG_DEBUG_PRINT != YES)) +# undef DRBG_DEBUG_PRINT +# define DRBG_DEBUG_PRINT NO // Default: Either YES or NO +# endif + +// If an assertion event it not going to produce any trace information (function and line number) +// then make FAIL_TRACE == NO +# if !(defined FAIL_TRACE) || ((FAIL_TRACE != NO) && (FAIL_TRACE != YES)) +# undef FAIL_TRACE +# define FAIL_TRACE YES // Default: Either YES or NO +# endif + +#endif // DEBUG + +/* Indicate if the implementation is going to give lockout time credit for time up to the last + orderly shutdown. */ +#if !(defined ACCUMULATE_SELF_HEAL_TIMER) \ + || ((ACCUMULATE_SELF_HEAL_TIMER != NO) && (ACCUMULATE_SELF_HEAL_TIMER != YES)) +# undef ACCUMULATE_SELF_HEAL_TIMER +# define ACCUMULATE_SELF_HEAL_TIMER YES // Default: Either YES or NO +#endif + +/* If the implementation is to compute the sizes of the proof and primary seed size values based on + the implemented algorithms, then use this define. */ +#if !(defined USE_SPEC_COMPLIANT_PROOFS) \ + || ((USE_SPEC_COMPLIANT_PROOFS != NO) && (USE_SPEC_COMPLIANT_PROOFS != YES)) +# undef USE_SPEC_COMPLIANT_PROOFS +# define USE_SPEC_COMPLIANT_PROOFS YES // Default: Either YES or NO +#endif + +// Comment this out to allow compile to continue even though the chosen proof values do not match +// the compliant values. This is written so that someone would have to proactively ignore errors. +#if !(defined SKIP_PROOF_ERRORS) \ + || ((SKIP_PROOF_ERRORS != NO) && (SKIP_PROOF_ERRORS != YES)) +# undef SKIP_PROOF_ERRORS +# define SKIP_PROOF_ERRORS NO // Default: Either YES or NO +#endif + +// This define is used to eliminate the use of bit-fields. It can be enabled for big- or +// little-endian machines. For big-endian architectures that number bits in registers from left to +// right (MSb0()) this must be enabled. Little-endian machines number from right to left with the +// least significant bit having assigned a bit number of 0. These are LSb0() machines (they are also +// little-endian so they are also least-significant byte 0 (LSB0) machines. Big-endian (MSB0) +// machines may number in either direction (MSb0() or LSb0()). For an MSB0+MSb0() machine this +// value is required to be NO + +#if !(defined USE_BIT_FIELD_STRUCTURES) \ + || ((USE_BIT_FIELD_STRUCTURES != NO) && (USE_BIT_FIELD_STRUCTURES != YES)) +# undef USE_BIT_FIELD_STRUCTURES +# define USE_BIT_FIELD_STRUCTURES NO // Default: Either YES or NO libtpms: NO +#endif + +// This define is used to control the debug for the CertifyX509() command. +#if !(defined CERTIFYX509_DEBUG) \ + || ((CERTIFYX509_DEBUG != NO) && (CERTIFYX509_DEBUG != YES)) +# undef CERTIFYX509_DEBUG +# define CERTIFYX509_DEBUG NO // libtpms: NO +#endif + +#if !(defined TABLE_DRIVEN_MARSHAL) \ + || ((TABLE_DRIVEN_MARSHAL != NO) && (TABLE_DRIVEN_MARSHAL != YES)) +# undef TABLE_DRIVEN_MARSHAL +# define TABLE_DRIVEN_MARSHAL NO // Default: Either YES or NO libtpms: NO +#endif + +/* Change these definitions to turn all algorithms or commands ON or OFF. That is, to turn all + algorithms on, set ALG_NO to YES. This is mostly useful as a debug feature. */ +#define ALG_YES YES +#define ALG_NO NO +#define CC_YES YES +#define CC_NO NO +#endif // _TPM_BUILD_SWITCHES_H_ + diff --git a/src/tpm2/TpmError.h b/src/tpm2/TpmError.h new file mode 100644 index 0000000..299ca2d --- /dev/null +++ b/src/tpm2/TpmError.h @@ -0,0 +1,84 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmError.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef TPMERROR_H +#define TPMERROR_H + +/* 5.23 TpmError.h */ + +#define FATAL_ERROR_ALLOCATION (1) +#define FATAL_ERROR_DIVIDE_ZERO (2) +#define FATAL_ERROR_INTERNAL (3) +#define FATAL_ERROR_PARAMETER (4) +#define FATAL_ERROR_ENTROPY (5) +#define FATAL_ERROR_SELF_TEST (6) +#define FATAL_ERROR_CRYPTO (7) +#define FATAL_ERROR_NV_UNRECOVERABLE (8) +#define FATAL_ERROR_REMANUFACTURED (9) // indicates that the TPM has + // been re-manufactured after an + // unrecoverable NV error +#define FATAL_ERROR_DRBG (10) +#define FATAL_ERROR_MOVE_SIZE (11) +#define FATAL_ERROR_COUNTER_OVERFLOW (12) +#define FATAL_ERROR_SUBTRACT (13) +#define FATAL_ERROR_FORCED (666) + +#endif diff --git a/src/tpm2/TpmFail.c b/src/tpm2/TpmFail.c new file mode 100644 index 0000000..8912f33 --- /dev/null +++ b/src/tpm2/TpmFail.c @@ -0,0 +1,527 @@ +/********************************************************************************/ +/* */ +/* Failure Mode Handling */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmFail.c 1644 2020-09-11 17:25:11Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 9.17 TpmFail.c */ +/* 9.17.1 Includes, Defines, and Types */ +#define TPM_FAIL_C +#include "Tpm.h" +#include +/* On MS C compiler, can save the alignment state and set the alignment to 1 for the duration of + the TpmTypes.h include. This will avoid a lot of alignment warnings from the compiler for + the unaligned structures. The alignment of the structures is not important as this function + does not use any of the structures in TpmTypes.h and only include it for the #defines of the + capabilities, properties, and command code values. */ +#include "TpmTypes.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" // libtpms added + +/* 9.17.2 Typedefs */ +/* These defines are used primarily for sizing of the local response buffer. */ +typedef struct +{ + TPM_ST tag; + UINT32 size; + TPM_RC code; +} HEADER; +typedef struct +{ + BYTE tag[sizeof(TPM_ST)]; + BYTE size[sizeof(UINT32)]; + BYTE code[sizeof(TPM_RC)]; +} PACKED_HEADER; +typedef struct +{ + BYTE size[sizeof(UINT16)]; + struct + { + BYTE function[sizeof(UINT32)]; + BYTE line[sizeof(UINT32)]; + BYTE code[sizeof(UINT32)]; + } values; + BYTE returnCode[sizeof(TPM_RC)]; +} GET_TEST_RESULT_PARAMETERS; +typedef struct +{ + BYTE moreData[sizeof(TPMI_YES_NO)]; + BYTE capability[sizeof(TPM_CAP)]; // Always TPM_CAP_TPM_PROPERTIES + BYTE tpmProperty[sizeof(TPML_TAGGED_TPM_PROPERTY)]; +} GET_CAPABILITY_PARAMETERS; +typedef struct +{ + BYTE header[sizeof(PACKED_HEADER)]; + BYTE getTestResult[sizeof(GET_TEST_RESULT_PARAMETERS)]; +} TEST_RESPONSE; +typedef struct +{ + BYTE header[sizeof(PACKED_HEADER)]; + BYTE getCap[sizeof(GET_CAPABILITY_PARAMETERS)]; +} CAPABILITY_RESPONSE; +typedef union +{ + BYTE test[sizeof(TEST_RESPONSE)]; + BYTE cap[sizeof(CAPABILITY_RESPONSE)]; +} RESPONSES; + +/* Buffer to hold the responses. This may be a little larger than required due to padding that a + compiler might add. */ +/* NOTE: This is not in Global.c because of the specialized data definitions above. Since the data + contained in this structure is not relevant outside of the execution of a single command (when + the TPM is in failure mode. There is no compelling reason to move all the typedefs to Global.h + and this structure to Global.c. */ +#ifndef __IGNORE_STATE__ // Don't define this value +static BYTE response[sizeof(RESPONSES)]; +#endif + +/* 9.17.3 Local Functions */ + +/* 9.17.3.1 MarshalUint16() */ +/* Function to marshal a 16 bit value to the output buffer. */ +static INT32 +MarshalUint16( + UINT16 integer, + BYTE **buffer + ) +{ + UINT16_TO_BYTE_ARRAY(integer, *buffer); + *buffer += 2; + return 2; +} + +/* 9.17.3.2 MarshalUint32() */ +/* Function to marshal a 32 bit value to the output buffer. */ +static INT32 +MarshalUint32( + UINT32 integer, + BYTE **buffer + ) +{ + UINT32_TO_BYTE_ARRAY(integer, *buffer); + *buffer += 4; + return 4; +} + +/* 9.17.3.3 Unmarshal32() */ +static BOOL Unmarshal32( + UINT32 *target, + BYTE **buffer, + INT32 *size + ) +{ + if((*size -= 4) < 0) + return FALSE; + *target = BYTE_ARRAY_TO_UINT32(*buffer); + *buffer += 4; + return TRUE; +} + +/* 9.17.3.4 Unmarshal16() */ +static BOOL Unmarshal16( + UINT16 *target, + BYTE **buffer, + INT32 *size + ) +{ + if((*size -= 2) < 0) + return FALSE; + *target = BYTE_ARRAY_TO_UINT16(*buffer); + *buffer += 2; + return TRUE; +} + +/* 9.17.4Public Functions */ +#if 0 /* libtpms added */ +/* 9.17.4.1 SetForceFailureMode() */ +/* This function is called by the simulator to enable failure mode testing. */ +LIB_EXPORT void +SetForceFailureMode( + void + ) +{ +#if SIMULATION + g_forceFailureMode = TRUE; +#endif + return; +} +#endif /* libtpms added */ + +/* 9.17.4.2 TpmLogFailure() */ +/* This function saves the failure values when the code will continue to operate. It if similar to + TpmFail() but returns to the caller. The assumption is that the caller will propagate a failure + back up the stack. */ +void +TpmLogFailure( +#if FAIL_TRACE + const char *function, + int line, +#endif + int code + ) +{ +#if 0 // libtpms added + // Save the values that indicate where the error occurred. + // On a 64-bit machine, this may truncate the address of the string + // of the function name where the error occurred. +#if FAIL_TRACE + memcpy(&s_failFunction, function, sizeof(uint32_t)); /* kgold */ + s_failLine = line; +#else + s_failFunction = 0; + s_failLine = 0; +#endif + s_failCode = code; + + // We are in failure mode + g_inFailureMode = TRUE; +#else // libtpms added begin + + TpmSetFailureMode( +#if FAIL_TRACE + function, line, +#endif + code); + +#endif // libtpms added end + return; +} +/* 9.17.4.2 TpmFail() */ +/* This function is called by TPM.lib when a failure occurs. It will set up the failure values to be + returned on TPM2_GetTestResult(). */ +NORETURN void +TpmFail( +#if FAIL_TRACE + const char *function, + int line, +#endif + int code + ) +{ +#if 0 /* libtpms added */ + // Save the values that indicate where the error occurred. + // On a 64-bit machine, this may truncate the address of the string + // of the function name where the error occurred. +#if FAIL_TRACE + memcpy(&s_failFunction, function, sizeof(uint32_t)); + s_failLine = line; +#else + s_failFunction = (UINT32)NULL; + s_failLine = 0; +#endif + s_failCode = code; + // We are in failure mode + g_inFailureMode = TRUE; + // if asserts are enabled, then do an assert unless the failure mode code + // is being tested. +#if SIMULATION +# ifndef NDEBUG + assert(g_forceFailureMode); +# endif + // Clear this flag + g_forceFailureMode = FALSE; +#endif + +#else /* libtpms added begin */ + + TpmSetFailureMode( +#if FAIL_TRACE + function, line, +#endif + code); + +#endif /* libtpms added end */ + // Jump to the failure mode code. + // Note: only get here if asserts are off or if we are testing failure mode + _plat__Fail(); +} + +/* libtpms added begin */ +void +TpmSetFailureMode( +#if FAIL_TRACE + const char *function, + int line, +#endif + int code + ) +{ + // Save the values that indicate where the error occurred. + // On a 64-bit machine, this may truncate the address of the string + // of the function name where the error occurred. +#if FAIL_TRACE + s_failFunction = *(UINT32 *)function; + s_failLine = line; +#else + s_failFunction = (UINT32)0; + s_failLine = 0; +#endif + s_failCode = code; + + TPMLIB_LogTPM2Error("Entering failure mode; code: %d" +#if FAIL_TRACE + ", location: %s line %d" +#endif + "\n", s_failCode +#if FAIL_TRACE + , function, s_failLine +#endif + ); + + // We are in failure mode + g_inFailureMode = TRUE; +} +/* libtpms added end */ +/* 9.17.5 TpmFailureMode */ +/* This function is called by the interface code when the platform is in failure mode. */ +void +TpmFailureMode( + unsigned int inRequestSize, // IN: command buffer size + unsigned char *inRequest, // IN: command buffer + unsigned int *outResponseSize, // OUT: response buffer size + unsigned char **outResponse // OUT: response buffer + ) +{ + UINT32 marshalSize; + UINT32 capability; + HEADER header; // unmarshaled command header + UINT32 pt; // unmarshaled property type + UINT32 count; // unmarshaled property count + UINT8 *buffer = inRequest; + INT32 size = inRequestSize; + + // If there is no command buffer, then just return TPM_RC_FAILURE + if(inRequestSize == 0 || inRequest == NULL) + goto FailureModeReturn; + // If the header is not correct for TPM2_GetCapability() or + // TPM2_GetTestResult() then just return the in failure mode response; + if(! (Unmarshal16(&header.tag, &buffer, &size) + && Unmarshal32(&header.size, &buffer, &size) + && Unmarshal32(&header.code, &buffer, &size))) + goto FailureModeReturn; + if(header.tag != TPM_ST_NO_SESSIONS + || header.size < 10) + goto FailureModeReturn; + switch(header.code) + { + case TPM_CC_GetTestResult: + // make sure that the command size is correct + if(header.size != 10) + goto FailureModeReturn; + buffer = &response[10]; + marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer); + marshalSize += MarshalUint32(s_failFunction, &buffer); + marshalSize += MarshalUint32(s_failLine, &buffer); + marshalSize += MarshalUint32(s_failCode, &buffer); + if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) + marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer); + else + marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); + break; + case TPM_CC_GetCapability: + // make sure that the size of the command is exactly the size + // returned for the capability, property, and count + if(header.size != (10 + (3 * sizeof(UINT32))) + // also verify that this is requesting TPM properties + || !Unmarshal32(&capability, &buffer, &size) + || capability != TPM_CAP_TPM_PROPERTIES + || !Unmarshal32(&pt, &buffer, &size) + || !Unmarshal32(&count, &buffer, &size)) + goto FailureModeReturn; + // If in failure mode because of an unrecoverable read error, and the + // property is 0 and the count is 0, then this is an indication to + // re-manufacture the TPM. Do the re-manufacture but stay in failure + // mode until the TPM is reset. + // Note: this behavior is not required by the specification and it is + // OK to leave the TPM permanently bricked due to an unrecoverable NV + // error. + if(count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) + { + g_manufactured = FALSE; + TPM_Manufacture(0); + } + if(count > 0) + count = 1; + else if(pt > TPM_PT_FIRMWARE_VERSION_2) + count = 0; + if(pt < TPM_PT_MANUFACTURER) + pt = TPM_PT_MANUFACTURER; + // set up for return + buffer = &response[10]; + // if the request was for a PT less than the last one + // then we indicate more, otherwise, not. + if(pt < TPM_PT_FIRMWARE_VERSION_2) + *buffer++ = YES; + else + *buffer++ = NO; + marshalSize = 1; + // indicate the capability type + marshalSize += MarshalUint32(capability, &buffer); + // indicate the number of values that are being returned (0 or 1) + marshalSize += MarshalUint32(count, &buffer); + // indicate the property + marshalSize += MarshalUint32(pt, &buffer); + if(count > 0) + switch(pt) + { + case TPM_PT_MANUFACTURER: + // the vendor ID unique to each TPM manufacturer +#ifdef MANUFACTURER + pt = *(UINT32*)MANUFACTURER; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_1: + // the first four characters of the vendor ID string +#ifdef VENDOR_STRING_1 + pt = *(UINT32*)VENDOR_STRING_1; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_2: + // the second four characters of the vendor ID string +#ifdef VENDOR_STRING_2 + pt = *(UINT32*)VENDOR_STRING_2; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_3: + // the third four characters of the vendor ID string +#ifdef VENDOR_STRING_3 + pt = *(UINT32*)VENDOR_STRING_3; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_4: + // the fourth four characters of the vendor ID string +#ifdef VENDOR_STRING_4 + pt = *(UINT32*)VENDOR_STRING_4; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_TPM_TYPE: + // vendor-defined value indicating the TPM model + // We just make up a number here + pt = 1; + break; + case TPM_PT_FIRMWARE_VERSION_1: + // the more significant 32-bits of a vendor-specific value + // indicating the version of the firmware +#ifdef FIRMWARE_V1 + pt = FIRMWARE_V1; +#else + pt = 0; +#endif + break; + default: // TPM_PT_FIRMWARE_VERSION_2: + // the less significant 32-bits of a vendor-specific value + // indicating the version of the firmware +#ifdef FIRMWARE_V2 + pt = FIRMWARE_V2; +#else + pt = 0; +#endif + break; + } + marshalSize += MarshalUint32(pt, &buffer); + break; + default: // default for switch (cc) + goto FailureModeReturn; + } + // Now do the header + buffer = response; + marshalSize = marshalSize + 10; // Add the header size to the + // stuff already marshaled + MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag + MarshalUint32(marshalSize, &buffer); // responseSize + MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code + *outResponseSize = marshalSize; + *outResponse = (unsigned char *)&response; + return; + FailureModeReturn: + buffer = response; + marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); + marshalSize += MarshalUint32(10, &buffer); + marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); + *outResponseSize = marshalSize; + *outResponse = (unsigned char *)response; + return; +} +#if 0 // libtpms added +/* 9.17.6 UnmarshalFail() */ +/* This is a stub that is used to catch an attempt to unmarshal an entry that is not defined. Don't + ever expect this to be called but... */ +void +UnmarshalFail( + void *type, + BYTE **buffer, + INT32 *size + ) +{ + NOT_REFERENCED(type); + NOT_REFERENCED(buffer); + NOT_REFERENCED(size); + FAIL(FATAL_ERROR_INTERNAL); +} +#endif // libtpms added diff --git a/src/tpm2/TpmFail_fp.h b/src/tpm2/TpmFail_fp.h new file mode 100644 index 0000000..f924689 --- /dev/null +++ b/src/tpm2/TpmFail_fp.h @@ -0,0 +1,114 @@ +/********************************************************************************/ +/* */ +/* Failure Mode Handling */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmFail_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef TPMFAIL_FP_H +#define TPMFAIL_FP_H + +#include "BaseTypes.h" + +#if 0 /* libtpms added */ +LIB_EXPORT void +SetForceFailureMode( + void + ); +#endif /* libtpms added */ +void +TpmLogFailure( +#if FAIL_TRACE + const char *function, + int line, +#endif + int code + ); +NORETURN void +TpmFail( +#if FAIL_TRACE /* libtpms added begin */ + const char *function, + int line, +#endif + int code + ); +void +TpmSetFailureMode( +#if FAIL_TRACE /* libtpms added end */ + const char *function, + int line, +#endif + int code + ); +void +TpmFailureMode( + unsigned int inRequestSize, // IN: command buffer size + unsigned char *inRequest, // IN: command buffer + unsigned int *outResponseSize, // OUT: response buffer size + unsigned char **outResponse // OUT: response buffer + ); +#if 0 /* libtpms added */ +void +UnmarshalFail( + void *type, + BYTE **buffer, + INT32 *size + ); +#endif /* libtpms added */ + + +#endif diff --git a/src/tpm2/TpmProfile.h b/src/tpm2/TpmProfile.h new file mode 100644 index 0000000..49aaad1 --- /dev/null +++ b/src/tpm2/TpmProfile.h @@ -0,0 +1,865 @@ +/********************************************************************************/ +/* */ +/* Constants Reflecting a Particular TPM Implementation (e.g. PC Client) */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmProfile.h 1629 2020-06-01 20:50:13Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2020 */ +/* */ +/********************************************************************************/ + +// FOR LIBTPMS: DO NOT EDIT THIS FILE! +// ANY MODIFICATION WILL LEAD TO AN UNSUPPORTED CONFIGURATION + +// A.2 TpmProfile.h +#ifndef _TPM_PROFILE_H_ +#define _TPM_PROFILE_H_ +// Table 2:4 - Defines for Logic Values +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 +#undef YES +#define YES 1 +#undef NO +#define NO 0 +#undef SET +#define SET 1 +#undef CLEAR +#define CLEAR 0 +// Table 0:1 - Defines for Processor Values +#if defined __FreeBSD__ || defined __DragonFly__ /* libtpms added begin */ +# include +#elif defined __APPLE__ +# include +#else +# include +#endif +#if defined __linux__ || defined __CYGWIN__ + #if __BYTE_ORDER == __LITTLE_ENDIAN + #define BIG_ENDIAN_TPM NO + #endif + #if __BYTE_ORDER == __BIG_ENDIAN + #define BIG_ENDIAN_TPM YES + #endif +#elif defined __OpenBSD__ || defined __FreeBSD__ || defined __NetBSD__ \ + || defined __DragonFly__ + #if _BYTE_ORDER == _LITTLE_ENDIAN + #define BIG_ENDIAN_TPM NO + #endif + #if _BYTE_ORDER == _BIG_ENDIAN + #define BIG_ENDIAN_TPM YES + #endif +#elif defined __APPLE__ + #define BIG_ENDIAN_TPM NO +#else + #error Unsupported OS +#endif /* libtpms added end */ +#ifndef BIG_ENDIAN_TPM +#define BIG_ENDIAN_TPM NO +#endif +#ifndef LITTLE_ENDIAN_TPM +#define LITTLE_ENDIAN_TPM !BIG_ENDIAN_TPM +#endif +#ifndef MOST_SIGNIFICANT_BIT_0 +#define MOST_SIGNIFICANT_BIT_0 NO +#endif +#ifndef LEAST_SIGNIFICANT_BIT_0 +#define LEAST_SIGNIFICANT_BIT_0 !MOST_SIGNIFICANT_BIT_0 +#endif +#ifndef AUTO_ALIGN +#define AUTO_ALIGN NO +#endif +// Table 0:4 - Defines for Implemented Curves +#ifndef ECC_NIST_P192 +#define ECC_NIST_P192 YES /* libtpms enabled */ +#endif +#ifndef ECC_NIST_P224 +#define ECC_NIST_P224 YES /* libtpms enabled */ +#endif +#ifndef ECC_NIST_P256 +#define ECC_NIST_P256 YES +#endif +#ifndef ECC_NIST_P384 +#define ECC_NIST_P384 YES +#endif +#ifndef ECC_NIST_P521 +#define ECC_NIST_P521 YES /* libtpms enabled */ +#endif +#ifndef ECC_BN_P256 +#define ECC_BN_P256 YES +#endif +#ifndef ECC_BN_P638 +#define ECC_BN_P638 YES /* libtpms enabled */ +#endif +#ifndef ECC_SM2_P256 +#define ECC_SM2_P256 YES /* libtpms enabled */ +#endif + +/* Table 0:6 - Defines for Implemented ACT */ + +#ifndef RH_ACT_0 +#define RH_ACT_0 NO /* libtpms: no */ +#endif +#ifndef RH_ACT_1 +#define RH_ACT_1 NO +#endif +#ifndef RH_ACT_A +#define RH_ACT_A NO /* libtpms: no */ +#endif +// libtpms added begin +#if RH_ACT_0 + RH_ACT_1 + RH_ACT_2 + RH_ACT_3 + RH_ACT_4 + \ + RH_ACT_1 + RH_ACT_5 + RH_ACT_6 + RH_ACT_7 + RH_ACT_8 + \ + RH_ACT_9 + RH_ACT_A + RH_ACT_B + RH_ACT_C + RH_ACT_D + \ + RH_ACT_E + RH_ACT_F == 0 +#define __ACT_DISABLED +#endif +// libtpms added end + +// Table 0:7 - Defines for Implementation Values +#ifndef FIELD_UPGRADE_IMPLEMENTED +#define FIELD_UPGRADE_IMPLEMENTED NO +#endif + +#ifdef TPM_POSIX // libtpms added begin +# include +# ifdef THIRTY_TWO_BIT +# define RADIX_BITS 32 +# endif +# ifdef SIXTY_FOUR_BIT_LONG +# define RADIX_BITS 64 +# endif +# ifndef RADIX_BITS +# error Need to determine RADIX_BITS value +# endif +#endif +#ifdef TPM_WINDOWS +#define RADIX_BITS 32 +#endif // libtpms added end + +#ifndef HASH_LIB +#define HASH_LIB Ossl +#endif +#ifndef SYM_LIB +#define SYM_LIB Ossl +#endif +#ifndef MATH_LIB +#define MATH_LIB Ossl +#endif +#ifndef IMPLEMENTATION_PCR +#define IMPLEMENTATION_PCR 24 +#endif +#ifndef PLATFORM_PCR +#define PLATFORM_PCR 24 +#endif +#ifndef DRTM_PCR +#define DRTM_PCR 17 +#endif +#ifndef HCRTM_PCR +#define HCRTM_PCR 0 +#endif +#ifndef NUM_LOCALITIES +#define NUM_LOCALITIES 5 +#endif +#ifndef MAX_HANDLE_NUM +#define MAX_HANDLE_NUM 3 +#endif +#ifndef MAX_ACTIVE_SESSIONS +#define MAX_ACTIVE_SESSIONS 64 +#endif +#ifndef CONTEXT_SLOT +#define CONTEXT_SLOT UINT16 /* libtpms: changed from UINT8 in v0.9.0 */ +#endif +#ifndef MAX_LOADED_SESSIONS +#define MAX_LOADED_SESSIONS 3 +#endif +#ifndef MAX_SESSION_NUM +#define MAX_SESSION_NUM 3 +#endif +#ifndef MAX_LOADED_OBJECTS +#define MAX_LOADED_OBJECTS 3 +#endif +#ifndef MIN_EVICT_OBJECTS +#define MIN_EVICT_OBJECTS 7 /* libtpms changed -- for PC profile */ +#endif +#ifndef NUM_POLICY_PCR_GROUP +#define NUM_POLICY_PCR_GROUP 1 +#endif +#ifndef NUM_AUTHVALUE_PCR_GROUP +#define NUM_AUTHVALUE_PCR_GROUP 1 +#endif +#ifndef MAX_CONTEXT_SIZE +#define MAX_CONTEXT_SIZE 2680 /* libtpms changed */ +#endif +#ifndef MAX_DIGEST_BUFFER +#define MAX_DIGEST_BUFFER 1024 +#endif +#ifndef MAX_NV_INDEX_SIZE +#define MAX_NV_INDEX_SIZE 2048 +#endif +#ifndef MAX_NV_BUFFER_SIZE +#define MAX_NV_BUFFER_SIZE 1024 +#endif +#ifndef MAX_CAP_BUFFER +#define MAX_CAP_BUFFER 1024 +#endif + +/* for PC client, permits + + 1300 bytes reserved + 7 * 2600 persistent objects + 4000 NV indexes + 60 * 68 nv index metadata +*/ + +#ifndef NV_MEMORY_SIZE +/* libtmps: 65 OBJECTs in USER NVRAM expanded by 704 bytes due to size + * increase of OBJECT from 2048 bit RSA keys to 3072 bit by 704 bytes*/ +#define NV_MEMORY_SIZE (128 * 1024 + 65 * 704) /* libtpms changed */ +#endif +#ifndef MIN_COUNTER_INDICES +#define MIN_COUNTER_INDICES 8 +#endif +#ifndef NUM_STATIC_PCR +#define NUM_STATIC_PCR 16 +#endif +#ifndef MAX_ALG_LIST_SIZE +#define MAX_ALG_LIST_SIZE 64 +#endif +#ifndef PRIMARY_SEED_SIZE +#define PRIMARY_SEED_SIZE 64 /* libtpms: 64 per define USE_SPEC_COMPLIANT_PROOFS */ +#endif +#ifndef CONTEXT_ENCRYPT_ALGORITHM +#define CONTEXT_ENCRYPT_ALGORITHM AES +#endif +#ifndef NV_CLOCK_UPDATE_INTERVAL +#define NV_CLOCK_UPDATE_INTERVAL 12 +#endif +#ifndef NUM_POLICY_PCR +#define NUM_POLICY_PCR 1 +#endif +#ifndef MAX_COMMAND_SIZE +#define MAX_COMMAND_SIZE TPM2_GetBufferSize() /* libtpms changed */ +#endif +#ifndef MAX_RESPONSE_SIZE +#define MAX_RESPONSE_SIZE TPM2_GetBufferSize() /* libtpms changed */ +#endif +#ifndef ORDERLY_BITS +#define ORDERLY_BITS 8 +#endif +#ifndef MAX_SYM_DATA +#define MAX_SYM_DATA 128 +#endif +#ifndef MAX_RNG_ENTROPY_SIZE +#define MAX_RNG_ENTROPY_SIZE 64 +#endif +#ifndef RAM_INDEX_SPACE +#define RAM_INDEX_SPACE 512 +#endif +#ifndef RSA_DEFAULT_PUBLIC_EXPONENT +#define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001 +#endif +#ifndef ENABLE_PCR_NO_INCREMENT +#define ENABLE_PCR_NO_INCREMENT YES +#endif +#ifndef CRT_FORMAT_RSA +#define CRT_FORMAT_RSA YES +#endif +#ifndef VENDOR_COMMAND_COUNT +#define VENDOR_COMMAND_COUNT 0 +#endif +#ifndef MAX_VENDOR_BUFFER_SIZE +#define MAX_VENDOR_BUFFER_SIZE 1024 +#endif +#ifndef SIZE_OF_X509_SERIAL_NUMBER +#define SIZE_OF_X509_SERIAL_NUMBER 20 +#endif +#ifndef PRIVATE_VENDOR_SPECIFIC_BYTES +#define PRIVATE_VENDOR_SPECIFIC_BYTES \ + ((MAX_RSA_KEY_BYTES/2) * (3 + CRT_FORMAT_RSA * 2)) /* libtpms: keep as was in rev 150 */ +#endif +// Table 0:2 - Defines for Implemented Algorithms +#ifndef ALG_AES +#define ALG_AES ALG_YES +#endif +#ifndef ALG_CAMELLIA +#define ALG_CAMELLIA ALG_YES /* libtpms: YES since v0.9 */ +#endif +#ifndef ALG_CBC +#define ALG_CBC ALG_YES +#endif +#ifndef ALG_CFB +#define ALG_CFB ALG_YES +#endif +#ifndef ALG_CMAC +#define ALG_CMAC ALG_YES +#endif +#ifndef ALG_CTR +#define ALG_CTR ALG_YES +#endif +#ifndef ALG_ECB +#define ALG_ECB ALG_YES +#endif +#ifndef ALG_ECC +#define ALG_ECC ALG_YES +#endif +#ifndef ALG_ECDAA +#define ALG_ECDAA (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECDH +#define ALG_ECDH (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECDSA +#define ALG_ECDSA (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECMQV +#define ALG_ECMQV (ALG_YES && ALG_ECC) /* libtpms enabled */ +#endif +#ifndef ALG_ECSCHNORR +#define ALG_ECSCHNORR (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_HMAC +#define ALG_HMAC ALG_YES +#endif +#ifndef ALG_KDF1_SP800_108 +#define ALG_KDF1_SP800_108 ALG_YES +#endif +#ifndef ALG_KDF1_SP800_56A +#define ALG_KDF1_SP800_56A (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_KDF2 +#define ALG_KDF2 ALG_YES +#endif +#ifndef ALG_KEYEDHASH +#define ALG_KEYEDHASH ALG_YES +#endif +#ifndef ALG_MGF1 +#define ALG_MGF1 ALG_YES +#endif +#ifndef ALG_OAEP +#define ALG_OAEP (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_OFB +#define ALG_OFB ALG_YES +#endif +#ifndef ALG_RSA +#define ALG_RSA ALG_YES +#endif +#ifndef ALG_RSAES +#define ALG_RSAES (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_RSAPSS +#define ALG_RSAPSS (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_RSASSA +#define ALG_RSASSA (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_SHA +#define ALG_SHA ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA1 +#define ALG_SHA1 ALG_YES +#endif +#ifndef ALG_SHA256 +#define ALG_SHA256 ALG_YES +#endif +#ifndef ALG_SHA384 +#define ALG_SHA384 ALG_YES +#endif +#ifndef ALG_SHA3_256 +#define ALG_SHA3_256 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA3_384 +#define ALG_SHA3_384 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA3_512 +#define ALG_SHA3_512 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA512 +#define ALG_SHA512 ALG_YES +#endif +#ifndef ALG_SM2 +#define ALG_SM2 (ALG_YES && ALG_ECC) /* libtpms enabled */ +#endif +#ifndef ALG_SM3_256 +#define ALG_SM3_256 ALG_NO /* libtpms: NO */ +#endif +#ifndef ALG_SM4 +#define ALG_SM4 ALG_NO /* libtpms: NO */ +#endif +#ifndef ALG_SYMCIPHER +#define ALG_SYMCIPHER ALG_YES +#endif +#ifndef ALG_TDES +#define ALG_TDES ALG_YES /* libtpms enabled */ +#endif +#ifndef ALG_XOR +#define ALG_XOR ALG_YES +#endif +// Table 1:00 - Defines for RSA Asymmetric Cipher Algorithm Constants +#ifndef RSA_1024 +#define RSA_1024 (ALG_RSA && YES) +#endif +#ifndef RSA_2048 +#define RSA_2048 (ALG_RSA && YES) +#endif +#ifndef RSA_3072 +#define RSA_3072 (ALG_RSA && YES) +#endif +#ifndef RSA_4096 +#define RSA_4096 (ALG_RSA && NO) +#endif +#ifndef RSA_16384 +#define RSA_16384 (ALG_RSA && NO) +#endif + +// Table 1:17 - Defines for AES Symmetric Cipher Algorithm Constants +#ifndef AES_128 +#define AES_128 (ALG_AES && YES) +#endif +#ifndef AES_192 +#define AES_192 (ALG_AES && NO) +#endif +#ifndef AES_256 +#define AES_256 (ALG_AES && YES) +#endif +// Table 1:18 - Defines for SM4 Symmetric Cipher Algorithm Constants +#ifndef SM4_128 +#define SM4_128 (ALG_SM4 && YES) +#endif +// Table 1:19 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants +#ifndef CAMELLIA_128 +#define CAMELLIA_128 (ALG_CAMELLIA && YES) +#endif +#ifndef CAMELLIA_192 +#define CAMELLIA_192 (ALG_CAMELLIA && NO) +#endif +#ifndef CAMELLIA_256 +#define CAMELLIA_256 (ALG_CAMELLIA && YES) +#endif +// Table 1:17 - Defines for TDES Symmetric Cipher Algorithm Constants +#ifndef TDES_128 +#define TDES_128 (ALG_TDES && YES) +#endif +#ifndef TDES_192 +#define TDES_192 (ALG_TDES && YES) +#endif +// Table 0:5 - Defines for Implemented Commands +#ifndef CC_ACT_SetTimeout +#define CC_ACT_SetTimeout CC_NO /* libtpms: NO */ +#endif +#ifndef CC_AC_GetCapability +#define CC_AC_GetCapability CC_NO /* kgold */ +#endif +#ifndef CC_AC_Send +#define CC_AC_Send CC_NO /* kgold */ +#endif +#ifndef CC_ActivateCredential +#define CC_ActivateCredential CC_YES +#endif +#ifndef CC_Certify +#define CC_Certify CC_YES +#endif +#ifndef CC_CertifyCreation +#define CC_CertifyCreation CC_YES +#endif +#ifndef CC_CertifyX509 +#define CC_CertifyX509 CC_YES +#endif +#ifndef CC_ChangeEPS +#define CC_ChangeEPS CC_YES +#endif +#ifndef CC_ChangePPS +#define CC_ChangePPS CC_YES +#endif +#ifndef CC_Clear +#define CC_Clear CC_YES +#endif +#ifndef CC_ClearControl +#define CC_ClearControl CC_YES +#endif +#ifndef CC_ClockRateAdjust +#define CC_ClockRateAdjust CC_YES +#endif +#ifndef CC_ClockSet +#define CC_ClockSet CC_YES +#endif +#ifndef CC_Commit +#define CC_Commit (CC_YES && ALG_ECC) +#endif +#ifndef CC_ContextLoad +#define CC_ContextLoad CC_YES +#endif +#ifndef CC_ContextSave +#define CC_ContextSave CC_YES +#endif +#ifndef CC_Create +#define CC_Create CC_YES +#endif +#ifndef CC_CreateLoaded +#define CC_CreateLoaded CC_YES +#endif +#ifndef CC_CreatePrimary +#define CC_CreatePrimary CC_YES +#endif +#ifndef CC_DictionaryAttackLockReset +#define CC_DictionaryAttackLockReset CC_YES +#endif +#ifndef CC_DictionaryAttackParameters +#define CC_DictionaryAttackParameters CC_YES +#endif +#ifndef CC_Duplicate +#define CC_Duplicate CC_YES +#endif +#ifndef CC_ECC_Decrypt +#define CC_ECC_Decrypt (CC_NO && ALG_ECC) +#endif +#ifndef CC_ECC_Encrypt +#define CC_ECC_Encrypt (CC_NO && ALG_ECC) +#endif +#ifndef CC_ECC_Parameters +#define CC_ECC_Parameters (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECDH_KeyGen +#define CC_ECDH_KeyGen (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECDH_ZGen +#define CC_ECDH_ZGen (CC_YES && ALG_ECC) +#endif +#ifndef CC_EC_Ephemeral +#define CC_EC_Ephemeral (CC_YES && ALG_ECC) +#endif +#ifndef CC_EncryptDecrypt +#define CC_EncryptDecrypt CC_YES +#endif +#ifndef CC_EncryptDecrypt2 +#define CC_EncryptDecrypt2 CC_YES +#endif +#ifndef CC_EventSequenceComplete +#define CC_EventSequenceComplete CC_YES +#endif +#ifndef CC_EvictControl +#define CC_EvictControl CC_YES +#endif +#ifndef CC_FieldUpgradeData +#define CC_FieldUpgradeData CC_NO +#endif +#ifndef CC_FieldUpgradeStart +#define CC_FieldUpgradeStart CC_NO +#endif +#ifndef CC_FirmwareRead +#define CC_FirmwareRead CC_NO +#endif +#ifndef CC_FlushContext +#define CC_FlushContext CC_YES +#endif +#ifndef CC_GetCapability +#define CC_GetCapability CC_YES +#endif +#ifndef CC_GetCommandAuditDigest +#define CC_GetCommandAuditDigest CC_YES +#endif +#ifndef CC_GetRandom +#define CC_GetRandom CC_YES +#endif +#ifndef CC_GetSessionAuditDigest +#define CC_GetSessionAuditDigest CC_YES +#endif +#ifndef CC_GetTestResult +#define CC_GetTestResult CC_YES +#endif +#ifndef CC_GetTime +#define CC_GetTime CC_YES +#endif +#ifndef CC_HMAC +#define CC_HMAC (CC_YES && !ALG_CMAC) +#endif +#ifndef CC_HMAC_Start +#define CC_HMAC_Start (CC_YES && !ALG_CMAC) +#endif +#ifndef CC_Hash +#define CC_Hash CC_YES +#endif +#ifndef CC_HashSequenceStart +#define CC_HashSequenceStart CC_YES +#endif +#ifndef CC_HierarchyChangeAuth +#define CC_HierarchyChangeAuth CC_YES +#endif +#ifndef CC_HierarchyControl +#define CC_HierarchyControl CC_YES +#endif +#ifndef CC_Import +#define CC_Import CC_YES +#endif +#ifndef CC_IncrementalSelfTest +#define CC_IncrementalSelfTest CC_YES +#endif +#ifndef CC_Load +#define CC_Load CC_YES +#endif +#ifndef CC_LoadExternal +#define CC_LoadExternal CC_YES +#endif +#ifndef CC_MAC +#define CC_MAC (CC_YES && ALG_CMAC) +#endif +#ifndef CC_MAC_Start +#define CC_MAC_Start (CC_YES && ALG_CMAC) +#endif +#ifndef CC_MakeCredential +#define CC_MakeCredential CC_YES +#endif +#ifndef CC_NV_Certify +#define CC_NV_Certify CC_YES +#endif +#ifndef CC_NV_ChangeAuth +#define CC_NV_ChangeAuth CC_YES +#endif +#ifndef CC_NV_DefineSpace +#define CC_NV_DefineSpace CC_YES +#endif +#ifndef CC_NV_Extend +#define CC_NV_Extend CC_YES +#endif +#ifndef CC_NV_GlobalWriteLock +#define CC_NV_GlobalWriteLock CC_YES +#endif +#ifndef CC_NV_Increment +#define CC_NV_Increment CC_YES +#endif +#ifndef CC_NV_Read +#define CC_NV_Read CC_YES +#endif +#ifndef CC_NV_ReadLock +#define CC_NV_ReadLock CC_YES +#endif +#ifndef CC_NV_ReadPublic +#define CC_NV_ReadPublic CC_YES +#endif +#ifndef CC_NV_SetBits +#define CC_NV_SetBits CC_YES +#endif +#ifndef CC_NV_UndefineSpace +#define CC_NV_UndefineSpace CC_YES +#endif +#ifndef CC_NV_UndefineSpaceSpecial +#define CC_NV_UndefineSpaceSpecial CC_YES +#endif +#ifndef CC_NV_Write +#define CC_NV_Write CC_YES +#endif +#ifndef CC_NV_WriteLock +#define CC_NV_WriteLock CC_YES +#endif +#ifndef CC_ObjectChangeAuth +#define CC_ObjectChangeAuth CC_YES +#endif +#ifndef CC_PCR_Allocate +#define CC_PCR_Allocate CC_YES +#endif +#ifndef CC_PCR_Event +#define CC_PCR_Event CC_YES +#endif +#ifndef CC_PCR_Extend +#define CC_PCR_Extend CC_YES +#endif +#ifndef CC_PCR_Read +#define CC_PCR_Read CC_YES +#endif +#ifndef CC_PCR_Reset +#define CC_PCR_Reset CC_YES +#endif +#ifndef CC_PCR_SetAuthPolicy +#define CC_PCR_SetAuthPolicy CC_YES +#endif +#ifndef CC_PCR_SetAuthValue +#define CC_PCR_SetAuthValue CC_YES +#endif +#ifndef CC_PP_Commands +#define CC_PP_Commands CC_YES +#endif +#ifndef CC_PolicyAuthValue +#define CC_PolicyAuthValue CC_YES +#endif +#ifndef CC_PolicyAuthorize +#define CC_PolicyAuthorize CC_YES +#endif +#ifndef CC_PolicyAuthorizeNV +#define CC_PolicyAuthorizeNV CC_YES +#endif +#ifndef CC_PolicyCommandCode +#define CC_PolicyCommandCode CC_YES +#endif +#ifndef CC_PolicyCounterTimer +#define CC_PolicyCounterTimer CC_YES +#endif +#ifndef CC_PolicyCpHash +#define CC_PolicyCpHash CC_YES +#endif +#ifndef CC_PolicyDuplicationSelect +#define CC_PolicyDuplicationSelect CC_YES +#endif +#ifndef CC_PolicyGetDigest +#define CC_PolicyGetDigest CC_YES +#endif +#ifndef CC_PolicyLocality +#define CC_PolicyLocality CC_YES +#endif +#ifndef CC_PolicyNV +#define CC_PolicyNV CC_YES +#endif +#ifndef CC_PolicyNameHash +#define CC_PolicyNameHash CC_YES +#endif +#ifndef CC_PolicyNvWritten +#define CC_PolicyNvWritten CC_YES +#endif +#ifndef CC_PolicyOR +#define CC_PolicyOR CC_YES +#endif +#ifndef CC_PolicyPCR +#define CC_PolicyPCR CC_YES +#endif +#ifndef CC_PolicyPassword +#define CC_PolicyPassword CC_YES +#endif +#ifndef CC_PolicyPhysicalPresence +#define CC_PolicyPhysicalPresence CC_YES +#endif +#ifndef CC_PolicyRestart +#define CC_PolicyRestart CC_YES +#endif +#ifndef CC_PolicySecret +#define CC_PolicySecret CC_YES +#endif +#ifndef CC_PolicySigned +#define CC_PolicySigned CC_YES +#endif +#ifndef CC_PolicyTemplate +#define CC_PolicyTemplate CC_YES +#endif +#ifndef CC_PolicyTicket +#define CC_PolicyTicket CC_YES +#endif +#ifndef CC_Policy_AC_SendSelect +#define CC_Policy_AC_SendSelect CC_NO /* kgold */ +#endif +#ifndef CC_Quote +#define CC_Quote CC_YES +#endif +#ifndef CC_RSA_Decrypt +#define CC_RSA_Decrypt (CC_YES && ALG_RSA) +#endif +#ifndef CC_RSA_Encrypt +#define CC_RSA_Encrypt (CC_YES && ALG_RSA) +#endif +#ifndef CC_ReadClock +#define CC_ReadClock CC_YES +#endif +#ifndef CC_ReadPublic +#define CC_ReadPublic CC_YES +#endif +#ifndef CC_Rewrap +#define CC_Rewrap CC_YES +#endif +#ifndef CC_SelfTest +#define CC_SelfTest CC_YES +#endif +#ifndef CC_SequenceComplete +#define CC_SequenceComplete CC_YES +#endif +#ifndef CC_SequenceUpdate +#define CC_SequenceUpdate CC_YES +#endif +#ifndef CC_SetAlgorithmSet +#define CC_SetAlgorithmSet CC_YES +#endif +#ifndef CC_SetCommandCodeAuditStatus +#define CC_SetCommandCodeAuditStatus CC_YES +#endif +#ifndef CC_SetPrimaryPolicy +#define CC_SetPrimaryPolicy CC_YES +#endif +#ifndef CC_Shutdown +#define CC_Shutdown CC_YES +#endif +#ifndef CC_Sign +#define CC_Sign CC_YES +#endif +#ifndef CC_StartAuthSession +#define CC_StartAuthSession CC_YES +#endif +#ifndef CC_Startup +#define CC_Startup CC_YES +#endif +#ifndef CC_StirRandom +#define CC_StirRandom CC_YES +#endif +#ifndef CC_TestParms +#define CC_TestParms CC_YES +#endif +#ifndef CC_Unseal +#define CC_Unseal CC_YES +#endif +#ifndef CC_Vendor_TCG_Test +#define CC_Vendor_TCG_Test CC_NO /* libtpms changed */ +#endif +#ifndef CC_VerifySignature +#define CC_VerifySignature CC_YES +#endif +#ifndef CC_ZGen_2Phase +#define CC_ZGen_2Phase (CC_YES && ALG_ECC) +#endif +#endif // _TPM_PROFIL diff --git a/src/tpm2/TpmSizeChecks.c b/src/tpm2/TpmSizeChecks.c new file mode 100644 index 0000000..01d0777 --- /dev/null +++ b/src/tpm2/TpmSizeChecks.c @@ -0,0 +1,229 @@ +/********************************************************************************/ +/* */ +/* TPM Size Checks */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmSizeChecks.c 1628 2020-05-27 19:35:29Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +//** Includes, Defines, and Types +#include "Tpm.h" +#include "PlatformACT_fp.h" /* kgold */ +#include "TpmSizeChecks_fp.h" +#include +#include + +#if RUNTIME_SIZE_CHECKS + +#if TABLE_DRIVEN_MARSHAL +extern uint32_t MarshalDataSize; +#endif + +static int once = 0; + +//** TpmSizeChecks() +// This function is used during the development process to make sure that the +// vendor-specific values result in a consistent implementation. When possible, +// the code contains #if to do compile-time checks. However, in some cases, the +// values require the use of "sizeof()" and that can't be used in an #if. +BOOL +TpmSizeChecks( + void + ) +{ + BOOL PASS = TRUE; +#if DEBUG + // + if(once++ != 0) + return 1; + { + UINT32 maxAsymSecurityStrength = MAX_ASYM_SECURITY_STRENGTH; + UINT32 maxHashSecurityStrength = MAX_HASH_SECURITY_STRENGTH; + UINT32 maxSymSecurityStrength = MAX_SYM_SECURITY_STRENGTH; + UINT32 maxSecurityStrengthBits = MAX_SECURITY_STRENGTH_BITS; + UINT32 proofSize = PROOF_SIZE; + UINT32 compliantProofSize = COMPLIANT_PROOF_SIZE; + UINT32 compliantPrimarySeedSize = COMPLIANT_PRIMARY_SEED_SIZE; + UINT32 primarySeedSize = PRIMARY_SEED_SIZE; + + UINT32 cmacState = sizeof(tpmCmacState_t); + UINT32 hashState = sizeof(HASH_STATE); + UINT32 keyScheduleSize = sizeof(tpmCryptKeySchedule_t); + // + NOT_REFERENCED(cmacState); + NOT_REFERENCED(hashState); + NOT_REFERENCED(keyScheduleSize); + NOT_REFERENCED(maxAsymSecurityStrength); + NOT_REFERENCED(maxHashSecurityStrength); + NOT_REFERENCED(maxSymSecurityStrength); + NOT_REFERENCED(maxSecurityStrengthBits); + NOT_REFERENCED(proofSize); + NOT_REFERENCED(compliantProofSize); + NOT_REFERENCED(compliantPrimarySeedSize); + NOT_REFERENCED(primarySeedSize); + + + { + TPMT_SENSITIVE *p; + // This assignment keeps compiler from complaining about a conditional + // comparison being between two constants + UINT16 max_rsa_key_bytes = MAX_RSA_KEY_BYTES; + if((max_rsa_key_bytes / 2) != (sizeof(p->sensitive.rsa.t.buffer) / 5)) + { + printf("Sensitive part of TPMT_SENSITIVE is undersized. May be caused" + " by use of wrong version of Part 2.\n"); + PASS = FALSE; + } + } +#if TABLE_DRIVEN_MARSHAL + printf("sizeof(MarshalData) = %zu\n", sizeof(MarshalData_st)); +#endif + + printf("Size of OBJECT = %zu\n", sizeof(OBJECT)); + printf("Size of components in TPMT_SENSITIVE = %zu\n", sizeof(TPMT_SENSITIVE)); + printf(" TPMI_ALG_PUBLIC %zu\n", sizeof(TPMI_ALG_PUBLIC)); + printf(" TPM2B_AUTH %zu\n", sizeof(TPM2B_AUTH)); + printf(" TPM2B_DIGEST %zu\n", sizeof(TPM2B_DIGEST)); + printf(" TPMU_SENSITIVE_COMPOSITE %zu\n", + sizeof(TPMU_SENSITIVE_COMPOSITE)); + } + // Make sure that the size of the context blob is large enough for the largest + // context + // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is + // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to + // determine the amount of data in the encrypted data. That part is not + // independently sized. This makes the actual size 2 bytes smaller than + // calculated using Part 2. Since this is opaque to the caller, it is not + // necessary to fix. The actual size is returned by TPM2_GetCapabilties(). + + // Initialize output handle. At the end of command action, the output + // handle of an object will be replaced, while the output handle + // for a session will be the same as input + + // Get the size of fingerprint in context blob. The sequence value in + // TPMS_CONTEXT structure is used as the fingerprint + { + UINT32 fingerprintSize = sizeof(UINT64); + UINT32 integritySize = sizeof(UINT16) + + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); + UINT32 biggestObject = MAX(MAX(sizeof(HASH_OBJECT), sizeof(OBJECT)), + sizeof(SESSION)); + UINT32 biggestContext = fingerprintSize + integritySize + biggestObject; + + // round required size up to nearest 8 byte boundary. + biggestContext = 8 * ((biggestContext + 7) / 8); + + if(MAX_CONTEXT_SIZE < biggestContext) + { + printf("MAX_CONTEXT_SIZE needs to be increased to at least to %d (%d)\n", + biggestContext, MAX_CONTEXT_SIZE); + PASS = FALSE; + } + else if (MAX_CONTEXT_SIZE > biggestContext) + { + printf("MAX_CONTEXT_SIZE can be reduced to %d (%d)\n", + biggestContext, MAX_CONTEXT_SIZE); + } + } + { + union u + { + TPMA_OBJECT attributes; + UINT32 uint32Value; + } u; + // these are defined so that compiler doesn't complain about conditional + // expressions comparing two constants. + int aSize = sizeof(u.attributes); + int uSize = sizeof(u.uint32Value); + u.uint32Value = 0; + SET_ATTRIBUTE(u.attributes, TPMA_OBJECT, fixedTPM); + if(u.uint32Value != 2) + { + printf("The bit allocation in a TPMA_OBJECT is not as expected"); + PASS = FALSE; + } + if(aSize != uSize) // comparison of two sizeof() values annoys compiler + { + printf("A TPMA_OBJECT is not the expected size."); + PASS = FALSE; + } + } + // Check that the platform implements each of the ACT that the TPM thinks are present + { + uint32_t act; + for(act = 0; act < 16; act++) + { + switch(act) + { + FOR_EACH_ACT(CASE_ACT_NUMBER) + if(!_plat__ACT_GetImplemented(act)) + { + printf("TPM_RH_ACT_%1X is not implemented by platform\n", + act); + PASS = FALSE; + } + default: + break; + } + } + } +#endif // DEBUG + return (PASS); +} + +#endif // RUNTIME_SIZE_CHECKS + + diff --git a/src/tpm2/TpmSizeChecks_fp.h b/src/tpm2/TpmSizeChecks_fp.h new file mode 100644 index 0000000..12f2714 --- /dev/null +++ b/src/tpm2/TpmSizeChecks_fp.h @@ -0,0 +1,67 @@ +/********************************************************************************/ +/* */ +/* Check COmpiler Options */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmSizeChecks_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef TPMSIZECHECKS_FP_H +#define TPMSIZECHECKS_FP_H + +BOOL TpmSizeChecks(void); + +#endif diff --git a/src/tpm2/TpmTcpProtocol.h b/src/tpm2/TpmTcpProtocol.h new file mode 100644 index 0000000..1fe8f66 --- /dev/null +++ b/src/tpm2/TpmTcpProtocol.h @@ -0,0 +1,140 @@ +/********************************************************************************/ +/* */ +/* TPM commands are communicated as BYTE streams on a TCP connection */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmTcpProtocol.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* D.3 TpmTcpProtocol.h */ +/* D.3.1. Introduction */ +/* TPM commands are communicated as uint8_t streams on a TCP connection. The TPM command protocol is + enveloped with the interface protocol described in this file. The command is indicated by a + uint32_t with one of the values below. Most commands take no parameters and return no TPM errors. In + these cases the TPM interface protocol acknowledges that command processing is completed by + returning a uint32_t = 0. The command TPM_SIGNAL_HASH_DATA takes a uint32_t-prepended variable length + byte array and the interface protocol acknowledges command completion with a uint32_t = 0. Most TPM + commands are enveloped using the TPM_SEND_COMMAND interface command. The parameters are as + indicated below. The interface layer also appends a uin32_t = 0 to the TPM response for + regularity. */ +/* D.3.2. Typedefs and Defines */ +#ifndef TCP_TPM_PROTOCOL_H +#define TCP_TPM_PROTOCOL_H +/* D.3.3. TPM Commands All commands acknowledge processing by returning a uint32_t = 0 except where + noted */ +#define TPM_SIGNAL_POWER_ON 1 +#define TPM_SIGNAL_POWER_OFF 2 +#define TPM_SIGNAL_PHYS_PRES_ON 3 +#define TPM_SIGNAL_PHYS_PRES_OFF 4 +#define TPM_SIGNAL_HASH_START 5 +#define TPM_SIGNAL_HASH_DATA 6 + // {uint32_t BufferSize, uint8_t[BufferSize] Buffer} +#define TPM_SIGNAL_HASH_END 7 +#define TPM_SEND_COMMAND 8 +// {uint8_t Locality, uint32_t InBufferSize, uint8_t[InBufferSize] InBuffer} -> +// {uint32_t OutBufferSize, uint8_t[OutBufferSize] OutBuffer} +#define TPM_SIGNAL_CANCEL_ON 9 +#define TPM_SIGNAL_CANCEL_OFF 10 +#define TPM_SIGNAL_NV_ON 11 +#define TPM_SIGNAL_NV_OFF 12 +#define TPM_SIGNAL_KEY_CACHE_ON 13 +#define TPM_SIGNAL_KEY_CACHE_OFF 14 +#define TPM_REMOTE_HANDSHAKE 15 +#define TPM_SET_ALTERNATIVE_RESULT 16 +#define TPM_SIGNAL_RESET 17 +#define TPM_SIGNAL_RESTART 18 +#define TPM_SESSION_END 20 +#define TPM_STOP 21 +#define TPM_GET_COMMAND_RESPONSE_SIZES 25 +#define TPM_ACT_GET_SIGNALED 26 +#define TPM_TEST_FAILURE_MODE 30 + +// D.3.4. Enumerations and Structures + +enum TpmEndPointInfo + { + tpmPlatformAvailable = 0x01, + tpmUsesTbs = 0x02, + tpmInRawMode = 0x04, + tpmSupportsPP = 0x08 + }; + +#ifdef _MSC_VER +# pragma warning(push, 3) +#endif + +// Existing RPC interface type definitions retained so that the implementation +// can be re-used +typedef struct in_buffer +{ + unsigned long BufferSize; + unsigned char *Buffer; +} _IN_BUFFER; +typedef unsigned char *_OUTPUT_BUFFER; +typedef struct out_buffer +{ + uint32_t BufferSize; + _OUTPUT_BUFFER Buffer; +} _OUT_BUFFER; +#ifdef _MSC_VER +# pragma warning(pop) +#endif +#ifndef WIN32 +typedef unsigned long DWORD; +typedef void *LPVOID; +#undef WINAPI +#endif +#endif diff --git a/src/tpm2/TpmTypes.h b/src/tpm2/TpmTypes.h new file mode 100644 index 0000000..a06d759 --- /dev/null +++ b/src/tpm2/TpmTypes.h @@ -0,0 +1,2473 @@ +/********************************************************************************/ +/* */ +/* TPM Part 2 Headers */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmTypes.h 1606 2020-04-14 16:26:05Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 5.21 TpmTypes.h */ + +#ifndef TPMTYPES_H +#define TPMTYPES_H + +/* TCG Algorithm Registry: Table 1:2 - Definition of TPM_ALG_ID Constants */ + +typedef UINT16 TPM_ALG_ID; +#define TYPE_OF_TPM_ALG_ID UINT16 +#define ALG_ERROR_VALUE 0x0000 +#define TPM_ALG_ERROR (TPM_ALG_ID)(ALG_ERROR_VALUE) +#define ALG_RSA_VALUE 0x0001 +#define TPM_ALG_RSA (TPM_ALG_ID)(ALG_RSA_VALUE) +#define ALG_TDES_VALUE 0x0003 +#define TPM_ALG_TDES (TPM_ALG_ID)(ALG_TDES_VALUE) +#define ALG_SHA_VALUE 0x0004 +#define TPM_ALG_SHA (TPM_ALG_ID)(ALG_SHA_VALUE) +#define ALG_SHA1_VALUE 0x0004 +#define TPM_ALG_SHA1 (TPM_ALG_ID)(ALG_SHA1_VALUE) +#define ALG_HMAC_VALUE 0x0005 +#define TPM_ALG_HMAC (TPM_ALG_ID)(ALG_HMAC_VALUE) +#define ALG_AES_VALUE 0x0006 +#define TPM_ALG_AES (TPM_ALG_ID)(ALG_AES_VALUE) +#define ALG_MGF1_VALUE 0x0007 +#define TPM_ALG_MGF1 (TPM_ALG_ID)(ALG_MGF1_VALUE) +#define ALG_KEYEDHASH_VALUE 0x0008 +#define TPM_ALG_KEYEDHASH (TPM_ALG_ID)(ALG_KEYEDHASH_VALUE) +#define ALG_XOR_VALUE 0x000A +#define TPM_ALG_XOR (TPM_ALG_ID)(ALG_XOR_VALUE) +#define ALG_SHA256_VALUE 0x000B +#define TPM_ALG_SHA256 (TPM_ALG_ID)(ALG_SHA256_VALUE) +#define ALG_SHA384_VALUE 0x000C +#define TPM_ALG_SHA384 (TPM_ALG_ID)(ALG_SHA384_VALUE) +#define ALG_SHA512_VALUE 0x000D +#define TPM_ALG_SHA512 (TPM_ALG_ID)(ALG_SHA512_VALUE) +#define ALG_NULL_VALUE 0x0010 +#define TPM_ALG_NULL (TPM_ALG_ID)(ALG_NULL_VALUE) +#define ALG_SM3_256_VALUE 0x0012 +#define TPM_ALG_SM3_256 (TPM_ALG_ID)(ALG_SM3_256_VALUE) +#define ALG_SM4_VALUE 0x0013 +#define TPM_ALG_SM4 (TPM_ALG_ID)(ALG_SM4_VALUE) +#define ALG_RSASSA_VALUE 0x0014 +#define TPM_ALG_RSASSA (TPM_ALG_ID)(ALG_RSASSA_VALUE) +#define ALG_RSAES_VALUE 0x0015 +#define TPM_ALG_RSAES (TPM_ALG_ID)(ALG_RSAES_VALUE) +#define ALG_RSAPSS_VALUE 0x0016 +#define TPM_ALG_RSAPSS (TPM_ALG_ID)(ALG_RSAPSS_VALUE) +#define ALG_OAEP_VALUE 0x0017 +#define TPM_ALG_OAEP (TPM_ALG_ID)(ALG_OAEP_VALUE) +#define ALG_ECDSA_VALUE 0x0018 +#define TPM_ALG_ECDSA (TPM_ALG_ID)(ALG_ECDSA_VALUE) +#define ALG_ECDH_VALUE 0x0019 +#define TPM_ALG_ECDH (TPM_ALG_ID)(ALG_ECDH_VALUE) +#define ALG_ECDAA_VALUE 0x001A +#define TPM_ALG_ECDAA (TPM_ALG_ID)(ALG_ECDAA_VALUE) +#define ALG_SM2_VALUE 0x001B +#define TPM_ALG_SM2 (TPM_ALG_ID)(ALG_SM2_VALUE) +#define ALG_ECSCHNORR_VALUE 0x001C +#define TPM_ALG_ECSCHNORR (TPM_ALG_ID)(ALG_ECSCHNORR_VALUE) +#define ALG_ECMQV_VALUE 0x001D +#define TPM_ALG_ECMQV (TPM_ALG_ID)(ALG_ECMQV_VALUE) +#define ALG_KDF1_SP800_56A_VALUE 0x0020 +#define TPM_ALG_KDF1_SP800_56A (TPM_ALG_ID)(ALG_KDF1_SP800_56A_VALUE) +#define ALG_KDF2_VALUE 0x0021 +#define TPM_ALG_KDF2 (TPM_ALG_ID)(ALG_KDF2_VALUE) +#define ALG_KDF1_SP800_108_VALUE 0x0022 +#define TPM_ALG_KDF1_SP800_108 (TPM_ALG_ID)(ALG_KDF1_SP800_108_VALUE) +#define ALG_ECC_VALUE 0x0023 +#define TPM_ALG_ECC (TPM_ALG_ID)(ALG_ECC_VALUE) +#define ALG_SYMCIPHER_VALUE 0x0025 +#define TPM_ALG_SYMCIPHER (TPM_ALG_ID)(ALG_SYMCIPHER_VALUE) +#define ALG_CAMELLIA_VALUE 0x0026 +#define TPM_ALG_CAMELLIA (TPM_ALG_ID)(ALG_CAMELLIA_VALUE) +#define ALG_SHA3_256_VALUE 0x0027 +#define TPM_ALG_SHA3_256 (TPM_ALG_ID)(ALG_SHA3_256_VALUE) +#define ALG_SHA3_384_VALUE 0x0028 +#define TPM_ALG_SHA3_384 (TPM_ALG_ID)(ALG_SHA3_384_VALUE) +#define ALG_SHA3_512_VALUE 0x0029 +#define TPM_ALG_SHA3_512 (TPM_ALG_ID)(ALG_SHA3_512_VALUE) +#define ALG_CMAC_VALUE 0x003F +#define TPM_ALG_CMAC (TPM_ALG_ID)(ALG_CMAC_VALUE) +#define ALG_CTR_VALUE 0x0040 +#define TPM_ALG_CTR (TPM_ALG_ID)(ALG_CTR_VALUE) +#define ALG_OFB_VALUE 0x0041 +#define TPM_ALG_OFB (TPM_ALG_ID)(ALG_OFB_VALUE) +#define ALG_CBC_VALUE 0x0042 +#define TPM_ALG_CBC (TPM_ALG_ID)(ALG_CBC_VALUE) +#define ALG_CFB_VALUE 0x0043 +#define TPM_ALG_CFB (TPM_ALG_ID)(ALG_CFB_VALUE) +#define ALG_ECB_VALUE 0x0044 +#define TPM_ALG_ECB (TPM_ALG_ID)(ALG_ECB_VALUE) + +/* Values derived from Table 1:2 */ +#define ALG_FIRST_VALUE 0x0001 +#define TPM_ALG_FIRST (TPM_ALG_ID)(ALG_FIRST_VALUE) +#define ALG_LAST_VALUE 0x0044 +#define TPM_ALG_LAST (TPM_ALG_ID)(ALG_LAST_VALUE) + +/* TCG Algorithm Registry: Table 1:3 - Definition of TPM_ECC_CURVE Constants */ +typedef UINT16 TPM_ECC_CURVE; +#define TYPE_OF_TPM_ECC_CURVE UINT16 +#define TPM_ECC_NONE (TPM_ECC_CURVE)(0x0000) +#define TPM_ECC_NIST_P192 (TPM_ECC_CURVE)(0x0001) +#define TPM_ECC_NIST_P224 (TPM_ECC_CURVE)(0x0002) +#define TPM_ECC_NIST_P256 (TPM_ECC_CURVE)(0x0003) +#define TPM_ECC_NIST_P384 (TPM_ECC_CURVE)(0x0004) +#define TPM_ECC_NIST_P521 (TPM_ECC_CURVE)(0x0005) +#define TPM_ECC_BN_P256 (TPM_ECC_CURVE)(0x0010) +#define TPM_ECC_BN_P638 (TPM_ECC_CURVE)(0x0011) +#define TPM_ECC_SM2_P256 (TPM_ECC_CURVE)(0x0020) + +/* TPM 2.0 Part 2: Table 2:12 - Definition of TPM_CC Constants */ +typedef UINT32 TPM_CC; +#define TYPE_OF_TPM_CC UINT32 +#define TPM_CC_NV_UndefineSpaceSpecial (TPM_CC)(0x0000011F) +#define TPM_CC_EvictControl (TPM_CC)(0x00000120) +#define TPM_CC_HierarchyControl (TPM_CC)(0x00000121) +#define TPM_CC_NV_UndefineSpace (TPM_CC)(0x00000122) +#define TPM_CC_ChangeEPS (TPM_CC)(0x00000124) +#define TPM_CC_ChangePPS (TPM_CC)(0x00000125) +#define TPM_CC_Clear (TPM_CC)(0x00000126) +#define TPM_CC_ClearControl (TPM_CC)(0x00000127) +#define TPM_CC_ClockSet (TPM_CC)(0x00000128) +#define TPM_CC_HierarchyChangeAuth (TPM_CC)(0x00000129) +#define TPM_CC_NV_DefineSpace (TPM_CC)(0x0000012A) +#define TPM_CC_PCR_Allocate (TPM_CC)(0x0000012B) +#define TPM_CC_PCR_SetAuthPolicy (TPM_CC)(0x0000012C) +#define TPM_CC_PP_Commands (TPM_CC)(0x0000012D) +#define TPM_CC_SetPrimaryPolicy (TPM_CC)(0x0000012E) +#define TPM_CC_FieldUpgradeStart (TPM_CC)(0x0000012F) +#define TPM_CC_ClockRateAdjust (TPM_CC)(0x00000130) +#define TPM_CC_CreatePrimary (TPM_CC)(0x00000131) +#define TPM_CC_NV_GlobalWriteLock (TPM_CC)(0x00000132) +#define TPM_CC_GetCommandAuditDigest (TPM_CC)(0x00000133) +#define TPM_CC_NV_Increment (TPM_CC)(0x00000134) +#define TPM_CC_NV_SetBits (TPM_CC)(0x00000135) +#define TPM_CC_NV_Extend (TPM_CC)(0x00000136) +#define TPM_CC_NV_Write (TPM_CC)(0x00000137) +#define TPM_CC_NV_WriteLock (TPM_CC)(0x00000138) +#define TPM_CC_DictionaryAttackLockReset (TPM_CC)(0x00000139) +#define TPM_CC_DictionaryAttackParameters (TPM_CC)(0x0000013A) +#define TPM_CC_NV_ChangeAuth (TPM_CC)(0x0000013B) +#define TPM_CC_PCR_Event (TPM_CC)(0x0000013C) +#define TPM_CC_PCR_Reset (TPM_CC)(0x0000013D) +#define TPM_CC_SequenceComplete (TPM_CC)(0x0000013E) +#define TPM_CC_SetAlgorithmSet (TPM_CC)(0x0000013F) +#define TPM_CC_SetCommandCodeAuditStatus (TPM_CC)(0x00000140) +#define TPM_CC_FieldUpgradeData (TPM_CC)(0x00000141) +#define TPM_CC_IncrementalSelfTest (TPM_CC)(0x00000142) +#define TPM_CC_SelfTest (TPM_CC)(0x00000143) +#define TPM_CC_Startup (TPM_CC)(0x00000144) +#define TPM_CC_Shutdown (TPM_CC)(0x00000145) +#define TPM_CC_StirRandom (TPM_CC)(0x00000146) +#define TPM_CC_ActivateCredential (TPM_CC)(0x00000147) +#define TPM_CC_Certify (TPM_CC)(0x00000148) +#define TPM_CC_PolicyNV (TPM_CC)(0x00000149) +#define TPM_CC_CertifyCreation (TPM_CC)(0x0000014A) +#define TPM_CC_Duplicate (TPM_CC)(0x0000014B) +#define TPM_CC_GetTime (TPM_CC)(0x0000014C) +#define TPM_CC_GetSessionAuditDigest (TPM_CC)(0x0000014D) +#define TPM_CC_NV_Read (TPM_CC)(0x0000014E) +#define TPM_CC_NV_ReadLock (TPM_CC)(0x0000014F) +#define TPM_CC_ObjectChangeAuth (TPM_CC)(0x00000150) +#define TPM_CC_PolicySecret (TPM_CC)(0x00000151) +#define TPM_CC_Rewrap (TPM_CC)(0x00000152) +#define TPM_CC_Create (TPM_CC)(0x00000153) +#define TPM_CC_ECDH_ZGen (TPM_CC)(0x00000154) +#define TPM_CC_HMAC (TPM_CC)(0x00000155) +#define TPM_CC_MAC (TPM_CC)(0x00000155) +#define TPM_CC_Import (TPM_CC)(0x00000156) +#define TPM_CC_Load (TPM_CC)(0x00000157) +#define TPM_CC_Quote (TPM_CC)(0x00000158) +#define TPM_CC_RSA_Decrypt (TPM_CC)(0x00000159) +#define TPM_CC_HMAC_Start (TPM_CC)(0x0000015B) +#define TPM_CC_MAC_Start (TPM_CC)(0x0000015B) +#define TPM_CC_SequenceUpdate (TPM_CC)(0x0000015C) +#define TPM_CC_Sign (TPM_CC)(0x0000015D) +#define TPM_CC_Unseal (TPM_CC)(0x0000015E) +#define TPM_CC_PolicySigned (TPM_CC)(0x00000160) +#define TPM_CC_ContextLoad (TPM_CC)(0x00000161) +#define TPM_CC_ContextSave (TPM_CC)(0x00000162) +#define TPM_CC_ECDH_KeyGen (TPM_CC)(0x00000163) +#define TPM_CC_EncryptDecrypt (TPM_CC)(0x00000164) +#define TPM_CC_FlushContext (TPM_CC)(0x00000165) +#define TPM_CC_LoadExternal (TPM_CC)(0x00000167) +#define TPM_CC_MakeCredential (TPM_CC)(0x00000168) +#define TPM_CC_NV_ReadPublic (TPM_CC)(0x00000169) +#define TPM_CC_PolicyAuthorize (TPM_CC)(0x0000016A) +#define TPM_CC_PolicyAuthValue (TPM_CC)(0x0000016B) +#define TPM_CC_PolicyCommandCode (TPM_CC)(0x0000016C) +#define TPM_CC_PolicyCounterTimer (TPM_CC)(0x0000016D) +#define TPM_CC_PolicyCpHash (TPM_CC)(0x0000016E) +#define TPM_CC_PolicyLocality (TPM_CC)(0x0000016F) +#define TPM_CC_PolicyNameHash (TPM_CC)(0x00000170) +#define TPM_CC_PolicyOR (TPM_CC)(0x00000171) +#define TPM_CC_PolicyTicket (TPM_CC)(0x00000172) +#define TPM_CC_ReadPublic (TPM_CC)(0x00000173) +#define TPM_CC_RSA_Encrypt (TPM_CC)(0x00000174) +#define TPM_CC_StartAuthSession (TPM_CC)(0x00000176) +#define TPM_CC_VerifySignature (TPM_CC)(0x00000177) +#define TPM_CC_ECC_Parameters (TPM_CC)(0x00000178) +#define TPM_CC_FirmwareRead (TPM_CC)(0x00000179) +#define TPM_CC_GetCapability (TPM_CC)(0x0000017A) +#define TPM_CC_GetRandom (TPM_CC)(0x0000017B) +#define TPM_CC_GetTestResult (TPM_CC)(0x0000017C) +#define TPM_CC_Hash (TPM_CC)(0x0000017D) +#define TPM_CC_PCR_Read (TPM_CC)(0x0000017E) +#define TPM_CC_PolicyPCR (TPM_CC)(0x0000017F) +#define TPM_CC_PolicyRestart (TPM_CC)(0x00000180) +#define TPM_CC_ReadClock (TPM_CC)(0x00000181) +#define TPM_CC_PCR_Extend (TPM_CC)(0x00000182) +#define TPM_CC_PCR_SetAuthValue (TPM_CC)(0x00000183) +#define TPM_CC_NV_Certify (TPM_CC)(0x00000184) +#define TPM_CC_EventSequenceComplete (TPM_CC)(0x00000185) +#define TPM_CC_HashSequenceStart (TPM_CC)(0x00000186) +#define TPM_CC_PolicyPhysicalPresence (TPM_CC)(0x00000187) +#define TPM_CC_PolicyDuplicationSelect (TPM_CC)(0x00000188) +#define TPM_CC_PolicyGetDigest (TPM_CC)(0x00000189) +#define TPM_CC_TestParms (TPM_CC)(0x0000018A) +#define TPM_CC_Commit (TPM_CC)(0x0000018B) +#define TPM_CC_PolicyPassword (TPM_CC)(0x0000018C) +#define TPM_CC_ZGen_2Phase (TPM_CC)(0x0000018D) +#define TPM_CC_EC_Ephemeral (TPM_CC)(0x0000018E) +#define TPM_CC_PolicyNvWritten (TPM_CC)(0x0000018F) +#define TPM_CC_PolicyTemplate (TPM_CC)(0x00000190) +#define TPM_CC_CreateLoaded (TPM_CC)(0x00000191) +#define TPM_CC_PolicyAuthorizeNV (TPM_CC)(0x00000192) +#define TPM_CC_EncryptDecrypt2 (TPM_CC)(0x00000193) +#define TPM_CC_AC_GetCapability (TPM_CC)(0x00000194) +#define TPM_CC_AC_Send (TPM_CC)(0x00000195) +#define TPM_CC_Policy_AC_SendSelect (TPM_CC)(0x00000196) +#define TPM_CC_CertifyX509 (TPM_CC)(0x00000197) +#define TPM_CC_ACT_SetTimeout (TPM_CC)(0x00000198) +#define TPM_CC_ECC_Encrypt (TPM_CC)(0x00000199) +#define TPM_CC_ECC_Decrypt (TPM_CC)(0x0000019A) +#define CC_VEND 0x20000000 +#define TPM_CC_Vendor_TCG_Test (TPM_CC)(0x20000000) + +/* Table 2:5 - Definition of Types for Documentation Clarity */ +typedef UINT32 TPM_ALGORITHM_ID; +#define TYPE_OF_TPM_ALGORITHM_ID UINT32 +typedef UINT32 TPM_MODIFIER_INDICATOR; +#define TYPE_OF_TPM_MODIFIER_INDICATOR UINT32 +typedef UINT32 TPM_AUTHORIZATION_SIZE; +#define TYPE_OF_TPM_AUTHORIZATION_SIZE UINT32 +typedef UINT32 TPM_PARAMETER_SIZE; +#define TYPE_OF_TPM_PARAMETER_SIZE UINT32 +typedef UINT16 TPM_KEY_SIZE; +#define TYPE_OF_TPM_KEY_SIZE UINT16 +typedef UINT16 TPM_KEY_BITS; +#define TYPE_OF_TPM_KEY_BITS UINT16 + +/* Table 2:6 - Definition of TPM_SPEC Constants */ +typedef UINT32 TPM_SPEC; +#define TYPE_OF_TPM_SPEC UINT32 +#define SPEC_FAMILY 0x322E3000 +#define TPM_SPEC_FAMILY (TPM_SPEC)(SPEC_FAMILY) +#define SPEC_LEVEL 00 +#define SPEC_LEVEL_NUM 0 // libtpms added: SPEC_LEVEL without leading zeros +#define TPM_SPEC_LEVEL (TPM_SPEC)(SPEC_LEVEL) +#define SPEC_VERSION 164 +#define TPM_SPEC_VERSION (TPM_SPEC)(SPEC_VERSION) +#define SPEC_YEAR 2021 +#define TPM_SPEC_YEAR (TPM_SPEC)(SPEC_YEAR) +#define SPEC_DAY_OF_YEAR 75 +#define TPM_SPEC_DAY_OF_YEAR (TPM_SPEC)(SPEC_DAY_OF_YEAR) + +/* Table 2:7 - Definition of TPM_CONSTANTS32 Constants */ + +typedef UINT32 TPM_CONSTANTS32; +#define TYPE_OF_TPM_CONSTANTS32 UINT32 +#define TPM_GENERATED_VALUE (TPM_CONSTANTS32)(0xFF544347) +#define TPM_MAX_DERIVATION_BITS (TPM_CONSTANTS32)8192 + +/* Table 2:16 - Definition of TPM_RC Constants */ +typedef UINT32 TPM_RC; +#define TYPE_OF_TPM_RC UINT32 +#define TPM_RC_SUCCESS (TPM_RC)(0x000) +#define TPM_RC_BAD_TAG (TPM_RC)(0x01E) +#define RC_VER1 (TPM_RC)(0x100) +#define TPM_RC_INITIALIZE (TPM_RC)(RC_VER1+0x000) +#define TPM_RC_FAILURE (TPM_RC)(RC_VER1+0x001) +#define TPM_RC_SEQUENCE (TPM_RC)(RC_VER1+0x003) +#define TPM_RC_PRIVATE (TPM_RC)(RC_VER1+0x00B) +#define TPM_RC_HMAC (TPM_RC)(RC_VER1+0x019) +#define TPM_RC_DISABLED (TPM_RC)(RC_VER1+0x020) +#define TPM_RC_EXCLUSIVE (TPM_RC)(RC_VER1+0x021) +#define TPM_RC_AUTH_TYPE (TPM_RC)(RC_VER1+0x024) +#define TPM_RC_AUTH_MISSING (TPM_RC)(RC_VER1+0x025) +#define TPM_RC_POLICY (TPM_RC)(RC_VER1+0x026) +#define TPM_RC_PCR (TPM_RC)(RC_VER1+0x027) +#define TPM_RC_PCR_CHANGED (TPM_RC)(RC_VER1+0x028) +#define TPM_RC_UPGRADE (TPM_RC)(RC_VER1+0x02D) +#define TPM_RC_TOO_MANY_CONTEXTS (TPM_RC)(RC_VER1+0x02E) +#define TPM_RC_AUTH_UNAVAILABLE (TPM_RC)(RC_VER1+0x02F) +#define TPM_RC_REBOOT (TPM_RC)(RC_VER1+0x030) +#define TPM_RC_UNBALANCED (TPM_RC)(RC_VER1+0x031) +#define TPM_RC_COMMAND_SIZE (TPM_RC)(RC_VER1+0x042) +#define TPM_RC_COMMAND_CODE (TPM_RC)(RC_VER1+0x043) +#define TPM_RC_AUTHSIZE (TPM_RC)(RC_VER1+0x044) +#define TPM_RC_AUTH_CONTEXT (TPM_RC)(RC_VER1+0x045) +#define TPM_RC_NV_RANGE (TPM_RC)(RC_VER1+0x046) +#define TPM_RC_NV_SIZE (TPM_RC)(RC_VER1+0x047) +#define TPM_RC_NV_LOCKED (TPM_RC)(RC_VER1+0x048) +#define TPM_RC_NV_AUTHORIZATION (TPM_RC)(RC_VER1+0x049) +#define TPM_RC_NV_UNINITIALIZED (TPM_RC)(RC_VER1+0x04A) +#define TPM_RC_NV_SPACE (TPM_RC)(RC_VER1+0x04B) +#define TPM_RC_NV_DEFINED (TPM_RC)(RC_VER1+0x04C) +#define TPM_RC_BAD_CONTEXT (TPM_RC)(RC_VER1+0x050) +#define TPM_RC_CPHASH (TPM_RC)(RC_VER1+0x051) +#define TPM_RC_PARENT (TPM_RC)(RC_VER1+0x052) +#define TPM_RC_NEEDS_TEST (TPM_RC)(RC_VER1+0x053) +#define TPM_RC_NO_RESULT (TPM_RC)(RC_VER1+0x054) +#define TPM_RC_SENSITIVE (TPM_RC)(RC_VER1+0x055) +#define RC_MAX_FM0 (TPM_RC)(RC_VER1+0x07F) +#define RC_FMT1 (TPM_RC)(0x080) +#define TPM_RC_ASYMMETRIC (TPM_RC)(RC_FMT1+0x001) +#define TPM_RCS_ASYMMETRIC (TPM_RC)(RC_FMT1+0x001) +#define TPM_RC_ATTRIBUTES (TPM_RC)(RC_FMT1+0x002) +#define TPM_RCS_ATTRIBUTES (TPM_RC)(RC_FMT1+0x002) +#define TPM_RC_HASH (TPM_RC)(RC_FMT1+0x003) +#define TPM_RCS_HASH (TPM_RC)(RC_FMT1+0x003) +#define TPM_RC_VALUE (TPM_RC)(RC_FMT1+0x004) +#define TPM_RCS_VALUE (TPM_RC)(RC_FMT1+0x004) +#define TPM_RC_HIERARCHY (TPM_RC)(RC_FMT1+0x005) +#define TPM_RCS_HIERARCHY (TPM_RC)(RC_FMT1+0x005) +#define TPM_RC_KEY_SIZE (TPM_RC)(RC_FMT1+0x007) +#define TPM_RCS_KEY_SIZE (TPM_RC)(RC_FMT1+0x007) +#define TPM_RC_MGF (TPM_RC)(RC_FMT1+0x008) +#define TPM_RCS_MGF (TPM_RC)(RC_FMT1+0x008) +#define TPM_RC_MODE (TPM_RC)(RC_FMT1+0x009) +#define TPM_RCS_MODE (TPM_RC)(RC_FMT1+0x009) +#define TPM_RC_TYPE (TPM_RC)(RC_FMT1+0x00A) +#define TPM_RCS_TYPE (TPM_RC)(RC_FMT1+0x00A) +#define TPM_RC_HANDLE (TPM_RC)(RC_FMT1+0x00B) +#define TPM_RCS_HANDLE (TPM_RC)(RC_FMT1+0x00B) +#define TPM_RC_KDF (TPM_RC)(RC_FMT1+0x00C) +#define TPM_RCS_KDF (TPM_RC)(RC_FMT1+0x00C) +#define TPM_RC_RANGE (TPM_RC)(RC_FMT1+0x00D) +#define TPM_RCS_RANGE (TPM_RC)(RC_FMT1+0x00D) +#define TPM_RC_AUTH_FAIL (TPM_RC)(RC_FMT1+0x00E) +#define TPM_RCS_AUTH_FAIL (TPM_RC)(RC_FMT1+0x00E) +#define TPM_RC_NONCE (TPM_RC)(RC_FMT1+0x00F) +#define TPM_RCS_NONCE (TPM_RC)(RC_FMT1+0x00F) +#define TPM_RC_PP (TPM_RC)(RC_FMT1+0x010) +#define TPM_RCS_PP (TPM_RC)(RC_FMT1+0x010) +#define TPM_RC_SCHEME (TPM_RC)(RC_FMT1+0x012) +#define TPM_RCS_SCHEME (TPM_RC)(RC_FMT1+0x012) +#define TPM_RC_SIZE (TPM_RC)(RC_FMT1+0x015) +#define TPM_RCS_SIZE (TPM_RC)(RC_FMT1+0x015) +#define TPM_RC_SYMMETRIC (TPM_RC)(RC_FMT1+0x016) +#define TPM_RCS_SYMMETRIC (TPM_RC)(RC_FMT1+0x016) +#define TPM_RC_TAG (TPM_RC)(RC_FMT1+0x017) +#define TPM_RCS_TAG (TPM_RC)(RC_FMT1+0x017) +#define TPM_RC_SELECTOR (TPM_RC)(RC_FMT1+0x018) +#define TPM_RCS_SELECTOR (TPM_RC)(RC_FMT1+0x018) +#define TPM_RC_INSUFFICIENT (TPM_RC)(RC_FMT1+0x01A) +#define TPM_RCS_INSUFFICIENT (TPM_RC)(RC_FMT1+0x01A) +#define TPM_RC_SIGNATURE (TPM_RC)(RC_FMT1+0x01B) +#define TPM_RCS_SIGNATURE (TPM_RC)(RC_FMT1+0x01B) +#define TPM_RC_KEY (TPM_RC)(RC_FMT1+0x01C) +#define TPM_RCS_KEY (TPM_RC)(RC_FMT1+0x01C) +#define TPM_RC_POLICY_FAIL (TPM_RC)(RC_FMT1+0x01D) +#define TPM_RCS_POLICY_FAIL (TPM_RC)(RC_FMT1+0x01D) +#define TPM_RC_INTEGRITY (TPM_RC)(RC_FMT1+0x01F) +#define TPM_RCS_INTEGRITY (TPM_RC)(RC_FMT1+0x01F) +#define TPM_RC_TICKET (TPM_RC)(RC_FMT1+0x020) +#define TPM_RCS_TICKET (TPM_RC)(RC_FMT1+0x020) +#define TPM_RC_RESERVED_BITS (TPM_RC)(RC_FMT1+0x021) +#define TPM_RCS_RESERVED_BITS (TPM_RC)(RC_FMT1+0x021) +#define TPM_RC_BAD_AUTH (TPM_RC)(RC_FMT1+0x022) +#define TPM_RCS_BAD_AUTH (TPM_RC)(RC_FMT1+0x022) +#define TPM_RC_EXPIRED (TPM_RC)(RC_FMT1+0x023) +#define TPM_RCS_EXPIRED (TPM_RC)(RC_FMT1+0x023) +#define TPM_RC_POLICY_CC (TPM_RC)(RC_FMT1+0x024) +#define TPM_RCS_POLICY_CC (TPM_RC)(RC_FMT1+0x024) +#define TPM_RC_BINDING (TPM_RC)(RC_FMT1+0x025) +#define TPM_RCS_BINDING (TPM_RC)(RC_FMT1+0x025) +#define TPM_RC_CURVE (TPM_RC)(RC_FMT1+0x026) +#define TPM_RCS_CURVE (TPM_RC)(RC_FMT1+0x026) +#define TPM_RC_ECC_POINT (TPM_RC)(RC_FMT1+0x027) +#define TPM_RCS_ECC_POINT (TPM_RC)(RC_FMT1+0x027) +#define RC_WARN (TPM_RC)(0x900) +#define TPM_RC_CONTEXT_GAP (TPM_RC)(RC_WARN+0x001) +#define TPM_RC_OBJECT_MEMORY (TPM_RC)(RC_WARN+0x002) +#define TPM_RC_SESSION_MEMORY (TPM_RC)(RC_WARN+0x003) +#define TPM_RC_MEMORY (TPM_RC)(RC_WARN+0x004) +#define TPM_RC_SESSION_HANDLES (TPM_RC)(RC_WARN+0x005) +#define TPM_RC_OBJECT_HANDLES (TPM_RC)(RC_WARN+0x006) +#define TPM_RC_LOCALITY (TPM_RC)(RC_WARN+0x007) +#define TPM_RC_YIELDED (TPM_RC)(RC_WARN+0x008) +#define TPM_RC_CANCELED (TPM_RC)(RC_WARN+0x009) +#define TPM_RC_TESTING (TPM_RC)(RC_WARN+0x00A) +#define TPM_RC_REFERENCE_H0 (TPM_RC)(RC_WARN+0x010) +#define TPM_RC_REFERENCE_H1 (TPM_RC)(RC_WARN+0x011) +#define TPM_RC_REFERENCE_H2 (TPM_RC)(RC_WARN+0x012) +#define TPM_RC_REFERENCE_H3 (TPM_RC)(RC_WARN+0x013) +#define TPM_RC_REFERENCE_H4 (TPM_RC)(RC_WARN+0x014) +#define TPM_RC_REFERENCE_H5 (TPM_RC)(RC_WARN+0x015) +#define TPM_RC_REFERENCE_H6 (TPM_RC)(RC_WARN+0x016) +#define TPM_RC_REFERENCE_S0 (TPM_RC)(RC_WARN+0x018) +#define TPM_RC_REFERENCE_S1 (TPM_RC)(RC_WARN+0x019) +#define TPM_RC_REFERENCE_S2 (TPM_RC)(RC_WARN+0x01A) +#define TPM_RC_REFERENCE_S3 (TPM_RC)(RC_WARN+0x01B) +#define TPM_RC_REFERENCE_S4 (TPM_RC)(RC_WARN+0x01C) +#define TPM_RC_REFERENCE_S5 (TPM_RC)(RC_WARN+0x01D) +#define TPM_RC_REFERENCE_S6 (TPM_RC)(RC_WARN+0x01E) +#define TPM_RC_NV_RATE (TPM_RC)(RC_WARN+0x020) +#define TPM_RC_LOCKOUT (TPM_RC)(RC_WARN+0x021) +#define TPM_RC_RETRY (TPM_RC)(RC_WARN+0x022) +#define TPM_RC_NV_UNAVAILABLE (TPM_RC)(RC_WARN+0x023) +#define TPM_RC_NOT_USED (TPM_RC)(RC_WARN+0x7F) +#define TPM_RC_H (TPM_RC)(0x000) +#define TPM_RC_P (TPM_RC)(0x040) +#define TPM_RC_S (TPM_RC)(0x800) +#define TPM_RC_1 (TPM_RC)(0x100) +#define TPM_RC_2 (TPM_RC)(0x200) +#define TPM_RC_3 (TPM_RC)(0x300) +#define TPM_RC_4 (TPM_RC)(0x400) +#define TPM_RC_5 (TPM_RC)(0x500) +#define TPM_RC_6 (TPM_RC)(0x600) +#define TPM_RC_7 (TPM_RC)(0x700) +#define TPM_RC_8 (TPM_RC)(0x800) +#define TPM_RC_9 (TPM_RC)(0x900) +#define TPM_RC_A (TPM_RC)(0xA00) +#define TPM_RC_B (TPM_RC)(0xB00) +#define TPM_RC_C (TPM_RC)(0xC00) +#define TPM_RC_D (TPM_RC)(0xD00) +#define TPM_RC_E (TPM_RC)(0xE00) +#define TPM_RC_F (TPM_RC)(0xF00) +#define TPM_RC_N_MASK (TPM_RC)(0xF00) + +/* Table 2:17 - Definition of TPM_CLOCK_ADJUST Constants */ +typedef INT8 TPM_CLOCK_ADJUST; +#define TYPE_OF_TPM_CLOCK_ADJUST UINT8 +#define TPM_CLOCK_COARSE_SLOWER (TPM_CLOCK_ADJUST)(-3) +#define TPM_CLOCK_MEDIUM_SLOWER (TPM_CLOCK_ADJUST)(-2) +#define TPM_CLOCK_FINE_SLOWER (TPM_CLOCK_ADJUST)(-1) +#define TPM_CLOCK_NO_CHANGE (TPM_CLOCK_ADJUST)(0) +#define TPM_CLOCK_FINE_FASTER (TPM_CLOCK_ADJUST)(1) +#define TPM_CLOCK_MEDIUM_FASTER (TPM_CLOCK_ADJUST)(2) +#define TPM_CLOCK_COARSE_FASTER (TPM_CLOCK_ADJUST)(3) + +/* Table 2:18 - Definition of TPM_EO Constants */ +typedef UINT16 TPM_EO; +#define TYPE_OF_TPM_EO UINT16 +#define TPM_EO_EQ (TPM_EO)(0x0000) +#define TPM_EO_NEQ (TPM_EO)(0x0001) +#define TPM_EO_SIGNED_GT (TPM_EO)(0x0002) +#define TPM_EO_UNSIGNED_GT (TPM_EO)(0x0003) +#define TPM_EO_SIGNED_LT (TPM_EO)(0x0004) +#define TPM_EO_UNSIGNED_LT (TPM_EO)(0x0005) +#define TPM_EO_SIGNED_GE (TPM_EO)(0x0006) +#define TPM_EO_UNSIGNED_GE (TPM_EO)(0x0007) +#define TPM_EO_SIGNED_LE (TPM_EO)(0x0008) +#define TPM_EO_UNSIGNED_LE (TPM_EO)(0x0009) +#define TPM_EO_BITSET (TPM_EO)(0x000A) +#define TPM_EO_BITCLEAR (TPM_EO)(0x000B) +/* Table 2:19 - Definition of TPM_ST Constants */ + +typedef UINT16 TPM_ST; +#define TYPE_OF_TPM_ST UINT16 +#define TPM_ST_RSP_COMMAND (TPM_ST)(0x00C4) +#define TPM_ST_NULL (TPM_ST)(0x8000) +#define TPM_ST_NO_SESSIONS (TPM_ST)(0x8001) +#define TPM_ST_SESSIONS (TPM_ST)(0x8002) +#define TPM_ST_ATTEST_NV (TPM_ST)(0x8014) +#define TPM_ST_ATTEST_COMMAND_AUDIT (TPM_ST)(0x8015) +#define TPM_ST_ATTEST_SESSION_AUDIT (TPM_ST)(0x8016) +#define TPM_ST_ATTEST_CERTIFY (TPM_ST)(0x8017) +#define TPM_ST_ATTEST_QUOTE (TPM_ST)(0x8018) +#define TPM_ST_ATTEST_TIME (TPM_ST)(0x8019) +#define TPM_ST_ATTEST_CREATION (TPM_ST)(0x801A) +#define TPM_ST_ATTEST_NV_DIGEST (TPM_ST)(0x801C) +#define TPM_ST_CREATION (TPM_ST)(0x8021) +#define TPM_ST_VERIFIED (TPM_ST)(0x8022) +#define TPM_ST_AUTH_SECRET (TPM_ST)(0x8023) +#define TPM_ST_HASHCHECK (TPM_ST)(0x8024) +#define TPM_ST_AUTH_SIGNED (TPM_ST)(0x8025) +#define TPM_ST_FU_MANIFEST (TPM_ST)(0x8029) + +/* Table 2:20 - Definition of TPM_SU Constants */ +typedef UINT16 TPM_SU; +#define TYPE_OF_TPM_SU UINT16 +#define TPM_SU_CLEAR (TPM_SU)(0x0000) +#define TPM_SU_STATE (TPM_SU)(0x0001) + +/* Table 2:21 - Definition of TPM_SE Constants */ +typedef UINT8 TPM_SE; +#define TYPE_OF_TPM_SE UINT8 +#define TPM_SE_HMAC (TPM_SE)(0x00) +#define TPM_SE_POLICY (TPM_SE)(0x01) +#define TPM_SE_TRIAL (TPM_SE)(0x03) + +/* Table 2:22 - Definition of TPM_CAP Constants */ +typedef UINT32 TPM_CAP; +#define TYPE_OF_TPM_CAP UINT32 +#define TPM_CAP_FIRST (TPM_CAP)(0x00000000) +#define TPM_CAP_ALGS (TPM_CAP)(0x00000000) +#define TPM_CAP_HANDLES (TPM_CAP)(0x00000001) +#define TPM_CAP_COMMANDS (TPM_CAP)(0x00000002) +#define TPM_CAP_PP_COMMANDS (TPM_CAP)(0x00000003) +#define TPM_CAP_AUDIT_COMMANDS (TPM_CAP)(0x00000004) +#define TPM_CAP_PCRS (TPM_CAP)(0x00000005) +#define TPM_CAP_TPM_PROPERTIES (TPM_CAP)(0x00000006) +#define TPM_CAP_PCR_PROPERTIES (TPM_CAP)(0x00000007) +#define TPM_CAP_ECC_CURVES (TPM_CAP)(0x00000008) +#define TPM_CAP_AUTH_POLICIES (TPM_CAP)(0x00000009) +#define TPM_CAP_ACT (TPM_CAP)(0x0000000a) +#define TPM_CAP_LAST (TPM_CAP)(0x0000000a) +#define TPM_CAP_VENDOR_PROPERTY (TPM_CAP)(0x00000100) + +/* Table 2:23 - Definition of TPM_PT Constants */ +typedef UINT32 TPM_PT; +#define TYPE_OF_TPM_PT UINT32 +#define TPM_PT_NONE (TPM_PT)(0x00000000) +#define PT_GROUP (TPM_PT)(0x00000100) +#define PT_FIXED (TPM_PT)(PT_GROUP*1) +#define TPM_PT_FAMILY_INDICATOR (TPM_PT)(PT_FIXED+0) +#define TPM_PT_LEVEL (TPM_PT)(PT_FIXED+1) +#define TPM_PT_REVISION (TPM_PT)(PT_FIXED+2) +#define TPM_PT_DAY_OF_YEAR (TPM_PT)(PT_FIXED+3) +#define TPM_PT_YEAR (TPM_PT)(PT_FIXED+4) +#define TPM_PT_MANUFACTURER (TPM_PT)(PT_FIXED+5) +#define TPM_PT_VENDOR_STRING_1 (TPM_PT)(PT_FIXED+6) +#define TPM_PT_VENDOR_STRING_2 (TPM_PT)(PT_FIXED+7) +#define TPM_PT_VENDOR_STRING_3 (TPM_PT)(PT_FIXED+8) +#define TPM_PT_VENDOR_STRING_4 (TPM_PT)(PT_FIXED+9) +#define TPM_PT_VENDOR_TPM_TYPE (TPM_PT)(PT_FIXED+10) +#define TPM_PT_FIRMWARE_VERSION_1 (TPM_PT)(PT_FIXED+11) +#define TPM_PT_FIRMWARE_VERSION_2 (TPM_PT)(PT_FIXED+12) +#define TPM_PT_INPUT_BUFFER (TPM_PT)(PT_FIXED+13) +#define TPM_PT_HR_TRANSIENT_MIN (TPM_PT)(PT_FIXED+14) +#define TPM_PT_HR_PERSISTENT_MIN (TPM_PT)(PT_FIXED+15) +#define TPM_PT_HR_LOADED_MIN (TPM_PT)(PT_FIXED+16) +#define TPM_PT_ACTIVE_SESSIONS_MAX (TPM_PT)(PT_FIXED+17) +#define TPM_PT_PCR_COUNT (TPM_PT)(PT_FIXED+18) +#define TPM_PT_PCR_SELECT_MIN (TPM_PT)(PT_FIXED+19) +#define TPM_PT_CONTEXT_GAP_MAX (TPM_PT)(PT_FIXED+20) +#define TPM_PT_NV_COUNTERS_MAX (TPM_PT)(PT_FIXED+22) +#define TPM_PT_NV_INDEX_MAX (TPM_PT)(PT_FIXED+23) +#define TPM_PT_MEMORY (TPM_PT)(PT_FIXED+24) +#define TPM_PT_CLOCK_UPDATE (TPM_PT)(PT_FIXED+25) +#define TPM_PT_CONTEXT_HASH (TPM_PT)(PT_FIXED+26) +#define TPM_PT_CONTEXT_SYM (TPM_PT)(PT_FIXED+27) +#define TPM_PT_CONTEXT_SYM_SIZE (TPM_PT)(PT_FIXED+28) +#define TPM_PT_ORDERLY_COUNT (TPM_PT)(PT_FIXED+29) +#define TPM_PT_MAX_COMMAND_SIZE (TPM_PT)(PT_FIXED+30) +#define TPM_PT_MAX_RESPONSE_SIZE (TPM_PT)(PT_FIXED+31) +#define TPM_PT_MAX_DIGEST (TPM_PT)(PT_FIXED+32) +#define TPM_PT_MAX_OBJECT_CONTEXT (TPM_PT)(PT_FIXED+33) +#define TPM_PT_MAX_SESSION_CONTEXT (TPM_PT)(PT_FIXED+34) +#define TPM_PT_PS_FAMILY_INDICATOR (TPM_PT)(PT_FIXED+35) +#define TPM_PT_PS_LEVEL (TPM_PT)(PT_FIXED+36) +#define TPM_PT_PS_REVISION (TPM_PT)(PT_FIXED+37) +#define TPM_PT_PS_DAY_OF_YEAR (TPM_PT)(PT_FIXED+38) +#define TPM_PT_PS_YEAR (TPM_PT)(PT_FIXED+39) +#define TPM_PT_SPLIT_MAX (TPM_PT)(PT_FIXED+40) +#define TPM_PT_TOTAL_COMMANDS (TPM_PT)(PT_FIXED+41) +#define TPM_PT_LIBRARY_COMMANDS (TPM_PT)(PT_FIXED+42) +#define TPM_PT_VENDOR_COMMANDS (TPM_PT)(PT_FIXED+43) +#define TPM_PT_NV_BUFFER_MAX (TPM_PT)(PT_FIXED+44) +#define TPM_PT_MODES (TPM_PT)(PT_FIXED+45) +#define TPM_PT_MAX_CAP_BUFFER (TPM_PT)(PT_FIXED+46) +#define PT_VAR (TPM_PT)(PT_GROUP*2) +#define TPM_PT_PERMANENT (TPM_PT)(PT_VAR+0) +#define TPM_PT_STARTUP_CLEAR (TPM_PT)(PT_VAR+1) +#define TPM_PT_HR_NV_INDEX (TPM_PT)(PT_VAR+2) +#define TPM_PT_HR_LOADED (TPM_PT)(PT_VAR+3) +#define TPM_PT_HR_LOADED_AVAIL (TPM_PT)(PT_VAR+4) +#define TPM_PT_HR_ACTIVE (TPM_PT)(PT_VAR+5) +#define TPM_PT_HR_ACTIVE_AVAIL (TPM_PT)(PT_VAR+6) +#define TPM_PT_HR_TRANSIENT_AVAIL (TPM_PT)(PT_VAR+7) +#define TPM_PT_HR_PERSISTENT (TPM_PT)(PT_VAR+8) +#define TPM_PT_HR_PERSISTENT_AVAIL (TPM_PT)(PT_VAR+9) +#define TPM_PT_NV_COUNTERS (TPM_PT)(PT_VAR+10) +#define TPM_PT_NV_COUNTERS_AVAIL (TPM_PT)(PT_VAR+11) +#define TPM_PT_ALGORITHM_SET (TPM_PT)(PT_VAR+12) +#define TPM_PT_LOADED_CURVES (TPM_PT)(PT_VAR+13) +#define TPM_PT_LOCKOUT_COUNTER (TPM_PT)(PT_VAR+14) +#define TPM_PT_MAX_AUTH_FAIL (TPM_PT)(PT_VAR+15) +#define TPM_PT_LOCKOUT_INTERVAL (TPM_PT)(PT_VAR+16) +#define TPM_PT_LOCKOUT_RECOVERY (TPM_PT)(PT_VAR+17) +#define TPM_PT_NV_WRITE_RECOVERY (TPM_PT)(PT_VAR+18) +#define TPM_PT_AUDIT_COUNTER_0 (TPM_PT)(PT_VAR+19) +#define TPM_PT_AUDIT_COUNTER_1 (TPM_PT)(PT_VAR+20) + +/* Table 2:24 - Definition of TPM_PT_PCR Constants */ +typedef UINT32 TPM_PT_PCR; +#define TYPE_OF_TPM_PT_PCR UINT32 +#define TPM_PT_PCR_FIRST (TPM_PT_PCR)(0x00000000) +#define TPM_PT_PCR_SAVE (TPM_PT_PCR)(0x00000000) +#define TPM_PT_PCR_EXTEND_L0 (TPM_PT_PCR)(0x00000001) +#define TPM_PT_PCR_RESET_L0 (TPM_PT_PCR)(0x00000002) +#define TPM_PT_PCR_EXTEND_L1 (TPM_PT_PCR)(0x00000003) +#define TPM_PT_PCR_RESET_L1 (TPM_PT_PCR)(0x00000004) +#define TPM_PT_PCR_EXTEND_L2 (TPM_PT_PCR)(0x00000005) +#define TPM_PT_PCR_RESET_L2 (TPM_PT_PCR)(0x00000006) +#define TPM_PT_PCR_EXTEND_L3 (TPM_PT_PCR)(0x00000007) +#define TPM_PT_PCR_RESET_L3 (TPM_PT_PCR)(0x00000008) +#define TPM_PT_PCR_EXTEND_L4 (TPM_PT_PCR)(0x00000009) +#define TPM_PT_PCR_RESET_L4 (TPM_PT_PCR)(0x0000000A) +#define TPM_PT_PCR_NO_INCREMENT (TPM_PT_PCR)(0x00000011) +#define TPM_PT_PCR_DRTM_RESET (TPM_PT_PCR)(0x00000012) +#define TPM_PT_PCR_POLICY (TPM_PT_PCR)(0x00000013) +#define TPM_PT_PCR_AUTH (TPM_PT_PCR)(0x00000014) +#define TPM_PT_PCR_LAST (TPM_PT_PCR)(0x00000014) + +/* Table 2:25 - Definition of TPM_PS Constants */ +typedef UINT32 TPM_PS; +#define TYPE_OF_TPM_PS UINT32 +#define TPM_PS_MAIN (TPM_PS)(0x00000000) +#define TPM_PS_PC (TPM_PS)(0x00000001) +#define TPM_PS_PDA (TPM_PS)(0x00000002) +#define TPM_PS_CELL_PHONE (TPM_PS)(0x00000003) +#define TPM_PS_SERVER (TPM_PS)(0x00000004) +#define TPM_PS_PERIPHERAL (TPM_PS)(0x00000005) +#define TPM_PS_TSS (TPM_PS)(0x00000006) +#define TPM_PS_STORAGE (TPM_PS)(0x00000007) +#define TPM_PS_AUTHENTICATION (TPM_PS)(0x00000008) +#define TPM_PS_EMBEDDED (TPM_PS)(0x00000009) +#define TPM_PS_HARDCOPY (TPM_PS)(0x0000000A) +#define TPM_PS_INFRASTRUCTURE (TPM_PS)(0x0000000B) +#define TPM_PS_VIRTUALIZATION (TPM_PS)(0x0000000C) +#define TPM_PS_TNC (TPM_PS)(0x0000000D) +#define TPM_PS_MULTI_TENANT (TPM_PS)(0x0000000E) +#define TPM_PS_TC (TPM_PS)(0x0000000F) + +/* Table 2:26 - Definition of Types for Handles */ +typedef UINT32 TPM_HANDLE; +#define TYPE_OF_TPM_HANDLE UINT32 + +/* Table 2:27 - Definition of TPM_HT Constants */ +typedef UINT8 TPM_HT; +#define TYPE_OF_TPM_HT UINT8 +#define TPM_HT_PCR (TPM_HT)(0x00) +#define TPM_HT_NV_INDEX (TPM_HT)(0x01) +#define TPM_HT_HMAC_SESSION (TPM_HT)(0x02) +#define TPM_HT_LOADED_SESSION (TPM_HT)(0x02) +#define TPM_HT_POLICY_SESSION (TPM_HT)(0x03) +#define TPM_HT_SAVED_SESSION (TPM_HT)(0x03) +#define TPM_HT_PERMANENT (TPM_HT)(0x40) +#define TPM_HT_TRANSIENT (TPM_HT)(0x80) +#define TPM_HT_PERSISTENT (TPM_HT)(0x81) +#define TPM_HT_AC (TPM_HT)(0x90) + +/* Table 2:28 - Definition of TPM_RH Constants */ +typedef TPM_HANDLE TPM_RH; +#define TPM_RH_FIRST (TPM_RH)(0x40000000) +#define TPM_RH_SRK (TPM_RH)(0x40000000) +#define TPM_RH_OWNER (TPM_RH)(0x40000001) +#define TPM_RH_REVOKE (TPM_RH)(0x40000002) +#define TPM_RH_TRANSPORT (TPM_RH)(0x40000003) +#define TPM_RH_OPERATOR (TPM_RH)(0x40000004) +#define TPM_RH_ADMIN (TPM_RH)(0x40000005) +#define TPM_RH_EK (TPM_RH)(0x40000006) +#define TPM_RH_NULL (TPM_RH)(0x40000007) +#define TPM_RH_UNASSIGNED (TPM_RH)(0x40000008) +#define TPM_RS_PW (TPM_RH)(0x40000009) +#define TPM_RH_LOCKOUT (TPM_RH)(0x4000000A) +#define TPM_RH_ENDORSEMENT (TPM_RH)(0x4000000B) +#define TPM_RH_PLATFORM (TPM_RH)(0x4000000C) +#define TPM_RH_PLATFORM_NV (TPM_RH)(0x4000000D) +#define TPM_RH_AUTH_00 (TPM_RH)(0x40000010) +#define TPM_RH_AUTH_FF (TPM_RH)(0x4000010F) +#define TPM_RH_ACT_0 (TPM_RH)(0x40000110) +#define TPM_RH_ACT_F (TPM_RH)(0x4000011F) +#define TPM_RH_LAST (TPM_RH)(0x4000011F) +/* Table 2:29 - Definition of TPM_HC Constants */ +typedef TPM_HANDLE TPM_HC; +#define HR_HANDLE_MASK (TPM_HC)(0x00FFFFFF) +#define HR_RANGE_MASK (TPM_HC)(0xFF000000) +#define HR_SHIFT (TPM_HC)(24) +#define HR_PCR (TPM_HC)((TPM_HT_PCR< */ +typedef struct { + TPM_HANDLE handle; + UINT32 timeout; + TPMA_ACT attributes; +} TPMS_ACT_DATA; +/* Table 2:97 - Definition of TPML_CC Structure */ +typedef struct { + UINT32 count; + TPM_CC commandCodes[MAX_CAP_CC]; +} TPML_CC; +/* Table 2:98 - Definition of TPML_CCA Structure */ +typedef struct { + UINT32 count; + TPMA_CC commandAttributes[MAX_CAP_CC]; +} TPML_CCA; +/* Table 2:99 - Definition of TPML_ALG Structure */ +typedef struct { + UINT32 count; + TPM_ALG_ID algorithms[MAX_ALG_LIST_SIZE]; +} TPML_ALG; +/* Table 2:100 - Definition of TPML_HANDLE Structure */ +typedef struct { + UINT32 count; + TPM_HANDLE handle[MAX_CAP_HANDLES]; +} TPML_HANDLE; +/* Table 2:101 - Definition of TPML_DIGEST Structure */ +typedef struct { + UINT32 count; + TPM2B_DIGEST digests[8]; +} TPML_DIGEST; +/* Table 2:102 - Definition of TPML_DIGEST_VALUES Structure */ +typedef struct { + UINT32 count; + TPMT_HA digests[HASH_COUNT]; +} TPML_DIGEST_VALUES; +/* Table 2:104 - Definition of TPML_PCR_SELECTION Structure */ +typedef struct { + UINT32 count; + TPMS_PCR_SELECTION pcrSelections[HASH_COUNT]; +} TPML_PCR_SELECTION; +/* Table 2:105 - Definition of TPML_ALG_PROPERTY Structure */ +typedef struct { + UINT32 count; + TPMS_ALG_PROPERTY algProperties[MAX_CAP_ALGS]; +} TPML_ALG_PROPERTY; +/* Table 2:106 - Definition of TPML_TAGGED_TPM_PROPERTY Structure */ +typedef struct { + UINT32 count; + TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES]; +} TPML_TAGGED_TPM_PROPERTY; +/* Table 2:107 - Definition of TPML_TAGGED_PCR_PROPERTY Structure */ +typedef struct { + UINT32 count; + TPMS_TAGGED_PCR_SELECT pcrProperty[MAX_PCR_PROPERTIES]; +} TPML_TAGGED_PCR_PROPERTY; +/* Table 2:108 - Definition of TPML_ECC_CURVE Structure */ +typedef struct { + UINT32 count; + TPM_ECC_CURVE eccCurves[MAX_ECC_CURVES]; +} TPML_ECC_CURVE; +/* Table 2:109 - Definition of TPML_TAGGED_POLICY Structure */ +typedef struct { + UINT32 count; + TPMS_TAGGED_POLICY policies[MAX_TAGGED_POLICIES]; +} TPML_TAGGED_POLICY; +/* Table 2:118 - Definition of TPML_ACT_DATA Structure */ +typedef struct { + UINT32 count; + TPMS_ACT_DATA actData[MAX_ACT_DATA]; +} TPML_ACT_DATA; +/* Table 2:110 - Definition of TPMU_CAPABILITIES Union */ +typedef union { + TPML_ALG_PROPERTY algorithms; + TPML_HANDLE handles; + TPML_CCA command; + TPML_CC ppCommands; + TPML_CC auditCommands; + TPML_PCR_SELECTION assignedPCR; + TPML_TAGGED_TPM_PROPERTY tpmProperties; + TPML_TAGGED_PCR_PROPERTY pcrProperties; +#if ALG_ECC + TPML_ECC_CURVE eccCurves; +#endif // ALG_ECC + TPML_TAGGED_POLICY authPolicies; + TPML_ACT_DATA actData; +} TPMU_CAPABILITIES; +/* Table 2:111 - Definition of TPMS_CAPABILITY_DATA Structure */ +typedef struct { + TPM_CAP capability; + TPMU_CAPABILITIES data; +} TPMS_CAPABILITY_DATA; +/* Table 2:112 - Definition of TPMS_CLOCK_INFO Structure */ +typedef struct { + UINT64 clock; + UINT32 resetCount; + UINT32 restartCount; + TPMI_YES_NO safe; +} TPMS_CLOCK_INFO; +/* Table 2:113 - Definition of TPMS_TIME_INFO Structure */ +typedef struct { + UINT64 time; + TPMS_CLOCK_INFO clockInfo; +} TPMS_TIME_INFO; +/* Table 2:114 - Definition of TPMS_TIME_ATTEST_INFO Structure */ +typedef struct { + TPMS_TIME_INFO time; + UINT64 firmwareVersion; +} TPMS_TIME_ATTEST_INFO; +/* Table 2:115 - Definition of TPMS_CERTIFY_INFO Structure */ +typedef struct { + TPM2B_NAME name; + TPM2B_NAME qualifiedName; +} TPMS_CERTIFY_INFO; +/* Table 2:116 - Definition of TPMS_QUOTE_INFO Structure */ +typedef struct { + TPML_PCR_SELECTION pcrSelect; + TPM2B_DIGEST pcrDigest; +} TPMS_QUOTE_INFO; +/* Table 2:117 - Definition of TPMS_COMMAND_AUDIT_INFO Structure */ +typedef struct { + UINT64 auditCounter; + TPM_ALG_ID digestAlg; + TPM2B_DIGEST auditDigest; + TPM2B_DIGEST commandDigest; +} TPMS_COMMAND_AUDIT_INFO; +/* Table 2:118 - Definition of TPMS_SESSION_AUDIT_INFO Structure */ +typedef struct { + TPMI_YES_NO exclusiveSession; + TPM2B_DIGEST sessionDigest; +} TPMS_SESSION_AUDIT_INFO; +/* Table 2:119 - Definition of TPMS_CREATION_INFO Structure */ +typedef struct { + TPM2B_NAME objectName; + TPM2B_DIGEST creationHash; +} TPMS_CREATION_INFO; +/* Table 2:120 - Definition of TPMS_NV_CERTIFY_INFO Structure */ +typedef struct { + TPM2B_NAME indexName; + UINT16 offset; + TPM2B_MAX_NV_BUFFER nvContents; +} TPMS_NV_CERTIFY_INFO; +/* Table 125 - Definition of TPMS_NV_DIGEST_CERTIFY_INFO Structure */ +typedef struct { + TPM2B_NAME indexName; + TPM2B_DIGEST nvDigest; +} TPMS_NV_DIGEST_CERTIFY_INFO; +/* Table 2:121 - Definition of TPMI_ST_ATTEST Type */ +typedef TPM_ST TPMI_ST_ATTEST; +/* Table 2:122 - Definition of TPMU_ATTEST Union */ +typedef union { + TPMS_CERTIFY_INFO certify; + TPMS_CREATION_INFO creation; + TPMS_QUOTE_INFO quote; + TPMS_COMMAND_AUDIT_INFO commandAudit; + TPMS_SESSION_AUDIT_INFO sessionAudit; + TPMS_TIME_ATTEST_INFO time; + TPMS_NV_CERTIFY_INFO nv; + TPMS_NV_DIGEST_CERTIFY_INFO nvDigest; +} TPMU_ATTEST; +/* Table 2:123 - Definition of TPMS_ATTEST Structure */ +typedef struct { + TPM_CONSTANTS32 magic; + TPMI_ST_ATTEST type; + TPM2B_NAME qualifiedSigner; + TPM2B_DATA extraData; + TPMS_CLOCK_INFO clockInfo; + UINT64 firmwareVersion; + TPMU_ATTEST attested; +} TPMS_ATTEST; +/* Table 2:124 - Definition of TPM2B_ATTEST Structure */ +typedef union { + struct { + UINT16 size; + BYTE attestationData[sizeof(TPMS_ATTEST)]; + } t; + TPM2B b; +} TPM2B_ATTEST; +/* Table 2:125 - Definition of TPMS_AUTH_COMMAND Structure */ +typedef struct { + TPMI_SH_AUTH_SESSION sessionHandle; + TPM2B_NONCE nonce; + TPMA_SESSION sessionAttributes; + TPM2B_AUTH hmac; +} TPMS_AUTH_COMMAND; +/* Table 2:126 - Definition of TPMS_AUTH_RESPONSE Structure */ +typedef struct { + TPM2B_NONCE nonce; + TPMA_SESSION sessionAttributes; + TPM2B_AUTH hmac; +} TPMS_AUTH_RESPONSE; +/* Table 2:127 - Definition of TPMI_TDES_KEY_BITS Type */ +typedef TPM_KEY_BITS TPMI_TDES_KEY_BITS; +/* Table 2:127 - Definition of TPMI_AES_KEY_BITS Type */ +typedef TPM_KEY_BITS TPMI_AES_KEY_BITS; +/* Table 2:127 - Definition of TPMI_SM4_KEY_BITS Type */ +typedef TPM_KEY_BITS TPMI_SM4_KEY_BITS; +/* Table 2:127 - Definition of TPMI_CAMELLIA_KEY_BITS Type */ +typedef TPM_KEY_BITS TPMI_CAMELLIA_KEY_BITS; +/* Table 2:128 - Definition of TPMU_SYM_KEY_BITS Union */ +typedef union { +#if ALG_TDES + TPMI_TDES_KEY_BITS tdes; +#endif // ALG_TDES +#if ALG_AES + TPMI_AES_KEY_BITS aes; +#endif // ALG_AES +#if ALG_SM4 + TPMI_SM4_KEY_BITS sm4; +#endif // ALG_SM4 +#if ALG_CAMELLIA + TPMI_CAMELLIA_KEY_BITS camellia; +#endif // ALG_CAMELLIA + TPM_KEY_BITS sym; +#if ALG_XOR + TPMI_ALG_HASH xorr; +#endif // ALG_XOR +} TPMU_SYM_KEY_BITS; +/* Table 2:129 - Definition of TPMU_SYM_MODE Union */ +typedef union { +#if ALG_TDES + TPMI_ALG_SYM_MODE tdes; +#endif // ALG_TDES +#if ALG_AES + TPMI_ALG_SYM_MODE aes; +#endif // ALG_AES +#if ALG_SM4 + TPMI_ALG_SYM_MODE sm4; +#endif // ALG_SM4 +#if ALG_CAMELLIA + TPMI_ALG_SYM_MODE camellia; +#endif // ALG_CAMELLIA + TPMI_ALG_SYM_MODE sym; +} TPMU_SYM_MODE; +/* Table 2:131 - Definition of TPMT_SYM_DEF Structure */ +typedef struct { + TPMI_ALG_SYM algorithm; + TPMU_SYM_KEY_BITS keyBits; + TPMU_SYM_MODE mode; +} TPMT_SYM_DEF; +/* Table 2:132 - Definition of TPMT_SYM_DEF_OBJECT Structure */ +typedef struct { + TPMI_ALG_SYM_OBJECT algorithm; + TPMU_SYM_KEY_BITS keyBits; + TPMU_SYM_MODE mode; +} TPMT_SYM_DEF_OBJECT; +/* Table 2:133 - Definition of TPM2B_SYM_KEY Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[MAX_SYM_KEY_BYTES]; + } t; + TPM2B b; +} TPM2B_SYM_KEY; +/* Table 2:134 - Definition of TPMS_SYMCIPHER_PARMS Structure */ +typedef struct { + TPMT_SYM_DEF_OBJECT sym; +} TPMS_SYMCIPHER_PARMS; +/* Table 2:135 - Definition of TPM2B_LABEL Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[LABEL_MAX_BUFFER]; + } t; + TPM2B b; +} TPM2B_LABEL; +/* Table 2:136 - Definition of TPMS_DERIVE Structure */ +typedef struct { + TPM2B_LABEL label; + TPM2B_LABEL context; +} TPMS_DERIVE; +/* Table 2:137 - Definition of TPM2B_DERIVE Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[sizeof(TPMS_DERIVE)]; + } t; + TPM2B b; +} TPM2B_DERIVE; +/* Table 2:138 - Definition of TPMU_SENSITIVE_CREATE Union */ +typedef union { + BYTE create[MAX_SYM_DATA]; + TPMS_DERIVE derive; +} TPMU_SENSITIVE_CREATE; +/* Table 2:139 - Definition of TPM2B_SENSITIVE_DATA Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[sizeof(TPMU_SENSITIVE_CREATE)]; + } t; + TPM2B b; +} TPM2B_SENSITIVE_DATA; +/* Table 2:140 - Definition of TPMS_SENSITIVE_CREATE Structure */ +typedef struct { + TPM2B_AUTH userAuth; + TPM2B_SENSITIVE_DATA data; +} TPMS_SENSITIVE_CREATE; +/* Table 2:141 - Definition of TPM2B_SENSITIVE_CREATE Structure */ +typedef struct { + UINT16 size; + TPMS_SENSITIVE_CREATE sensitive; +} TPM2B_SENSITIVE_CREATE; +/* Table 2:142 - Definition of TPMS_SCHEME_HASH Structure */ +typedef struct { + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_HASH; +/* Table 2:143 - Definition of TPMS_SCHEME_ECDAA Structure */ +typedef struct { + TPMI_ALG_HASH hashAlg; + UINT16 count; +} TPMS_SCHEME_ECDAA; +/* Table 2:144 - Definition of TPMI_ALG_KEYEDHASH_SCHEME Type */ +typedef TPM_ALG_ID TPMI_ALG_KEYEDHASH_SCHEME; +/* Table 2:145 - Definition of Types for HMAC_SIG_SCHEME */ +typedef TPMS_SCHEME_HASH TPMS_SCHEME_HMAC; +/* Table 2:146 - Definition of TPMS_SCHEME_XOR Structure */ +typedef struct { + TPMI_ALG_HASH hashAlg; + TPMI_ALG_KDF kdf; +} TPMS_SCHEME_XOR; +/* Table 2:147 - Definition of TPMU_SCHEME_KEYEDHASH Union */ +typedef union { +#if ALG_HMAC + TPMS_SCHEME_HMAC hmac; +#endif // ALG_HMAC +#if ALG_XOR + TPMS_SCHEME_XOR xorr; +#endif // ALG_XOR +} TPMU_SCHEME_KEYEDHASH; +/* Table 2:148 - Definition of TPMT_KEYEDHASH_SCHEME Structure */ +typedef struct { + TPMI_ALG_KEYEDHASH_SCHEME scheme; + TPMU_SCHEME_KEYEDHASH details; +} TPMT_KEYEDHASH_SCHEME; +/* Table 2:149 - Definition of Types for RSA Signature Schemes */ +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_RSASSA; +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_RSAPSS; +/* Table 2:150 - Definition of Types for ECC Signature Schemes */ +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_ECDSA; +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_SM2; +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_ECSCHNORR; +typedef TPMS_SCHEME_ECDAA TPMS_SIG_SCHEME_ECDAA; +/* Table 2:151 - Definition of TPMU_SIG_SCHEME Union */ +typedef union { +#if ALG_ECC + TPMS_SIG_SCHEME_ECDAA ecdaa; +#endif // ALG_ECC +#if ALG_RSASSA + TPMS_SIG_SCHEME_RSASSA rsassa; +#endif // ALG_RSASSA +#if ALG_RSAPSS + TPMS_SIG_SCHEME_RSAPSS rsapss; +#endif // ALG_RSAPSS +#if ALG_ECDSA + TPMS_SIG_SCHEME_ECDSA ecdsa; +#endif // ALG_ECDSA +#if ALG_SM2 + TPMS_SIG_SCHEME_SM2 sm2; +#endif // ALG_SM2 +#if ALG_ECSCHNORR + TPMS_SIG_SCHEME_ECSCHNORR ecschnorr; +#endif // ALG_ECSCHNORR +#if ALG_HMAC + TPMS_SCHEME_HMAC hmac; +#endif // ALG_HMAC + TPMS_SCHEME_HASH any; +} TPMU_SIG_SCHEME; +/* Table 2:152 - Definition of TPMT_SIG_SCHEME Structure */ +typedef struct { + TPMI_ALG_SIG_SCHEME scheme; + TPMU_SIG_SCHEME details; +} TPMT_SIG_SCHEME; +/* Table 2:153 - Definition of Types for Encryption Schemes */ +typedef TPMS_SCHEME_HASH TPMS_ENC_SCHEME_OAEP; +typedef TPMS_EMPTY TPMS_ENC_SCHEME_RSAES; +/* Table 2:154 - Definition of Types for ECC Key Exchange */ +typedef TPMS_SCHEME_HASH TPMS_KEY_SCHEME_ECDH; +typedef TPMS_SCHEME_HASH TPMS_KEY_SCHEME_ECMQV; +/* Table 2:155 - Definition of Types for KDF Schemes */ +typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_MGF1; +typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF1_SP800_56A; +typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF2; +typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF1_SP800_108; +/* Table 2:156 - Definition of TPMU_KDF_SCHEME Union */ +typedef union { +#if ALG_MGF1 + TPMS_KDF_SCHEME_MGF1 mgf1; +#endif // ALG_MGF1 +#if ALG_KDF1_SP800_56A + TPMS_KDF_SCHEME_KDF1_SP800_56A kdf1_sp800_56a; +#endif // ALG_KDF1_SP800_56A +#if ALG_KDF2 + TPMS_KDF_SCHEME_KDF2 kdf2; +#endif // ALG_KDF2 +#if ALG_KDF1_SP800_108 + TPMS_KDF_SCHEME_KDF1_SP800_108 kdf1_sp800_108; +#endif // ALG_KDF1_SP800_108 + TPMS_SCHEME_HASH anyKdf; +} TPMU_KDF_SCHEME; +/* Table 2:157 - Definition of TPMT_KDF_SCHEME Structure */ +typedef struct { + TPMI_ALG_KDF scheme; + TPMU_KDF_SCHEME details; +} TPMT_KDF_SCHEME; +/* Table 2:158 - Definition of TPMI_ALG_ASYM_SCHEME Type */ +typedef TPM_ALG_ID TPMI_ALG_ASYM_SCHEME; +/* Table 2:159 - Definition of TPMU_ASYM_SCHEME Union */ +typedef union { +#if ALG_ECDH + TPMS_KEY_SCHEME_ECDH ecdh; +#endif // ALG_ECDH +#if ALG_ECMQV + TPMS_KEY_SCHEME_ECMQV ecmqv; +#endif // ALG_ECMQV +#if ALG_ECC + TPMS_SIG_SCHEME_ECDAA ecdaa; +#endif // ALG_ECC +#if ALG_RSASSA + TPMS_SIG_SCHEME_RSASSA rsassa; +#endif // ALG_RSASSA +#if ALG_RSAPSS + TPMS_SIG_SCHEME_RSAPSS rsapss; +#endif // ALG_RSAPSS +#if ALG_ECDSA + TPMS_SIG_SCHEME_ECDSA ecdsa; +#endif // ALG_ECDSA +#if ALG_SM2 + TPMS_SIG_SCHEME_SM2 sm2; +#endif // ALG_SM2 +#if ALG_ECSCHNORR + TPMS_SIG_SCHEME_ECSCHNORR ecschnorr; +#endif // ALG_ECSCHNORR +#if ALG_RSAES + TPMS_ENC_SCHEME_RSAES rsaes; +#endif // ALG_RSAES +#if ALG_OAEP + TPMS_ENC_SCHEME_OAEP oaep; +#endif // ALG_OAEP + TPMS_SCHEME_HASH anySig; +} TPMU_ASYM_SCHEME; +/* Table 2:160 - Definition of TPMT_ASYM_SCHEME Structure */ +typedef struct { + TPMI_ALG_ASYM_SCHEME scheme; + TPMU_ASYM_SCHEME details; +} TPMT_ASYM_SCHEME; +/* Table 2:161 - Definition of TPMI_ALG_RSA_SCHEME Type */ +typedef TPM_ALG_ID TPMI_ALG_RSA_SCHEME; +/* Table 2:162 - Definition of TPMT_RSA_SCHEME Structure */ +typedef struct { + TPMI_ALG_RSA_SCHEME scheme; + TPMU_ASYM_SCHEME details; +} TPMT_RSA_SCHEME; +/* Table 2:163 - Definition of TPMI_ALG_RSA_DECRYPT Type */ +typedef TPM_ALG_ID TPMI_ALG_RSA_DECRYPT; +/* Table 2:164 - Definition of TPMT_RSA_DECRYPT Structure */ +typedef struct { + TPMI_ALG_RSA_DECRYPT scheme; + TPMU_ASYM_SCHEME details; +} TPMT_RSA_DECRYPT; +/* Table 2:165 - Definition of TPM2B_PUBLIC_KEY_RSA Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[MAX_RSA_KEY_BYTES]; + } t; + TPM2B b; +} TPM2B_PUBLIC_KEY_RSA; +/* Table 2:166 - Definition of TPMI_RSA_KEY_BITS Type */ +typedef TPM_KEY_BITS TPMI_RSA_KEY_BITS; +/* Table 2:167 - Definition of TPM2B_PRIVATE_KEY_RSA Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[RSA_PRIVATE_SIZE]; + } t; + TPM2B b; +} TPM2B_PRIVATE_KEY_RSA; +/* Table 2:168 - Definition of TPM2B_ECC_PARAMETER Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[MAX_ECC_KEY_BYTES]; + } t; + TPM2B b; +} TPM2B_ECC_PARAMETER; +/* Table 2:169 - Definition of TPMS_ECC_POINT Structure */ +typedef struct { + TPM2B_ECC_PARAMETER x; + TPM2B_ECC_PARAMETER y; +} TPMS_ECC_POINT; +/* Table 2:170 - Definition of TPM2B_ECC_POINT Structure */ +typedef struct { + UINT16 size; + TPMS_ECC_POINT point; +} TPM2B_ECC_POINT; +/* Table 2:171 - Definition of TPMI_ALG_ECC_SCHEME Type */ +typedef TPM_ALG_ID TPMI_ALG_ECC_SCHEME; +/* Table 2:172 - Definition of TPMI_ECC_CURVE Type */ +typedef TPM_ECC_CURVE TPMI_ECC_CURVE; +/* Table 2:173 - Definition of TPMT_ECC_SCHEME Structure */ +typedef struct { + TPMI_ALG_ECC_SCHEME scheme; + TPMU_ASYM_SCHEME details; +} TPMT_ECC_SCHEME; +/* Table 2:174 - Definition of TPMS_ALGORITHM_DETAIL_ECC Structure */ +typedef struct { + TPM_ECC_CURVE curveID; + UINT16 keySize; + TPMT_KDF_SCHEME kdf; + TPMT_ECC_SCHEME sign; + TPM2B_ECC_PARAMETER p; + TPM2B_ECC_PARAMETER a; + TPM2B_ECC_PARAMETER b; + TPM2B_ECC_PARAMETER gX; + TPM2B_ECC_PARAMETER gY; + TPM2B_ECC_PARAMETER n; + TPM2B_ECC_PARAMETER h; +} TPMS_ALGORITHM_DETAIL_ECC; +/* Table 2:175 - Definition of TPMS_SIGNATURE_RSA Structure */ +typedef struct { + TPMI_ALG_HASH hash; + TPM2B_PUBLIC_KEY_RSA sig; +} TPMS_SIGNATURE_RSA; +/* Table 2:176 - Definition of Types for Signature */ +typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSASSA; +typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSAPSS; +/* Table 2:177 - Definition of TPMS_SIGNATURE_ECC Structure */ +typedef struct { + TPMI_ALG_HASH hash; + TPM2B_ECC_PARAMETER signatureR; + TPM2B_ECC_PARAMETER signatureS; +} TPMS_SIGNATURE_ECC; +/* Table 2:178 - Definition of Types for TPMS_SIGNATURE_ECC */ +typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDAA; +typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDSA; +typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_SM2; +typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECSCHNORR; +/* Table 2:179 - Definition of TPMU_SIGNATURE Union */ +typedef union { +#if ALG_ECC + TPMS_SIGNATURE_ECDAA ecdaa; +#endif // ALG_ECC +#if ALG_RSA + TPMS_SIGNATURE_RSASSA rsassa; +#endif // ALG_RSA +#if ALG_RSA + TPMS_SIGNATURE_RSAPSS rsapss; +#endif // ALG_RSA +#if ALG_ECC + TPMS_SIGNATURE_ECDSA ecdsa; +#endif // ALG_ECC +#if ALG_ECC + TPMS_SIGNATURE_SM2 sm2; +#endif // ALG_ECC +#if ALG_ECC + TPMS_SIGNATURE_ECSCHNORR ecschnorr; +#endif // ALG_ECC +#if ALG_HMAC + TPMT_HA hmac; +#endif // ALG_HMAC + TPMS_SCHEME_HASH any; +} TPMU_SIGNATURE; +/* Table 2:180 - Definition of TPMT_SIGNATURE Structure */ +typedef struct { + TPMI_ALG_SIG_SCHEME sigAlg; + TPMU_SIGNATURE signature; +} TPMT_SIGNATURE; +/* Table 2:181 - Definition of TPMU_ENCRYPTED_SECRET Union */ +typedef union { +#if ALG_ECC + BYTE ecc[sizeof(TPMS_ECC_POINT)]; +#endif // ALG_ECC +#if ALG_RSA + BYTE rsa[MAX_RSA_KEY_BYTES]; +#endif // ALG_RSA +#if ALG_SYMCIPHER + BYTE symmetric[sizeof(TPM2B_DIGEST)]; +#endif // ALG_SYMCIPHER +#if ALG_KEYEDHASH + BYTE keyedHash[sizeof(TPM2B_DIGEST)]; +#endif // ALG_KEYEDHASH +} TPMU_ENCRYPTED_SECRET; +/* Table 2:182 - Definition of TPM2B_ENCRYPTED_SECRET Structure */ +typedef union { + struct { + UINT16 size; + BYTE secret[sizeof(TPMU_ENCRYPTED_SECRET)]; + } t; + TPM2B b; +} TPM2B_ENCRYPTED_SECRET; +/* Table 2:183 - Definition of TPMI_ALG_PUBLIC Type */ +typedef TPM_ALG_ID TPMI_ALG_PUBLIC; +/* Table 2:184 - Definition of TPMU_PUBLIC_ID Union */ +typedef union { +#if ALG_KEYEDHASH + TPM2B_DIGEST keyedHash; +#endif // ALG_KEYEDHASH +#if ALG_SYMCIPHER + TPM2B_DIGEST sym; +#endif // ALG_SYMCIPHER +#if ALG_RSA + TPM2B_PUBLIC_KEY_RSA rsa; +#endif // ALG_RSA +#if ALG_ECC + TPMS_ECC_POINT ecc; +#endif // ALG_ECC + TPMS_DERIVE derive; +} TPMU_PUBLIC_ID; +/* Table 2:185 - Definition of TPMS_KEYEDHASH_PARMS Structure */ +typedef struct { + TPMT_KEYEDHASH_SCHEME scheme; +} TPMS_KEYEDHASH_PARMS; +/* Table 2:186 - Definition of TPMS_ASYM_PARMS Structure */ +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_ASYM_SCHEME scheme; +} TPMS_ASYM_PARMS; +/* Table 2:187 - Definition of TPMS_RSA_PARMS Structure */ +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_RSA_SCHEME scheme; + TPMI_RSA_KEY_BITS keyBits; + UINT32 exponent; +} TPMS_RSA_PARMS; +/* Table 2:188 - Definition of TPMS_ECC_PARMS Structure */ +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_ECC_SCHEME scheme; + TPMI_ECC_CURVE curveID; + TPMT_KDF_SCHEME kdf; +} TPMS_ECC_PARMS; +/* Table 2:189 - Definition of TPMU_PUBLIC_PARMS Union */ +typedef union { +#if ALG_KEYEDHASH + TPMS_KEYEDHASH_PARMS keyedHashDetail; +#endif // ALG_KEYEDHASH +#if ALG_SYMCIPHER + TPMS_SYMCIPHER_PARMS symDetail; +#endif // ALG_SYMCIPHER +#if ALG_RSA + TPMS_RSA_PARMS rsaDetail; +#endif // ALG_RSA +#if ALG_ECC + TPMS_ECC_PARMS eccDetail; +#endif // ALG_ECC + TPMS_ASYM_PARMS asymDetail; +} TPMU_PUBLIC_PARMS; +/* Table 2:190 - Definition of TPMT_PUBLIC_PARMS Structure */ +typedef struct { + TPMI_ALG_PUBLIC type; + TPMU_PUBLIC_PARMS parameters; +} TPMT_PUBLIC_PARMS; +/* Table 2:191 - Definition of TPMT_PUBLIC Structure */ +typedef struct { + TPMI_ALG_PUBLIC type; + TPMI_ALG_HASH nameAlg; + TPMA_OBJECT objectAttributes; + TPM2B_DIGEST authPolicy; + TPMU_PUBLIC_PARMS parameters; + TPMU_PUBLIC_ID unique; +} TPMT_PUBLIC; +/* Table 2:192 - Definition of TPM2B_PUBLIC Structure */ +typedef struct { + UINT16 size; + TPMT_PUBLIC publicArea; +} TPM2B_PUBLIC; +/* Table 2:193 - Definition of TPM2B_TEMPLATE Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[sizeof(TPMT_PUBLIC)]; + } t; + TPM2B b; +} TPM2B_TEMPLATE; +/* Table 2:194 - Definition of TPM2B_PRIVATE_VENDOR_SPECIFIC Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[PRIVATE_VENDOR_SPECIFIC_BYTES]; + } t; + TPM2B b; +} TPM2B_PRIVATE_VENDOR_SPECIFIC; +/* Table 2:195 - Definition of TPMU_SENSITIVE_COMPOSITE Union */ +typedef union { +#if ALG_RSA + TPM2B_PRIVATE_KEY_RSA rsa; +#endif // ALG_RSA +#if ALG_ECC + TPM2B_ECC_PARAMETER ecc; +#endif // ALG_ECC +#if ALG_KEYEDHASH + TPM2B_SENSITIVE_DATA bits; +#endif // ALG_KEYEDHASH +#if ALG_SYMCIPHER + TPM2B_SYM_KEY sym; +#endif // ALG_SYMCIPHER + TPM2B_PRIVATE_VENDOR_SPECIFIC any; +} TPMU_SENSITIVE_COMPOSITE; +/* Table 2:196 - Definition of TPMT_SENSITIVE Structure */ +typedef struct { + TPMI_ALG_PUBLIC sensitiveType; + TPM2B_AUTH authValue; + TPM2B_DIGEST seedValue; + TPMU_SENSITIVE_COMPOSITE sensitive; +} TPMT_SENSITIVE; +/* Table 2:197 - Definition of TPM2B_SENSITIVE Structure */ +typedef struct { + UINT16 size; + TPMT_SENSITIVE sensitiveArea; +} TPM2B_SENSITIVE; +/* Table 2:198 - Definition of _PRIVATE Structure */ +typedef struct { + TPM2B_DIGEST integrityOuter; + TPM2B_DIGEST integrityInner; + TPM2B_SENSITIVE sensitive; +} _PRIVATE; +/* Table 2:199 - Definition of TPM2B_PRIVATE Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[sizeof(_PRIVATE)]; + } t; + TPM2B b; +} TPM2B_PRIVATE; +/* Table 2:203 - Definition of TPMS_ID_OBJECT Structure */ +typedef struct { + TPM2B_DIGEST integrityHMAC; + TPM2B_DIGEST encIdentity; +} TPMS_ID_OBJECT; +/* Table 204 - Definition of TPM2B_ID_OBJECT Structure */ +typedef union { + struct { + UINT16 size; + BYTE credential[sizeof(TPMS_ID_OBJECT)]; + } t; + TPM2B b; +} TPM2B_ID_OBJECT; + +#define TYPE_OF_TPM_NV_INDEX UINT32 +#define TPM_NV_INDEX_TO_UINT32(a) (*((UINT32 *)&(a))) +#define UINT32_TO_TPM_NV_INDEX(a) (*((TPM_NV_INDEX *)&(a))) +#define TPM_NV_INDEX_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPM_NV_INDEX_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPM_NV_INDEX(i, a) \ + { UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPM_NV_INDEX(x); } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPM_NV_INDEX { // Table 2:205 + unsigned index : 24; + unsigned RH_NV : 8; +} TPM_NV_INDEX; +// This is the initializer for a TPM_NV_INDEX structure +#define TPM_NV_INDEX_INITIALIZER(index, rh_nv) {index, rh_nv} +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:205 TPM_NV_INDEX using bit masking +typedef UINT32 TPM_NV_INDEX; +#define TPM_NV_INDEX_index_SHIFT 0 +#define TPM_NV_INDEX_index ((TPM_NV_INDEX)0xffffff << 0) +#define TPM_NV_INDEX_RH_NV_SHIFT 24 +#define TPM_NV_INDEX_RH_NV ((TPM_NV_INDEX)0xff << 24) +// This is the initializer for a TPM_NV_INDEX bit array. +#define TPM_NV_INDEX_INITIALIZER(index, rh_nv) \ + (TPM_NV_INDEX)( \ + (index << 0) + (rh_nv << 24)) +#endif // USE_BIT_FIELD_STRUCTURES + +// Table 2:206 - Definition of TPM_NT Constants +typedef UINT32 TPM_NT; +#define TYPE_OF_TPM_NT UINT32 +#define TPM_NT_ORDINARY (TPM_NT)(0x0) +#define TPM_NT_COUNTER (TPM_NT)(0x1) +#define TPM_NT_BITS (TPM_NT)(0x2) +#define TPM_NT_EXTEND (TPM_NT)(0x4) +#define TPM_NT_PIN_FAIL (TPM_NT)(0x8) +#define TPM_NT_PIN_PASS (TPM_NT)(0x9) +// Table 2:207 +typedef struct { + UINT32 pinCount; + UINT32 pinLimit; +} TPMS_NV_PIN_COUNTER_PARAMETERS; + +#define TYPE_OF_TPMA_NV UINT32 +#define TPMA_NV_TO_UINT32(a) (*((UINT32 *)&(a))) +#define UINT32_TO_TPMA_NV(a) (*((TPMA_NV *)&(a))) +#define TPMA_NV_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_NV_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_NV(i, a) \ + { UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPMA_NV(x); } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_NV { // Table 2:208 + unsigned PPWRITE : 1; + unsigned OWNERWRITE : 1; + unsigned AUTHWRITE : 1; + unsigned POLICYWRITE : 1; + unsigned TPM_NT : 4; + unsigned Reserved_bits_at_8 : 2; + unsigned POLICY_DELETE : 1; + unsigned WRITELOCKED : 1; + unsigned WRITEALL : 1; + unsigned WRITEDEFINE : 1; + unsigned WRITE_STCLEAR : 1; + unsigned GLOBALLOCK : 1; + unsigned PPREAD : 1; + unsigned OWNERREAD : 1; + unsigned AUTHREAD : 1; + unsigned POLICYREAD : 1; + unsigned Reserved_bits_at_20 : 5; + unsigned NO_DA : 1; + unsigned ORDERLY : 1; + unsigned CLEAR_STCLEAR : 1; + unsigned READLOCKED : 1; + unsigned WRITTEN : 1; + unsigned PLATFORMCREATE : 1; + unsigned READ_STCLEAR : 1; +} TPMA_NV; +// This is the initializer for a TPMA_NV structure +#define TPMA_NV_INITIALIZER( \ + ppwrite, ownerwrite, authwrite, policywrite, \ + tpm_nt, bits_at_8, policy_delete, writelocked, \ + writeall, writedefine, write_stclear, globallock, \ + ppread, ownerread, authread, policyread, \ + bits_at_20, no_da, orderly, clear_stclear, \ + readlocked, written, platformcreate, read_stclear) \ + {ppwrite, ownerwrite, authwrite, policywrite, \ + tpm_nt, bits_at_8, policy_delete, writelocked, \ + writeall, writedefine, write_stclear, globallock, \ + ppread, ownerread, authread, policyread, \ + bits_at_20, no_da, orderly, clear_stclear, \ + readlocked, written, platformcreate, read_stclear} +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:208 TPMA_NV using bit masking +typedef UINT32 TPMA_NV; +#define TYPE_OF_TPMA_NV UINT32 +#define TPMA_NV_PPWRITE ((TPMA_NV)1 << 0) +#define TPMA_NV_OWNERWRITE ((TPMA_NV)1 << 1) +#define TPMA_NV_AUTHWRITE ((TPMA_NV)1 << 2) +#define TPMA_NV_POLICYWRITE ((TPMA_NV)1 << 3) +#define TPMA_NV_TPM_NT_SHIFT 4 +#define TPMA_NV_TPM_NT ((TPMA_NV)0xf << 4) +#define TPMA_NV_POLICY_DELETE ((TPMA_NV)1 << 10) +#define TPMA_NV_WRITELOCKED ((TPMA_NV)1 << 11) +#define TPMA_NV_WRITEALL ((TPMA_NV)1 << 12) +#define TPMA_NV_WRITEDEFINE ((TPMA_NV)1 << 13) +#define TPMA_NV_WRITE_STCLEAR ((TPMA_NV)1 << 14) +#define TPMA_NV_GLOBALLOCK ((TPMA_NV)1 << 15) +#define TPMA_NV_PPREAD ((TPMA_NV)1 << 16) +#define TPMA_NV_OWNERREAD ((TPMA_NV)1 << 17) +#define TPMA_NV_AUTHREAD ((TPMA_NV)1 << 18) +#define TPMA_NV_POLICYREAD ((TPMA_NV)1 << 19) +#define TPMA_NV_NO_DA ((TPMA_NV)1 << 25) +#define TPMA_NV_ORDERLY ((TPMA_NV)1 << 26) +#define TPMA_NV_CLEAR_STCLEAR ((TPMA_NV)1 << 27) +#define TPMA_NV_READLOCKED ((TPMA_NV)1 << 28) +#define TPMA_NV_WRITTEN ((TPMA_NV)1 << 29) +#define TPMA_NV_PLATFORMCREATE ((TPMA_NV)1 << 30) +#define TPMA_NV_READ_STCLEAR ((TPMA_NV)1 << 31) +#define TPMA_NV_RESERVED (0x00000300 | 0x01f00000) +// This is the initializer for a TPMA_NV bit array. +#define TPMA_NV_INITIALIZER( \ + ppwrite, ownerwrite, authwrite, policywrite, \ + tpm_nt, bits_at_8, policy_delete, writelocked, \ + writeall, writedefine, write_stclear, globallock, \ + ppread, ownerread, authread, policyread, \ + bits_at_20, no_da, orderly, clear_stclear, \ + readlocked, written, platformcreate, read_stclear) \ + (TPMA_NV)( \ + (ppwrite << 0) + (ownerwrite << 1) + \ + (authwrite << 2) + (policywrite << 3) + \ + (tpm_nt << 4) + (policy_delete << 10) + \ + (writelocked << 11) + (writeall << 12) + \ + (writedefine << 13) + (write_stclear << 14) + \ + (globallock << 15) + (ppread << 16) + \ + (ownerread << 17) + (authread << 18) + \ + (policyread << 19) + (no_da << 25) + \ + (orderly << 26) + (clear_stclear << 27) + \ + (readlocked << 28) + (written << 29) + \ + (platformcreate << 30) + (read_stclear << 31)) +#endif // USE_BIT_FIELD_STRUCTURES + +/* Table 2:209 - Definition of TPMS_NV_PUBLIC Structure */ +typedef struct { + TPMI_RH_NV_INDEX nvIndex; + TPMI_ALG_HASH nameAlg; + TPMA_NV attributes; + TPM2B_DIGEST authPolicy; + UINT16 dataSize; +} TPMS_NV_PUBLIC; +/* Table 2:207 - Definition of TPM2B_NV_PUBLIC Structure */ +typedef struct { + UINT16 size; + TPMS_NV_PUBLIC nvPublic; +} TPM2B_NV_PUBLIC; +/* Table 2:208 - Definition of TPM2B_CONTEXT_SENSITIVE Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[MAX_CONTEXT_SIZE]; + } t; + TPM2B b; +} TPM2B_CONTEXT_SENSITIVE; +/* Table 2:209 - Definition of TPMS_CONTEXT_DATA Structure */ +typedef struct { + TPM2B_DIGEST integrity; + TPM2B_CONTEXT_SENSITIVE encrypted; +} TPMS_CONTEXT_DATA; +/* Table 2:210 - Definition of TPM2B_CONTEXT_DATA Structure */ +typedef union { + struct { + UINT16 size; + BYTE buffer[sizeof(TPMS_CONTEXT_DATA)]; + } t; + TPM2B b; +} TPM2B_CONTEXT_DATA; +/* Table 2:211 - Definition of TPMS_CONTEXT Structure */ +typedef struct { + UINT64 sequence; + TPMI_DH_SAVED savedHandle; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_CONTEXT_DATA contextBlob; +} TPMS_CONTEXT; +/* Table 2:213 - Definition of TPMS_CREATION_DATA Structure */ +typedef struct { + TPML_PCR_SELECTION pcrSelect; + TPM2B_DIGEST pcrDigest; + TPMA_LOCALITY locality; + TPM_ALG_ID parentNameAlg; + TPM2B_NAME parentName; + TPM2B_NAME parentQualifiedName; + TPM2B_DATA outsideInfo; +} TPMS_CREATION_DATA; +/* Table 2:214 - Definition of TPM2B_CREATION_DATA Structure */ +typedef struct { + UINT16 size; + TPMS_CREATION_DATA creationData; +} TPM2B_CREATION_DATA; /* Structure */ + +// Table 2:220 - Definition of TPM_AT Constants +typedef UINT32 TPM_AT; +#define TYPE_OF_TPM_AT UINT32 +#define TPM_AT_ANY (TPM_AT)(0x00000000) +#define TPM_AT_ERROR (TPM_AT)(0x00000001) +#define TPM_AT_PV1 (TPM_AT)(0x00000002) +#define TPM_AT_VEND (TPM_AT)(0x80000000) + +// Table 2:221 - Definition of TPM_AE Constants +typedef UINT32 TPM_AE; +#define TYPE_OF_TPM_AE UINT32 +#define TPM_AE_NONE (TPM_AE)(0x00000000) + +typedef struct { // Table 2:222 + TPM_AT tag; + UINT32 data; +} TPMS_AC_OUTPUT; + +/* Table 2:218 - Definition of TPML_AC_CAPABILITIES Structure */ +typedef struct { + UINT32 count; + TPMS_AC_OUTPUT acCapabilities[MAX_AC_CAPABILITIES]; +} TPML_AC_CAPABILITIES; + + +#endif diff --git a/src/tpm2/Unique.c b/src/tpm2/Unique.c new file mode 100644 index 0000000..272d106 --- /dev/null +++ b/src/tpm2/Unique.c @@ -0,0 +1,109 @@ +/********************************************************************************/ +/* */ +/* Secret Value to the TPM */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Unique.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* C.12 Unique.c */ +/* C.12.1. Introduction */ +/* In some implementations of the TPM, the hardware can provide a secret value to the TPM. This + secret value is statistically unique to the instance of the TPM. Typical uses of this value are + to provide personalization to the random number generation and as a shared secret between the TPM + and the manufacturer. */ +/* C.12.2. Includes */ +#include "Platform.h" +const char notReallyUnique[] = + "This is not really a unique value. A real unique value should" + " be generated by the platform."; +/* C.12.3. _plat__GetUnique() */ +/* This function is used to access the platform-specific unique value. This function places the + unique value in the provided buffer (b) and returns the number of bytes transferred. The function + will not copy more data than bSize. */ +/* NOTE: If a platform unique value has unequal distribution of uniqueness and bSize is smaller than + the size of the unique value, the bSize portion with the most uniqueness should be returned. */ +LIB_EXPORT uint32_t +_plat__GetUnique( + uint32_t which, // authorities (0) or details + uint32_t bSize, // size of the buffer + unsigned char *b // output buffer + ) +{ + const char *from = notReallyUnique; + uint32_t retVal = 0; + if(which == 0) // the authorities value + { + for(retVal = 0; + *from != 0 && retVal < bSize; + retVal++) + { + *b++ = *from++; + } + } + else + { +#define uSize sizeof(notReallyUnique) + b = &b[((bSize < uSize) ? bSize : uSize) - 1]; + for(retVal = 0; + *from != 0 && retVal < bSize; + retVal++) + { + *b-- = *from++; + } + } + return retVal; +} diff --git a/src/tpm2/Unmarshal.c b/src/tpm2/Unmarshal.c new file mode 100644 index 0000000..e2395c3 --- /dev/null +++ b/src/tpm2/Unmarshal.c @@ -0,0 +1,4532 @@ +/********************************************************************************/ +/* */ +/* Parameter Unmarshaling */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Unmarshal.c 1635 2020-06-12 21:48:27Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2015 - 2018 */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* rev 136 */ + +#include + +#include "Unmarshal_fp.h" +#include "CryptEccMain_fp.h" // libtpms added + +TPM_RC +UINT8_Unmarshal(UINT8 *target, BYTE **buffer, INT32 *size) +{ + if ((UINT32)*size < sizeof(UINT8)) { + return TPM_RC_INSUFFICIENT; + } + *target = (*buffer)[0]; + *buffer += sizeof(UINT8); + *size -= sizeof(UINT8); + return TPM_RC_SUCCESS; +} + +TPM_RC +INT8_Unmarshal(INT8 *target, BYTE **buffer, INT32 *size) +{ + return UINT8_Unmarshal((UINT8 *)target, buffer, size); +} + +TPM_RC +UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size) +{ + if ((UINT32)*size < sizeof(UINT16)) { + return TPM_RC_INSUFFICIENT; + } + *target = ((UINT16)((*buffer)[0]) << 8) | + ((UINT16)((*buffer)[1]) << 0); + *buffer += sizeof(UINT16); + *size -= sizeof(UINT16); + return TPM_RC_SUCCESS; +} + +TPM_RC +UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size) +{ + if ((UINT32)*size < sizeof(UINT32)) { + return TPM_RC_INSUFFICIENT; + } + *target = ((UINT32)((*buffer)[0]) << 24) | + ((UINT32)((*buffer)[1]) << 16) | + ((UINT32)((*buffer)[2]) << 8) | + ((UINT32)((*buffer)[3]) << 0); + *buffer += sizeof(UINT32); + *size -= sizeof(UINT32); + return TPM_RC_SUCCESS; +} + +TPM_RC +UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size) +{ + if ((UINT32)*size < sizeof(UINT64)) { + return TPM_RC_INSUFFICIENT; + } + *target = ((UINT64)((*buffer)[0]) << 56) | + ((UINT64)((*buffer)[1]) << 48) | + ((UINT64)((*buffer)[2]) << 40) | + ((UINT64)((*buffer)[3]) << 32) | + ((UINT64)((*buffer)[4]) << 24) | + ((UINT64)((*buffer)[5]) << 16) | + ((UINT64)((*buffer)[6]) << 8) | + ((UINT64)((*buffer)[7]) << 0); + *buffer += sizeof(UINT64); + *size -= sizeof(UINT64); + return TPM_RC_SUCCESS; +} + +TPM_RC +Array_Unmarshal(BYTE *targetBuffer, UINT16 targetSize, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (targetSize > *size) { + rc = TPM_RC_INSUFFICIENT; + } + else { + memcpy(targetBuffer, *buffer, targetSize); + *buffer += targetSize; + *size -= targetSize; + } + return rc; +} + +TPM_RC +TPM2B_Unmarshal(TPM2B *target, UINT16 targetSize, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size > targetSize) { + rc = TPM_RC_SIZE; + target->size = 0; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal(target->buffer, target->size, buffer, size); + } + return rc; +} + +/* Table 5 - Definition of Types for Documentation Clarity */ + +TPM_RC +TPM_KEY_BITS_Unmarshal(TPM_KEY_BITS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 7 - Definition of (UINT32) TPM_GENERATED Constants */ + +#if 0 +TPM_RC +TPM_GENERATED_Unmarshal(TPM_GENERATED *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_GENERATED orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (*target != TPM_GENERATED_VALUE) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} +#endif + +/* Table 9 - Definition of (UINT16) TPM_ALG_ID Constants */ + +TPM_RC +TPM_ALG_ID_Unmarshal(TPM_ALG_ID *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 10 - Definition of (UINT16) {ECC} TPM_ECC_CURVE Constants */ + +#if ALG_ECC +TPM_RC +TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_ECC_CURVE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_ECC_NONE: + case TPM_ECC_NIST_P192: + case TPM_ECC_NIST_P224: + case TPM_ECC_NIST_P256: + case TPM_ECC_NIST_P384: + case TPM_ECC_NIST_P521: + case TPM_ECC_BN_P256: + case TPM_ECC_BN_P638: + case TPM_ECC_SM2_P256: + break; + default: + rc = TPM_RC_CURVE; + *target = orig_target; // libtpms added + } + } + return rc; +} +#endif + +/* Table 13 - Definition of (UINT32) TPM_CC Constants (Numeric Order) */ + +TPM_RC +TPM_CC_Unmarshal(TPM_RC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 18 - Definition of (INT8) TPM_CLOCK_ADJUST Constants */ + +TPM_RC +TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_CLOCK_ADJUST orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = INT8_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_CLOCK_COARSE_SLOWER: + case TPM_CLOCK_MEDIUM_SLOWER: + case TPM_CLOCK_FINE_SLOWER: + case TPM_CLOCK_NO_CHANGE: + case TPM_CLOCK_FINE_FASTER: + case TPM_CLOCK_MEDIUM_FASTER: + case TPM_CLOCK_COARSE_FASTER: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 19 - Definition of (UINT16) TPM_EO Constants */ + +TPM_RC +TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_EO orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_EO_EQ: + case TPM_EO_NEQ: + case TPM_EO_SIGNED_GT: + case TPM_EO_UNSIGNED_GT: + case TPM_EO_SIGNED_LT: + case TPM_EO_UNSIGNED_LT: + case TPM_EO_SIGNED_GE: + case TPM_EO_UNSIGNED_GE: + case TPM_EO_SIGNED_LE: + case TPM_EO_UNSIGNED_LE: + case TPM_EO_BITSET: + case TPM_EO_BITCLEAR: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 20 - Definition of (UINT16) TPM_ST Constants */ + +TPM_RC +TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_ST orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_ST_RSP_COMMAND: + case TPM_ST_NULL: + case TPM_ST_NO_SESSIONS: + case TPM_ST_SESSIONS: + case TPM_ST_ATTEST_NV: + case TPM_ST_ATTEST_COMMAND_AUDIT: + case TPM_ST_ATTEST_SESSION_AUDIT: + case TPM_ST_ATTEST_CERTIFY: + case TPM_ST_ATTEST_QUOTE: + case TPM_ST_ATTEST_TIME: + case TPM_ST_ATTEST_CREATION: + case TPM_ST_CREATION: + case TPM_ST_VERIFIED: + case TPM_ST_AUTH_SECRET: + case TPM_ST_HASHCHECK: + case TPM_ST_AUTH_SIGNED: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 20 - Definition of (UINT16) TPM_SU Constants */ + +TPM_RC +TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_SU orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_SU_CLEAR: + case TPM_SU_STATE: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 21 - Definition of (UINT8) TPM_SE Constants */ + +TPM_RC +TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_SE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_SE_HMAC: + case TPM_SE_POLICY: + case TPM_SE_TRIAL: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 22 - Definition of (UINT32) TPM_CAP Constants */ + +TPM_RC +TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_CAP orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_CAP_ALGS: + case TPM_CAP_HANDLES: + case TPM_CAP_COMMANDS: + case TPM_CAP_PP_COMMANDS: + case TPM_CAP_AUDIT_COMMANDS: + case TPM_CAP_PCRS: + case TPM_CAP_TPM_PROPERTIES: + case TPM_CAP_PCR_PROPERTIES: + case TPM_CAP_ECC_CURVES: + case TPM_CAP_AUTH_POLICIES: + case TPM_CAP_ACT: + case TPM_CAP_VENDOR_PROPERTY: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 24 - Definition of (UINT32) TPM_PT Constants */ + +TPM_RC +TPM_PT_Unmarshal(TPM_HANDLE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 25 - Definition of (UINT32) TPM_PT_PCR Constants */ + +TPM_RC +TPM_PT_PCR_Unmarshal(TPM_PT_PCR *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 27 - Definition of Types for Handles */ + +TPM_RC +TPM_HANDLE_Unmarshal(TPM_HANDLE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 31 - Definition of (UINT32) TPMA_ALGORITHM Bits */ + +TPM_RC +TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMA_ALGORITHM orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ + } + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_ALGORITHM_reserved) { + rc = TPM_RC_RESERVED_BITS; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 32 - Definition of (UINT32) TPMA_OBJECT Bits */ + +TPM_RC +TPMA_OBJECT_Unmarshal(TPMA_OBJECT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMA_OBJECT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ + } + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_OBJECT_reserved) { + rc = TPM_RC_RESERVED_BITS; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 33 - Definition of (UINT8) TPMA_SESSION Bits */ + +TPM_RC +TPMA_SESSION_Unmarshal(TPMA_SESSION *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMA_SESSION orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal((UINT8 *)target, buffer, size); /* libtpms changed */ + } + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_SESSION_reserved) { + rc = TPM_RC_RESERVED_BITS; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 34 - Definition of (UINT8) TPMA_LOCALITY Bits */ + +TPM_RC +TPMA_LOCALITY_Unmarshal(TPMA_LOCALITY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal((UINT8 *)target, buffer, size); /* libtpms changed */ + } + return rc; +} + +/* Table 38 - Definition of (TPM_CC) TPMA_CC Bits */ + +TPM_RC +TPMA_CC_Unmarshal(TPMA_CC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMA_CC orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ + } + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_CC_reserved) { + rc = TPM_RC_RESERVED_BITS; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 39 - Definition of (BYTE) TPMI_YES_NO Type */ + +TPM_RC +TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_YES_NO orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case NO: + case YES: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 40 - Definition of (TPM_HANDLE) TPMI_DH_OBJECT Type */ + +TPM_RC +TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_DH_OBJECT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotTransient = (*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST); + BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); + BOOL isNotLegalNull = (*target != TPM_RH_NULL) || !allowNull; + if (isNotTransient && + isNotPersistent && + isNotLegalNull) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 2:41 - Definition of TPMI_DH_PARENT Type (InterfaceTable()) */ + +TPM_RC +TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_DH_PARENT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotTransient = (*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST); + BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); + BOOL isNotOwner = *target != TPM_RH_OWNER; + BOOL isNotPlatform = *target != TPM_RH_PLATFORM; + BOOL isNotEndorsement = *target != TPM_RH_ENDORSEMENT; + BOOL isNotLegalNull = (*target != TPM_RH_NULL) || !allowNull; + if (isNotTransient && + isNotPersistent && + isNotOwner && + isNotPlatform && + isNotEndorsement && + isNotLegalNull) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 41 - Definition of (TPM_HANDLE) TPMI_DH_PERSISTENT Type */ + +TPM_RC +TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_DH_PERSISTENT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); + if (isNotPersistent) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 42 - Definition of (TPM_HANDLE) TPMI_DH_ENTITY Type */ + +TPM_RC +TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_DH_ENTITY orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotOwner = *target != TPM_RH_OWNER; + BOOL isNotEndorsement = *target != TPM_RH_ENDORSEMENT; + BOOL isNotPlatform = *target != TPM_RH_PLATFORM; + BOOL isNotLockout = *target != TPM_RH_LOCKOUT; + BOOL isNotTransient = (*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST); + BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); + BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST); + BOOL isNotPcr = (*target > PCR_LAST); + BOOL isNotAuth = (*target < TPM_RH_AUTH_00) || (*target > TPM_RH_AUTH_FF); + BOOL isNotLegalNull = (*target != TPM_RH_NULL) || !allowNull; + if (isNotOwner && + isNotEndorsement && + isNotPlatform && + isNotLockout && + isNotTransient && + isNotPersistent && + isNotNv && + isNotPcr && + isNotAuth && + isNotLegalNull) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 43 - Definition of (TPM_HANDLE) TPMI_DH_PCR Type */ + +TPM_RC +TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_DH_PCR orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotPcr = (*target > PCR_LAST); + BOOL isNotLegalNull = (*target != TPM_RH_NULL) || !allowNull; + if (isNotPcr && + isNotLegalNull) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 44 - Definition of (TPM_HANDLE) TPMI_SH_AUTH_SESSION Type */ + +TPM_RC +TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT32 *size, BOOL allowPwd) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_SH_AUTH_SESSION orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); + BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); + BOOL isNotLegalPwd = (*target != TPM_RS_PW) || !allowPwd; + if (isNotHmacSession && + isNotPolicySession && + isNotLegalPwd) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 45 - Definition of (TPM_HANDLE) TPMI_SH_HMAC Type */ + +TPM_RC +TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_SH_HMAC orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); + if (isNotHmacSession) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 46 - Definition of (TPM_HANDLE) TPMI_SH_POLICY Type */ + +TPM_RC +TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_SH_POLICY orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); + if (isNotPolicySession) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 47 - Definition of (TPM_HANDLE) TPMI_DH_CONTEXT Type */ + +TPM_RC +TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_DH_CONTEXT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); + BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); + BOOL isNotTransient = (*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST); + if (isNotHmacSession && + isNotPolicySession && + isNotTransient) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 49 - Definition of (TPM_HANDLE) TPMI_DH_SAVED Type */ + +TPM_RC +TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_DH_SAVED orig_target = *target; // libtpms added + allowNull = allowNull; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); + BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); + BOOL isNotTransientObject = (*target != 0x80000000); + BOOL isNotSequenceObject = (*target != 0x80000001); + BOOL isNotTransientStClear = (*target != 0x80000002); + if (isNotHmacSession && + isNotPolicySession && + isNotTransientObject && + isNotSequenceObject && + isNotTransientStClear) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 48 - Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY Type */ + +TPM_RC +TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_HIERARCHY orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + break; + case TPM_RH_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 49 - Definition of (TPM_HANDLE) TPMI_RH_ENABLES Type */ + +TPM_RC +TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_ENABLES orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + case TPM_RH_PLATFORM_NV: + break; + case TPM_RH_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 50 - Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY_AUTH Type */ + +TPM_RC +TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_HIERARCHY_AUTH orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + case TPM_RH_LOCKOUT: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 50 - Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY_POLICY Type */ + +TPM_RC +TPMI_RH_HIERARCHY_POLICY_Unmarshal(TPMI_RH_HIERARCHY_POLICY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_HIERARCHY_POLICY orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + case TPM_RH_LOCKOUT: + break; + default: + { + BOOL isNotHP = (*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F); + if (isNotHP) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + } + } + return rc; +} + +/* Table 51 - Definition of (TPM_HANDLE) TPMI_RH_PLATFORM Type */ + +TPM_RC +TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_PLATFORM orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_PLATFORM: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 53 - Definition of (TPM_HANDLE) TPMI_RH_ENDORSEMENT Type */ + +TPM_RC +TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_ENDORSEMENT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_ENDORSEMENT: + break; + case TPM_RH_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 54 - Definition of (TPM_HANDLE) TPMI_RH_PROVISION Type */ + +TPM_RC +TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_PROVISION orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 55 - Definition of (TPM_HANDLE) TPMI_RH_CLEAR Type */ + +TPM_RC +TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_CLEAR orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_LOCKOUT: + case TPM_RH_PLATFORM: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 56 - Definition of (TPM_HANDLE) TPMI_RH_NV_AUTH Type */ + +TPM_RC +TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_NV_AUTH orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + break; + default: + { + BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST); + if (isNotNv) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + } + } + return rc; +} + +/* Table 57 - Definition of (TPM_HANDLE) TPMI_RH_LOCKOUT Type */ + +TPM_RC +TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_LOCKOUT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_RH_LOCKOUT: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 58 - Definition of (TPM_HANDLE) TPMI_RH_NV_INDEX Type */ + +TPM_RC +TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_NV_INDEX orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST); + if (isNotNv) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 64 - Definition of (TPM_HANDLE) TPMI_RH_AC Type */ + +TPM_RC +TPMI_RH_AC_Unmarshal(TPMI_RH_AC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_AC orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotAC = (*target < AC_FIRST) || (*target > AC_LAST); + if (isNotAC) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 65 - Definition of (TPM_HANDLE) TPMI_RH_ACT Type */ + +TPM_RC +TPMI_RH_ACT_Unmarshal( TPMI_RH_ACT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RH_ACT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + BOOL isNotACT = (*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F); + if (isNotACT) { + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 59 - Definition of (TPM_ALG_ID) TPMI_ALG_HASH Type */ + +TPM_RC +TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_HASH orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_SHA1 + case TPM_ALG_SHA1: +#endif +#if ALG_SHA256 + case TPM_ALG_SHA256: +#endif +#if ALG_SHA384 + case TPM_ALG_SHA384: +#endif +#if ALG_SHA512 + case TPM_ALG_SHA512: +#endif +#if ALG_SM3_256 + case TPM_ALG_SM3_256: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_HASH; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 61 - Definition of (TPM_ALG_ID) TPMI_ALG_SYM Type */ + +TPM_RC +TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_SYM orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_AES + case TPM_ALG_AES: +#endif +#if ALG_SM4 + case TPM_ALG_SM4: +#endif +#if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: +#endif +#if ALG_TDES // libtpms added begin + case TPM_ALG_TDES: +#endif // libtpms added end +#if ALG_XOR + case TPM_ALG_XOR: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_SYMMETRIC; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 62 - Definition of (TPM_ALG_ID) TPMI_ALG_SYM_OBJECT Type */ + +TPM_RC +TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_SYM_OBJECT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_AES + case TPM_ALG_AES: +#endif +#if ALG_SM4 + case TPM_ALG_SM4: +#endif +#if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: +#endif +#if ALG_TDES // libtpms added begin + case TPM_ALG_TDES: +#endif // iibtpms added end + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_SYMMETRIC; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 63 - Definition of (TPM_ALG_ID) TPMI_ALG_SYM_MODE Type */ + +TPM_RC +TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_SYM_MODE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_CTR + case TPM_ALG_CTR: +#endif +#if ALG_OFB + case TPM_ALG_OFB: +#endif +#if ALG_CBC + case TPM_ALG_CBC: +#endif +#if ALG_CFB + case TPM_ALG_CFB: +#endif +#if ALG_ECB + case TPM_ALG_ECB: +#endif +#if ALG_CMAC + case TPM_ALG_CMAC: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_MODE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 64 - Definition of (TPM_ALG_ID) TPMI_ALG_KDF Type */ + +TPM_RC +TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_KDF orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_MGF1 + case TPM_ALG_MGF1: +#endif +#if ALG_KDF1_SP800_56A + case TPM_ALG_KDF1_SP800_56A: +#endif +#if ALG_KDF2 + case TPM_ALG_KDF2: +#endif +#if ALG_KDF1_SP800_108 + case TPM_ALG_KDF1_SP800_108: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_KDF; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 65 - Definition of (TPM_ALG_ID) TPMI_ALG_SIG_SCHEME Type */ + +TPM_RC +TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_SIG_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_HMAC + case TPM_ALG_HMAC: +#endif +#if ALG_RSASSA + case TPM_ALG_RSASSA: +#endif +#if ALG_RSAPSS + case TPM_ALG_RSAPSS: +#endif +#if ALG_ECDSA + case TPM_ALG_ECDSA: +#endif +#if ALG_ECDAA + case TPM_ALG_ECDAA: +#endif +#if ALG_SM2 + case TPM_ALG_SM2: +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_SCHEME; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 66 - Definition of (TPM_ALG_ID) TPMI_ECC_KEY_EXCHANGE Type */ + +TPM_RC +TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ECC_KEY_EXCHANGE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_ECDH + case TPM_ALG_ECDH: +#endif +#if ALG_ECMQV + case TPM_ALG_ECMQV: +#endif +#if ALG_SM2 + case TPM_ALG_SM2: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_SCHEME; + *target = orig_target; // libtpms added + } + } + return rc; +} + + +/* Table 67 - Definition of (TPM_ST) TPMI_ST_COMMAND_TAG Type */ + +TPM_RC +TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ST_COMMAND_TAG orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_ST_NO_SESSIONS: + case TPM_ST_SESSIONS: + break; + default: + rc = TPM_RC_BAD_TAG; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 70 TPMI_ALG_MAC_SCHEME */ + +TPM_RC +TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_MAC_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_SHA1 + case TPM_ALG_SHA1: +#endif +#if ALG_SHA256 + case TPM_ALG_SHA256: +#endif +#if ALG_SHA384 + case TPM_ALG_SHA384: +#endif +#if ALG_SHA512 + case TPM_ALG_SHA512: +#endif +#if ALG_SM3_256 + case TPM_ALG_SM3_256: +#endif +#if ALG_CMAC + case TPM_ALG_CMAC: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_SYMMETRIC; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 70 TPMI_ALG_CIPHER_MODE */ + +TPM_RC +TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_CIPHER_MODE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_CTR + case TPM_ALG_CTR: +#endif +#if ALG_OFB + case TPM_ALG_OFB: +#endif +#if ALG_CBC + case TPM_ALG_CBC: +#endif +#if ALG_CFB + case TPM_ALG_CFB: +#endif +#if ALG_ECB + case TPM_ALG_ECB: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_MODE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 68 - Definition of TPMS_EMPTY Structure */ + +TPM_RC +TPMS_EMPTY_Unmarshal(TPMS_EMPTY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + target = target; + buffer = buffer; + size = size; + return rc; +} + +/* Table 70 - Definition of TPMU_HA Union */ + +TPM_RC +TPMU_HA_Unmarshal(TPMU_HA *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_SHA1 + case TPM_ALG_SHA1: + rc = Array_Unmarshal(target->sha1, SHA1_DIGEST_SIZE, buffer, size); + break; +#endif +#if ALG_SHA256 + case TPM_ALG_SHA256: + rc = Array_Unmarshal(target->sha256, SHA256_DIGEST_SIZE, buffer, size); + break; +#endif +#if ALG_SHA384 + case TPM_ALG_SHA384: + rc = Array_Unmarshal(target->sha384, SHA384_DIGEST_SIZE, buffer, size); + break; +#endif +#if ALG_SHA512 + case TPM_ALG_SHA512: + rc = Array_Unmarshal(target->sha512, SHA512_DIGEST_SIZE, buffer, size); + break; +#endif +#if ALG_SM3_256 + case TPM_ALG_SM3_256: + rc = Array_Unmarshal(target->sm3_256, SM3_256_DIGEST_SIZE, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 71 - Definition of TPMT_HA Structure */ + +TPM_RC +TPMT_HA_Unmarshal(TPMT_HA *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->hashAlg, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_HA_Unmarshal(&target->digest, buffer, size, target->hashAlg); + } + return rc; +} + +/* Table 72 - Definition of TPM2B_DIGEST Structure */ + +TPM_RC +TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPMU_HA), buffer, size); + } + return rc; +} + +/* Table 73 - Definition of TPM2B_DATA Structure */ + +TPM_RC +TPM2B_DATA_Unmarshal(TPM2B_DATA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPMT_HA), buffer, size); + } + return rc; +} + +/* Table 74 - Definition of Types for TPM2B_NONCE */ + +TPM_RC +TPM2B_NONCE_Unmarshal(TPM2B_NONCE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 75 - Definition of Types for TPM2B_AUTH */ + +TPM_RC +TPM2B_AUTH_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 77 - Definition of TPM2B_EVENT Structure */ + +TPM_RC +TPM2B_EVENT_Unmarshal(TPM2B_EVENT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPM2B_EVENT) - sizeof(UINT16), buffer, size); + } + return rc; +} + +/* Table 78 - Definition of TPM2B_MAX_BUFFER Structure */ + +TPM_RC +TPM2B_MAX_BUFFER_Unmarshal(TPM2B_MAX_BUFFER *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_DIGEST_BUFFER, buffer, size); + } + return rc; +} + +/* Table 79 - Definition of TPM2B_MAX_NV_BUFFER Structure */ + +TPM_RC +TPM2B_MAX_NV_BUFFER_Unmarshal(TPM2B_MAX_NV_BUFFER *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_NV_BUFFER_SIZE, buffer, size); + } + return rc; +} + +/* Table 80 - Definition of TPM2B_TIMEOUT Structure */ + +TPM_RC +TPM2B_TIMEOUT_Unmarshal(TPM2B_TIMEOUT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(target->t.buffer), buffer, size); + } + return rc; +} + +/* Table 81 - Definition of TPM2B_IV Structure */ + +TPM_RC +TPM2B_IV_Unmarshal(TPM2B_IV *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_SYM_BLOCK_SIZE, buffer, size); + } + return rc; +} + +/* Table 83 - Definition of TPM2B_NAME Structure */ + +TPM_RC +TPM2B_NAME_Unmarshal(TPM2B_NAME *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPMU_NAME), buffer, size); + } + return rc; +} + +/* Table 85 - Definition of TPMS_PCR_SELECTION Structure */ + +TPM_RC +TPMS_PCR_SELECTION_Unmarshal(TPMS_PCR_SELECTION *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->hash, buffer, size, NO); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(&target->sizeofSelect, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if ((target->sizeofSelect < PCR_SELECT_MIN) || + (target->sizeofSelect > PCR_SELECT_MAX)) { + rc = TPM_RC_VALUE; + target->sizeofSelect = 0; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal(target->pcrSelect, target->sizeofSelect, buffer, size); + } + return rc; +} + +/* Table 88 - Definition of TPMT_TK_CREATION Structure */ + +TPM_RC +TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_ST orig_tag = target->tag; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(&target->tag, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->tag != TPM_ST_CREATION) { + rc = TPM_RC_TAG; + target->tag = orig_tag; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->digest, buffer, size); + } + return rc; +} + +/* Table 89 - Definition of TPMT_TK_VERIFIED Structure */ + +TPM_RC +TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_ST orig_tag = target->tag; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(&target->tag, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->tag != TPM_ST_VERIFIED) { + rc = TPM_RC_TAG; + target->tag = orig_tag; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->digest, buffer, size); + } + return rc; +} + +/* Table 90 - Definition of TPMT_TK_AUTH Structure */ + +TPM_RC +TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_ST orig_tag = target->tag; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(&target->tag, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if ((target->tag != TPM_ST_AUTH_SIGNED) && + (target->tag != TPM_ST_AUTH_SECRET)) { + rc = TPM_RC_TAG; + target->tag = orig_tag; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->digest, buffer, size); + } + return rc; +} + +/* Table 91 - Definition of TPMT_TK_HASHCHECK Structure */ + +TPM_RC +TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPM_ST orig_tag = target->tag; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(&target->tag, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->tag != TPM_ST_HASHCHECK) { + rc = TPM_RC_TAG; + target->tag = orig_tag; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->digest, buffer, size); + } + return rc; +} + +/* Table 92 - Definition of TPMS_ALG_PROPERTY Structure */ + +#if 0 // libtpms added +TPM_RC +TPMS_ALG_PROPERTY_Unmarshal(TPMS_ALG_PROPERTY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&target->alg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMA_ALGORITHM_Unmarshal(&target->algProperties, buffer, size); + } + return rc; +} +#endif // libtpms added + +/* Table 93 - Definition of TPMS_TAGGED_PROPERTY Structure */ + +#if 0 // libtpms added +TPM_RC +TPMS_TAGGED_PROPERTY_Unmarshal(TPMS_TAGGED_PROPERTY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_PT_Unmarshal(&target->property, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->value, buffer, size); + } + return rc; +} +#endif // libtpms added + +/* Table 94 - Definition of TPMS_TAGGED_PCR_SELECT Structure */ + +#if 0 // libtpms added +TPM_RC +TPMS_TAGGED_PCR_SELECT_Unmarshal(TPMS_TAGGED_PCR_SELECT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_PT_PCR_Unmarshal(&target->tag, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(&target->sizeofSelect, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = Array_Unmarshal(target->pcrSelect, target->sizeofSelect, buffer, size); + } + return rc; +} +#endif // libtpms added + +/* Table 95 - Definition of TPML_CC Structure */ + +TPM_RC +TPML_CC_Unmarshal(TPML_CC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_CAP_CC) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPM_CC_Unmarshal(&target->commandCodes[i], buffer, size); + } + return rc; +} + +/* Table 2:96 - Definition of TPMS_TAGGED_POLICY Structure (StructuresTable()) */ + +#if 0 // libtpms added +TPM_RC +TPMS_TAGGED_POLICY_Unmarshal(TPMS_TAGGED_POLICY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(&target->handle, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_HA_Unmarshal(&target->policyHash, buffer, size, NO); + } + return rc; +} +#endif // libtpms added + +/* Table 96 - Definition of TPML_CCA Structure */ + +#if 0 // libtpms added +TPM_RC +TPML_CCA_Unmarshal(TPML_CCA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_CAP_CC) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPMA_CC_Unmarshal(&target->commandAttributes[i], buffer, size); + } + return rc; +} +#endif // libtpms added + +/* Table 97 - Definition of TPML_ALG Structure */ + +TPM_RC +TPML_ALG_Unmarshal(TPML_ALG *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_ALG_LIST_SIZE) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPM_ALG_ID_Unmarshal(&target->algorithms[i], buffer, size); + } + return rc; +} + +/* Table 98 - Definition of TPML_HANDLE Structure */ + +#if 0 // libtpms added +TPM_RC +TPML_HANDLE_Unmarshal(TPML_HANDLE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_CAP_HANDLES) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPM_HANDLE_Unmarshal(&target->handle[i], buffer, size); + } + return rc; +} +#endif // libtpms added + +/* Table 99 - Definition of TPML_DIGEST Structure */ + +/* PolicyOr has a restriction of at least a count of two. This function is also used to unmarshal + PCR_Read, where a count of one is permitted. +*/ + +TPM_RC +TPML_DIGEST_Unmarshal(TPML_DIGEST *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + /* TPM side is hard coded to 2 minimum */ + if (target->count < 2) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > 8) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPM2B_DIGEST_Unmarshal(&target->digests[i], buffer, size); + } + return rc; +} + +/* Table 100 - Definition of TPML_DIGEST_VALUES Structure */ + +TPM_RC +TPML_DIGEST_VALUES_Unmarshal(TPML_DIGEST_VALUES *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > HASH_COUNT) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPMT_HA_Unmarshal(&target->digests[i], buffer, size, NO); + } + return rc; +} + +/* Table 102 - Definition of TPML_PCR_SELECTION Structure */ + +TPM_RC +TPML_PCR_SELECTION_Unmarshal(TPML_PCR_SELECTION *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > HASH_COUNT) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPMS_PCR_SELECTION_Unmarshal(&target->pcrSelections[i], buffer, size); + } + return rc; +} + + +#if 0 + +/* Table 103 - Definition of TPML_ALG_PROPERTY Structure */ + +TPM_RC +TPML_ALG_PROPERTY_Unmarshal(TPML_ALG_PROPERTY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_CAP_ALGS) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPMS_ALG_PROPERTY_Unmarshal(&target->algProperties[i], buffer, size); + } + return rc; +} + +/* Table 104 - Definition of TPML_TAGGED_TPM_PROPERTY Structure */ + +TPM_RC +TPML_TAGGED_TPM_PROPERTY_Unmarshal(TPML_TAGGED_TPM_PROPERTY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_TPM_PROPERTIES) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPMS_TAGGED_PROPERTY_Unmarshal(&target->tpmProperty[i], buffer, size); + } + return rc; +} + +/* Table 105 - Definition of TPML_TAGGED_PCR_PROPERTY Structure */ + +TPM_RC +TPML_TAGGED_PCR_PROPERTY_Unmarshal(TPML_TAGGED_PCR_PROPERTY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_PCR_PROPERTIES) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPMS_TAGGED_PCR_SELECT_Unmarshal(&target->pcrProperty[i], buffer, size); + } + return rc; +} + +/* Table 106 - Definition of {ECC} TPML_ECC_CURVE Structure */ + +TPM_RC +TPML_ECC_CURVE_Unmarshal(TPML_ECC_CURVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_ECC_CURVES) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPM_ECC_CURVE_Unmarshal(&target->eccCurves[i], buffer, size); + } + return rc; +} + +/* Table 2:109 - Definition of TPML_TAGGED_POLICY Structure (StructuresTable()) */ + +TPM_RC +TPML_TAGGED_POLICY_Unmarshal(TPML_TAGGED_POLICY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + UINT32 i; + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->count, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_TAGGED_POLICIES) { + rc = TPM_RC_SIZE; + target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { + rc = TPMS_TAGGED_POLICY_Unmarshal(&target->policies[i], buffer, size); + } + return rc; +} + +/* Table 2:110 - Definition of TPMU_CAPABILITIES Union (StructuresTable()) */ + +TPM_RC +TPMU_CAPABILITIES_Unmarshal(TPMU_CAPABILITIES *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { + case TPM_CAP_ALGS: + rc = TPML_ALG_PROPERTY_Unmarshal(&target->algorithms, buffer, size); + break; + case TPM_CAP_HANDLES: + rc = TPML_HANDLE_Unmarshal(&target->handles, buffer, size); + break; + case TPM_CAP_COMMANDS: + rc = TPML_CCA_Unmarshal(&target->command, buffer, size); + break; + case TPM_CAP_PP_COMMANDS: + rc = TPML_CC_Unmarshal(&target->ppCommands, buffer, size); + break; + case TPM_CAP_AUDIT_COMMANDS: + rc = TPML_CC_Unmarshal(&target->auditCommands, buffer, size); + break; + case TPM_CAP_PCRS: + rc = TPML_PCR_SELECTION_Unmarshal(&target->assignedPCR, buffer, size); + break; + case TPM_CAP_TPM_PROPERTIES: + rc = TPML_TAGGED_TPM_PROPERTY_Unmarshal(&target->tpmProperties, buffer, size); + break; + case TPM_CAP_PCR_PROPERTIES: + rc = TPML_TAGGED_PCR_PROPERTY_Unmarshal(&target->pcrProperties, buffer, size); + break; + case TPM_CAP_ECC_CURVES: + rc = TPML_ECC_CURVE_Unmarshal(&target->eccCurves, buffer, size); + break; + case TPM_CAP_AUTH_POLICIES: + rc = TPML_TAGGED_POLICY_Unmarshal(&target->authPolicies, buffer, size); + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 2:111 - Definition of TPMS_CAPABILITY_DATA Structure (StructuresTable()) */ + +TPM_RC +TPMS_CAPABILITY_DATA_Unmarshal(TPMS_CAPABILITY_DATA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_CAP_Unmarshal(&target->capability, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_CAPABILITIES_Unmarshal(&target->data, buffer, size, target->capability); + } + return rc; +} + +/* Table 109 - Definition of TPMS_CLOCK_INFO Structure */ + +TPM_RC +TPMS_CLOCK_INFO_Unmarshal(TPMS_CLOCK_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&target->clock, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->resetCount, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->restartCount, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_YES_NO_Unmarshal(&target->safe, buffer, size); + } + return rc; +} + +/* Table 110 - Definition of TPMS_TIME_INFO Structure */ + +TPM_RC +TPMS_TIME_INFO_Unmarshal(TPMS_TIME_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&target->time, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_CLOCK_INFO_Unmarshal(&target->clockInfo, buffer, size); + } + return rc; +} + +/* Table 111 - Definition of TPMS_TIME_ATTEST_INFO Structure */ + +TPM_RC +TPMS_TIME_ATTEST_INFO_Unmarshal(TPMS_TIME_ATTEST_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_TIME_INFO_Unmarshal(&target->time, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&target->firmwareVersion, buffer, size); + } + return rc; +} + +/* Table 112 - Definition of TPMS_CERTIFY_INFO Structure */ + +TPM_RC +TPMS_CERTIFY_INFO_Unmarshal(TPMS_CERTIFY_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NAME_Unmarshal(&target->name, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NAME_Unmarshal(&target->qualifiedName, buffer, size); + } + return rc; +} + +/* Table 113 - Definition of TPMS_QUOTE_INFO Structure */ + +TPM_RC +TPMS_QUOTE_INFO_Unmarshal(TPMS_QUOTE_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPML_PCR_SELECTION_Unmarshal(&target->pcrSelect, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->pcrDigest, buffer, size); + } + return rc; +} + +/* Table 114 - Definition of TPMS_COMMAND_AUDIT_INFO Structure */ + +TPM_RC +TPMS_COMMAND_AUDIT_INFO_Unmarshal(TPMS_COMMAND_AUDIT_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&target->auditCounter, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(&target->digestAlg, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->auditDigest, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->commandDigest, buffer, size); + } + return rc; +} + +/* Table 115 - Definition of TPMS_SESSION_AUDIT_INFO Structure */ + +TPM_RC +TPMS_SESSION_AUDIT_INFO_Unmarshal(TPMS_SESSION_AUDIT_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_YES_NO_Unmarshal(&target->exclusiveSession, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->sessionDigest, buffer, size); + } + return rc; +} + +/* Table 116 - Definition of TPMS_CREATION_INFO Structure */ + +TPM_RC +TPMS_CREATION_INFO_Unmarshal(TPMS_CREATION_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NAME_Unmarshal(&target->objectName, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->creationHash, buffer, size); + } + return rc; +} + +/* Table 117 - Definition of TPMS_NV_CERTIFY_INFO Structure */ + +TPM_RC +TPMS_NV_CERTIFY_INFO_Unmarshal(TPMS_NV_CERTIFY_INFO *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NAME_Unmarshal(&target->indexName, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->offset, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_MAX_NV_BUFFER_Unmarshal(&target->nvContents, buffer, size); + } + return rc; +} + +/* Table 118 - Definition of (TPM_ST) TPMI_ST_ATTEST Type */ + +TPM_RC +TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ST_ATTEST orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case TPM_ST_ATTEST_CERTIFY: + case TPM_ST_ATTEST_CREATION: + case TPM_ST_ATTEST_QUOTE: + case TPM_ST_ATTEST_COMMAND_AUDIT: + case TPM_ST_ATTEST_SESSION_AUDIT: + case TPM_ST_ATTEST_TIME: + case TPM_ST_ATTEST_NV: + break; + default: + rc = TPM_RC_SELECTOR; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 119 - Definition of TPMU_ATTEST Union */ + +TPM_RC +TPMU_ATTEST_Unmarshal(TPMU_ATTEST *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { + case TPM_ST_ATTEST_CERTIFY: + rc = TPMS_CERTIFY_INFO_Unmarshal(&target->certify, buffer, size); + break; + case TPM_ST_ATTEST_CREATION: + rc = TPMS_CREATION_INFO_Unmarshal(&target->creation, buffer, size); + break; + case TPM_ST_ATTEST_QUOTE: + rc = TPMS_QUOTE_INFO_Unmarshal(&target->quote, buffer, size); + break; + case TPM_ST_ATTEST_COMMAND_AUDIT: + rc = TPMS_COMMAND_AUDIT_INFO_Unmarshal(&target->commandAudit, buffer, size); + break; + case TPM_ST_ATTEST_SESSION_AUDIT: + rc = TPMS_SESSION_AUDIT_INFO_Unmarshal(&target->sessionAudit, buffer, size); + break; + case TPM_ST_ATTEST_TIME: + rc = TPMS_TIME_ATTEST_INFO_Unmarshal(&target->time, buffer, size); + break; + case TPM_ST_ATTEST_NV: + rc = TPMS_NV_CERTIFY_INFO_Unmarshal(&target->nv, buffer, size); + break; + default: + rc = TPM_RC_SELECTOR; + + } + return rc; +} + +/* Table 120 - Definition of TPMS_ATTEST Structure */ + +TPM_RC +TPMS_ATTEST_Unmarshal(TPMS_ATTEST *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_GENERATED_Unmarshal(&target->magic, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ST_ATTEST_Unmarshal(&target->type, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_NAME_Unmarshal(&target->qualifiedSigner, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DATA_Unmarshal(&target->extraData, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_CLOCK_INFO_Unmarshal(&target->clockInfo, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&target->firmwareVersion, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_ATTEST_Unmarshal(&target->attested, buffer, size, target->type); + } + return rc; +} + +/* Table 121 - Definition of TPM2B_ATTEST Structure */ + +TPM_RC +TPM2B_ATTEST_Unmarshal(TPM2B_ATTEST *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPMS_ATTEST), buffer, size); + } + return rc; +} + +#endif + +/* Table 124 - Definition of {!ALG.S} (TPM_KEY_BITS) TPMI_!ALG.S_KEY_BITS Type */ + +#if ALG_AES +TPM_RC +TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_AES_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if AES_128 // libtpms added + case 128: +#endif // libtpms added begin +#if AES_192 + case 192: +#endif +#if AES_256 // libtpms added end + case 256: +#endif // libtpms added + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} +#endif + +#if ALG_CAMELLIA +TPM_RC +TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_CAMELLIA_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if CAMELLIA_128 // libtpms added + case 128: +#endif // libtpms added begin +#if CAMELLIA_192 + case 192: +#endif +#if CAMELLIA_256 + case 256: +#endif // libtpms added end + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} +#endif + +#if ALG_SM4 +TPM_RC +TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_SM4_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case 128: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} +#endif + +#if ALG_TDES // libtpms added begin +TPM_RC +TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_SM4_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case 128: + case 192: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} +#endif // libtpms added end + +/* Table 125 - Definition of TPMU_SYM_KEY_BITS Union */ + +TPM_RC +TPMU_SYM_KEY_BITS_Unmarshal(TPMU_SYM_KEY_BITS *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_AES + case TPM_ALG_AES: + rc = TPMI_AES_KEY_BITS_Unmarshal(&target->aes, buffer, size); + break; +#endif +#if ALG_SM4 + case TPM_ALG_SM4: + rc = TPMI_SM4_KEY_BITS_Unmarshal(&target->sm4, buffer, size); + break; +#endif +#if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + rc = TPMI_CAMELLIA_KEY_BITS_Unmarshal(&target->camellia, buffer, size); + break; +#endif +#if ALG_TDES // libtpms added beging + case TPM_ALG_TDES: + rc = TPMI_TDES_KEY_BITS_Unmarshal(&target->tdes, buffer, size); + break; +#endif // libtpms added end +#if ALG_XOR + case TPM_ALG_XOR: + rc = TPMI_ALG_HASH_Unmarshal(&target->xorr, buffer, size, NO); + break; +#endif + case TPM_ALG_NULL: + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 126 - Definition of TPMU_SYM_MODE Union */ + +TPM_RC +TPMU_SYM_MODE_Unmarshal(TPMU_SYM_MODE *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_AES + case TPM_ALG_AES: + rc = TPMI_ALG_SYM_MODE_Unmarshal(&target->aes, buffer, size, YES); + break; +#endif +#if ALG_SM4 + case TPM_ALG_SM4: + rc = TPMI_ALG_SYM_MODE_Unmarshal(&target->sm4, buffer, size, YES); + break; +#endif +#if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + rc = TPMI_ALG_SYM_MODE_Unmarshal(&target->camellia, buffer, size, YES); + break; +#endif +#if ALG_TDES // libtpms added begin + case TPM_ALG_TDES: + rc = TPMI_ALG_SYM_MODE_Unmarshal(&target->tdes, buffer, size, YES); + break; +#endif // libtpms added end + case TPM_ALG_XOR: + case TPM_ALG_NULL: + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 131 - Definition of TPMT_SYM_DEF Structure */ + +TPM_RC +TPMT_SYM_DEF_Unmarshal(TPMT_SYM_DEF *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_SYM_Unmarshal(&target->algorithm, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_SYM_KEY_BITS_Unmarshal(&target->keyBits, buffer, size, target->algorithm); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_SYM_MODE_Unmarshal(&target->mode, buffer, size, target->algorithm); + } + return rc; +} + +/* Table 132 - Definition of TPMT_SYM_DEF_OBJECT Structure */ + +TPM_RC +TPMT_SYM_DEF_OBJECT_Unmarshal(TPMT_SYM_DEF_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_SYM_OBJECT_Unmarshal(&target->algorithm, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_SYM_KEY_BITS_Unmarshal(&target->keyBits, buffer, size, target->algorithm); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_SYM_MODE_Unmarshal(&target->mode, buffer, size, target->algorithm); + } + return rc; +} + +/* Table 133 - Definition of TPM2B_SYM_KEY Structure */ + +TPM_RC +TPM2B_SYM_KEY_Unmarshal(TPM2B_SYM_KEY *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_SYM_KEY_BYTES, buffer, size); + } + return rc; +} + +/* Table 134 - Definition of TPMS_SYMCIPHER_PARMS Structure */ + +TPM_RC +TPMS_SYMCIPHER_PARMS_Unmarshal(TPMS_SYMCIPHER_PARMS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_SYM_DEF_OBJECT_Unmarshal(&target->sym, buffer, size, NO); + } + return rc; +} + +/* Table 2:135 - Definition of TPM2B_LABEL Structure (StructuresTable()) */ + +TPM_RC +TPM2B_LABEL_Unmarshal(TPM2B_LABEL *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, LABEL_MAX_BUFFER, buffer, size); + } + return rc; +} + +/* Table 2:136 - Definition of TPMS_DERIVE Structure (StructuresTable()) */ + +TPM_RC +TPMS_DERIVE_Unmarshal(TPMS_DERIVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_LABEL_Unmarshal(&target->label, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_LABEL_Unmarshal(&target->context, buffer, size); + } + return rc; +} + +/* Table 139 - Definition of TPM2B_SENSITIVE_DATA Structure */ + +TPM_RC +TPM2B_SENSITIVE_DATA_Unmarshal(TPM2B_SENSITIVE_DATA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_SYM_DATA, buffer, size); + } + return rc; +} + +/* Table 133 - Definition of TPMS_SENSITIVE_CREATE Structure */ + +TPM_RC +TPMS_SENSITIVE_CREATE_Unmarshal(TPMS_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&target->userAuth, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_SENSITIVE_DATA_Unmarshal(&target->data, buffer, size); + } + return rc; +} + +/* Table 134 - Definition of TPM2B_SENSITIVE_CREATE Structure */ + +TPM_RC +TPM2B_SENSITIVE_CREATE_Unmarshal(TPM2B_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + INT32 startSize; + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size == 0) { + rc = TPM_RC_SIZE; + } + } + if (rc == TPM_RC_SUCCESS) { + startSize = *size; + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SENSITIVE_CREATE_Unmarshal(&target->sensitive, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; + target->size = 0; // libtpms added + } + } + return rc; +} + +/* Table 135 - Definition of TPMS_SCHEME_HASH Structure */ + +TPM_RC +TPMS_SCHEME_HASH_Unmarshal(TPMS_SCHEME_HASH *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->hashAlg, buffer, size, NO); + } + return rc; +} + +/* Table 136 - Definition of {ECC} TPMS_SCHEME_ECDAA Structure */ + +TPM_RC +TPMS_SCHEME_ECDAA_Unmarshal(TPMS_SCHEME_ECDAA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->hashAlg, buffer, size, NO); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->count, buffer, size); + } + return rc; +} + +/* Table 137 - Definition of (TPM_ALG_ID) TPMI_ALG_KEYEDHASH_SCHEME Type */ + +TPM_RC +TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_KEYEDHASH_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_HMAC + case TPM_ALG_HMAC: +#endif +#if ALG_XOR + case TPM_ALG_XOR: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 138 - Definition of Types for HMAC_SIG_SCHEME */ + +TPM_RC +TPMS_SCHEME_HMAC_Unmarshal(TPMS_SCHEME_HMAC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 139 - Definition of TPMS_SCHEME_XOR Structure */ + +TPM_RC +TPMS_SCHEME_XOR_Unmarshal(TPMS_SCHEME_XOR *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->hashAlg, buffer, size, NO); /* as of rev 147 */ + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_KDF_Unmarshal(&target->kdf, buffer, size, YES); + } + return rc; +} + +/* Table 140 - Definition of TPMU_SCHEME_KEYEDHASH Union */ + +TPM_RC +TPMU_SCHEME_KEYEDHASH_Unmarshal(TPMU_SCHEME_KEYEDHASH *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_HMAC + case TPM_ALG_HMAC: + rc = TPMS_SCHEME_HMAC_Unmarshal(&target->hmac, buffer, size); + break; +#endif +#if ALG_XOR + case TPM_ALG_XOR: + rc = TPMS_SCHEME_XOR_Unmarshal(&target->xorr, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 141 - Definition of TPMT_KEYEDHASH_SCHEME Structure */ + +TPM_RC +TPMT_KEYEDHASH_SCHEME_Unmarshal(TPMT_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(&target->scheme, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_SCHEME_KEYEDHASH_Unmarshal(&target->details, buffer, size, target->scheme); + } + return rc; +} + +/* Table 142 - Definition of {RSA} Types for RSA Signature Schemes */ + +TPM_RC +TPMS_SIG_SCHEME_RSAPSS_Unmarshal(TPMS_SIG_SCHEME_RSAPSS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 142 - Definition of {RSA} Types for RSA Signature Schemes */ + +TPM_RC +TPMS_SIG_SCHEME_RSASSA_Unmarshal(TPMS_SIG_SCHEME_RSASSA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 143 - Definition of {ECC} Types for ECC Signature Schemes */ + +TPM_RC +TPMS_SIG_SCHEME_ECDAA_Unmarshal(TPMS_SIG_SCHEME_ECDAA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_ECDAA_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 143 - Definition of {ECC} Types for ECC Signature Schemes */ + +TPM_RC +TPMS_SIG_SCHEME_ECDSA_Unmarshal(TPMS_SIG_SCHEME_ECDSA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 143 - Definition of {ECC} Types for ECC Signature Schemes */ + +TPM_RC +TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(TPMS_SIG_SCHEME_ECSCHNORR *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 143 - Definition of {ECC} Types for ECC Signature Schemes */ + +TPM_RC +TPMS_SIG_SCHEME_SM2_Unmarshal(TPMS_SIG_SCHEME_SM2 *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 144 - Definition of TPMU_SIG_SCHEME Union */ + +TPM_RC +TPMU_SIG_SCHEME_Unmarshal(TPMU_SIG_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_RSASSA + case TPM_ALG_RSASSA: + rc = TPMS_SIG_SCHEME_RSASSA_Unmarshal(&target->rsassa, buffer, size); + break; +#endif +#if ALG_RSAPSS + case TPM_ALG_RSAPSS: + rc = TPMS_SIG_SCHEME_RSAPSS_Unmarshal(&target->rsapss, buffer, size); + break; +#endif +#if ALG_ECDSA + case TPM_ALG_ECDSA: + rc = TPMS_SIG_SCHEME_ECDSA_Unmarshal(&target->ecdsa, buffer, size); + break; +#endif +#if ALG_ECDAA + case TPM_ALG_ECDAA: + rc = TPMS_SIG_SCHEME_ECDAA_Unmarshal(&target->ecdaa, buffer, size); + break; +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + rc = TPMS_SIG_SCHEME_SM2_Unmarshal(&target->sm2, buffer, size); + break; +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + rc = TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(&target->ecschnorr, buffer, size); + break; +#endif +#if ALG_HMAC + case TPM_ALG_HMAC: + rc = TPMS_SCHEME_HMAC_Unmarshal(&target->hmac, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 145 - Definition of TPMT_SIG_SCHEME Structure */ + +TPM_RC +TPMT_SIG_SCHEME_Unmarshal(TPMT_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_SIG_SCHEME_Unmarshal(&target->scheme, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_SIG_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); + } + return rc; +} + +/* Table 146 - Definition of Types for {RSA} Encryption Schemes */ + +TPM_RC +TPMS_ENC_SCHEME_OAEP_Unmarshal(TPMS_ENC_SCHEME_OAEP *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 146 - Definition of Types for {RSA} Encryption Schemes */ + +TPM_RC +TPMS_ENC_SCHEME_RSAES_Unmarshal(TPMS_ENC_SCHEME_RSAES *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_EMPTY_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 147 - Definition of Types for {ECC} ECC Key Exchange */ + +TPM_RC +TPMS_KEY_SCHEME_ECDH_Unmarshal(TPMS_KEY_SCHEME_ECDH *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 147 - Definition of Types for {ECC} ECC Key Exchange */ + +TPM_RC +TPMS_KEY_SCHEME_ECMQV_Unmarshal(TPMS_KEY_SCHEME_ECMQV *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 148 - Definition of Types for KDF Schemes, hash-based key- or mask-generation functions */ + +TPM_RC +TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_108 *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 148 - Definition of Types for KDF Schemes, hash-based key- or mask-generation functions */ + +TPM_RC +TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_56A *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 148 - Definition of Types for KDF Schemes, hash-based key- or mask-generation functions */ + +TPM_RC +TPMS_KDF_SCHEME_KDF2_Unmarshal(TPMS_KDF_SCHEME_KDF2 *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 148 - Definition of Types for KDF Schemes, hash-based key- or mask-generation functions */ + +TPM_RC +TPMS_KDF_SCHEME_MGF1_Unmarshal(TPMS_KDF_SCHEME_MGF1 *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 149 - Definition of TPMU_KDF_SCHEME Union */ + +TPM_RC +TPMU_KDF_SCHEME_Unmarshal(TPMU_KDF_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_MGF1 + case TPM_ALG_MGF1: + rc = TPMS_KDF_SCHEME_MGF1_Unmarshal(&target->mgf1, buffer, size); + break; +#endif +#if ALG_KDF1_SP800_56A + case TPM_ALG_KDF1_SP800_56A: + rc = TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(&target->kdf1_sp800_56a, buffer, size); + break; +#endif +#if ALG_KDF2 + case TPM_ALG_KDF2: + rc = TPMS_KDF_SCHEME_KDF2_Unmarshal(&target->kdf2, buffer, size); + break; +#endif +#if ALG_KDF1_SP800_108 + case TPM_ALG_KDF1_SP800_108: + rc = TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(&target->kdf1_sp800_108, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 150 - Definition of TPMT_KDF_SCHEME Structure */ + +TPM_RC +TPMT_KDF_SCHEME_Unmarshal(TPMT_KDF_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_KDF_Unmarshal(&target->scheme, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_KDF_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); + } + return rc; +} + +/* Table 151 - Definition of (TPM_ALG_ID) TPMI_ALG_ASYM_SCHEME Type <> */ + +#if 0 +TPM_RC +TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_ASYM_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_ECDH + case TPM_ALG_ECDH: +#endif +#if ALG_ECMQV + case TPM_ALG_ECMQV: +#endif +#if ALG_RSASSA + case TPM_ALG_RSASSA: +#endif +#if ALG_RSAPSS + case TPM_ALG_RSAPSS: +#endif +#if ALG_ECDSA + case TPM_ALG_ECDSA: +#endif +#if ALG_ECDAA + case TPM_ALG_ECDAA: +#endif +#if ALG_SM2 + case TPM_ALG_SM2: +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +#endif +#if ALG_RSAES + case TPM_ALG_RSAES: +#endif +#if ALG_OAEP + case TPM_ALG_OAEP: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} +#endif + +/* Table 152 - Definition of TPMU_ASYM_SCHEME Union */ + +TPM_RC +TPMU_ASYM_SCHEME_Unmarshal(TPMU_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_ECDH + case TPM_ALG_ECDH: + rc = TPMS_KEY_SCHEME_ECDH_Unmarshal(&target->ecdh, buffer, size); + break; +#endif +#if ALG_ECMQV + case TPM_ALG_ECMQV: + rc = TPMS_KEY_SCHEME_ECMQV_Unmarshal(&target->ecmqv, buffer, size); + break; +#endif +#if ALG_RSASSA + case TPM_ALG_RSASSA: + rc = TPMS_SIG_SCHEME_RSASSA_Unmarshal(&target->rsassa, buffer, size); + break; +#endif +#if ALG_RSAPSS + case TPM_ALG_RSAPSS: + rc = TPMS_SIG_SCHEME_RSAPSS_Unmarshal(&target->rsapss, buffer, size); + break; +#endif +#if ALG_ECDSA + case TPM_ALG_ECDSA: + rc = TPMS_SIG_SCHEME_ECDSA_Unmarshal(&target->ecdsa, buffer, size); + break; +#endif +#if ALG_ECDAA + case TPM_ALG_ECDAA: + rc = TPMS_SIG_SCHEME_ECDAA_Unmarshal(&target->ecdaa, buffer, size); + break; +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + rc = TPMS_SIG_SCHEME_SM2_Unmarshal(&target->sm2, buffer, size); + break; +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + rc = TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(&target->ecschnorr, buffer, size); + break; +#endif +#if ALG_RSAES + case TPM_ALG_RSAES: + rc = TPMS_ENC_SCHEME_RSAES_Unmarshal(&target->rsaes, buffer, size); + break; +#endif +#if ALG_OAEP + case TPM_ALG_OAEP: + rc = TPMS_ENC_SCHEME_OAEP_Unmarshal(&target->oaep, buffer, size); + break; +#endif + case TPM_ALG_NULL: + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 154 - Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_SCHEME Type */ + +TPM_RC +TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_RSA_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_RSASSA + case TPM_ALG_RSASSA: +#endif +#if ALG_RSAPSS + case TPM_ALG_RSAPSS: +#endif +#if ALG_RSAES + case TPM_ALG_RSAES: +#endif +#if ALG_OAEP + case TPM_ALG_OAEP: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 155 - Definition of {RSA} TPMT_RSA_SCHEME Structure */ + +TPM_RC +TPMT_RSA_SCHEME_Unmarshal(TPMT_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_RSA_SCHEME_Unmarshal(&target->scheme, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_ASYM_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); + } + return rc; +} + +/* Table 156 - Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_DECRYPT Type */ + +TPM_RC +TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_RSA_DECRYPT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_RSAES + case TPM_ALG_RSAES: +#endif +#if ALG_OAEP + case TPM_ALG_OAEP: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 157 - Definition of {RSA} TPMT_RSA_DECRYPT Structure */ + +TPM_RC +TPMT_RSA_DECRYPT_Unmarshal(TPMT_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_RSA_DECRYPT_Unmarshal(&target->scheme, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_ASYM_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); + } + return rc; +} + +/* Table 158 - Definition of {RSA} TPM2B_PUBLIC_KEY_RSA Structure */ + +TPM_RC +TPM2B_PUBLIC_KEY_RSA_Unmarshal(TPM2B_PUBLIC_KEY_RSA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_RSA_KEY_BYTES, buffer, size); + } + return rc; +} + +/* Table 159 - Definition of {RSA} (TPM_KEY_BITS) TPMI_RSA_KEY_BITS Type */ + +TPM_RC +TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_RSA_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { + case 1024: + case 2048: + case 3072: + break; + default: + rc = TPM_RC_VALUE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 160 - Definition of {RSA} TPM2B_PRIVATE_KEY_RSA Structure */ + +TPM_RC +TPM2B_PRIVATE_KEY_RSA_Unmarshal(TPM2B_PRIVATE_KEY_RSA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_RSA_KEY_BYTES/2, buffer, size); + } + return rc; +} + +/* Table 161 - Definition of {ECC} TPM2B_ECC_PARAMETER Structure */ + +TPM_RC +TPM2B_ECC_PARAMETER_Unmarshal(TPM2B_ECC_PARAMETER *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_ECC_KEY_BYTES, buffer, size); + } + return rc; +} + +/* Table 162 - Definition of {ECC} TPMS_ECC_POINT Structure */ + +TPM_RC +TPMS_ECC_POINT_Unmarshal(TPMS_ECC_POINT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->x, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->y, buffer, size); + } + return rc; +} + +/* Table 163 - Definition of {ECC} TPM2B_ECC_POINT Structure */ + +TPM_RC +TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + INT32 startSize; + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size == 0) { + rc = TPM_RC_SIZE; + } + } + if (rc == TPM_RC_SUCCESS) { + startSize = *size; + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_ECC_POINT_Unmarshal(&target->point, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; + target->size = 0; // libtpms added + } + } + return rc; +} + +/* Table 164 - Definition of (TPM_ALG_ID) {ECC} TPMI_ALG_ECC_SCHEME Type */ + +TPM_RC +TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_ECC_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_ECDSA + case TPM_ALG_ECDSA: +#endif +#if ALG_SM2 + case TPM_ALG_SM2: +#endif +#if ALG_ECDAA + case TPM_ALG_ECDAA: +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +#endif +#if ALG_ECDH + case TPM_ALG_ECDH: +#endif +#if ALG_ECMQV + case TPM_ALG_ECMQV: +#endif + break; + case TPM_ALG_NULL: + if (allowNull) { + break; + } + default: + rc = TPM_RC_SCHEME; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 165 - Definition of {ECC} (TPM_ECC_CURVE) TPMI_ECC_CURVE Type */ + +TPM_RC +TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ECC_CURVE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ECC_CURVE_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ECC_BN_P256 + case TPM_ECC_BN_P256: +#endif +#if ECC_BN_P638 // libtpms added begin + case TPM_ECC_BN_P638: +#endif +#if ECC_NIST_P192 + case TPM_ECC_NIST_P192: +#endif +#if ECC_NIST_P224 + case TPM_ECC_NIST_P224: +#endif // libtpms added end +#if ECC_NIST_P256 + case TPM_ECC_NIST_P256: +#endif +#if ECC_NIST_P384 + case TPM_ECC_NIST_P384: +#endif +#if ECC_NIST_P521 // libtpms added begin + case TPM_ECC_NIST_P521: +#endif +#if ECC_SM2_P256 + case TPM_ECC_SM2_P256: +#endif + if (!CryptEccIsCurveRuntimeUsable(*target)) + rc = TPM_RC_CURVE; + // libtpms added end + break; + default: + rc = TPM_RC_CURVE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 166 - Definition of (TPMT_SIG_SCHEME) {ECC} TPMT_ECC_SCHEME Structure */ + +TPM_RC +TPMT_ECC_SCHEME_Unmarshal(TPMT_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_ECC_SCHEME_Unmarshal(&target->scheme, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_ASYM_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); + } + return rc; +} + +/* Table 168 - Definition of {RSA} TPMS_SIGNATURE_RSA Structure */ + +TPM_RC +TPMS_SIGNATURE_RSA_Unmarshal(TPMS_SIGNATURE_RSA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->hash, buffer, size, NO); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&target->sig, buffer, size); + } + return rc; +} + +/* Table 169 - Definition of Types for {RSA} Signature */ + +TPM_RC +TPMS_SIGNATURE_RSASSA_Unmarshal(TPMS_SIGNATURE_RSASSA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SIGNATURE_RSA_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 169 - Definition of Types for {RSA} Signature */ + +TPM_RC +TPMS_SIGNATURE_RSAPSS_Unmarshal(TPMS_SIGNATURE_RSAPSS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SIGNATURE_RSA_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 170 - Definition of {ECC} TPMS_SIGNATURE_ECC Structure */ + +TPM_RC +TPMS_SIGNATURE_ECC_Unmarshal(TPMS_SIGNATURE_ECC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->hash, buffer, size, NO); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->signatureR, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->signatureS, buffer, size); + } + return rc; +} + +/* Table 171 - Definition of Types for {ECC} TPMS_SIGNATURE_ECC */ + +TPM_RC +TPMS_SIGNATURE_ECDSA_Unmarshal(TPMS_SIGNATURE_ECDSA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size); + } + return rc; +} + +TPM_RC +TPMS_SIGNATURE_ECDAA_Unmarshal(TPMS_SIGNATURE_ECDAA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size); + } + return rc; +} + +TPM_RC +TPMS_SIGNATURE_SM2_Unmarshal(TPMS_SIGNATURE_SM2 *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size); + } + return rc; +} + +TPM_RC +TPMS_SIGNATURE_ECSCHNORR_Unmarshal(TPMS_SIGNATURE_ECSCHNORR *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size); + } + return rc; +} + +/* Table 172 - Definition of TPMU_SIGNATURE Union */ + +TPM_RC +TPMU_SIGNATURE_Unmarshal(TPMU_SIGNATURE *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_RSASSA + case TPM_ALG_RSASSA: + rc = TPMS_SIGNATURE_RSASSA_Unmarshal(&target->rsassa, buffer, size); + break; +#endif +#if ALG_RSAPSS + case TPM_ALG_RSAPSS: + rc = TPMS_SIGNATURE_RSAPSS_Unmarshal(&target->rsapss, buffer, size); + break; +#endif +#if ALG_ECDSA + case TPM_ALG_ECDSA: + rc = TPMS_SIGNATURE_ECDSA_Unmarshal(&target->ecdsa, buffer, size); + break; +#endif +#if ALG_ECDAA + case TPM_ALG_ECDAA: + rc = TPMS_SIGNATURE_ECDAA_Unmarshal(&target->ecdaa, buffer, size); + break; +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + rc = TPMS_SIGNATURE_SM2_Unmarshal(&target->sm2, buffer, size); + break; +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + rc = TPMS_SIGNATURE_ECSCHNORR_Unmarshal(&target->ecschnorr, buffer, size); + break; +#endif +#if ALG_HMAC + case TPM_ALG_HMAC: + rc = TPMT_HA_Unmarshal(&target->hmac, buffer, size, NO); + break; +#endif + case TPM_ALG_NULL: + break; + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 173 - Definition of TPMT_SIGNATURE Structure */ + +TPM_RC +TPMT_SIGNATURE_Unmarshal(TPMT_SIGNATURE *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_SIG_SCHEME_Unmarshal(&target->sigAlg, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_SIGNATURE_Unmarshal(&target->signature, buffer, size, target->sigAlg); + } + return rc; +} + +/* Table 175 - Definition of TPM2B_ENCRYPTED_SECRET Structure */ + +TPM_RC +TPM2B_ENCRYPTED_SECRET_Unmarshal(TPM2B_ENCRYPTED_SECRET *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPMU_ENCRYPTED_SECRET), buffer, size); + } + return rc; +} + +/* Table 176 - Definition of (TPM_ALG_ID) TPMI_ALG_PUBLIC Type */ + +TPM_RC +TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMI_ALG_PUBLIC orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (*target) { +#if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: +#endif +#if ALG_RSA + case TPM_ALG_RSA: +#endif +#if ALG_ECC + case TPM_ALG_ECC: +#endif +#if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: +#endif + break; + default: + rc = TPM_RC_TYPE; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 177 - Definition of TPMU_PUBLIC_ID Union */ + +TPM_RC +TPMU_PUBLIC_ID_Unmarshal(TPMU_PUBLIC_ID *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + rc = TPM2B_DIGEST_Unmarshal(&target->keyedHash, buffer, size); + break; +#endif +#if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + rc = TPM2B_DIGEST_Unmarshal(&target->sym, buffer, size); + break; +#endif +#if ALG_RSA + case TPM_ALG_RSA: + rc = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&target->rsa, buffer, size); + break; +#endif +#if ALG_ECC + case TPM_ALG_ECC: + rc = TPMS_ECC_POINT_Unmarshal(&target->ecc, buffer, size); + break; +#endif + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 178 - Definition of TPMS_KEYEDHASH_PARMS Structure */ + +TPM_RC +TPMS_KEYEDHASH_PARMS_Unmarshal(TPMS_KEYEDHASH_PARMS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_KEYEDHASH_SCHEME_Unmarshal(&target->scheme, buffer, size, YES); + } + return rc; +} + +/* Table 180 - Definition of {RSA} TPMS_RSA_PARMS Structure */ + +TPM_RC +TPMS_RSA_PARMS_Unmarshal(TPMS_RSA_PARMS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_SYM_DEF_OBJECT_Unmarshal(&target->symmetric, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_RSA_SCHEME_Unmarshal(&target->scheme, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_RSA_KEY_BITS_Unmarshal(&target->keyBits, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(&target->exponent, buffer, size); + } + return rc; +} + +/* Table 181 - Definition of {ECC} TPMS_ECC_PARMS Structure */ + +TPM_RC +TPMS_ECC_PARMS_Unmarshal(TPMS_ECC_PARMS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_SYM_DEF_OBJECT_Unmarshal(&target->symmetric, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_ECC_SCHEME_Unmarshal(&target->scheme, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ECC_CURVE_Unmarshal(&target->curveID, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_KDF_SCHEME_Unmarshal(&target->kdf, buffer, size, YES); + } + return rc; +} + +/* Table 182 - Definition of TPMU_PUBLIC_PARMS Union */ + +TPM_RC +TPMU_PUBLIC_PARMS_Unmarshal(TPMU_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + rc = TPMS_KEYEDHASH_PARMS_Unmarshal(&target->keyedHashDetail, buffer, size); + break; +#endif +#if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + rc = TPMS_SYMCIPHER_PARMS_Unmarshal(&target->symDetail, buffer, size); + break; +#endif +#if ALG_RSA + case TPM_ALG_RSA: + rc = TPMS_RSA_PARMS_Unmarshal(&target->rsaDetail, buffer, size); + break; +#endif +#if ALG_ECC + case TPM_ALG_ECC: + rc = TPMS_ECC_PARMS_Unmarshal(&target->eccDetail, buffer, size); + break; +#endif + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 183 - Definition of TPMT_PUBLIC_PARMS Structure */ + +TPM_RC +TPMT_PUBLIC_PARMS_Unmarshal(TPMT_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_PUBLIC_Unmarshal(&target->type, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_PUBLIC_PARMS_Unmarshal(&target->parameters, buffer, size, target->type); + } + return rc; +} + +/* Table 191 - Definition of TPMT_PUBLIC Structure */ + +TPM_RC +TPMT_PUBLIC_Unmarshal(TPMT_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_PUBLIC_Unmarshal(&target->type, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->nameAlg, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMA_OBJECT_Unmarshal(&target->objectAttributes, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->authPolicy, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_PUBLIC_PARMS_Unmarshal(&target->parameters, buffer, size, target->type); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_PUBLIC_ID_Unmarshal(&target->unique, buffer, size, target->type); + } + return rc; +} + +/* Table 192 - Definition of TPM2B_PUBLIC Structure */ + +TPM_RC +TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL allowNull) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + INT32 startSize; + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size == 0) { + rc = TPM_RC_SIZE; + } + } + if (rc == TPM_RC_SUCCESS) { + startSize = *size; + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_PUBLIC_Unmarshal(&target->publicArea, buffer, size, allowNull); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; + target->size = 0; // libtpms added + } + } + return rc; +} + +/* Table 2:193 - Definition of TPM2B_TEMPLATE Structure (StructuresTable()) */ + +TPM_RC +TPM2B_TEMPLATE_Unmarshal(TPM2B_TEMPLATE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPMT_PUBLIC), buffer, size); + } + return rc; +} + +/* Table 187 - Definition of TPMU_SENSITIVE_COMPOSITE Union */ + +TPM_RC +TPMU_SENSITIVE_COMPOSITE_Unmarshal(TPMU_SENSITIVE_COMPOSITE *target, BYTE **buffer, INT32 *size, UINT32 selector) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + switch (selector) { +#if ALG_RSA + case TPM_ALG_RSA: + rc = TPM2B_PRIVATE_KEY_RSA_Unmarshal(&target->rsa, buffer, size); + break; +#endif +#if ALG_ECC + case TPM_ALG_ECC: + rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->ecc, buffer, size); + break; +#endif +#if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + rc = TPM2B_SENSITIVE_DATA_Unmarshal(&target->bits, buffer, size); + break; +#endif +#if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + rc = TPM2B_SYM_KEY_Unmarshal(&target->sym, buffer, size); + break; +#endif + default: + rc = TPM_RC_SELECTOR; + } + return rc; +} + +/* Table 188 - Definition of TPMT_SENSITIVE Structure */ + +TPM_RC +TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_PUBLIC_Unmarshal(&target->sensitiveType, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&target->authValue, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->seedValue, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMU_SENSITIVE_COMPOSITE_Unmarshal(&target->sensitive, buffer, size, target->sensitiveType); + } + return rc; +} + +/* Table 189 - Definition of TPM2B_SENSITIVE Structure */ + +TPM_RC +TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + INT32 startSize; + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->size, buffer, size); + } + if (target->size != 0) { + if (rc == TPM_RC_SUCCESS) { + startSize = *size; + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMT_SENSITIVE_Unmarshal(&target->sensitiveArea, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; + target->size = 0; // libtpms added + } + } + } + return rc; +} + +/* Table 191 - Definition of TPM2B_PRIVATE Structure */ + +TPM_RC +TPM2B_PRIVATE_Unmarshal(TPM2B_PRIVATE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(_PRIVATE), buffer, size); + } + return rc; +} + +/* Table 193 - Definition of TPM2B_ID_OBJECT Structure */ + +TPM_RC +TPM2B_ID_OBJECT_Unmarshal(TPM2B_ID_OBJECT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPMS_ID_OBJECT), buffer, size); + } + return rc; +} + +/* Table 196 - Definition of (UINT32) TPMA_NV Bits */ + +TPM_RC +TPMA_NV_Unmarshal(TPMA_NV *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + TPMA_NV orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ + } + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_NV_RESERVED) { + rc = TPM_RC_RESERVED_BITS; + *target = orig_target; // libtpms added + } + } + return rc; +} + +/* Table 197 - Definition of TPMS_NV_PUBLIC Structure */ + +TPM_RC +TPMS_NV_PUBLIC_Unmarshal(TPMS_NV_PUBLIC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_RH_NV_INDEX_Unmarshal(&target->nvIndex, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_ALG_HASH_Unmarshal(&target->nameAlg, buffer, size, NO); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMA_NV_Unmarshal(&target->attributes, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->authPolicy, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->dataSize, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->dataSize > MAX_NV_INDEX_SIZE) { + rc = TPM_RC_SIZE; + target->dataSize = 0; // libtpms added + } + } + return rc; +} + +/* Table 198 - Definition of TPM2B_NV_PUBLIC Structure */ + +TPM_RC +TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + INT32 startSize; + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&target->size, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size == 0) { + rc = TPM_RC_SIZE; + } + } + if (rc == TPM_RC_SUCCESS) { + startSize = *size; + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMS_NV_PUBLIC_Unmarshal(&target->nvPublic, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; + target->size = 0; // libtpms added + } + } + return rc; +} + +/* Table 199 - Definition of TPM2B_CONTEXT_SENSITIVE Structure */ + +#if 0 // libtpms added +TPM_RC +TPM2B_CONTEXT_SENSITIVE_Unmarshal(TPM2B_CONTEXT_SENSITIVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, MAX_CONTEXT_SIZE, buffer, size); + } + return rc; +} +#endif // libtpms added + +/* Table 201 - Definition of TPM2B_CONTEXT_DATA Structure */ + +TPM_RC +TPM2B_CONTEXT_DATA_Unmarshal(TPM2B_CONTEXT_DATA *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_Unmarshal(&target->b, sizeof(TPMS_CONTEXT_DATA), buffer, size); + } + return rc; +} + +/* Table 202 - Definition of TPMS_CONTEXT Structure */ + +TPM_RC +TPMS_CONTEXT_Unmarshal(TPMS_CONTEXT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + INT32 orig_size = *size; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT64_Unmarshal(&target->sequence, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_DH_SAVED_Unmarshal(&target->savedHandle, buffer, size, NO); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_CONTEXT_DATA_Unmarshal(&target->contextBlob, buffer, size); + } + // libtpms added begin + if (rc == TPM_RC_SUCCESS) { + if (*size > 0) { + /* Windows 2019 server pads the command TPM_ContextLoad up to the value of + * TPM_PT_MAX_OBJECT_CONTENT for the TPMS_CONTEXT part and we end up with + * left-over padding bytes here that will make the TPM2_ContextLoad command + * fail. This is because we don't just write an OBJECT as the context but use + * ANY_OBJECT_Marshal to write it, which consumes less bytes. We had to do + * this due to a Linux TPM resource manager bug that couldn't deal with the + * larger context sizes once RSA 3072 was enabled and it ran out of memory + * when receiving contexts. + * Luckily only one command needs TPMS_CONTEXT unmarshalled, so we can adjust + * for the left-over padding here but also ONLY do this if + * 'orig_size' == value(TPM_PT_MAX_OBJECT_CONTENT). + */ + static UINT32 tpm_pt_max_object_context; + + if (tpm_pt_max_object_context == 0) { + TPML_TAGGED_TPM_PROPERTY tttp; + + TPMCapGetProperties(TPM_PT_MAX_OBJECT_CONTEXT, 1, &tttp); + if (tttp.count == 1) + tpm_pt_max_object_context = tttp.tpmProperty[0].value; + } + if ((UINT32)orig_size == tpm_pt_max_object_context) + *size = 0; /* consume the padding bytes */ + } + } + // libtpms added end + return rc; +} + +/* Table 225 - Definition of (UINT32) TPM_AT Constants */ + +TPM_RC +TPM_AT_Unmarshal(TPM_AT *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); + } + return rc; +} diff --git a/src/tpm2/Unmarshal_fp.h b/src/tpm2/Unmarshal_fp.h new file mode 100644 index 0000000..e541347 --- /dev/null +++ b/src/tpm2/Unmarshal_fp.h @@ -0,0 +1,477 @@ +/********************************************************************************/ +/* */ +/* Unmarshal Prototypes */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Unmarshal_fp.h 1603 2020-04-03 17:48:43Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012 - 2019 */ +/* */ +/********************************************************************************/ + +/* rev 136 */ + +#ifndef UNMARSHAL_FP_H +#define UNMARSHAL_FP_H + +#include "Tpm.h" +#include "TpmTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + + LIB_EXPORT TPM_RC + UINT8_Unmarshal(UINT8 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + INT8_Unmarshal(INT8 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + Array_Unmarshal(BYTE *targetBuffer, UINT16 targetSize, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_Unmarshal(TPM2B *target, UINT16 targetSize, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_KEY_BITS_Unmarshal(TPM_KEY_BITS *target, BYTE **buffer, INT32 *size); +#if 0 + LIB_EXPORT TPM_RC + TPM_GENERATED_Unmarshal(TPM_GENERATED *target, BYTE **buffer, INT32 *size); +#endif + LIB_EXPORT TPM_RC + TPM_ALG_ID_Unmarshal(TPM_ALG_ID *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_CC_Unmarshal(TPM_RC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_PT_Unmarshal(TPM_HANDLE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_PT_PCR_Unmarshal(TPM_PT_PCR *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_HANDLE_Unmarshal(TPM_HANDLE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMA_OBJECT_Unmarshal(TPMA_OBJECT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMA_SESSION_Unmarshal(TPMA_SESSION *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMA_LOCALITY_Unmarshal(TPMA_LOCALITY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMA_CC_Unmarshal(TPMA_CC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT32 *size, BOOL allowPwd); + LIB_EXPORT TPM_RC + TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_HIERARCHY_POLICY_Unmarshal(TPMI_RH_HIERARCHY_POLICY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_AC_Unmarshal(TPMI_RH_AC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RH_ACT_Unmarshal(TPMI_RH_ACT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMS_EMPTY_Unmarshal(TPMS_EMPTY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_HA_Unmarshal(TPMU_HA *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMT_HA_Unmarshal(TPMT_HA *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_DATA_Unmarshal(TPM2B_DATA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_NONCE_Unmarshal(TPM2B_NONCE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_AUTH_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_EVENT_Unmarshal(TPM2B_EVENT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_MAX_BUFFER_Unmarshal(TPM2B_MAX_BUFFER *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_MAX_NV_BUFFER_Unmarshal(TPM2B_MAX_NV_BUFFER *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_TIMEOUT_Unmarshal(TPM2B_TIMEOUT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_IV_Unmarshal(TPM2B_IV *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_NAME_Unmarshal(TPM2B_NAME *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_PCR_SELECTION_Unmarshal(TPMS_PCR_SELECTION *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_ALG_PROPERTY_Unmarshal(TPMS_ALG_PROPERTY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_TAGGED_PROPERTY_Unmarshal(TPMS_TAGGED_PROPERTY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_TAGGED_PCR_SELECT_Unmarshal(TPMS_TAGGED_PCR_SELECT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_CC_Unmarshal(TPML_CC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_TAGGED_POLICY_Unmarshal(TPMS_TAGGED_POLICY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_CCA_Unmarshal(TPML_CCA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_ALG_Unmarshal(TPML_ALG *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_HANDLE_Unmarshal(TPML_HANDLE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_DIGEST_Unmarshal(TPML_DIGEST *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_DIGEST_VALUES_Unmarshal(TPML_DIGEST_VALUES *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_PCR_SELECTION_Unmarshal(TPML_PCR_SELECTION *target, BYTE **buffer, INT32 *size); +#if 0 /* libtpms added */ + LIB_EXPORT TPM_RC + TPML_ALG_PROPERTY_Unmarshal(TPML_ALG_PROPERTY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_TAGGED_TPM_PROPERTY_Unmarshal(TPML_TAGGED_TPM_PROPERTY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_TAGGED_PCR_PROPERTY_Unmarshal(TPML_TAGGED_PCR_PROPERTY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_ECC_CURVE_Unmarshal(TPML_ECC_CURVE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPML_TAGGED_POLICY_Unmarshal(TPML_TAGGED_POLICY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_CAPABILITIES_Unmarshal(TPMU_CAPABILITIES *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMS_CLOCK_INFO_Unmarshal(TPMS_CLOCK_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_TIME_INFO_Unmarshal(TPMS_TIME_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_TIME_ATTEST_INFO_Unmarshal(TPMS_TIME_ATTEST_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_CERTIFY_INFO_Unmarshal(TPMS_CERTIFY_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_QUOTE_INFO_Unmarshal(TPMS_QUOTE_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_COMMAND_AUDIT_INFO_Unmarshal(TPMS_COMMAND_AUDIT_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SESSION_AUDIT_INFO_Unmarshal(TPMS_SESSION_AUDIT_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_CREATION_INFO_Unmarshal(TPMS_CREATION_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_NV_CERTIFY_INFO_Unmarshal(TPMS_NV_CERTIFY_INFO *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_ATTEST_Unmarshal(TPMU_ATTEST *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMS_ATTEST_Unmarshal(TPMS_ATTEST *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_ATTEST_Unmarshal(TPM2B_ATTEST *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_CAPABILITY_DATA_Unmarshal(TPMS_CAPABILITY_DATA *target, BYTE **buffer, INT32 *size); +#endif /* libtpms added */ + LIB_EXPORT TPM_RC + TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC /* libtpms added */ + TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_SYM_KEY_BITS_Unmarshal(TPMU_SYM_KEY_BITS *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMU_SYM_MODE_Unmarshal(TPMU_SYM_MODE *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMT_SYM_DEF_Unmarshal(TPMT_SYM_DEF *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMT_SYM_DEF_OBJECT_Unmarshal(TPMT_SYM_DEF_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPM2B_SYM_KEY_Unmarshal(TPM2B_SYM_KEY *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SYMCIPHER_PARMS_Unmarshal(TPMS_SYMCIPHER_PARMS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_LABEL_Unmarshal(TPM2B_LABEL *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_DERIVE_Unmarshal(TPMS_DERIVE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_SENSITIVE_DATA_Unmarshal(TPM2B_SENSITIVE_DATA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SENSITIVE_CREATE_Unmarshal(TPMS_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_SENSITIVE_CREATE_Unmarshal(TPM2B_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SCHEME_HASH_Unmarshal(TPMS_SCHEME_HASH *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SCHEME_ECDAA_Unmarshal(TPMS_SCHEME_ECDAA *target, BYTE **buffer, INT32 *size) ; + LIB_EXPORT TPM_RC + TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMS_SCHEME_HMAC_Unmarshal(TPMS_SCHEME_HMAC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SCHEME_XOR_Unmarshal(TPMS_SCHEME_XOR *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_SCHEME_KEYEDHASH_Unmarshal(TPMU_SCHEME_KEYEDHASH *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMT_KEYEDHASH_SCHEME_Unmarshal(TPMT_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMS_SIG_SCHEME_ECDAA_Unmarshal(TPMS_SIG_SCHEME_ECDAA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIG_SCHEME_ECDSA_Unmarshal(TPMS_SIG_SCHEME_ECDSA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(TPMS_SIG_SCHEME_ECSCHNORR *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIG_SCHEME_RSAPSS_Unmarshal(TPMS_SIG_SCHEME_RSAPSS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIG_SCHEME_RSASSA_Unmarshal(TPMS_SIG_SCHEME_RSASSA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIG_SCHEME_SM2_Unmarshal(TPMS_SIG_SCHEME_SM2 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_SIG_SCHEME_Unmarshal(TPMU_SIG_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMT_SIG_SCHEME_Unmarshal(TPMT_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMS_ENC_SCHEME_OAEP_Unmarshal(TPMS_ENC_SCHEME_OAEP *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_ENC_SCHEME_RSAES_Unmarshal(TPMS_ENC_SCHEME_RSAES *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_KEY_SCHEME_ECDH_Unmarshal(TPMS_KEY_SCHEME_ECDH *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_KEY_SCHEME_ECMQV_Unmarshal(TPMS_KEY_SCHEME_ECMQV *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_108 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_56A *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_KDF_SCHEME_KDF2_Unmarshal(TPMS_KDF_SCHEME_KDF2 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_KDF_SCHEME_MGF1_Unmarshal(TPMS_KDF_SCHEME_MGF1 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_KDF_SCHEME_Unmarshal(TPMU_KDF_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMT_KDF_SCHEME_Unmarshal(TPMT_KDF_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); +#if 0 /* libtpms added */ + LIB_EXPORT TPM_RC + TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); +#endif /* libtpms added */ + LIB_EXPORT TPM_RC + TPMU_ASYM_SCHEME_Unmarshal(TPMU_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMT_RSA_SCHEME_Unmarshal(TPMT_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMT_RSA_DECRYPT_Unmarshal(TPMT_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPM2B_PUBLIC_KEY_RSA_Unmarshal(TPM2B_PUBLIC_KEY_RSA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_PRIVATE_KEY_RSA_Unmarshal(TPM2B_PRIVATE_KEY_RSA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_ECC_PARAMETER_Unmarshal(TPM2B_ECC_PARAMETER *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_ECC_POINT_Unmarshal(TPMS_ECC_POINT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMT_ECC_SCHEME_Unmarshal(TPMT_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPMS_SIGNATURE_RSA_Unmarshal(TPMS_SIGNATURE_RSA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIGNATURE_RSASSA_Unmarshal(TPMS_SIGNATURE_RSASSA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIGNATURE_RSAPSS_Unmarshal(TPMS_SIGNATURE_RSAPSS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIGNATURE_ECC_Unmarshal(TPMS_SIGNATURE_ECC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIGNATURE_ECDSA_Unmarshal(TPMS_SIGNATURE_ECDSA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIGNATURE_ECDAA_Unmarshal(TPMS_SIGNATURE_ECDAA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIGNATURE_SM2_Unmarshal(TPMS_SIGNATURE_SM2 *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_SIGNATURE_ECSCHNORR_Unmarshal(TPMS_SIGNATURE_ECSCHNORR *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_SIGNATURE_Unmarshal(TPMU_SIGNATURE *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMT_SIGNATURE_Unmarshal(TPMT_SIGNATURE *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPM2B_ENCRYPTED_SECRET_Unmarshal(TPM2B_ENCRYPTED_SECRET *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_PUBLIC_ID_Unmarshal(TPMU_PUBLIC_ID *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMS_KEYEDHASH_PARMS_Unmarshal(TPMS_KEYEDHASH_PARMS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_RSA_PARMS_Unmarshal(TPMS_RSA_PARMS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_ECC_PARMS_Unmarshal(TPMS_ECC_PARMS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_PUBLIC_PARMS_Unmarshal(TPMU_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMT_PUBLIC_PARMS_Unmarshal(TPMT_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMT_PUBLIC_Unmarshal(TPMT_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL allowNull); + LIB_EXPORT TPM_RC + TPM2B_TEMPLATE_Unmarshal(TPM2B_TEMPLATE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMU_SENSITIVE_COMPOSITE_Unmarshal(TPMU_SENSITIVE_COMPOSITE *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC + TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_PRIVATE_Unmarshal(TPM2B_PRIVATE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_ID_OBJECT_Unmarshal(TPM2B_ID_OBJECT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMA_NV_Unmarshal(TPMA_NV *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_NV_PUBLIC_Unmarshal(TPMS_NV_PUBLIC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_CONTEXT_SENSITIVE_Unmarshal(TPM2B_CONTEXT_SENSITIVE *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM2B_CONTEXT_DATA_Unmarshal(TPM2B_CONTEXT_DATA *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPMS_CONTEXT_Unmarshal(TPMS_CONTEXT *target, BYTE **buffer, INT32 *size); + LIB_EXPORT TPM_RC + TPM_AT_Unmarshal(TPM_AT *target, BYTE **buffer, INT32 *size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/tpm2/Unseal_fp.h b/src/tpm2/Unseal_fp.h new file mode 100644 index 0000000..84fa0a4 --- /dev/null +++ b/src/tpm2/Unseal_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Unseal_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef UNSEAL_FP_H +#define UNSEAL_FP_H + +typedef struct { + TPMI_DH_OBJECT itemHandle; +} Unseal_In; + +#define RC_Unseal_itemHandle (TPM_RC_H + TPM_RC_1) + +typedef struct { + TPM2B_SENSITIVE_DATA outData; +} Unseal_Out; + +TPM_RC +TPM2_Unseal( + Unseal_In *in, + Unseal_Out *out + ); + +#endif diff --git a/src/tpm2/Utils.h b/src/tpm2/Utils.h new file mode 100644 index 0000000..b9becef --- /dev/null +++ b/src/tpm2/Utils.h @@ -0,0 +1,54 @@ +/********************************************************************************/ +/* */ +/* Utility functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef UTILS_H +#define UTILS_H + +#include "Memory_fp.h" + +#define TPM2_ROUNDUP(VAL, SIZE) \ + ( ( (VAL) + (SIZE) - 1) / (SIZE) ) * (SIZE) + +__attribute__((unused)) static inline void clear_and_free(void *ptr, size_t size) { + if (ptr) { + MemorySet(ptr, 0, size); + free(ptr); + } +} + +#endif /* UTILS_H */ diff --git a/src/tpm2/VendorString.h b/src/tpm2/VendorString.h new file mode 100644 index 0000000..e33800d --- /dev/null +++ b/src/tpm2/VendorString.h @@ -0,0 +1,108 @@ +/********************************************************************************/ +/* */ +/* Vendor String */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: VendorString.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef VENDORSTRING_H +#define VENDORSTRING_H + +/* Define up to 4-byte values for MANUFACTURER. This value defines the response for + TPM_PT_MANUFACTURER in TPM2_GetCapability(). The following line should be un-commented and a + vendor specific string should be provided here. */ +#define MANUFACTURER "IBM" + +/* The following #if macro may be deleted after a proper MANUFACTURER is provided. */ +#ifndef MANUFACTURER +#error MANUFACTURER is not provided. \ + Please modify VendorString.h to provide a specific \ + manufacturer name. +#endif + +/* Define up to 4, 4-byte, vendor-specific values. The values must each be 4 bytes long and the + last value used may contain trailing zeros. These values define the response for + TPM_PT_VENDOR_STRING_(1-4) in TPM2_GetCapability(). The following line should be un-commented + and a vendor specific string. The vendor strings 2-4 may also be defined as appropriate. */ + +#define VENDOR_STRING_1 "SW " +#define VENDOR_STRING_2 " TPM" +//#define VENDOR_STRING_3 +//#define VENDOR_STRING_4 + +/* The following #if macro may be deleted after a proper VENDOR_STRING_1 is provided. */ +#ifndef VENDOR_STRING_1 +#error VENDOR_STRING_1 is not provided. \ + Please modify VendorString.h to provide a vendor specific string. +#endif + +/* the more significant 32-bits of a vendor-specific value indicating the version of the firmware + The following line should be un-commented and a vendor specific firmware V1 should be provided + here. The FIRMWARE_V2 may also be defined as appropriate. */ +#define FIRMWARE_V1 (0x20191023) + +// the less significant 32-bits of a vendor-specific value indicating the version of the firmware +#define FIRMWARE_V2 (0x00163636) + +// The following #if macro may be deleted after a proper FIRMWARE_V1 is provided. +#ifndef FIRMWARE_V1 +#error FIRMWARE_V1 is not provided. \ + Please modify VendorString.h to provide a vendor specific firmware \ + version +#endif + +#endif diff --git a/src/tpm2/Vendor_TCG_Test.c b/src/tpm2/Vendor_TCG_Test.c new file mode 100644 index 0000000..74c2d11 --- /dev/null +++ b/src/tpm2/Vendor_TCG_Test.c @@ -0,0 +1,76 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Vendor_TCG_Test.c 1548 2019-12-13 23:15:40Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "Vendor_TCG_Test_fp.h" +#include "Marshal_fp.h" +#if CC_Vendor_TCG_Test +/* A dummy function for testing. */ +TPM_RC +TPM2_Vendor_TCG_Test( + Vendor_TCG_Test_In *in, // IN: input parameter list + Vendor_TCG_Test_Out *out // OUT: output parameter list + ) +{ + out->outputData = in->inputData; + return TPM_RC_SUCCESS; +} +#endif // CC_Vendor_TCG_Test diff --git a/src/tpm2/Vendor_TCG_Test_fp.h b/src/tpm2/Vendor_TCG_Test_fp.h new file mode 100644 index 0000000..036ade0 --- /dev/null +++ b/src/tpm2/Vendor_TCG_Test_fp.h @@ -0,0 +1,79 @@ +/********************************************************************************/ +/* */ +/* Sample Vendor Specific Command */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Vendor_TCG_Test_fp.h 1635 2020-06-12 21:48:27Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +#ifndef VENDOR_TCG_TEST_FP_H +#define VENDOR_TCG_TEST_FP_H + +typedef struct { + TPM2B_DATA inputData; +} Vendor_TCG_Test_In; + +typedef struct { + TPM2B_DATA outputData; +} Vendor_TCG_Test_Out; + +TPM_RC +TPM2_Vendor_TCG_Test( + Vendor_TCG_Test_In *in, // IN: input parameter list + Vendor_TCG_Test_Out *out // OUT: output parameter list + ); + +#endif diff --git a/src/tpm2/VerifySignature_fp.h b/src/tpm2/VerifySignature_fp.h new file mode 100644 index 0000000..d90c83a --- /dev/null +++ b/src/tpm2/VerifySignature_fp.h @@ -0,0 +1,88 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: VerifySignature_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef VERIFYSIGNATURE_FP_H +#define VERIFYSIGNATURE_FP_H + +typedef struct { + TPMI_DH_OBJECT keyHandle; + TPM2B_DIGEST digest; + TPMT_SIGNATURE signature; +} VerifySignature_In; + +#define RC_VerifySignature_keyHandle (TPM_RC_H + TPM_RC_1) +#define RC_VerifySignature_digest (TPM_RC_P + TPM_RC_1) +#define RC_VerifySignature_signature (TPM_RC_P + TPM_RC_2) + +typedef struct { + TPMT_TK_VERIFIED validation; +} VerifySignature_Out; + +TPM_RC +TPM2_VerifySignature( + VerifySignature_In *in, // IN: input parameter list + VerifySignature_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/Volatile.c b/src/tpm2/Volatile.c new file mode 100644 index 0000000..ff15c7f --- /dev/null +++ b/src/tpm2/Volatile.c @@ -0,0 +1,119 @@ +/********************************************************************************/ +/* */ +/* Marshalling and unmarshalling of state */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#if defined __FreeBSD__ || defined __DragonFly__ +# include +#elif defined __APPLE__ +# include +#else +# include +#endif +#include + +#include "config.h" + +#include "assert.h" +#include "NVMarshal.h" +#include "Volatile.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" + +TPM_RC +VolatileState_Load(BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + BYTE hash[SHA1_DIGEST_SIZE], acthash[SHA1_DIGEST_SIZE]; + UINT16 hashAlg = TPM_ALG_SHA1; + + if (rc == TPM_RC_SUCCESS) { + if ((UINT32)*size < sizeof(hash)) + return TPM_RC_INSUFFICIENT; + + CryptHashBlock(hashAlg, *size - sizeof(hash), *buffer, + sizeof(acthash), acthash); + rc = VolatileState_Unmarshal(buffer, size); + /* specific error has already been reported */ + } + + if (rc == TPM_RC_SUCCESS) { + /* + * advance pointer towards hash if we have a later version of + * the state that has extra data we didn't read + */ + if (*size > 0 && (UINT32)*size > sizeof(hash)) { + *buffer += *size - sizeof(hash); + *size = sizeof(hash); + } + rc = Array_Unmarshal(hash, sizeof(hash), buffer, size); + if (rc != TPM_RC_SUCCESS) + TPMLIB_LogTPM2Error("Error unmarshalling volatile state hash: " + "0x%02x\n", rc); + } + + if (rc == TPM_RC_SUCCESS) { + if (memcmp(acthash, hash, sizeof(hash))) { + rc = TPM_RC_HASH; + TPMLIB_LogTPM2Error("Volatile state checksum error: 0x%02x\n", + rc); + } + } + + if (rc != TPM_RC_SUCCESS) + g_inFailureMode = TRUE; + + return rc; +} + +UINT16 +VolatileState_Save(BYTE **buffer, INT32 *size) +{ + UINT16 written; + const BYTE *start; + BYTE hash[SHA1_DIGEST_SIZE]; + TPM_ALG_ID hashAlg = TPM_ALG_SHA1; + + start = *buffer; + written = VolatileState_Marshal(buffer, size); + + /* append the checksum */ + CryptHashBlock(hashAlg, written, start, sizeof(hash), hash); + written += Array_Marshal(hash, sizeof(hash), buffer, size); + + return written; +} diff --git a/src/tpm2/Volatile.h b/src/tpm2/Volatile.h new file mode 100644 index 0000000..9913e8d --- /dev/null +++ b/src/tpm2/Volatile.h @@ -0,0 +1,47 @@ +/********************************************************************************/ +/* */ +/* Marshalling and unmarshalling of state */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2017,2018. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef VOLATILE_H +#define VOLATILE_H + +#include "BaseTypes.h" + +TPM_RC VolatileState_Load(BYTE **buffer, INT32 *size); +UINT16 VolatileState_Save(BYTE **buffer, INT32 *size); + +#endif /* VOLATILE_H */ diff --git a/src/tpm2/X509.h b/src/tpm2/X509.h new file mode 100644 index 0000000..42c46e5 --- /dev/null +++ b/src/tpm2/X509.h @@ -0,0 +1,142 @@ +/********************************************************************************/ +/* */ +/* Macro and Structure Definitions for the X509 Commands and Functions. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: X509.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2021 */ +/* */ +/********************************************************************************/ + +// 10.1.16 X509.h +// 10.1.16.1 Introduction +// This file contains the macro and structure definitions for the X509 commands and functions. +#ifndef _X509_H_ +#define _X509_H_ +// 10.1.16.2 Includes +#include "Tpm.h" +#include "TpmAsn1.h" +// 10.1.16.3 Defined Constants +// 10.1.16.3.1 X509 Application-specific types +#define X509_SELECTION 0xA0 +#define X509_ISSUER_UNIQUE_ID 0xA1 +#define X509_SUBJECT_UNIQUE_ID 0xA2 +#define X509_EXTENSIONS 0xA3 +// These defines give the order in which values appear in the TBScertificate of an x.509 +// certificate. These values are used to index into an array of +#define ENCODED_SIZE_REF 0 +#define VERSION_REF (ENCODED_SIZE_REF + 1) +#define SERIAL_NUMBER_REF (VERSION_REF + 1) +#define SIGNATURE_REF (SERIAL_NUMBER_REF + 1) +#define ISSUER_REF (SIGNATURE_REF + 1) +#define VALIDITY_REF (ISSUER_REF + 1) +#define SUBJECT_KEY_REF (VALIDITY_REF + 1) +#define SUBJECT_PUBLIC_KEY_REF (SUBJECT_KEY_REF + 1) +#define EXTENSIONS_REF (SUBJECT_PUBLIC_KEY_REF + 1) +#define REF_COUNT (EXTENSIONS_REF + 1) + +// 10.1.16.4 Structures Used to access the fields of a TBSsignature some of which are in the +// in_CertifyX509 structure and some of which are in the out_CertifyX509 structure. +typedef struct stringRef +{ + BYTE *buf; + INT16 len; +} stringRef; +// This is defined to avoid bit by bit comparisons within a UINT32 +typedef union x509KeyUsageUnion { + TPMA_X509_KEY_USAGE x509; + UINT32 integer; +} x509KeyUsageUnion; + +// 10.1.16.5 Global X509 Constants + +// These values are instanced by X509_spt.c and referenced by other X509-related files. This is the +// DER-encoded value for the Key Usage OID (2.5.29.15). This is the full OID, not just the numeric +// value + +#define OID_KEY_USAGE_EXTENSION_VALUE 0x06, 0x03, 0x55, 0x1D, 0x0F +MAKE_OID(_KEY_USAGE_EXTENSION); + +// This is the DER-encoded value for the TCG-defined TPMA_OBJECT OID (2.23.133.10.1.1.1) + +#define OID_TCG_TPMA_OBJECT_VALUE 0x06, 0x07, 0x67, 0x81, 0x05, 0x0a, 0x01, \ + 0x01, 0x01 +MAKE_OID(_TCG_TPMA_OBJECT); + +#ifdef _X509_SPT_ + +// If a bit is SET in KEY_USAGE_SIGN is also SET in keyUsage then the associated key has to have +// sign SET. + +const x509KeyUsageUnion KEY_USAGE_SIGN = + {TPMA_X509_KEY_USAGE_INITIALIZER( + /* bits_at_0 */ 0, /* decipheronly */ 0, /* encipheronly */ 0, + /* crlsign */ 1, /* keycertsign */ 1, /* keyagreement */ 0, + /* dataencipherment */ 0, /* keyencipherment */ 0, /* nonrepudiation */ 0, + /* digitalsignature */ 1)}; + +// If a bit is SET in KEY_USAGE_DECRYPT is also SET in keyUsage then the associated key has to have decrypt SET. + +const x509KeyUsageUnion KEY_USAGE_DECRYPT = + {TPMA_X509_KEY_USAGE_INITIALIZER( + /* bits_at_0 */ 0, /* decipheronly */ 1, /* encipheronly */ 1, + /* crlsign */ 0, /* keycertsign */ 0, /* keyagreement */ 1, + /* dataencipherment */ 1, /* keyencipherment */ 1, /* nonrepudiation */ 0, + /* digitalsignature */ 0)}; +#else +extern x509KeyUsageUnion KEY_USAGE_SIGN; +extern x509KeyUsageUnion KEY_USAGE_DECRYPT; +#endif + +#endif // _X509_H_ diff --git a/src/tpm2/X509_ECC.c b/src/tpm2/X509_ECC.c new file mode 100644 index 0000000..703b9ff --- /dev/null +++ b/src/tpm2/X509_ECC.c @@ -0,0 +1,173 @@ +/********************************************************************************/ +/* */ +/* TPM X509 ECC */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: X509_ECC.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.24 X509_ECC.c */ +/* 10.2.24.1 Includes */ +#include "Tpm.h" +#include "X509.h" +#include "OIDs.h" +#include "TpmAsn1_fp.h" +#include "X509_ECC_fp.h" +#include "X509_spt_fp.h" +#include "CryptHash_fp.h" + +/* 10.2.24.2 Functions */ +/* 10.2.24.2.1 X509PushPoint() */ +/* This seems like it might be used more than once so... */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +X509PushPoint( + ASN1MarshalContext *ctx, + TPMS_ECC_POINT *p + ) +{ + // Push a bit string containing the public key. For now, push the x, and y + // coordinates of the public point, bottom up + ASN1StartMarshalContext(ctx); // BIT STRING + { + ASN1PushBytes(ctx, p->y.t.size, p->y.t.buffer); + ASN1PushBytes(ctx, p->x.t.size, p->x.t.buffer); + ASN1PushByte(ctx, 0x04); + } + return ASN1EndEncapsulation(ctx, ASN1_BITSTRING); // Ends BIT STRING +} +/* 10.2.24.2.2 X509AddSigningAlgorithmECC() */ +/* This creates the singing algorithm data. */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +X509AddSigningAlgorithmECC( + OBJECT *signKey, + TPMT_SIG_SCHEME *scheme, + ASN1MarshalContext *ctx + ) +{ + PHASH_DEF hashDef = CryptGetHashDef(scheme->details.any.hashAlg); + // + NOT_REFERENCED(signKey); + // If the desired hashAlg definition wasn't found... + if(hashDef->hashAlg != scheme->details.any.hashAlg) + return 0; + + switch(scheme->scheme) + { +#if ALG_ECDSA + case TPM_ALG_ECDSA: + // Make sure that we have an OID for this hash and ECC + if((hashDef->ECDSA)[0] != ASN1_OBJECT_IDENTIFIER) + break; + // if this is just an implementation check, indicate that this + // combination is supported + if(!ctx) + return 1; + ASN1StartMarshalContext(ctx); + ASN1PushOID(ctx, hashDef->ECDSA); + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); +#endif // ALG_ECDSA + default: + break; + } + return 0; +} +/* 10.2.24.2.3 X509AddPublicECC() */ +/* This function will add the publicKey description to the DER data. If ctx is NULL, then no data is + transferred and this function will indicate if the TPM has the values for DER-encoding of the + public key. */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +X509AddPublicECC( + OBJECT *object, + ASN1MarshalContext *ctx + ) +{ + const BYTE *curveOid = + CryptEccGetOID(object->publicArea.parameters.eccDetail.curveID); + if((curveOid == NULL) || (*curveOid != ASN1_OBJECT_IDENTIFIER)) + return 0; + // + // + // SEQUENCE (2 elem) 1st + // SEQUENCE (2 elem) 2nd + // OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type) + // OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named curve) + // BIT STRING (520 bit) 000001001010000111010101010111001001101101000100000010... + // + // If this is a check to see if the key can be encoded, it can. + // Need to mark the end sequence + if(ctx == NULL) + return 1; + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st + { + X509PushPoint(ctx, &object->publicArea.unique.ecc); // BIT STRING + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 2nd + { + ASN1PushOID(ctx, curveOid); // curve dependent + ASN1PushOID(ctx, OID_ECC_PUBLIC); // (1.2.840.10045.2.1) + } + ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 2nd + } + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 1st +} diff --git a/src/tpm2/X509_ECC_fp.h b/src/tpm2/X509_ECC_fp.h new file mode 100644 index 0000000..95cf33c --- /dev/null +++ b/src/tpm2/X509_ECC_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* TPM X509 ECC */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: X509_ECC_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#ifndef X509_ECC_FP_H +#define X509_ECC_FP_H + +INT16 +X509PushPoint( + ASN1MarshalContext *ctx, + TPMS_ECC_POINT *p + ); +INT16 +X509AddSigningAlgorithmECC( + OBJECT *signKey, + TPMT_SIG_SCHEME *scheme, + ASN1MarshalContext *ctx + ); +INT16 +X509AddPublicECC( + OBJECT *object, + ASN1MarshalContext *ctx + ); + + +#endif diff --git a/src/tpm2/X509_RSA.c b/src/tpm2/X509_RSA.c new file mode 100644 index 0000000..3375b3d --- /dev/null +++ b/src/tpm2/X509_RSA.c @@ -0,0 +1,249 @@ +/********************************************************************************/ +/* */ +/* TPM X509 RSA */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: X509_RSA.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.25 X509_RSA.c */ +/* 10.2.25.1 Includes */ +#include "Tpm.h" +#include "X509.h" +#include "TpmAsn1_fp.h" +#include "X509_RSA_fp.h" +#include "X509_spt_fp.h" +#include "CryptHash_fp.h" +#include "CryptRsa_fp.h" + +/* 10.2.25.2 Functions */ +#if ALG_RSA +/* 10.2.25.2.1 X509AddSigningAlgorithmRSA() */ +/* This creates the singing algorithm data. */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +X509AddSigningAlgorithmRSA( + OBJECT *signKey, + TPMT_SIG_SCHEME *scheme, + ASN1MarshalContext *ctx + ) +{ + TPM_ALG_ID hashAlg = scheme->details.any.hashAlg; + PHASH_DEF hashDef = CryptGetHashDef(hashAlg); + // + NOT_REFERENCED(signKey); + // return failure if hash isn't implemented + if(hashDef->hashAlg != hashAlg) + return 0; + switch(scheme->scheme) + { + case TPM_ALG_RSASSA: + { + // if the hash is implemented but there is no PKCS1 OID defined + // then this is not a valid signing combination. + if(hashDef->PKCS1[0] != ASN1_OBJECT_IDENTIFIER) + break; + if(ctx == NULL) + return 1; + return X509PushAlgorithmIdentifierSequence(ctx, hashDef->PKCS1); + } + case TPM_ALG_RSAPSS: + // leave if this is just an implementation check + if(ctx == NULL) + return 1; + // In the case of SHA1, everything is default and RFC4055 says that + // implementations that do signature generation MUST omit the parameter + // when defaults are used. )-: + if(hashDef->hashAlg == TPM_ALG_SHA1) + { + return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS); + } + else + { + // Going to build something that looks like: + // SEQUENCE (2 elem) + // OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1) + // SEQUENCE (3 elem) + // [0] (1 elem) + // SEQUENCE (2 elem) + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 + // NULL + // [1] (1 elem) + // SEQUENCE (2 elem) + // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF + // SEQUENCE (2 elem) + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 + // NULL + // [2] (1 elem) salt length + // INTEGER 32 + + // The indentation is just to keep track of where we are in the + // structure + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elements) + { + ASN1StartMarshalContext(ctx); // SEQUENCE (3 elements) + { + // [2] (1 elem) salt length + // INTEGER 32 + ASN1StartMarshalContext(ctx); + { + INT16 saltSize = + CryptRsaPssSaltSize((INT16)hashDef->digestSize, + (INT16)signKey->publicArea.unique.rsa.t.size); + ASN1PushUINT(ctx, saltSize); + } + ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 2); + + // Add the mask generation algorithm + // [1] (1 elem) + // SEQUENCE (2 elem) 1st + // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF + // SEQUENCE (2 elem) 2nd + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 + // NULL + ASN1StartMarshalContext(ctx); // mask context [1] (1 elem) + { + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st + // Handle the 2nd Sequence (sequence (object, null)) + { + // This adds a NULL, then an OID and a SEQUENCE + // wrapper. + X509PushAlgorithmIdentifierSequence(ctx, + hashDef->OID); + // add the pkcs1-MGF OID + ASN1PushOID(ctx, OID_MGF1); + } + // End outer sequence + ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); + } + // End the [1] + ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 1); + + // Add the hash algorithm + // [0] (1 elem) + // SEQUENCE (2 elem) (done by + // X509PushAlgorithmIdentifierSequence) + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST) + // NULL + ASN1StartMarshalContext(ctx); // [0] (1 elem) + { + X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID); + } + ASN1EndEncapsulation(ctx, (ASN1_APPLICAIION_SPECIFIC + 0)); + } + // SEQUENCE (3 elements) end + ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); + + // RSA PSS OID + // OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1) + ASN1PushOID(ctx, OID_RSAPSS); + } + // End Sequence (2 elements) + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); + } + default: + break; + } + return 0; +} +/* 10.2.25.2.2 X509AddPublicRSA() */ +/* This function will add the publicKey description to the DER data. If fillPtr is NULL, then no + data is transferred and this function will indicate if the TPM has the values for DER-encoding of + the public key. */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +X509AddPublicRSA( + OBJECT *object, + ASN1MarshalContext *ctx + ) +{ + UINT32 exp = object->publicArea.parameters.rsaDetail.exponent; + // + // If this is a check to see if the key can be encoded, it can. + // Need to mark the end sequence + if(ctx == NULL) + return 1; + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st + ASN1StartMarshalContext(ctx); // BIT STRING + ASN1StartMarshalContext(ctx); // SEQUENCE *(2 elem) 3rd + + // Get public exponent in big-endian byte order. + if(exp == 0) + exp = RSA_DEFAULT_PUBLIC_EXPONENT; + + // Push a 4 byte integer. This might get reduced if there are leading zeros or + // extended if the high order byte is negative. + ASN1PushUINT(ctx, exp); + // Push the public key as an integer + ASN1PushInteger(ctx, object->publicArea.unique.rsa.t.size, + object->publicArea.unique.rsa.t.buffer); + // Embed this in a SEQUENCE tag and length in for the key, exponent sequence + ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // SEQUENCE (3rd) + + // Embed this in a BIT STRING + ASN1EndEncapsulation(ctx, ASN1_BITSTRING); + + // Now add the formatted SEQUENCE for the RSA public key OID. This is a + // fully constructed value so it doesn't need to have a context started + X509PushAlgorithmIdentifierSequence(ctx, OID_PKCS1_PUB); + + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); +} +#endif // ALG_RSA diff --git a/src/tpm2/X509_RSA_fp.h b/src/tpm2/X509_RSA_fp.h new file mode 100644 index 0000000..a660e9c --- /dev/null +++ b/src/tpm2/X509_RSA_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* TPM X509 RSA */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: X509_RSA_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#ifndef X509_RSA_FP_H +#define X509_RSA_FP_H + +INT16 +X509AddSigningAlgorithmRSA( + OBJECT *signKey, + TPMT_SIG_SCHEME *scheme, + ASN1MarshalContext *ctx + ); +INT16 +X509AddPublicRSA( + OBJECT *object, + ASN1MarshalContext *ctx + ); + + +#endif diff --git a/src/tpm2/X509_spt.c b/src/tpm2/X509_spt.c new file mode 100644 index 0000000..564a4d3 --- /dev/null +++ b/src/tpm2/X509_spt.c @@ -0,0 +1,318 @@ +/********************************************************************************/ +/* */ +/* X509 Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: X509_spt.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG rants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 - 2021 */ +/* */ +/********************************************************************************/ + + +/* 10.2.26 X509_spt.c */ +/* 10.2.26.1 Includes */ +#include "Tpm.h" +#include "TpmAsn1.h" +#include "TpmAsn1_fp.h" +#define _X509_SPT_ +#include "X509.h" +#include "X509_spt_fp.h" +#if ALG_RSA +# include "X509_RSA_fp.h" +#endif // ALG_RSA +#if ALG_ECC +# include "X509_ECC_fp.h" +#endif // ALG_ECC +#if ALG_SM2 +//# include "X509_SM2_fp.h" +#endif // ALG_RSA +/* 10.2.26.2 Unmarshaling Functions */ +/* 10.2.26.2.1 X509FindExtensionByOID() */ +/* This will search a list of X509 extensions to find an extension with the requested OID. If the + extension is found, the output context (ctx) is set up to point to the OID in the extension. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure (could be catastrophic) */ +BOOL +X509FindExtensionByOID( + ASN1UnmarshalContext *ctxIn, // IN: the context to search + ASN1UnmarshalContext *ctx, // OUT: the extension context + const BYTE *OID // IN: oid to search for + ) +{ + INT16 length; + // + pAssert(ctxIn != NULL); + // Make the search non-destructive of the input if ctx provided. Otherwise, use + // the provided context. + if (ctx == NULL) + ctx = ctxIn; + // if the provided search context is different from the context of the extension, + // then copy the search context to the search context. + else if(ctx != ctxIn) + *ctx = *ctxIn; + // Now, search in the extension context + for(;ctx->size > ctx->offset; ctx->offset += length) + { + VERIFY((length = ASN1NextTag(ctx)) >= 0); + // If this is not a constructed sequence, then it doesn't belong + // in the extensions. + VERIFY(ctx->tag == ASN1_CONSTRUCTED_SEQUENCE); + // Make sure that this entry could hold the OID + if (length >= OID_SIZE(OID)) + { + // See if this is a match for the provided object identifier. + if (MemoryEqual(OID, &(ctx->buffer[ctx->offset]), OID_SIZE(OID))) + { + // Return with ' ctx' set to point to the start of the OID with the size + // set to be the size of the SEQUENCE + ctx->buffer += ctx->offset; + ctx->offset = 0; + ctx->size = length; + return TRUE; + } + } + } + VERIFY(ctx->offset == ctx->size); + return FALSE; + Error: + ctxIn->size = -1; + ctx->size = -1; + return FALSE; +} +/* 10.2.26.2.2 X509GetExtensionBits() */ +/* This function will extract a bit field from an extension. If the extension doesn't contain a bit + string, it will fail. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure */ +UINT32 +X509GetExtensionBits( + ASN1UnmarshalContext *ctx, + UINT32 *value + ) +{ + INT16 length; + // + while (((length = ASN1NextTag(ctx)) > 0) && (ctx->size > ctx->offset)) + { + // Since this is an extension, the extension value will be in an OCTET STRING + if (ctx->tag == ASN1_OCTET_STRING) + { + return ASN1GetBitStringValue(ctx, value); + } + ctx->offset += length; + } + ctx->size = -1; + return FALSE; +} +/* 10.2.26.2.3 X509ProcessExtensions() */ +/* This function is used to process the TPMA_OBJECT and KeyUsage() extensions. It is not in the + CertifyX509.c code because it makes the code harder to follow. */ +/* Error Returns Meaning */ +/* TPM_RCS_ATTRIBUTES the attributes of object are not consistent with the extension setting */ +/* TPM_RC_VALUE problem parsing the extensions */ +TPM_RC +X509ProcessExtensions( + OBJECT *object, // IN: The object with the attributes to + // check + stringRef *extension // IN: The start and length of the extensions + ) +{ + ASN1UnmarshalContext ctx; + ASN1UnmarshalContext extensionCtx; + INT16 length; + UINT32 value; + TPMA_OBJECT attributes = object->publicArea.objectAttributes; + // + if(!ASN1UnmarshalContextInitialize(&ctx, extension->len, extension->buf) + || ((length = ASN1NextTag(&ctx)) < 0) + || (ctx.tag != X509_EXTENSIONS)) + return TPM_RCS_VALUE; + if( ((length = ASN1NextTag(&ctx)) < 0) + || (ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE))) + return TPM_RCS_VALUE; + + // Get the extension for the TPMA_OBJECT if there is one + if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_TCG_TPMA_OBJECT) && + X509GetExtensionBits(&extensionCtx, &value)) + { + // If an keyAttributes extension was found, it must be exactly the same as the + // attributes of the object. + // NOTE: MemoryEqual() is used rather than a simple UINT32 compare to avoid + // type-punned pointer warning/error. + if(!MemoryEqual(&value, &attributes, sizeof(value))) + return TPM_RCS_ATTRIBUTES; + } + // Make sure the failure to find the value wasn't because of a fatal error + else if(extensionCtx.size < 0) + return TPM_RCS_VALUE; + + // Get the keyUsage extension. This one is required + if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_KEY_USAGE_EXTENSION) && + X509GetExtensionBits(&extensionCtx, &value)) + { + x509KeyUsageUnion keyUsage; + BOOL badSign; + BOOL badDecrypt; + BOOL badFixedTPM; + BOOL badRestricted; + + keyUsage.integer = value; + + // For KeyUsage: + // 1) 'sign' is SET if Key Usage includes signing + badSign = ((KEY_USAGE_SIGN.integer & keyUsage.integer) != 0) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign); + // 2) 'decrypt' is SET if Key Usage includes decryption uses + badDecrypt = ((KEY_USAGE_DECRYPT.integer & keyUsage.integer) != 0) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt); + // 3) 'fixedTPM' is SET if Key Usage is non-repudiation + badFixedTPM = IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, + nonrepudiation) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM); + // 4)'restricted' is SET if Key Usage is for key agreement. + badRestricted = IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, keyAgreement) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted); + if(badSign || badDecrypt || badFixedTPM || badRestricted) + return TPM_RCS_VALUE; + } + else + // The KeyUsage extension is required + return TPM_RCS_VALUE; + + return TPM_RC_SUCCESS; +} +/* 10.2.26.3 Marshaling Functions */ +/* 10.2.26.3.1 X509AddSigningAlgorithm() */ +/* This creates the singing algorithm data. */ +/* Return Value Meaning */ +/* > 0 number of octets added */ +/* <= 0 failure */ +INT16 +X509AddSigningAlgorithm( + ASN1MarshalContext *ctx, + OBJECT *signKey, + TPMT_SIG_SCHEME *scheme + ) +{ + switch(signKey->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + return X509AddSigningAlgorithmRSA(signKey, scheme, ctx); +#endif // ALG_RSA +#if ALG_ECC + case TPM_ALG_ECC: + return X509AddSigningAlgorithmECC(signKey, scheme, ctx); +#endif // ALG_ECC +#if ALG_SM2 + case TPM_ALG_SM2: + break; // no signing algorithm for SM2 yet + // return X509AddSigningAlgorithmSM2(signKey, scheme, ctx); +#endif // ALG_SM2 + default: + break; + } + return 0; +} +/* 10.2.26.3.2 X509AddPublicKey() */ +/* This function will add the publicKey description to the DER data. If fillPtr is NULL, then no + data is transferred and this function will indicate if the TPM has the values for DER-encoding of + the public key. */ +/* Return Value Meaning */ +/* > 0 number of octets added */ +/* == 0 failure */ +INT16 +X509AddPublicKey( + ASN1MarshalContext *ctx, + OBJECT *object + ) +{ + switch(object->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + return X509AddPublicRSA(object, ctx); +#endif +#if ALG_ECC + case TPM_ALG_ECC: + return X509AddPublicECC(object, ctx); +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + break; +#endif + default: + break; + } + return FALSE; +} +/* 10.2.26.3.3 X509PushAlgorithmIdentifierSequence() */ +/* The function adds the algorithm identifier sequence. */ +/* Return Value Meaning */ +/* > 0 number of bytes added */ +/* == 0 failure */ +INT16 +X509PushAlgorithmIdentifierSequence( + ASN1MarshalContext *ctx, + const BYTE *OID + ) +{ + ASN1StartMarshalContext(ctx); // hash algorithm + ASN1PushNull(ctx); + ASN1PushOID(ctx, OID); + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); +} + diff --git a/src/tpm2/X509_spt_fp.h b/src/tpm2/X509_spt_fp.h new file mode 100644 index 0000000..96a1587 --- /dev/null +++ b/src/tpm2/X509_spt_fp.h @@ -0,0 +1,98 @@ +/********************************************************************************/ +/* */ +/* X509 Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: X509_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019. */ +/* */ +/********************************************************************************/ + +#ifndef X509_SPT_FP_H +#define X509_SPT_FP_H + +BOOL +X509FindExtensionByOID( + ASN1UnmarshalContext *ctxIn, // IN: the context to search + ASN1UnmarshalContext *ctx, // OUT: the extension context + const BYTE *OID // IN: oid to search for + ); +UINT32 +X509GetExtensionBits( + ASN1UnmarshalContext *ctx, + UINT32 *value + ); +TPM_RC +X509ProcessExtensions( + OBJECT *object, // IN: The object with the attributes to + // check + stringRef *extension // IN: The start and length of the extensions + ); +INT16 +X509AddSigningAlgorithm( + ASN1MarshalContext *ctx, + OBJECT *signKey, + TPMT_SIG_SCHEME *scheme + ); +INT16 +X509AddPublicKey( + ASN1MarshalContext *ctx, + OBJECT *object + ); +INT16 +X509PushAlgorithmIdentifierSequence( + ASN1MarshalContext *ctx, + const BYTE *OID + ); +#endif diff --git a/src/tpm2/ZGen_2Phase_fp.h b/src/tpm2/ZGen_2Phase_fp.h new file mode 100644 index 0000000..6bfb974 --- /dev/null +++ b/src/tpm2/ZGen_2Phase_fp.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: ZGen_2Phase_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2012-2015 */ +/* */ +/********************************************************************************/ + +/* rev 119 */ + +#ifndef ZGEN_2PHASE_FP_H +#define ZGEN_2PHASE_FP_H + +typedef struct { + TPMI_DH_OBJECT keyA; + TPM2B_ECC_POINT inQsB; + TPM2B_ECC_POINT inQeB; + TPMI_ECC_KEY_EXCHANGE inScheme; + UINT16 counter; +} ZGen_2Phase_In; + +#define RC_ZGen_2Phase_keyA (TPM_RC_H + TPM_RC_1) +#define RC_ZGen_2Phase_inQsB (TPM_RC_P + TPM_RC_1) +#define RC_ZGen_2Phase_inQeB (TPM_RC_P + TPM_RC_2) +#define RC_ZGen_2Phase_inScheme (TPM_RC_P + TPM_RC_3) +#define RC_ZGen_2Phase_counter (TPM_RC_P + TPM_RC_4) + +typedef struct { + TPM2B_ECC_POINT outZ1; + TPM2B_ECC_POINT outZ2; +} ZGen_2Phase_Out; + +TPM_RC +TPM2_ZGen_2Phase( + ZGen_2Phase_In *in, // IN: input parameter list + ZGen_2Phase_Out *out // OUT: output parameter list + ); + + +#endif diff --git a/src/tpm2/_TPM_Hash_Data_fp.h b/src/tpm2/_TPM_Hash_Data_fp.h new file mode 100644 index 0000000..0da24c5 --- /dev/null +++ b/src/tpm2/_TPM_Hash_Data_fp.h @@ -0,0 +1,72 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: _TPM_Hash_Data_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef _TPM_HASH_DATA_FP_H +#define _TPM_HASH_DATA_FP_H + +LIB_EXPORT void +_TPM_Hash_Data( + uint32_t dataSize, // IN: size of data to be extend + unsigned char *data // IN: data buffer + ); + + +#endif diff --git a/src/tpm2/_TPM_Hash_End_fp.h b/src/tpm2/_TPM_Hash_End_fp.h new file mode 100644 index 0000000..c99c7f6 --- /dev/null +++ b/src/tpm2/_TPM_Hash_End_fp.h @@ -0,0 +1,71 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: _TPM_Hash_End_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef _TPM_HASH_END_FP_H +#define _TPM_HASH_END_FP_H + +LIB_EXPORT void +_TPM_Hash_End( + void + ); + + +#endif diff --git a/src/tpm2/_TPM_Hash_Start_fp.h b/src/tpm2/_TPM_Hash_Start_fp.h new file mode 100644 index 0000000..9980653 --- /dev/null +++ b/src/tpm2/_TPM_Hash_Start_fp.h @@ -0,0 +1,71 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: _TPM_Hash_Start_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef _TPM_HASH_START_FP_H +#define _TPM_HASH_START_FP_H + +LIB_EXPORT void +_TPM_Hash_Start( + void + ); + + +#endif diff --git a/src/tpm2/_TPM_Init_fp.h b/src/tpm2/_TPM_Init_fp.h new file mode 100644 index 0000000..29929fb --- /dev/null +++ b/src/tpm2/_TPM_Init_fp.h @@ -0,0 +1,73 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: _TPM_Init_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef _TPM_INIT_FP_H +#define _TPM_INIT_FP_H + +LIB_EXPORT void +_TPM_Init( + void + ); + + + + +#endif diff --git a/src/tpm2/crypto/CryptCmac_fp.h b/src/tpm2/crypto/CryptCmac_fp.h new file mode 100644 index 0000000..f1df646 --- /dev/null +++ b/src/tpm2/crypto/CryptCmac_fp.h @@ -0,0 +1,86 @@ +/********************************************************************************/ +/* Message Authentication Codes Based on a Symmetric Block Cipher */ +/* Implementation of cryptographic functions for hashing. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptCmac_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2018 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTCMAC_FP_H +#define CRYPTCMAC_FP_H +#include "Tpm.h" + +UINT16 +CryptCmacStart( + SMAC_STATE *state, + TPMU_PUBLIC_PARMS *keyParms, + TPM_ALG_ID macAlg, + TPM2B *key + ); +void +CryptCmacData( + SMAC_STATES *state, + UINT32 size, + const BYTE *buffer + ); +UINT16 +CryptCmacEnd( + SMAC_STATES *state, + UINT32 outSize, + BYTE *outBuffer + ); + +#endif diff --git a/src/tpm2/crypto/CryptDes_fp.h b/src/tpm2/crypto/CryptDes_fp.h new file mode 100644 index 0000000..1c1c3cd --- /dev/null +++ b/src/tpm2/crypto/CryptDes_fp.h @@ -0,0 +1,82 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptDes_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTDES_FP_H +#define CRYPTDES_FP_H + +UINT64 +CryptSetOddByteParity( + UINT64 k + ); +BOOL +CryptDesValidateKey( + TPM2B_SYM_KEY *desKey // IN: key to validate + ); +TPM_RC +CryptGenerateKeyDes( + TPMT_PUBLIC *publicArea, // IN/OUT: The public area template + // for the new key. + TPMT_SENSITIVE *sensitive, // OUT: sensitive area + RAND_STATE *rand // IN: the "entropy" source for + ); + + +#endif diff --git a/src/tpm2/crypto/CryptEcc.h b/src/tpm2/crypto/CryptEcc.h new file mode 100644 index 0000000..282e12f --- /dev/null +++ b/src/tpm2/crypto/CryptEcc.h @@ -0,0 +1,103 @@ +/********************************************************************************/ +/* */ +/* Structure definitions used for ECC */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEcc.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 10.1.2 CryptEcc.h */ +/* 10.1.2.1 Introduction */ +/* This file contains structure definitions used for ECC. The structures in this file are only used + internally. The ECC-related structures that cross the TPM interface are defined in TpmTypes.h */ +#ifndef _CRYPT_ECC_H +#define _CRYPT_ECC_H + +/* 10.1.2.2 Structures */ +typedef struct ECC_CURVE +{ + const TPM_ECC_CURVE curveId; + const UINT16 keySizeBits; + const TPMT_KDF_SCHEME kdf; + const TPMT_ECC_SCHEME sign; + const ECC_CURVE_DATA *curveData; // the address of the curve data + const BYTE *OID; +} ECC_CURVE; + + +/* 10.1.2.2.1 Macros */ +/* This macro is used to instance an ECC_CURVE_DATA structure for the curve. This structure is + referenced by the ECC_CURVE structure */ +#define CURVE_DATA_DEF(CURVE) \ + const ECC_CURVE_DATA CURVE = { \ + (bigNum)&CURVE##_p_DATA, (bigNum)&CURVE##_n_DATA, (bigNum)&CURVE##_h_DATA, \ + (bigNum)&CURVE##_a_DATA, (bigNum)&CURVE##_b_DATA, \ + {(bigNum)&CURVE##_gX_DATA, (bigNum)&CURVE##_gY_DATA, (bigNum)&BN_ONE} }; + +extern const ECC_CURVE eccCurves[ECC_CURVE_COUNT]; + +#define CURVE_DEF(CURVE) \ + { \ + TPM_ECC_##CURVE, \ + CURVE##_KEY_SIZE, \ + CURVE##_KDF, \ + CURVE##_SIGN, \ + &##CURVE, \ + OID_ECC_##CURVE \ + } +#define CURVE_NAME(N) + +#endif diff --git a/src/tpm2/crypto/CryptEccCrypt_fp.h b/src/tpm2/crypto/CryptEccCrypt_fp.h new file mode 100644 index 0000000..3bb52ce --- /dev/null +++ b/src/tpm2/crypto/CryptEccCrypt_fp.h @@ -0,0 +1,67 @@ +/********************************************************************************/ +/* */ +/* Include Headers for Internal Routines */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEccCrypt_fp.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2020 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTECCCRYPT_FP_H +#define CRYPTECCCRYPT_FP_H + + + +#endif diff --git a/src/tpm2/crypto/CryptEccKeyExchange_fp.h b/src/tpm2/crypto/CryptEccKeyExchange_fp.h new file mode 100644 index 0000000..e4f0b5a --- /dev/null +++ b/src/tpm2/crypto/CryptEccKeyExchange_fp.h @@ -0,0 +1,78 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEccKeyExchange_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTECCKEYEXCHANGE_FP_H +#define CRYPTECCKEYEXCHANGE_FP_H + +LIB_EXPORT TPM_RC +CryptEcc2PhaseKeyExchange( + TPMS_ECC_POINT *outZ1, // OUT: a computed point + TPMS_ECC_POINT *outZ2, // OUT: and optional second point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM_ALG_ID scheme, // IN: the key exchange scheme + TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key + TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key + TPMS_ECC_POINT *QsB, // IN: static public party B key + TPMS_ECC_POINT *QeB // IN: ephemeral public party B key + ); + + +#endif diff --git a/src/tpm2/crypto/CryptEccMain_fp.h b/src/tpm2/crypto/CryptEccMain_fp.h new file mode 100644 index 0000000..2c04fc1 --- /dev/null +++ b/src/tpm2/crypto/CryptEccMain_fp.h @@ -0,0 +1,232 @@ +/********************************************************************************/ +/* */ +/* ECC Main */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEccMain_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTECCMAIN_FP_H +#define CRYPTECCMAIN_FP_H + +void +EccSimulationEnd( + void + ); +BOOL +CryptEccInit( + void + ); +BOOL +CryptEccStartup( + void + ); +void +ClearPoint2B( + TPMS_ECC_POINT *p // IN: the point + ); +LIB_EXPORT const ECC_CURVE * +CryptEccGetParametersByCurveId( + TPM_ECC_CURVE curveId // IN: the curveID + ); +LIB_EXPORT UINT16 +CryptEccGetKeySizeForCurve( + TPM_ECC_CURVE curveId // IN: the curve + ); +const ECC_CURVE_DATA * +GetCurveData( + TPM_ECC_CURVE curveId // IN: the curveID + ); +const BYTE * +CryptEccGetOID( + TPM_ECC_CURVE curveId + ); +LIB_EXPORT TPM_ECC_CURVE +CryptEccGetCurveByIndex( + UINT16 i + ); +LIB_EXPORT BOOL +CryptEccGetParameter( + TPM2B_ECC_PARAMETER *out, // OUT: place to put parameter + char p, // IN: the parameter selector + TPM_ECC_CURVE curveId // IN: the curve id + ); +TPMI_YES_NO +CryptCapGetECCCurve( + TPM_ECC_CURVE curveID, // IN: the starting ECC curve + UINT32 maxCount, // IN: count of returned curves + TPML_ECC_CURVE *curveList // OUT: ECC curve list + ); +const TPMT_ECC_SCHEME * +CryptGetCurveSignScheme( + TPM_ECC_CURVE curveId // IN: The curve selector + ); +BOOL +CryptGenerateR( + TPM2B_ECC_PARAMETER *r, // OUT: the generated random value + UINT16 *c, // IN/OUT: count value. + TPMI_ECC_CURVE curveID, // IN: the curve for the value + TPM2B_NAME *name // IN: optional name of a key to + // associate with 'r' + ); +UINT16 +CryptCommit( + void + ); +void +CryptEndCommit( + UINT16 c // IN: the counter value of the commitment + ); +BOOL +CryptEccGetParameters( + TPM_ECC_CURVE curveId, // IN: ECC curve ID + TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameters + ); +const bignum_t * +BnGetCurvePrime( + TPM_ECC_CURVE curveId + ); +const bignum_t * +BnGetCurveOrder( + TPM_ECC_CURVE curveId + ); +BOOL +BnIsOnCurve( + pointConst Q, + const ECC_CURVE_DATA *C + ); +BOOL +BnIsValidPrivateEcc( + bigConst x, // IN: private key to check + bigCurve E // IN: the curve to check + ); +LIB_EXPORT BOOL +CryptEccIsValidPrivateKey( + TPM2B_ECC_PARAMETER *d, + TPM_ECC_CURVE curveId + ); +TPM_RC +BnPointMult( + bigPoint R, // OUT: computed point + pointConst S, // IN: optional point to multiply by 'd' + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: optional second point + bigConst u, // IN: optional second scalar + bigCurve E // IN: curve parameters + ); +BOOL +BnEccGetPrivate( + bigNum dOut, // OUT: the qualified random value + const ECC_CURVE_DATA *C, // IN: curve for which the private key +#if USE_OPENSSL_FUNCTIONS_EC + const EC_GROUP *G, // IN: the EC_GROUP to use; must be != NULL for rand == NULL + BOOL noLeadingZeros, // IN: require that all bytes in the private key be set + // result may not have leading zero bytes +#endif + // needs to be appropriate + RAND_STATE *rand // IN: state for DRBG + ); +BOOL +BnEccGenerateKeyPair( + bigNum bnD, // OUT: private scalar + bn_point_t *ecQ, // OUT: public point + bigCurve E, // IN: curve for the point + RAND_STATE *rand // IN: DRBG state to use + ); +LIB_EXPORT TPM_RC +CryptEccNewKeyPair( + TPMS_ECC_POINT *Qout, // OUT: the public point + TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar + TPM_ECC_CURVE curveId // IN: the curve for the key + ); +LIB_EXPORT TPM_RC +CryptEccPointMultiply( + TPMS_ECC_POINT *Rout, // OUT: the product point R + TPM_ECC_CURVE curveId, // IN: the curve to use + TPMS_ECC_POINT *Pin, // IN: first point (can be null) + TPM2B_ECC_PARAMETER *dIn, // IN: scalar value for [dIn]Qin + // the Pin + TPMS_ECC_POINT *Qin, // IN: point Q + TPM2B_ECC_PARAMETER *uIn // IN: scalar value for the multiplier + // of Q + ); +LIB_EXPORT BOOL +CryptEccIsPointOnCurve( + TPM_ECC_CURVE curveId, // IN: the curve selector + TPMS_ECC_POINT *Qin // IN: the point. + ); +LIB_EXPORT TPM_RC +CryptEccGenerateKey( + TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for + // the new key. The public key + // area will be replaced computed + // ECC public key + TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be + // updated to contain the private + // ECC key and the symmetric + // encryption key + RAND_STATE *rand // IN: if not NULL, the deterministic + // RNG state + ); + +// libtpms added begin +LIB_EXPORT BOOL +CryptEccIsCurveRuntimeUsable( + TPMI_ECC_CURVE curveId + ); +// libtpms added end + +#endif diff --git a/src/tpm2/crypto/CryptEccSignature_fp.h b/src/tpm2/crypto/CryptEccSignature_fp.h new file mode 100644 index 0000000..5ee813e --- /dev/null +++ b/src/tpm2/crypto/CryptEccSignature_fp.h @@ -0,0 +1,111 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEccSignature_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTECCSIGNATURE_FP_H +#define CRYPTECCSIGNATURE_FP_H + +TPM_RC +BnSignEcdsa( + bigNum bnR, // OUT: r component of the signature + bigNum bnS, // OUT: s component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigNum bnD, // IN: private signing key + const TPM2B_DIGEST *digest, // IN: the digest to sign + RAND_STATE *rand // IN: used in debug of signing + ); +LIB_EXPORT TPM_RC +CryptEccSign( + TPMT_SIGNATURE *signature, // OUT: signature + OBJECT *signKey, // IN: ECC key to sign the hash + const TPM2B_DIGEST *digest, // IN: digest to sign + TPMT_ECC_SCHEME *scheme, // IN: signing scheme + RAND_STATE *rand + ); +TPM_RC +BnValidateSignatureEcdsa( + bigNum bnR, // IN: r component of the signature + bigNum bnS, // IN: s component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bn_point_t *ecQ, // IN: the public point of the key + const TPM2B_DIGEST *digest // IN: the digest that was signed + ); +LIB_EXPORT TPM_RC +CryptEccValidateSignature( + TPMT_SIGNATURE *signature, // IN: signature to be verified + OBJECT *signKey, // IN: ECC key signed the hash + const TPM2B_DIGEST *digest // IN: digest that was signed + ); +LIB_EXPORT TPM_RC +CryptEccCommitCompute( + TPMS_ECC_POINT *K, // OUT: [d]B or [r]Q + TPMS_ECC_POINT *L, // OUT: [r]B + TPMS_ECC_POINT *E, // OUT: [r]M + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPMS_ECC_POINT *M, // IN: M (optional) + TPMS_ECC_POINT *B, // IN: B (optional) + TPM2B_ECC_PARAMETER *d, // IN: d (optional) + TPM2B_ECC_PARAMETER *r // IN: the computed r value (required) + ); + + +#endif diff --git a/src/tpm2/crypto/CryptHash.h b/src/tpm2/crypto/CryptHash.h new file mode 100644 index 0000000..20f52e8 --- /dev/null +++ b/src/tpm2/crypto/CryptHash.h @@ -0,0 +1,343 @@ +/********************************************************************************/ +/* */ +/* Hash structure definitions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptHash.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTHASH_H +#define CRYPTHASH_H + +/* 10.1.3.1 Introduction */ + +/* This header contains the hash structure definitions used in the TPM code to define the amount of + space to be reserved for the hash state. This allows the TPM code to not have to import all of + the symbols used by the hash computations. This lets the build environment of the TPM code not to + have include the header files associated with the CryptoEngine() code. */ + +/* 10.1.3.2 Hash-related Structures */ + +union SMAC_STATES; + +/* These definitions add the high-level methods for processing state that may be an SMAC */ +typedef void(* SMAC_DATA_METHOD)( + union SMAC_STATES *state, + UINT32 size, + const BYTE *buffer + ); +typedef UINT16(* SMAC_END_METHOD)( + union SMAC_STATES *state, + UINT32 size, + BYTE *buffer + ); +typedef struct sequenceMethods { + SMAC_DATA_METHOD data; + SMAC_END_METHOD end; +} SMAC_METHODS; +#define SMAC_IMPLEMENTED (CC_MAC || CC_MAC_Start) + +/* These definitions are here because the SMAC state is in the union of hash states. */ + +typedef struct tpmCmacState { + TPM_ALG_ID symAlg; + UINT16 keySizeBits; + INT16 bcount; // current count of bytes accumulated in IV + TPM2B_IV iv; // IV buffer + TPM2B_SYM_KEY symKey; +} tpmCmacState_t; + +typedef union SMAC_STATES { +#if ALG_CMAC + tpmCmacState_t cmac; +#endif + UINT64 pad; +} SMAC_STATES; + +typedef struct SMAC_STATE { + SMAC_METHODS smacMethods; + SMAC_STATES state; +} SMAC_STATE; + +#if ALG_SHA1 +# define IF_IMPLEMENTED_SHA1(op) op(SHA1, Sha1) +#else +# define IF_IMPLEMENTED_SHA1(op) +#endif +#if ALG_SHA256 +# define IF_IMPLEMENTED_SHA256(op) op(SHA256, Sha256) +#else +# define IF_IMPLEMENTED_SHA256(op) +#endif +#if ALG_SHA384 +# define IF_IMPLEMENTED_SHA384(op) op(SHA384, Sha384) +#else +# define IF_IMPLEMENTED_SHA384(op) +#endif +#if ALG_SHA512 +# define IF_IMPLEMENTED_SHA512(op) op(SHA512, Sha512) +#else +# define IF_IMPLEMENTED_SHA512(op) +#endif +#if ALG_SM3_256 +# define IF_IMPLEMENTED_SM3_256(op) op(SM3_256, Sm3_256) +#else +# define IF_IMPLEMENTED_SM3_256(op) +#endif +#if ALG_SHA3_256 +# define IF_IMPLEMENTED_SHA3_256(op) op(SHA3_256, Sha3_256) +#else +# define IF_IMPLEMENTED_SHA3_256(op) +#endif +#if ALG_SHA3_384 +# define IF_IMPLEMENTED_SHA3_384(op) op(SHA3_384, Sha3_384) +#else +# define IF_IMPLEMENTED_SHA3_384(op) +#endif +#if ALG_SHA3_512 +# define IF_IMPLEMENTED_SHA3_512(op) op(SHA3_512, Sha3_512) +#else +# define IF_IMPLEMENTED_SHA3_512(op) +#endif + +/* SHA512 added kgold */ +#define FOR_EACH_HASH(op) \ + IF_IMPLEMENTED_SHA1(op) \ + IF_IMPLEMENTED_SHA256(op) \ + IF_IMPLEMENTED_SHA384(op) \ + IF_IMPLEMENTED_SHA512(op) \ + IF_IMPLEMENTED_SM3_256(op) \ + IF_IMPLEMENTED_SHA3_256(op) \ + IF_IMPLEMENTED_SHA3_384(op) \ + IF_IMPLEMENTED_SHA3_512(op) + +#define HASH_TYPE(HASH, Hash) tpmHashState##HASH##_t Hash; + +typedef union +{ + FOR_EACH_HASH(HASH_TYPE) + // Additions for symmetric block cipher MAC +#if SMAC_IMPLEMENTED + SMAC_STATE smac; +#endif + // to force structure alignment to be no worse than HASH_ALIGNMENT +#if HASH_ALIGNMENT == 8 + uint64_t align; +#else + uint32_t align; +#endif +} ANY_HASH_STATE; + +typedef ANY_HASH_STATE *PANY_HASH_STATE; +typedef const ANY_HASH_STATE *PCANY_HASH_STATE; +#define ALIGNED_SIZE(x, b) ((((x) + (b) - 1) / (b)) * (b)) +/* MAX_HASH_STATE_SIZE will change with each implementation. It is assumed that a hash state will + not be larger than twice the block size plus some overhead (in this case, 16 bytes). The overall + size needs to be as large as any of the hash contexts. The structure needs to start on an + alignment boundary and be an even multiple of the alignment */ +#define MAX_HASH_STATE_SIZE ((2 * MAX_HASH_BLOCK_SIZE) + 16) +#define MAX_HASH_STATE_SIZE_ALIGNED \ + ALIGNED_SIZE(MAX_HASH_STATE_SIZE, HASH_ALIGNMENT) +/* This is an aligned byte array that will hold any of the hash contexts. */ +typedef ANY_HASH_STATE ALIGNED_HASH_STATE; +/* The header associated with the hash library is expected to define the methods which include the + calling sequence. When not compiling CryptHash.c, the methods are not defined so we need + placeholder functions for the structures */ +#ifndef HASH_START_METHOD_DEF +# define HASH_START_METHOD_DEF void (HASH_START_METHOD)(void) +#endif +#ifndef HASH_DATA_METHOD_DEF +# define HASH_DATA_METHOD_DEF void (HASH_DATA_METHOD)(void) +#endif +#ifndef HASH_END_METHOD_DEF +# define HASH_END_METHOD_DEF void (HASH_END_METHOD)(void) +#endif +#ifndef HASH_STATE_COPY_METHOD_DEF +# define HASH_STATE_COPY_METHOD_DEF void (HASH_STATE_COPY_METHOD)(void) +#endif +#ifndef HASH_STATE_EXPORT_METHOD_DEF +# define HASH_STATE_EXPORT_METHOD_DEF void (HASH_STATE_EXPORT_METHOD)(void) +#endif +#ifndef HASH_STATE_IMPORT_METHOD_DEF +# define HASH_STATE_IMPORT_METHOD_DEF void (HASH_STATE_IMPORT_METHOD)(void) +#endif +/* Define the prototypical function call for each of the methods. This defines the order in which + the parameters are passed to the underlying function. */ +typedef HASH_START_METHOD_DEF; +typedef HASH_DATA_METHOD_DEF; +typedef HASH_END_METHOD_DEF; +typedef HASH_STATE_COPY_METHOD_DEF; +typedef HASH_STATE_EXPORT_METHOD_DEF; +typedef HASH_STATE_IMPORT_METHOD_DEF; +typedef struct _HASH_METHODS +{ + HASH_START_METHOD *start; + HASH_DATA_METHOD *data; + HASH_END_METHOD *end; + HASH_STATE_COPY_METHOD *copy; // Copy a hash block + HASH_STATE_EXPORT_METHOD *copyOut; // Copy a hash block from a hash + // context + HASH_STATE_IMPORT_METHOD *copyIn; // Copy a hash block to a proper hash + // context +} HASH_METHODS, *PHASH_METHODS; + +#define HASH_TPM2B(HASH, Hash) TPM2B_TYPE(HASH##_DIGEST, HASH##_DIGEST_SIZE); + +FOR_EACH_HASH(HASH_TPM2B) + +/* When the TPM implements RSA, the hash-dependent OID pointers are part of the HASH_DEF. These + macros conditionally add the OID reference to the HASH_DEF and the HASH_DEF_TEMPLATE. */ +#if ALG_RSA +#define PKCS1_HASH_REF const BYTE *PKCS1; +#define PKCS1_OID(NAME) , OID_PKCS1_##NAME +#else +#define PKCS1_HASH_REF +#define PKCS1_OID(NAME) +#endif + +/* When the TPM implements ECC, the hash-dependent OID pointers are part of the HASH_DEF. These + macros conditionally add the OID reference to the HASH_DEF and the HASH_DEF_TEMPLATE. */ +#if ALG_ECDSA +#define ECDSA_HASH_REF const BYTE *ECDSA; +#define ECDSA_OID(NAME) , OID_ECDSA_##NAME +#else +#define ECDSA_HASH_REF +#define ECDSA_OID(NAME) +#endif + +typedef const struct +{ + HASH_METHODS method; + uint16_t blockSize; + uint16_t digestSize; + uint16_t contextSize; + uint16_t hashAlg; + const BYTE *OID; + PKCS1_HASH_REF // PKCS1 OID + ECDSA_HASH_REF // ECDSA OID +} HASH_DEF, *PHASH_DEF; + +/* Macro to fill in the HASH_DEF for an algorithm. For SHA1, the instance would be: + HASH_DEF_TEMPLATE(Sha1, SHA1) This handles the difference in capitalization for the various + pieces. */ + +#define HASH_DEF_TEMPLATE(HASH, Hash) \ + HASH_DEF Hash##_Def= { \ + {(HASH_START_METHOD *)&tpmHashStart_##HASH, \ + (HASH_DATA_METHOD *)&tpmHashData_##HASH, \ + (HASH_END_METHOD *)&tpmHashEnd_##HASH, \ + (HASH_STATE_COPY_METHOD *)&tpmHashStateCopy_##HASH, \ + (HASH_STATE_EXPORT_METHOD *)&tpmHashStateExport_##HASH, \ + (HASH_STATE_IMPORT_METHOD *)&tpmHashStateImport_##HASH, \ + }, \ + HASH##_BLOCK_SIZE, /*block size */ \ + HASH##_DIGEST_SIZE, /*data size */ \ + sizeof(tpmHashState##HASH##_t), \ + TPM_ALG_##HASH, OID_##HASH \ + PKCS1_OID(HASH) ECDSA_OID(HASH)}; + +/* These definitions are for the types that can be in a hash state structure. These types are used + in the cryptographic utilities. This is a define rather than an enum so that the size of this + field can be explicit. */ +typedef BYTE HASH_STATE_TYPE; +#define HASH_STATE_EMPTY ((HASH_STATE_TYPE) 0) +#define HASH_STATE_HASH ((HASH_STATE_TYPE) 1) +#define HASH_STATE_HMAC ((HASH_STATE_TYPE) 2) +#if CC_MAC || CC_MAC_Start +#define HASH_STATE_SMAC ((HASH_STATE_TYPE) 3) +#endif +/* This is the structure that is used for passing a context into the hashing functions. It should be + the same size as the function context used within the hashing functions. This is checked when the + hash function is initialized. This version uses a new layout for the contexts and a different + definition. The state buffer is an array of HASH_UNIT values so that a decent compiler will put + the structure on a HASH_UNIT boundary. If the structure is not properly aligned, the code that + manipulates the structure will copy to a properly aligned structure before it is used and copy + the result back. This just makes things slower. */ +/* NOTE: This version of the state had the pointer to the update method in the state. This is to + allow the SMAC functions to use the same structure without having to replicate the entire + HASH_DEF structure. */ +typedef struct _HASH_STATE +{ + HASH_STATE_TYPE type; // type of the context + TPM_ALG_ID hashAlg; + PHASH_DEF def; + ANY_HASH_STATE state; +} HASH_STATE, *PHASH_STATE; +typedef const HASH_STATE *PCHASH_STATE; + +/* 10.1.3.3 HMAC State Structures */ +/* This header contains the hash structure definitions used in the TPM code to define the amount of + space to be reserved for the hash state. This allows the TPM code to not have to import all of + the symbols used by the hash computations. This lets the build environment of the TPM code not to + have include the header files associated with the CryptoEngine() code. */ + +/* An HMAC_STATE structure contains an opaque HMAC stack state. A caller would use this structure + when performing incremental HMAC operations. This structure contains a hash state and an HMAC key + and allows slightly better stack optimization than adding an HMAC key to each hash state. */ +typedef struct hmacState +{ + HASH_STATE hashState; // the hash state + TPM2B_HASH_BLOCK hmacKey; // the HMAC key +} HMAC_STATE, *PHMAC_STATE; +/* This is for the external hash state. This implementation assumes that the size of the exported + hash state is no larger than the internal hash state. */ +typedef struct +{ + BYTE buffer[sizeof(HASH_STATE)]; +} EXPORT_HASH_STATE, *PEXPORT_HASH_STATE; +typedef const EXPORT_HASH_STATE *PCEXPORT_HASH_STATE; + +#endif // _CRYPT_HASH_H diff --git a/src/tpm2/crypto/CryptHash_fp.h b/src/tpm2/crypto/CryptHash_fp.h new file mode 100644 index 0000000..adf1ba9 --- /dev/null +++ b/src/tpm2/crypto/CryptHash_fp.h @@ -0,0 +1,219 @@ +/********************************************************************************/ +/* */ +/* Implementation of cryptographic functions for hashing. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptHash_fp.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTHASH_FP_H +#define CRYPTHASH_FP_H + +BOOL +CryptHashInit( + void + ); +BOOL +CryptHashStartup( + void + ); +PHASH_DEF +CryptGetHashDef( + TPM_ALG_ID hashAlg + ); +BOOL +CryptHashIsValidAlg( + TPM_ALG_ID hashAlg, + BOOL flag + ); +LIB_EXPORT TPM_ALG_ID +CryptHashGetAlgByIndex( + UINT32 index // IN: the index + ); +LIB_EXPORT UINT16 +CryptHashGetDigestSize( + TPM_ALG_ID hashAlg // IN: hash algorithm to look up + ); +LIB_EXPORT UINT16 +CryptHashGetBlockSize( + TPM_ALG_ID hashAlg // IN: hash algorithm to look up + ); +LIB_EXPORT const BYTE * +CryptHashGetOid( + TPM_ALG_ID hashAlg + ); +TPM_ALG_ID +CryptHashGetContextAlg( + PHASH_STATE state // IN: the context to check + ); +LIB_EXPORT void +CryptHashCopyState( + HASH_STATE *out, // OUT: destination of the state + const HASH_STATE *in // IN: source of the state + ); +void +CryptHashExportState( + PCHASH_STATE internalFmt, // IN: the hash state formatted for use by + // library + PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state + ); +void +CryptHashImportState( + PHASH_STATE internalFmt, // OUT: the hash state formatted for use by + // the library + PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state + ); +LIB_EXPORT UINT16 +CryptHashStart( + PHASH_STATE hashState, // OUT: the running hash state + TPM_ALG_ID hashAlg // IN: hash algorithm + ); +LIB_EXPORT void +CryptDigestUpdate( + PHASH_STATE hashState, // IN: the hash context information + UINT32 dataSize, // IN: the size of data to be added + const BYTE *data // IN: data to be hashed + ); +LIB_EXPORT UINT16 +CryptHashEnd( + PHASH_STATE hashState, // IN: the state of hash stack + UINT32 dOutSize, // IN: size of digest buffer + BYTE *dOut // OUT: hash digest + ); +LIB_EXPORT UINT16 +CryptHashBlock( + TPM_ALG_ID hashAlg, // IN: The hash algorithm + UINT32 dataSize, // IN: size of buffer to hash + const BYTE *data, // IN: the buffer to hash + UINT32 dOutSize, // IN: size of the digest buffer + BYTE *dOut // OUT: digest buffer + ); +LIB_EXPORT void +CryptDigestUpdate2B( + PHASH_STATE state, // IN: the digest state + const TPM2B *bIn // IN: 2B containing the data + ); +LIB_EXPORT UINT16 +CryptHashEnd2B( + PHASH_STATE state, // IN: the hash state + P2B digest // IN: the size of the buffer Out: requested + // number of bytes + ); +LIB_EXPORT void +CryptDigestUpdateInt( + void *state, // IN: the state of hash stack + UINT32 intSize, // IN: the size of 'intValue' in bytes + UINT64 intValue // IN: integer value to be hashed + ); +LIB_EXPORT UINT16 +CryptHmacStart( + PHMAC_STATE state, // IN/OUT: the state buffer + TPM_ALG_ID hashAlg, // IN: the algorithm to use + UINT16 keySize, // IN: the size of the HMAC key + const BYTE *key // IN: the HMAC key + ); +LIB_EXPORT UINT16 +CryptHmacEnd( + PHMAC_STATE state, // IN: the hash state buffer + UINT32 dOutSize, // IN: size of digest buffer + BYTE *dOut // OUT: hash digest + ); +LIB_EXPORT UINT16 +CryptHmacStart2B( + PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used + // in HMAC update and completion + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + P2B key // IN: HMAC key + ); +LIB_EXPORT UINT16 +CryptHmacEnd2B( + PHMAC_STATE hmacState, // IN: the state of HMAC stack + P2B digest // OUT: HMAC + ); +LIB_EXPORT UINT16 +CryptMGF_KDF( + UINT32 mSize, // IN: length of the mask to be produced + BYTE *mask, // OUT: buffer to receive the mask + TPM_ALG_ID hashAlg, // IN: hash to use + UINT32 seedSize, // IN: size of the seed + BYTE *seed, // IN: seed size + UINT32 counter // IN: counter initial value + ); +LIB_EXPORT UINT16 +CryptKDFa( + TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC + const TPM2B *key, // IN: HMAC key + const TPM2B *label, // IN: a label for the KDF + const TPM2B *contextU, // IN: context U + const TPM2B *contextV, // IN: context V + UINT32 sizeInBits, // IN: size of generated key in bits + BYTE *keyStream, // OUT: key buffer + UINT32 *counterInOut, // IN/OUT: caller may provide the iteration + UINT16 blocks // IN: If non-zero, this is the maximum number + ); +LIB_EXPORT UINT16 +CryptKDFe( + TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC + TPM2B *Z, // IN: Z + const TPM2B *label, // IN: a label value for the KDF + TPM2B *partyUInfo, // IN: PartyUInfo + TPM2B *partyVInfo, // IN: PartyVInfo + UINT32 sizeInBits, // IN: size of generated key in bits + BYTE *keyStream // OUT: key buffer + ); + + +#endif diff --git a/src/tpm2/crypto/CryptPrimeSieve_fp.h b/src/tpm2/crypto/CryptPrimeSieve_fp.h new file mode 100644 index 0000000..66639a3 --- /dev/null +++ b/src/tpm2/crypto/CryptPrimeSieve_fp.h @@ -0,0 +1,101 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptPrimeSieve_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTPRIMESIEVE_FP_H +#define CRYPTPRIMESIEVE_FP_H + +LIB_EXPORT void +RsaAdjustPrimeLimit( + uint32_t requestedPrimes + ); +LIB_EXPORT uint32_t +RsaNextPrime( + uint32_t lastPrime + ); +LIB_EXPORT int +FindNthSetBit( + const UINT16 aSize, // IN: the size of the array to check + const BYTE *a, // IN: the array to check + const UINT32 n // IN, the number of the SET bit + ); +LIB_EXPORT UINT32 +PrimeSieve( + bigNum bnN, // IN/OUT: number to sieve + UINT32 fieldSize, // IN: size of the field area in bytes + BYTE *field // IN: field + ); +LIB_EXPORT uint32_t +SetFieldSize( + uint32_t newFieldSize + ); +LIB_EXPORT TPM_RC +PrimeSelectWithSieve( + bigNum candidate, // IN/OUT: The candidate to filter + UINT32 e, // IN: the exponent + RAND_STATE *rand // IN: the random number generator state + ); +void +RsaSimulationEnd( + void + ); + + +#endif diff --git a/src/tpm2/crypto/CryptPrime_fp.h b/src/tpm2/crypto/CryptPrime_fp.h new file mode 100644 index 0000000..d9acfcb --- /dev/null +++ b/src/tpm2/crypto/CryptPrime_fp.h @@ -0,0 +1,104 @@ +/********************************************************************************/ +/* */ +/* Code for prime validation */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptPrime_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTPRIME_FP_H +#define CRYPTPRIME_FP_H + +BOOL +IsPrimeInt( + uint32_t n + ); +BOOL +BnIsProbablyPrime( + bigNum prime, // IN: + RAND_STATE *rand // IN: the random state just + // in case Miller-Rabin is required + ); +UINT32 +MillerRabinRounds( + UINT32 bits // IN: Number of bits in the RSA prime + ); +BOOL +MillerRabin( + bigNum bnW, + RAND_STATE *rand + ); +TPM_RC +RsaCheckPrime( + bigNum prime, + UINT32 exponent, + RAND_STATE *rand + ); +LIB_EXPORT void +RsaAdjustPrimeCandidate( + bigNum prime, + SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added + ); +TPM_RC +BnGeneratePrimeForRSA( + bigNum prime, + UINT32 bits, + UINT32 exponent, + RAND_STATE *rand + ); + + +#endif diff --git a/src/tpm2/crypto/CryptRand.h b/src/tpm2/crypto/CryptRand.h new file mode 100644 index 0000000..d339285 --- /dev/null +++ b/src/tpm2/crypto/CryptRand.h @@ -0,0 +1,193 @@ +/********************************************************************************/ +/* */ +/* DRBG with a behavior according to SP800-90A */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptRand.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 10.1.4 CryptRand.h */ +/* 10.1.4.1 Introduction */ +/* This file contains constant definition shared by CryptUtil() and the parts of the Crypto + Engine. */ +#ifndef _CRYPT_RAND_H +#define _CRYPT_RAND_H +/* DRBG Structures and Defines Values and structures for the random number generator. These values + are defined in this header file so that the size of the RNG state can be known to TPM.lib. This + allows the allocation of some space in NV memory for the state to be stored on an orderly + shutdown. The DRBG based on a symmetric block cipher is defined by three values, */ +/* a) the key size */ +/* b) the block size (the IV size) */ +/* c) the symmetric algorithm */ +#define DRBG_KEY_SIZE_BITS AES_MAX_KEY_SIZE_BITS +#define DRBG_IV_SIZE_BITS (AES_MAX_BLOCK_SIZE * 8) +#define DRBG_ALGORITHM TPM_ALG_AES +typedef tpmKeyScheduleAES DRBG_KEY_SCHEDULE; +#define DRBG_ENCRYPT_SETUP(key, keySizeInBits, schedule) \ + TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) +#define DRBG_ENCRYPT(keySchedule, in, out) \ + TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)) +#if ((DRBG_KEY_SIZE_BITS % RADIX_BITS) != 0) \ + || ((DRBG_IV_SIZE_BITS % RADIX_BITS) != 0) +#error "Key size and IV for DRBG must be even multiples of the radix" +#endif +#if (DRBG_KEY_SIZE_BITS % DRBG_IV_SIZE_BITS) != 0 +#error "Key size for DRBG must be even multiple of the cypher block size" +#endif +/* Derived values */ +#define DRBG_MAX_REQUESTS_PER_RESEED (1 << 48) +#define DRBG_MAX_REQEST_SIZE (1 << 32) +#define pDRBG_KEY(seed) ((DRBG_KEY *)&(((BYTE *)(seed))[0])) +#define pDRBG_IV(seed) ((DRBG_IV *)&(((BYTE *)(seed))[DRBG_KEY_SIZE_BYTES])) +#define DRBG_KEY_SIZE_WORDS (BITS_TO_CRYPT_WORDS(DRBG_KEY_SIZE_BITS)) +#define DRBG_KEY_SIZE_BYTES (DRBG_KEY_SIZE_WORDS * RADIX_BYTES) +#define DRBG_IV_SIZE_WORDS (BITS_TO_CRYPT_WORDS(DRBG_IV_SIZE_BITS)) +#define DRBG_IV_SIZE_BYTES (DRBG_IV_SIZE_WORDS * RADIX_BYTES) +#define DRBG_SEED_SIZE_WORDS (DRBG_KEY_SIZE_WORDS + DRBG_IV_SIZE_WORDS) +#define DRBG_SEED_SIZE_BYTES (DRBG_KEY_SIZE_BYTES + DRBG_IV_SIZE_BYTES) +typedef union +{ + BYTE bytes[DRBG_KEY_SIZE_BYTES]; + crypt_uword_t words[DRBG_KEY_SIZE_WORDS]; +} DRBG_KEY; +typedef union +{ + BYTE bytes[DRBG_IV_SIZE_BYTES]; + crypt_uword_t words[DRBG_IV_SIZE_WORDS]; +} DRBG_IV; +typedef union +{ + BYTE bytes[DRBG_SEED_SIZE_BYTES]; + crypt_uword_t words[DRBG_SEED_SIZE_WORDS]; +} DRBG_SEED; +#define CTR_DRBG_MAX_REQUESTS_PER_RESEED ((UINT64)1 << 20) +#define CTR_DRBG_MAX_BYTES_PER_REQUEST (1 << 16) +# define CTR_DRBG_MIN_ENTROPY_INPUT_LENGTH DRBG_SEED_SIZE_BYTES +# define CTR_DRBG_MAX_ENTROPY_INPUT_LENGTH DRBG_SEED_SIZE_BYTES +# define CTR_DRBG_MAX_ADDITIONAL_INPUT_LENGTH DRBG_SEED_SIZE_BYTES +#define TESTING (1 << 0) +#define ENTROPY (1 << 1) +#define TESTED (1 << 2) +#define IsTestStateSet(BIT) ((g_cryptoSelfTestState.rng & BIT) != 0) +#define SetTestStateBit(BIT) (g_cryptoSelfTestState.rng |= BIT) +#define ClearTestStateBit(BIT) (g_cryptoSelfTestState.rng &= ~BIT) +#define IsSelfTest() IsTestStateSet(TESTING) +#define SetSelfTest() SetTestStateBit(TESTING) +#define ClearSelfTest() ClearTestStateBit(TESTING) +#define IsEntropyBad() IsTestStateSet(ENTROPY) +#define SetEntropyBad() SetTestStateBit(ENTROPY) +#define ClearEntropyBad() ClearTestStateBit(ENTROPY) +#define IsDrbgTested() IsTestStateSet(TESTED) +#define SetDrbgTested() SetTestStateBit(TESTED) +#define ClearDrbgTested() ClearTestStateBit(TESTED) + typedef struct + { + UINT64 reseedCounter; + UINT32 magic; + DRBG_SEED seed; // contains the key and IV for the counter mode DRBG + SEED_COMPAT_LEVEL seedCompatLevel; // libtpms added: the compatibility level for keeping backwards compatibility + UINT32 lastValue[4]; // used when the TPM does continuous self-test + // for FIPS compliance of DRBG + } DRBG_STATE, *pDRBG_STATE; +#define DRBG_MAGIC ((UINT32) 0x47425244) // "DRBG" backwards so that it displays +typedef struct KDF_STATE +{ + UINT64 counter; + UINT32 magic; + UINT32 limit; + TPM2B *seed; + const TPM2B *label; + TPM2B *context; + TPM_ALG_ID hash; + TPM_ALG_ID kdf; + UINT16 digestSize; + TPM2B_DIGEST residual; +} KDF_STATE, *pKDR_STATE; +#define KDF_MAGIC ((UINT32) 0x4048444a) // "KDF " backwards +/* Make sure that any other structures added to this union start with a 64-bit counter and a 32-bit + magic number */ +typedef union +{ + DRBG_STATE drbg; + KDF_STATE kdf; +} RAND_STATE; +/* This is the state used when the library uses a random number generator. A special function is + installed for the library to call. That function picks up the state from this location and uses + it for the generation of the random number. */ +extern RAND_STATE *s_random; +/* When instrumenting RSA key sieve */ +#if RSA_INSTRUMENT +#define PRIME_INDEX(x) ((x) == 512 ? 0 : (x) == 1024 ? 1 : 2) +# define INSTRUMENT_SET(a, b) ((a) = (b)) +# define INSTRUMENT_ADD(a, b) (a) = (a) + (b) +# define INSTRUMENT_INC(a) (a) = (a) + 1 +extern UINT32 PrimeIndex; +extern UINT32 failedAtIteration[10]; +extern UINT32 PrimeCounts[3]; +extern UINT32 MillerRabinTrials[3]; +extern UINT32 totalFieldsSieved[3]; +extern UINT32 bitsInFieldAfterSieve[3]; +extern UINT32 emptyFieldsSieved[3]; +extern UINT32 noPrimeFields[3]; +extern UINT32 primesChecked[3]; +extern UINT16 lastSievePrime; +#else +# define INSTRUMENT_SET(a, b) +# define INSTRUMENT_ADD(a, b) +# define INSTRUMENT_INC(a) +#endif +#endif // _CRYPT_RAND_H + diff --git a/src/tpm2/crypto/CryptRand_fp.h b/src/tpm2/crypto/CryptRand_fp.h new file mode 100644 index 0000000..e5dee5b --- /dev/null +++ b/src/tpm2/crypto/CryptRand_fp.h @@ -0,0 +1,158 @@ +/********************************************************************************/ +/* */ +/* DRBG with a behavior according to SP800-90A */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptRand_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTRAND_FP_H +#define CRYPTRAND_FP_H + +BOOL +DRBG_GetEntropy( + UINT32 requiredEntropy, // IN: requested number of bytes of full + // entropy + BYTE *entropy // OUT: buffer to return collected entropy + ); +void +IncrementIv( + DRBG_IV *iv + ); +BOOL +DRBG_Reseed( + DRBG_STATE *drbgState, // IN: the state to update + DRBG_SEED *providedEntropy, // IN: entropy + DRBG_SEED *additionalData // IN: + ); +BOOL +DRBG_SelfTest( + void + ); +LIB_EXPORT TPM_RC +CryptRandomStir( + UINT16 additionalDataSize, + BYTE *additionalData + ); +LIB_EXPORT UINT16 +CryptRandomGenerate( + UINT16 randomSize, + BYTE *buffer + ); +LIB_EXPORT BOOL +DRBG_InstantiateSeededKdf( + KDF_STATE *state, // IN: buffer to hold the state + TPM_ALG_ID hashAlg, // IN: hash algorithm + TPM_ALG_ID kdf, // IN: the KDF to use + TPM2B *seed, // IN: the seed to use + const TPM2B *label, // IN: a label for the generation process. + TPM2B *context, // IN: the context value + UINT32 limit // IN: Maximum number of bits from the KDF + ); +LIB_EXPORT void +DRBG_AdditionalData( + DRBG_STATE *drbgState, // IN:OUT state to update + TPM2B *additionalData // IN: value to incorporate + ); +LIB_EXPORT TPM_RC +DRBG_InstantiateSeeded( + DRBG_STATE *drbgState, // IN: buffer to hold the state + const TPM2B *seed, // IN: the seed to use + const TPM2B *purpose, // IN: a label for the generation process. + const TPM2B *name, // IN: name of the object + const TPM2B *additional, // IN: additional data + SEED_COMPAT_LEVEL seedCompatLevel// IN: compatibility level (associated with seed); libtpms added + ); +LIB_EXPORT BOOL +CryptRandStartup( + void + ); +LIB_EXPORT BOOL +CryptRandInit( + void + ); +LIB_EXPORT UINT16 +DRBG_Generate( + RAND_STATE *state, + BYTE *random, // OUT: buffer to receive the random values + UINT16 randomSize // IN: the number of bytes to generate + ); +// libtpms added begin +LIB_EXPORT SEED_COMPAT_LEVEL +DRBG_GetSeedCompatLevel( + RAND_STATE *state // IN + ); +// libtpms added end +LIB_EXPORT BOOL +DRBG_Instantiate( + DRBG_STATE *drbgState, // OUT: the instantiated value + UINT16 pSize, // IN: Size of personalization string + BYTE *personalization // IN: The personalization string + ); +LIB_EXPORT TPM_RC +DRBG_Uninstantiate( + DRBG_STATE *drbgState // IN/OUT: working state to erase + ); +LIB_EXPORT NUMBYTES +CryptRandMinMax( + BYTE *out, + UINT32 max, + UINT32 min, + RAND_STATE *rand + ); + + +#endif diff --git a/src/tpm2/crypto/CryptRsa.h b/src/tpm2/crypto/CryptRsa.h new file mode 100644 index 0000000..f3c1fa1 --- /dev/null +++ b/src/tpm2/crypto/CryptRsa.h @@ -0,0 +1,99 @@ +/********************************************************************************/ +/* */ +/* RSA-related structures and defines */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptRsa.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +// 10.1.5 CryptRsa.h +// This file contains the RSA-related structures and defines. +#ifndef _CRYPT_RSA_H +#define _CRYPT_RSA_H + +/* This structure is a succinct representation of the cryptographic components of an RSA key. It is + used in testing */ +typedef struct +{ + UINT32 exponent; // The public exponent pointer + TPM2B *publicKey; // Pointer to the public modulus + TPM2B *privateKey; // The private prime +} RSA_KEY; +/* These values are used in the bigNum representation of various RSA values. */ +#define RSA_BITS (MAX_RSA_KEY_BYTES * 8) +BN_TYPE(rsa, RSA_BITS); +#define BN_RSA(name) BN_VAR(name, RSA_BITS) +#define BN_RSA_INITIALIZED(name, initializer) \ + BN_INITIALIZED(name, RSA_BITS, initializer) +#define BN_PRIME(name) BN_VAR(name, (RSA_BITS / 2)) +BN_TYPE(prime, (RSA_BITS / 2)); +#define BN_PRIME_INITIALIZED(name, initializer) \ + BN_INITIALIZED(name, RSA_BITS / 2, initializer) +typedef struct privateExponent +{ +#if CRT_FORMAT_RSA == NO + bn_rsa_t D; +#else + bn_prime_t Q; + bn_prime_t dP; + bn_prime_t dQ; + bn_prime_t qInv; +#endif // CRT_FORMAT_RSA +} privateExponent_t; +#endif // _CRYPT_RSA_H + + + diff --git a/src/tpm2/crypto/CryptRsa_fp.h b/src/tpm2/crypto/CryptRsa_fp.h new file mode 100644 index 0000000..d473b51 --- /dev/null +++ b/src/tpm2/crypto/CryptRsa_fp.h @@ -0,0 +1,139 @@ +/********************************************************************************/ +/* */ +/* Implementation of cryptographic primitives for RSA */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptRsa_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTRSA_FP_H +#define CRYPTRSA_FP_H + +BOOL +CryptRsaInit( + void + ); +BOOL +CryptRsaStartup( + void + ); +void +RsaInitializeExponent( + privateExponent_t *pExp + ); +INT16 +CryptRsaPssSaltSize( + INT16 hashSize, + INT16 outSize + ); +TPMT_RSA_DECRYPT* +CryptRsaSelectScheme( + TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key + TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme + ); +TPM_RC +CryptRsaLoadPrivateExponent( + OBJECT *rsaKey // IN: the RSA key object + ); +LIB_EXPORT TPM_RC +CryptRsaEncrypt( + TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data + TPM2B *dIn, // IN: the data to encrypt + OBJECT *key, // IN: the key used for encryption + TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash + // if needed + const TPM2B *label, // IN: in case it is needed + RAND_STATE *rand // IN: random number generator + // state (mostly for testing) + ); +LIB_EXPORT TPM_RC +CryptRsaDecrypt( + TPM2B *dOut, // OUT: the decrypted data + TPM2B *cIn, // IN: the data to decrypt + OBJECT *key, // IN: the key to use for decryption + TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme + const TPM2B *label // IN: in case it is needed for the scheme + ); +LIB_EXPORT TPM_RC +CryptRsaSign( + TPMT_SIGNATURE *sigOut, + OBJECT *key, // IN: key to use + TPM2B_DIGEST *hIn, // IN: the digest to sign + RAND_STATE *rand // IN: the random number generator + // to use (mostly for testing) + ); +LIB_EXPORT TPM_RC +CryptRsaValidateSignature( + TPMT_SIGNATURE *sig, // IN: signature + OBJECT *key, // IN: public modulus + TPM2B_DIGEST *digest // IN: The digest being validated + ); +LIB_EXPORT TPM_RC +CryptRsaGenerateKey( + OBJECT *rsaKey, // IN/OUT: The object structure in which + // the key is created. + RAND_STATE *rand // IN: if not NULL, the deterministic + // RNG state + ); +INT16 +MakeDerTag( + TPM_ALG_ID hashAlg, + INT16 sizeOfBuffer, + BYTE *buffer + ); + + +#endif diff --git a/src/tpm2/crypto/CryptSelfTest_fp.h b/src/tpm2/crypto/CryptSelfTest_fp.h new file mode 100644 index 0000000..8dd3822 --- /dev/null +++ b/src/tpm2/crypto/CryptSelfTest_fp.h @@ -0,0 +1,87 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptSelfTest_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTSELFTEST_FP_H +#define CRYPTSELFTEST_FP_H + +LIB_EXPORT +TPM_RC +CryptSelfTest( + TPMI_YES_NO fullTest // IN: if full test is required + ); +TPM_RC +CryptIncrementalSelfTest( + TPML_ALG *toTest, // IN: list of algorithms to be tested + TPML_ALG *toDoList // OUT: list of algorithms needing test + ); +void +CryptInitializeToTest( + void + ); +LIB_EXPORT +TPM_RC +CryptTestAlgorithm( + TPM_ALG_ID alg, + ALGORITHM_VECTOR *toTest + ); + + +#endif diff --git a/src/tpm2/crypto/CryptSmac_fp.h b/src/tpm2/crypto/CryptSmac_fp.h new file mode 100644 index 0000000..b93e8ac --- /dev/null +++ b/src/tpm2/crypto/CryptSmac_fp.h @@ -0,0 +1,98 @@ +/********************************************************************************/ +/* Message Authentication Codes Based on a Symmetric Block Cipher */ +/* Implementation of cryptographic functions for hashing. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptSmac_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2018 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTSMAC_FP_H +#define CRYPTSMAC_FP_H +#include "Tpm.h" + +UINT16 +CryptSmacStart( + HASH_STATE *state, + TPMU_PUBLIC_PARMS *keyParameters, + TPM_ALG_ID macAlg, + TPM2B *key + ); +UINT16 +CryptMacStart( + HMAC_STATE *state, + TPMU_PUBLIC_PARMS *keyParameters, + TPM_ALG_ID macAlg, + TPM2B *key + ); +UINT16 +CryptMacEnd( + HMAC_STATE *state, + UINT32 size, + BYTE *buffer + ); +UINT16 +CryptMacEnd( + HMAC_STATE *state, + UINT32 size, + BYTE *buffer + ); +UINT16 +CryptMacEnd2B ( + HMAC_STATE *state, + TPM2B *data + ); + +#endif diff --git a/src/tpm2/crypto/CryptSym.h b/src/tpm2/crypto/CryptSym.h new file mode 100644 index 0000000..66cfb97 --- /dev/null +++ b/src/tpm2/crypto/CryptSym.h @@ -0,0 +1,142 @@ +/********************************************************************************/ +/* */ +/* Implementation of the symmetric block cipher modes */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptSym.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2017 - 2021 */ +/* */ +/********************************************************************************/ + + +#ifndef CRYPTSYM_H +#define CRYPTSYM_H + +#if ALG_AES +# define IF_IMPLEMENTED_AES(op) op(AES, aes) +#else +# define IF_IMPLEMENTED_AES(op) +#endif +#if ALG_SM4 +# define IF_IMPLEMENTED_SM4(op) op(SM4, sm4) +#else +# define IF_IMPLEMENTED_SM4(op) +#endif +#if ALG_CAMELLIA +# define IF_IMPLEMENTED_CAMELLIA(op) op(CAMELLIA, camellia) +#else +# define IF_IMPLEMENTED_CAMELLIA(op) +#endif +#if ALG_TDES +# define IF_IMPLEMENTED_TDES(op) op(TDES, tdes) +#else +# define IF_IMPLEMENTED_TDES(op) +#endif + +#define FOR_EACH_SYM(op) \ + IF_IMPLEMENTED_AES(op) \ + IF_IMPLEMENTED_SM4(op) \ + IF_IMPLEMENTED_CAMELLIA(op) \ + IF_IMPLEMENTED_TDES(op) + + /* libtpms added begin */ +#define FOR_EACH_SYM_WITHOUT_TDES(op) \ + IF_IMPLEMENTED_AES(op) \ + IF_IMPLEMENTED_SM4(op) \ + IF_IMPLEMENTED_CAMELLIA(op) /* libtpms added end */ + +/* Macros for creating the key schedule union */ + +#define KEY_SCHEDULE(SYM, sym) tpmKeySchedule##SYM sym; +//#define TDES DES[3] /* libtpms commented */ +typedef union tpmCryptKeySchedule_t { + FOR_EACH_SYM_WITHOUT_TDES(KEY_SCHEDULE) /* libtpms changed from FOR_EACH_SYM */ + tpmKeyScheduleTDES tdes[3]; /* libtpms added */ + +#if SYMMETRIC_ALIGNMENT == 8 + uint64_t alignment; +#else + uint32_t alignment; +#endif +} tpmCryptKeySchedule_t; + +/* Each block cipher within a library is expected to conform to the same calling conventions with + three parameters (keySchedule, in, and out) in the same order. That means that all algorithms + would use the same order of the same parameters. The code is written assuming the (keySchedule, + in, and out) order. However, if the library uses a different order, the order can be changed with + a SWIZZLE macro that puts the parameters in the correct order. Note that all algorithms have to + use the same order and number of parameters because the code to build the calling list is common + for each call to encrypt or decrypt with the algorithm chosen by setting a function pointer to + select the algorithm that is used. */ +# define ENCRYPT(keySchedule, in, out) \ + encrypt(SWIZZLE(keySchedule, in, out)) +# define DECRYPT(keySchedule, in, out) \ + decrypt(SWIZZLE(keySchedule, in, out)) + +/* Note that the macros rely on encrypt as local values in the functions that use these + macros. Those parameters are set by the macro that set the key schedule to be used for the + call. */ + +#define ENCRYPT_CASE(ALG, alg) \ + case TPM_ALG_##ALG: \ + TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.alg); \ + encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG; \ + break; +#define DECRYPT_CASE(ALG, alg) \ + case TPM_ALG_##ALG: \ + TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.alg); \ + decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG; \ + break; + +#endif diff --git a/src/tpm2/crypto/CryptSym_fp.h b/src/tpm2/crypto/CryptSym_fp.h new file mode 100644 index 0000000..e78215f --- /dev/null +++ b/src/tpm2/crypto/CryptSym_fp.h @@ -0,0 +1,111 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptSym_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTSYM_FP_H +#define CRYPTSYM_FP_H + +BOOL +CryptSymInit( + void + ); +BOOL +CryptSymStartup( + void + ); +LIB_EXPORT INT16 +CryptGetSymmetricBlockSize( + TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm + UINT16 keySizeInBits // IN: the key size + ); +LIB_EXPORT TPM_RC +CryptSymmetricEncrypt( + BYTE *dOut, // OUT: + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE *key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE *dIn // IN: data buffer + ); +LIB_EXPORT TPM_RC +CryptSymmetricDecrypt( + BYTE *dOut, // OUT: decrypted data + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE *key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE *dIn // IN: data buffer + ); +TPM_RC +CryptSymKeyValidate( + TPMT_SYM_DEF_OBJECT *symDef, + TPM2B_SYM_KEY *key + ); + + +#endif diff --git a/src/tpm2/crypto/CryptTest.h b/src/tpm2/crypto/CryptTest.h new file mode 100644 index 0000000..ce2321b --- /dev/null +++ b/src/tpm2/crypto/CryptTest.h @@ -0,0 +1,93 @@ +/********************************************************************************/ +/* */ +/* constant definitions used for self-test. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptTest.h 1594 2020-03-26 22:15:48Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTTEST_H +#define CRYPTTEST_H + +/* 10.1.7 CryptTest.h */ +/* This file contains constant definitions used for self test */ +/* This is the definition of a bit array with one bit per algorithm */ +/* NOTE: Since bit numbering starts at zero, when TPM_ALG_LAST is a multiple of 8, + ALGORITHM_VECTOR will need to have byte for the single bit in the last byte. So, for example, + when TPM_ALG_LAST is 8, ALGORITHM_VECTOR will need 2 bytes. */ +#define ALGORITHM_VECTOR_BYTES ((TPM_ALG_LAST + 8) / 8) +typedef BYTE ALGORITHM_VECTOR[ALGORITHM_VECTOR_BYTES]; +#ifdef TEST_SELF_TEST +LIB_EXPORT extern ALGORITHM_VECTOR LibToTest; +#endif +/* This structure is used to contain self-test tracking information for the cryptographic + modules. Each of the major modules is given a 32-bit value in which it may maintain its own self + test information. The convention for this state is that when all of the bits in this structure + are 0, all functions need to be tested. */ +typedef struct +{ + UINT32 rng; + UINT32 hash; + UINT32 sym; +#if ALG_RSA + UINT32 rsa; +#endif +#if ALG_ECC + UINT32 ecc; +#endif +} CRYPTO_SELF_TEST_STATE; +#endif // _CRYPT_TEST_H + diff --git a/src/tpm2/crypto/CryptUtil_fp.h b/src/tpm2/crypto/CryptUtil_fp.h new file mode 100644 index 0000000..2ca16e7 --- /dev/null +++ b/src/tpm2/crypto/CryptUtil_fp.h @@ -0,0 +1,232 @@ +/********************************************************************************/ +/* */ +/* Interfaces to the CryptoEngine */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptUtil_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef CRYPTUTIL_FP_H +#define CRYPTUTIL_FP_H + +BOOL +CryptIsSchemeAnonymous( + TPM_ALG_ID scheme // IN: the scheme algorithm to test + ); +void +ParmDecryptSym( + TPM_ALG_ID symAlg, // IN: the symmetric algorithm + TPM_ALG_ID hash, // IN: hash algorithm for KDFa + UINT16 keySizeInBits, // IN: the key size in bits + TPM2B *key, // IN: KDF HMAC key + TPM2B *nonceCaller, // IN: nonce caller + TPM2B *nonceTpm, // IN: nonce TPM + UINT32 dataSize, // IN: size of parameter buffer + BYTE *data // OUT: buffer to be decrypted + ); +void +ParmEncryptSym( + TPM_ALG_ID symAlg, // IN: symmetric algorithm + TPM_ALG_ID hash, // IN: hash algorithm for KDFa + UINT16 keySizeInBits, // IN: AES key size in bits + TPM2B *key, // IN: KDF HMAC key + TPM2B *nonceCaller, // IN: nonce caller + TPM2B *nonceTpm, // IN: nonce TPM + UINT32 dataSize, // IN: size of parameter buffer + BYTE *data // OUT: buffer to be encrypted + ); +void +CryptXORObfuscation( + TPM_ALG_ID hash, // IN: hash algorithm for KDF + TPM2B *key, // IN: KDF key + TPM2B *contextU, // IN: contextU + TPM2B *contextV, // IN: contextV + UINT32 dataSize, // IN: size of data buffer + BYTE *data // IN/OUT: data to be XORed in place + ); +BOOL +CryptInit( + void + ); +BOOL +CryptStartup( + STARTUP_TYPE type // IN: the startup type + ); +BOOL +CryptIsAsymAlgorithm( + TPM_ALG_ID algID // IN: algorithm ID + ); +TPM_RC +CryptSecretEncrypt( + OBJECT *encryptKey, // IN: encryption key object + const TPM2B *label, // IN: a null-terminated string as L + TPM2B_DATA *data, // OUT: secret value + TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure + ); +TPM_RC +CryptSecretDecrypt( + OBJECT *decryptKey, // IN: decrypt key + TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for + // symmetric decryption. For + // asymmetric decryption, this + // parameter is NULL + const TPM2B *label, // IN: a value for L + TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret + TPM2B_DATA *data // OUT: decrypted secret value + ); +void +CryptParameterEncryption( + TPM_HANDLE handle, // IN: encrypt session handle + TPM2B *nonceCaller, // IN: nonce caller + UINT16 leadingSizeInByte, // IN: the size of the leading size field in + // bytes + TPM2B_AUTH *extraKey, // IN: additional key material other than + // sessionAuth + BYTE *buffer // IN/OUT: parameter buffer to be encrypted + ); +TPM_RC +CryptParameterDecryption( + TPM_HANDLE handle, // IN: encrypted session handle + TPM2B *nonceCaller, // IN: nonce caller + UINT32 bufferSize, // IN: size of parameter buffer + UINT16 leadingSizeInByte, // IN: the size of the leading size field in + // byte + TPM2B_AUTH *extraKey, // IN: the authValue + BYTE *buffer // IN/OUT: parameter buffer to be decrypted + ); +void +CryptComputeSymmetricUnique( + TPMT_PUBLIC *publicArea, // IN: the object's public area + TPMT_SENSITIVE *sensitive, // IN: the associated sensitive area + TPM2B_DIGEST *unique // OUT: unique buffer + ); +TPM_RC +CryptCreateObject( + OBJECT *object, // IN: new object structure pointer + TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation + RAND_STATE *rand // IN: the random number generator + // to use + ); +TPMI_ALG_HASH +CryptGetSignHashAlg( + TPMT_SIGNATURE *auth // IN: signature + ); +BOOL +CryptIsSplitSign( + TPM_ALG_ID scheme // IN: the algorithm selector + ); +BOOL +CryptIsAsymSignScheme( + TPMI_ALG_PUBLIC publicType, // IN: Type of the object + TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme + ); +BOOL +CryptIsAsymDecryptScheme( + TPMI_ALG_PUBLIC publicType, // IN: Type of the object + TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme + ); +BOOL +CryptSelectSignScheme( + OBJECT *signObject, // IN: signing key + TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme + ); +TPM_RC +CryptSign( + OBJECT *signKey, // IN: signing key + TPMT_SIG_SCHEME *signScheme, // IN: sign scheme. + TPM2B_DIGEST *digest, // IN: The digest being signed + TPMT_SIGNATURE *signature // OUT: signature + ); +TPM_RC +CryptValidateSignature( + TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key + TPM2B_DIGEST *digest, // IN: The digest being validated + TPMT_SIGNATURE *signature // IN: signature + ); +TPM_RC +CryptGetTestResult( + TPM2B_MAX_BUFFER *outData // OUT: test result data + ); +TPM_RC +CryptValidateKeys( + TPMT_PUBLIC *publicArea, + TPMT_SENSITIVE *sensitive, + TPM_RC blamePublic, + TPM_RC blameSensitive + ); +TPM_RC +CryptSelectMac( + TPMT_PUBLIC *publicArea, + TPMI_ALG_MAC_SCHEME *inMac + ); +BOOL +CryptMacIsValidForKey( + TPM_ALG_ID keyType, + TPM_ALG_ID macAlg, + BOOL flag + ); +BOOL +CryptSmacIsValidAlg( + TPM_ALG_ID alg, + BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid + ); +BOOL +CryptSymModeIsValid( + TPM_ALG_ID mode, + BOOL flag + ); + +#endif diff --git a/src/tpm2/crypto/openssl/BnConvert_fp.h b/src/tpm2/crypto/openssl/BnConvert_fp.h new file mode 100644 index 0000000..dd60da0 --- /dev/null +++ b/src/tpm2/crypto/openssl/BnConvert_fp.h @@ -0,0 +1,108 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: BnConvert_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef BNCONVERT_FP_H +#define BNCONVERT_FP_H + +LIB_EXPORT bigNum +BnFromBytes( + bigNum bn, + const BYTE *bytes, + NUMBYTES nBytes + ); +LIB_EXPORT bigNum +BnFrom2B( + bigNum bn, // OUT: + const TPM2B *a2B // IN: number to convert + ); +LIB_EXPORT bigNum +BnFromHex( + bigNum bn, // OUT: + const char *hex // IN: + ); +LIB_EXPORT BOOL +BnToBytes( + bigConst bn, + BYTE *buffer, + NUMBYTES *size // This the number of bytes that are + // available in the buffer. The result + // should be this big. + ); +LIB_EXPORT BOOL +BnTo2B( + bigConst bn, // IN: + TPM2B *a2B, // OUT: + NUMBYTES size // IN: the desired size + ); +LIB_EXPORT bn_point_t * +BnPointFrom2B( + bigPoint ecP, // OUT: the preallocated point structure + TPMS_ECC_POINT *p // IN: the number to convert + ); +LIB_EXPORT BOOL +BnPointTo2B( + TPMS_ECC_POINT *p, // OUT: the converted 2B structure + bigPoint ecP, // IN: the values to be converted + bigCurve E // IN: curve descriptor for the point + ); + + +#endif diff --git a/src/tpm2/crypto/openssl/BnMath_fp.h b/src/tpm2/crypto/openssl/BnMath_fp.h new file mode 100644 index 0000000..62ba7b2 --- /dev/null +++ b/src/tpm2/crypto/openssl/BnMath_fp.h @@ -0,0 +1,163 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: BnMath_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef BNMATH_FP_H +#define BNMATH_FP_H + +LIB_EXPORT BOOL +BnAdd( + bigNum result, + bigConst op1, + bigConst op2 + ); +LIB_EXPORT BOOL +BnAddWord( + bigNum result, + bigConst op, + crypt_uword_t word + ); +LIB_EXPORT BOOL +BnSub( + bigNum result, + bigConst op1, + bigConst op2 + ); +LIB_EXPORT BOOL +BnSubWord( + bigNum result, + bigConst op, + crypt_uword_t word + ); +LIB_EXPORT int +BnUnsignedCmp( + bigConst op1, + bigConst op2 + ); +LIB_EXPORT int +BnUnsignedCmpWord( + bigConst op1, + crypt_uword_t word + ); +LIB_EXPORT crypt_word_t +BnModWord( + bigConst numerator, + crypt_word_t modulus + ); +LIB_EXPORT int +Msb( + crypt_uword_t word + ); +LIB_EXPORT int +BnMsb( + bigConst bn + ); +LIB_EXPORT unsigned +BnSizeInBits( + bigConst n + ); +LIB_EXPORT bigNum +BnSetWord( + bigNum n, + crypt_uword_t w + ); +LIB_EXPORT BOOL +BnSetBit( + bigNum bn, // IN/OUT: big number to modify + unsigned int bitNum // IN: Bit number to SET + ); +LIB_EXPORT BOOL +BnTestBit( + bigNum bn, // IN: number to check + unsigned int bitNum // IN: bit to test + ); +LIB_EXPORT BOOL +BnMaskBits( + bigNum bn, // IN/OUT: number to mask + crypt_uword_t maskBit // IN: the bit number for the mask. + ); +LIB_EXPORT BOOL +BnShiftRight( + bigNum result, + bigConst toShift, + uint32_t shiftAmount + ); +LIB_EXPORT BOOL +BnGetRandomBits( + bigNum n, + size_t bits, + RAND_STATE *rand + ); +LIB_EXPORT BOOL +BnGenerateRandomInRange( + bigNum dest, + bigConst limit, + RAND_STATE *rand + ); +// libtpms added begin +LIB_EXPORT BOOL +BnGenerateRandomInRangeAllBytes( + bigNum dest, + bigConst limit, + RAND_STATE *rand + ); +// libtpms added end + +#endif diff --git a/src/tpm2/crypto/openssl/BnMemory_fp.h b/src/tpm2/crypto/openssl/BnMemory_fp.h new file mode 100644 index 0000000..819a0a6 --- /dev/null +++ b/src/tpm2/crypto/openssl/BnMemory_fp.h @@ -0,0 +1,108 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: BnMemory_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef BNMEMORY_FP_H +#define BNMEMORY_FP_H + +LIB_EXPORT bigNum +BnSetTop( + bigNum bn, // IN/OUT: number to clean + crypt_uword_t top // IN: the new top + ); +#if 0 /* libtpms added */ +LIB_EXPORT bigNum +BnClearTop( + bigNum bn + ); +#endif /* libtpms added */ +LIB_EXPORT bigNum +BnInitializeWord( + bigNum bn, // IN: + crypt_uword_t allocated, // IN: + crypt_uword_t word // IN: + ); +LIB_EXPORT bigNum +BnInit( + bigNum bn, + crypt_uword_t allocated + ); +LIB_EXPORT BOOL +BnCopy( + bigNum out, + bigConst in + ); +#if 0 /* libtpms added */ +LIB_EXPORT BOOL +BnPointCopy( + bigPoint pOut, + pointConst pIn + ); +#endif /* libtpms added */ +LIB_EXPORT bn_point_t * +BnInitializePoint( + bigPoint p, // OUT: structure to receive pointers + bigNum x, // IN: x coordinate + bigNum y, // IN: y coordinate + bigNum z // IN: x coordinate + ); + + +#endif diff --git a/src/tpm2/crypto/openssl/BnValues.h b/src/tpm2/crypto/openssl/BnValues.h new file mode 100644 index 0000000..1e0164d --- /dev/null +++ b/src/tpm2/crypto/openssl/BnValues.h @@ -0,0 +1,329 @@ +/********************************************************************************/ +/* */ +/* For defining the internal BIGNUM structure */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: BnValues.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.1.1 BnValues.h */ +/* This file contains the definitions needed for defining the internal BIGNUM structure. A BIGNUM is + a pointer to a structure. The structure has three fields. The last field is and array (d) of + crypt_uword_t. Each word is in machine format (big- or little-endian) with the words in ascending + significance (i.e. words in little-endian order). This is the order that seems to be used in + every big number library in the worlds, so... */ +/* The first field in the structure (allocated) is the number of words in d. This is the upper limit + on the size of the number that can be held in the structure. This differs from libraries like + OpenSSL() as this is not intended to deal with numbers of arbitrary size; just numbers that are + needed to deal with the algorithms that are defined in the TPM implementation. */ +/* The second field in the structure (size) is the number of significant words in n. When this + number is zero, the number is zero. The word at used-1 should never be zero. All words between + d[size] and d[allocated-1] should be zero. */ +#ifndef _BN_NUMBERS_H +#define _BN_NUMBERS_H +#if RADIX_BITS == 64 +# define RADIX_LOG2 6 +#elif RADIX_BITS == 32 +#define RADIX_LOG2 5 +#else +# error "Unsupported radix" +#endif +#define RADIX_MOD(x) ((x) & ((1 << RADIX_LOG2) - 1)) +#define RADIX_DIV(x) ((x) >> RADIX_LOG2) +#define RADIX_MASK ((((crypt_uword_t)1) << RADIX_LOG2) - 1) +#define BITS_TO_CRYPT_WORDS(bits) RADIX_DIV((bits) + (RADIX_BITS - 1)) +#define BYTES_TO_CRYPT_WORDS(bytes) BITS_TO_CRYPT_WORDS(bytes * 8) +#define SIZE_IN_CRYPT_WORDS(thing) BYTES_TO_CRYPT_WORDS(sizeof(thing)) +#if RADIX_BITS == 64 +#define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_64(x) +typedef uint64_t crypt_uword_t; +typedef int64_t crypt_word_t; +# define TO_CRYPT_WORD_64 BIG_ENDIAN_BYTES_TO_UINT64 +# define TO_CRYPT_WORD_32(a, b, c, d) TO_CRYPT_WORD_64(0, 0, 0, 0, a, b, c, d) +#define BN_PAD 0 /* libtpms added */ +#elif RADIX_BITS == 32 +#define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_32((x)) +typedef uint32_t crypt_uword_t; +typedef int32_t crypt_word_t; +# define TO_CRYPT_WORD_64(a, b, c, d, e, f, g, h) \ + BIG_ENDIAN_BYTES_TO_UINT32(e, f, g, h), \ + BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d) +# define TO_CRYPT_WORD_32 BIG_ENDIAN_BYTES_TO_UINT32 +#define BN_PAD 1 /* libtpms added */ +#endif +#define MAX_CRYPT_UWORD (~((crypt_uword_t)0)) +#define MAX_CRYPT_WORD ((crypt_word_t)(MAX_CRYPT_UWORD >> 1)) +#define MIN_CRYPT_WORD (~MAX_CRYPT_WORD) +#define LARGEST_NUMBER (MAX((ALG_RSA * MAX_RSA_KEY_BYTES), \ + MAX((ALG_ECC * MAX_ECC_KEY_BYTES), MAX_DIGEST_SIZE))) +#define LARGEST_NUMBER_BITS (LARGEST_NUMBER * 8) +#define MAX_ECC_PARAMETER_BYTES (MAX_ECC_KEY_BYTES * ALG_ECC) +/* These are the basic big number formats. This is convertible to the library- specific format + without too much difficulty. For the math performed using these numbers, the value is always + positive. */ +#define BN_STRUCT_DEF(count) struct { \ + crypt_uword_t allocated; \ + crypt_uword_t size; \ + crypt_uword_t d[count + BN_PAD + BN_PAD + BN_PAD]; /* libtpms changed */ \ + } +typedef BN_STRUCT_DEF(1) bignum_t; +#ifndef bigNum +typedef bignum_t *bigNum; +typedef const bignum_t *bigConst; +#endif +extern const bignum_t BnConstZero; +/* The Functions to access the properties of a big number. Get number of allocated words */ +#define BnGetAllocated(x) (unsigned)((x)->allocated) +/* Get number of words used */ +#define BnGetSize(x) ((x)->size) +/* Get a pointer to the data array */ +#define BnGetArray(x) ((crypt_uword_t *)&((x)->d[0])) +/* Get the nth word of a BIGNUM (zero-based) */ +#define BnGetWord(x, i) (crypt_uword_t)((x)->d[i]) +/* Some things that are done often. Test to see if a bignum_t is equal to zero */ +#define BnEqualZero(bn) (BnGetSize(bn) == 0) +/* Test to see if a bignum_t is equal to a word type */ +#define BnEqualWord(bn, word) \ + ((BnGetSize(bn) == 1) && (BnGetWord(bn, 0) == (crypt_uword_t)word)) +/* Determine if a BIGNUM is even. A zero is even. Although the indication that a number is zero is + that its size is zero, all words of the number are 0 so this test works on zero. */ +#define BnIsEven(n) ((BnGetWord(n, 0) & 1) == 0) +/* The macros below are used to define BIGNUM values of the required size. The values are allocated + on the stack so they can be treated like simple local values. This will call the initialization + function for a defined bignum_t. This sets the allocated and used fields and clears the words of + n. */ +#define BN_INIT(name) \ + (bigNum)BnInit((bigNum)&(name), \ + BYTES_TO_CRYPT_WORDS(sizeof(name.d))) +/* In some cases, a function will need the address of the structure associated with a variable. The + structure for a BIGNUM variable of name is name_. Generally, when the structure is created, it is + initialized and a parameter is created with a pointer to the structure. The pointer has the name + and the structure it points to is name_ */ +#define BN_ADDRESS(name) (bigNum)&name##_ + +#define BN_CONST(name, words, initializer) \ + typedef const struct name##_type { \ + crypt_uword_t allocated; \ + crypt_uword_t size; \ + crypt_uword_t d[words < 1 ? 1 : words]; \ + } name##_type; \ + name##_type name = {(words < 1 ? 1 : words), words, {initializer}}; + +#define BN_STRUCT_ALLOCATION(bits) (BITS_TO_CRYPT_WORDS(bits) + 1) +/* Create a structure of the correct size. */ +#define BN_STRUCT(bits) \ + BN_STRUCT_DEF(BN_STRUCT_ALLOCATION(bits)) +/* Define a BIGNUM type with a specific allocation */ +#define BN_TYPE(name, bits) \ + typedef BN_STRUCT(bits) bn_##name##_t +/* This creates a local BIGNUM variable of a specific size and initializes it from a TPM2B input + parameter. */ +#define BN_INITIALIZED(name, bits, initializer) \ + BN_STRUCT(bits) name##_; \ + bigNum name = BnFrom2B(BN_INIT(name##_), \ + (const TPM2B *)initializer) +/* Create a local variable that can hold a number with bits */ +#define BN_VAR(name, bits) \ + BN_STRUCT(bits) _##name; \ + bigNum name = BN_INIT(_##name) +/* Create a type that can hold the largest number defined by the implementation. */ +#define BN_MAX(name) BN_VAR(name, LARGEST_NUMBER_BITS) +#define BN_MAX_INITIALIZED(name, initializer) \ + BN_INITIALIZED(name, LARGEST_NUMBER_BITS, initializer) +/* A word size value is useful */ +#define BN_WORD(name) BN_VAR(name, RADIX_BITS) +/* This is used to create a word-size BIGNUM and initialize it with an input parameter to a + function. */ +#define BN_WORD_INITIALIZED(name, initial) \ + BN_STRUCT(RADIX_BITS) name##_; \ + bigNum name = BnInitializeWord((bigNum)&name##_, \ + BN_STRUCT_ALLOCATION(RADIX_BITS), initial) +/* ECC-Specific Values This is the format for a point. It is always in affine format. The Z value is + carried as part of the point, primarily to simplify the interface to the support library. Rather + than have the interface layer have to create space for the point each time it is used... The x, + y, and z values are pointers to bigNum values and not in-line versions of the numbers. This is a + relic of the days when there was no standard TPM format for the numbers */ +typedef struct _bn_point_t +{ + bigNum x; + bigNum y; + bigNum z; +} bn_point_t; +typedef bn_point_t *bigPoint; +typedef const bn_point_t *pointConst; +typedef struct constant_point_t +{ + bigConst x; + bigConst y; + bigConst z; +} constant_point_t; +#define ECC_BITS (MAX_ECC_KEY_BYTES * 8) +BN_TYPE(ecc, ECC_BITS); +#define ECC_NUM(name) BN_VAR(name, ECC_BITS) +#define ECC_INITIALIZED(name, initializer) \ + BN_INITIALIZED(name, ECC_BITS, initializer) +#define POINT_INSTANCE(name, bits) \ + BN_STRUCT (bits) name##_x = \ + {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \ + BN_STRUCT ( bits ) name##_y = \ + {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \ + BN_STRUCT ( bits ) name##_z = \ + {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \ + bn_point_t name##_ +#define POINT_INITIALIZER(name) \ + BnInitializePoint(&name##_, (bigNum)&name##_x, \ + (bigNum)&name##_y, (bigNum)&name##_z) +#define POINT_INITIALIZED(name, initValue) \ + POINT_INSTANCE(name, MAX_ECC_KEY_BITS); \ + bigPoint name = BnPointFrom2B( \ + POINT_INITIALIZER(name), \ + initValue) +#define POINT_VAR(name, bits) \ + POINT_INSTANCE (name, bits); \ + bigPoint name = POINT_INITIALIZER(name) +#define POINT(name) POINT_VAR(name, MAX_ECC_KEY_BITS) +/* Structure for the curve parameters. This is an analog to the TPMS_ALGORITHM_DETAIL_ECC */ +typedef struct +{ + bigConst prime; // a prime number + bigConst order; // the order of the curve + bigConst h; // cofactor + bigConst a; // linear coefficient + bigConst b; // constant term + constant_point_t base; // base point +} ECC_CURVE_DATA; +/* Access macros for the ECC_CURVE structure. The parameter C is a pointer to an ECC_CURVE_DATA + structure. In some libraries, the curve structure contains a pointer to an ECC_CURVE_DATA + structure as well as some other bits. For those cases, the AccessCurveData() macro is used in the + code to first get the pointer to the ECC_CURVE_DATA for access. In some cases, the macro does + nothing. */ +#define CurveGetPrime(C) ((C)->prime) +#define CurveGetOrder(C) ((C)->order) +#define CurveGetCofactor(C) ((C)->h) +#define CurveGet_a(C) ((C)->a) +#define CurveGet_b(C) ((C)->b) +#define CurveGetG(C) ((pointConst)&((C)->base)) +#define CurveGetGx(C) ((C)->base.x) +#define CurveGetGy(C) ((C)->base.y) +/* Convert bytes in initializers according to the endianness of the system. This is used for + CryptEccData.c. */ +#define BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d) \ + ( ((UINT32)(a) << 24) \ + + ((UINT32)(b) << 16) \ + + ((UINT32)(c) << 8) \ + + ((UINT32)(d)) \ + ) +#define BIG_ENDIAN_BYTES_TO_UINT64(a, b, c, d, e, f, g, h) \ + ( ((UINT64)(a) << 56) \ + + ((UINT64)(b) << 48) \ + + ((UINT64)(c) << 40) \ + + ((UINT64)(d) << 32) \ + + ((UINT64)(e) << 24) \ + + ((UINT64)(f) << 16) \ + + ((UINT64)(g) << 8) \ + + ((UINT64)(h)) \ + ) + +#ifndef RADIX_BYTES +# if RADIX_BITS == 32 +# define RADIX_BYTES 4 +# elif RADIX_BITS == 64 +# define RADIX_BYTES 8 +# else +# error "RADIX_BITS must either be 32 or 64" +# endif +#endif + +/* These macros are used for data initialization of big number ECC constants These two macros + combine a macro for data definition with a macro for structure initialization. The a parameter is + a macro that gives numbers to each of the bytes of the initializer and defines where each of the + numberd bytes will show up in the final structure. The b value is a structure that contains the + requisite number of bytes in big endian order. S, the MJOIN and JOIND macros will combine a macro + defining a data layout with a macro defining the data to be places. Generally, these macros will + only need expansion when CryptEccData().c gets compiled. */ +#define JOINED(a,b) a b +#define MJOIN(a,b) a b + +#define B4_TO_BN(a, b, c, d) (((((a << 8) + b) << 8) + c) + d) +#if RADIX_BYTES == 64 +#define B8_TO_BN(a, b, c, d, e, f, g, h) \ + (UINT64)(((((((((((((((a) << 8) | b) << 8) | c) << 8) | d) << 8) \ + e) << 8) | f) << 8) | g) << 8) | h) +#define B1_TO_BN(a) B8_TO_BN(0, 0, 0, 0, 0, 0, 0, a) +#define B2_TO_BN(a, b) B8_TO_BN(0, 0, 0, 0, 0, 0, a, b) +#define B3_TO_BN(a, b, c) B8_TO_BN(0, 0, 0, 0, 0, a, b, c) +#define B4_TO_BN(a, b, c, d) B8_TO_BN(0, 0, 0, 0, a, b, c, d) +#define B5_TO_BN(a, b, c, d, e) B8_TO_BN(0, 0, 0, a, b, c, d, e) +#define B6_TO_BN(a, b, c, d, e, f) B8_TO_BN(0, 0, a, b, c, d, e, f) +#define B7_TO_BN(a, b, c, d, e, f, g) B8_TO_BN(0, a, b, c, d, e, f, g) +#else +#define B1_TO_BN(a) B4_TO_BN(0, 0, 0, a) +#define B2_TO_BN(a, b) B4_TO_BN(0, 0, a, b) +#define B3_TO_BN(a, b, c) B4_TO_BN(0, a, b, c) +#define B4_TO_BN(a, b, c, d) (((((a << 8) + b) << 8) + c) + d) +#define B5_TO_BN(a, b, c, d, e) B4_TO_BN(b, c, d, e), B1_TO_BN(a) +#define B6_TO_BN(a, b, c, d, e, f) B4_TO_BN(c, d, e, f), B2_TO_BN(a, b) +#define B7_TO_BN(a, b, c, d, e, f, g) B4_TO_BN(d, e, f, g), B3_TO_BN(a, b, c) +#define B8_TO_BN(a, b, c, d, e, f, g, h) B4_TO_BN(e, f, g, h), B4_TO_BN(a, b, c, d) + +#endif + +/* Add implementation dependent definitions for other ECC Values and for linkages */ + +#include LIB_INCLUDE(MATH_LIB, Math) + +#endif // _BN_NUMBERS_H + diff --git a/src/tpm2/crypto/openssl/ConsttimeUtils.h b/src/tpm2/crypto/openssl/ConsttimeUtils.h new file mode 100644 index 0000000..3364bee --- /dev/null +++ b/src/tpm2/crypto/openssl/ConsttimeUtils.h @@ -0,0 +1,117 @@ +/********************************************************************************/ +/* */ +/* Constant time debugging helper functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2020 */ +/* */ +/********************************************************************************/ + +#ifndef CONSTTIME_UTILS_H +#define CONSTTIME_UTILS_H + +#include +#include + +#include "BnValues.h" + +#include + +static __inline__ unsigned long long rdtsc() { + unsigned long h, l; + + __asm__ __volatile__ ("rdtsc" : "=a"(l), "=d"(h)); + + return (unsigned long long)l | + ((unsigned long long)h << 32 ); +} + +// Make sure that the given BIGNUM has the given number of expected bytes. +// Skip over any leading zeros the BIGNUM may have. +static inline void assert_ossl_num_bytes(const BIGNUM *a, + unsigned int num_bytes, + int verbose, + const char *caller) { + unsigned char buffer[LARGEST_NUMBER] = { 0, }; + int len, i; + + len = BN_bn2bin(a, buffer); + for (i = 0; i < len; i++) { + if (buffer[i]) + break; + } + len -= i; + if (num_bytes != (unsigned int)len) { + printf("%s: Expected %u bytes but found %d (caller: %s)\n", __func__, num_bytes, len, caller); + } else { + if (verbose) + printf("%s: check passed; num_bytes = %d (caller: %s)\n",__func__, num_bytes, caller); + } + assert(num_bytes == (unsigned int)len); +} + +// Make sure that the bigNum has the expected number of bytes after it was +// converted to an OpenSSL BIGNUM. +static inline void assert_bn_ossl_num_bytes(bigNum tpmb, + unsigned int num_bytes, + int verbose, + const char *caller) { + BIG_INITIALIZED(osslb, tpmb); + + assert_ossl_num_bytes(osslb, num_bytes, verbose, caller); + + BN_free(osslb); +} + +#endif /* CONSTTIME_UTILS_H */ diff --git a/src/tpm2/crypto/openssl/CryptCmac.c b/src/tpm2/crypto/openssl/CryptCmac.c new file mode 100644 index 0000000..0461e78 --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptCmac.c @@ -0,0 +1,210 @@ +/********************************************************************************/ +/* */ +/* Message Authentication Codes Based on a Symmetric Block Cipher */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptCmac.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2018 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.6 CryptCmac.c */ +/* 10.2.6.1 Introduction */ +/* This file contains the implementation of the message authentication codes based on a symmetric + block cipher. These functions only use the single block encryption functions of the selected + symmetric cryptographic library. */ +/* 10.2.6.2 Includes, Defines, and Typedefs */ +#define _CRYPT_HASH_C_ +#include "Tpm.h" +#include "CryptSym.h" +#if ALG_CMAC + /* 10.2.6.3 Functions */ + /* 10.2.6.3.1 CryptCmacStart() */ + /* This is the function to start the CMAC sequence operation. It initializes the dispatch + functions for the data and end operations for CMAC and initializes the parameters that are + used for the processing of data, including the key, key size and block cipher algorithm. */ +UINT16 +CryptCmacStart( + SMAC_STATE *state, + TPMU_PUBLIC_PARMS *keyParms, + TPM_ALG_ID macAlg, + TPM2B *key + ) +{ + tpmCmacState_t *cState = &state->state.cmac; + TPMT_SYM_DEF_OBJECT *def = &keyParms->symDetail.sym; + // + if(macAlg != TPM_ALG_CMAC) + return 0; + MemorySet(cState, 0, sizeof(*cState)); // libtpms bugfix + // set up the encryption algorithm and parameters + cState->symAlg = def->algorithm; + cState->keySizeBits = def->keyBits.sym; + cState->iv.t.size = CryptGetSymmetricBlockSize(def->algorithm, + def->keyBits.sym); + MemoryCopy2B(&cState->symKey.b, key, sizeof(cState->symKey.t.buffer)); + // Set up the dispatch methods for the CMAC + state->smacMethods.data = CryptCmacData; + state->smacMethods.end = CryptCmacEnd; + return cState->iv.t.size; +} + +/* 10.2.5.3.2 CryptCmacData() */ +/* This function is used to add data to the CMAC sequence computation. The function will XOR new + data into the IV. If the buffer is full, and there is additional input data, the data is + encrypted into the IV buffer, the new data is then XOR into the IV. When the data runs out, the + function returns without encrypting even if the buffer is full. The last data block of a sequence + will not be encrypted until the call to CryptCmacEnd(). This is to allow the proper subkey to be + computed and applied before the last block is encrypted. */ +void +CryptCmacData( + SMAC_STATES *state, + UINT32 size, + const BYTE *buffer + ) +{ + tpmCmacState_t *cmacState = &state->cmac; + TPM_ALG_ID algorithm = cmacState->symAlg; + BYTE *key = cmacState->symKey.t.buffer; + UINT16 keySizeInBits = cmacState->keySizeBits; + tpmCryptKeySchedule_t keySchedule; + TpmCryptSetSymKeyCall_t encrypt; + // + memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */ + // Set up the encryption values based on the algorithm + switch (algorithm) + { + FOR_EACH_SYM(ENCRYPT_CASE) + default: + FAIL(FATAL_ERROR_INTERNAL); + } + while(size > 0) + { + if(cmacState->bcount == cmacState->iv.t.size) + { + ENCRYPT(&keySchedule, cmacState->iv.t.buffer, cmacState->iv.t.buffer); + cmacState->bcount = 0; + } + for(;(size > 0) && (cmacState->bcount < cmacState->iv.t.size); + size--, cmacState->bcount++) + { + cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++; + } + } +} + +/* 10.2.6.3.3 CryptCmacEnd() */ +/* This is the completion function for the CMAC. It does padding, if needed, and selects the subkey + to be applied before the last block is encrypted. */ +UINT16 +CryptCmacEnd( + SMAC_STATES *state, + UINT32 outSize, + BYTE *outBuffer + ) +{ + tpmCmacState_t *cState = &state->cmac; + // Need to set algorithm, key, and keySizeInBits in the local context so that + // the SELECT and ENCRYPT macros will work here + TPM_ALG_ID algorithm = cState->symAlg; + BYTE *key = cState->symKey.t.buffer; + UINT16 keySizeInBits = cState->keySizeBits; + tpmCryptKeySchedule_t keySchedule; + TpmCryptSetSymKeyCall_t encrypt; + TPM2B_IV subkey = {{0, {0}}}; + BOOL xorVal; + UINT16 i; + memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */ + + subkey.t.size = cState->iv.t.size; + // Encrypt a block of zero + // Set up the encryption values based on the algorithm + switch (algorithm) + { + FOR_EACH_SYM(ENCRYPT_CASE) + default: + return 0; + } + ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer); + + // shift left by 1 and XOR with 0x0...87 if the MSb was 0 + xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; + ShiftLeft(&subkey.b); + subkey.t.buffer[subkey.t.size - 1] ^= xorVal; + // this is a sanity check to make sure that the algorithm is working properly. + // remove this check when debug is done + pAssert(cState->bcount <= cState->iv.t.size); + // If the buffer is full then no need to compute subkey 2. + if(cState->bcount < cState->iv.t.size) + { + //Pad the data + cState->iv.t.buffer[cState->bcount++] ^= 0x80; + // The rest of the data is a pad of zero which would simply be XORed + // with the iv value so nothing to do... + // Now compute K2 + xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; + ShiftLeft(&subkey.b); + subkey.t.buffer[subkey.t.size - 1] ^= xorVal; + } + // XOR the subkey into the IV + for(i = 0; i < subkey.t.size; i++) + cState->iv.t.buffer[i] ^= subkey.t.buffer[i]; + ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer); + i = (UINT16)MIN(cState->iv.t.size, outSize); + MemoryCopy(outBuffer, cState->iv.t.buffer, i); + + return i; +} + +#endif diff --git a/src/tpm2/crypto/openssl/CryptDes.c b/src/tpm2/crypto/openssl/CryptDes.c new file mode 100644 index 0000000..9efa3ce --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptDes.c @@ -0,0 +1,189 @@ +/********************************************************************************/ +/* */ +/* Functions Required for TDES */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptDes.c 1398 2018-12-17 22:37:57Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +/* 10.2.9 CryptDes.c */ +/* 10.2.9.1 Introduction */ +/* This file contains the extra functions required for TDES. */ +/* 10.2.9.2 Includes, Defines, and Typedefs */ +#include "Tpm.h" +#include "Helpers_fp.h" // libtpms added +#if ALG_TDES +#define DES_NUM_WEAK 64 +const UINT64 DesWeakKeys[DES_NUM_WEAK] = { + 0x0101010101010101ULL, 0xFEFEFEFEFEFEFEFEULL, 0xE0E0E0E0F1F1F1F1ULL, 0x1F1F1F1F0E0E0E0EULL, + 0x011F011F010E010EULL, 0x1F011F010E010E01ULL, 0x01E001E001F101F1ULL, 0xE001E001F101F101ULL, + 0x01FE01FE01FE01FEULL, 0xFE01FE01FE01FE01ULL, 0x1FE01FE00EF10EF1ULL, 0xE01FE01FF10EF10EULL, + 0x1FFE1FFE0EFE0EFEULL, 0xFE1FFE1FFE0EFE0EULL, 0xE0FEE0FEF1FEF1FEULL, 0xFEE0FEE0FEF1FEF1ULL, + 0x01011F1F01010E0EULL, 0x1F1F01010E0E0101ULL, 0xE0E01F1FF1F10E0EULL, 0x0101E0E00101F1F1ULL, + 0x1F1FE0E00E0EF1F1ULL, 0xE0E0FEFEF1F1FEFEULL, 0x0101FEFE0101FEFEULL, 0x1F1FFEFE0E0EFEFEULL, + 0xE0FE011FF1FE010EULL, 0x011F1F01010E0E01ULL, 0x1FE001FE0EF101FEULL, 0xE0FE1F01F1FE0E01ULL, + 0x011FE0FE010EF1FEULL, 0x1FE0E01F0EF1F10EULL, 0xE0FEFEE0F1FEFEF1ULL, 0x011FFEE0010EFEF1ULL, + 0x1FE0FE010EF1FE01ULL, 0xFE0101FEFE0101FEULL, 0x01E01FFE01F10EFEULL, 0x1FFE01E00EFE01F1ULL, + 0xFE011FE0FE010EF1ULL, 0xFE01E01FFE01F10EULL, 0x1FFEE0010EFEF101ULL, 0xFE1F01E0FE0E01F1ULL, + 0x01E0E00101F1F101ULL, 0x1FFEFE1F0EFEFE0EULL, 0xFE1FE001FE0EF101ULL, 0x01E0FE1F01F1FE0EULL, + 0xE00101E0F10101F1ULL, 0xFE1F1FFEFE0E0EFEULL, 0x01FE1FE001FE0EF1ULL, 0xE0011FFEF1010EFEULL, + 0xFEE0011FFEF1010EULL, 0x01FEE01F01FEF10EULL, 0xE001FE1FF101FE0EULL, 0xFEE01F01FEF10E01ULL, + 0x01FEFE0101FEFE01ULL, 0xE01F01FEF10E01FEULL, 0xFEE0E0FEFEF1F1FEULL, 0x1F01011F0E01010EULL, + 0xE01F1FE0F10E0EF1ULL, 0xFEFE0101FEFE0101ULL, 0x1F01E0FE0E01F1FEULL, 0xE01FFE01F10EFE01ULL, + 0xFEFE1F1FFEFE0E0EULL, 0x1F01FEE00E01FEF1ULL, 0xE0E00101F1F10101ULL, 0xFEFEE0E0FEFEF1F1ULL}; +/* 10.2.9.2.1 CryptSetOddByteParity() */ +/* This function sets the per byte parity of a 64-bit value. The least-significant bit is of each + byte is replaced with the odd parity of the other 7 bits in the byte. With odd parity, no byte + will ever be 0x00. */ +UINT64 +CryptSetOddByteParity( + UINT64 k + ) +{ +#define PMASK 0x0101010101010101ULL + UINT64 out; + k |= PMASK; // set the parity bit + out = k; + k ^= k >> 4; + k ^= k >> 2; + k ^= k >> 1; + k &= PMASK; // odd parity extracted + out ^= k; // out is now even parity because parity bit was already set + out ^= PMASK; // out is now even parity + return out; +} +/* 10.2.9.2.2 CryptDesIsWeakKey() */ +/* Check to see if a DES key is on the list of weak, semi-weak, or possibly weak keys. */ +/* Return Value Meaning */ +/* TRUE(1) DES key is weak */ +/* FALSE(0) DES key is not weak */ +static BOOL +CryptDesIsWeakKey( + UINT64 k + ) +{ + int i; + // + for(i = 0; i < DES_NUM_WEAK; i++) + { + if(k == DesWeakKeys[i]) + return TRUE; + } + return FALSE; +} +/* 10.2.9.2.3 CryptDesValidateKey() */ +/* Function to check to see if the input key is a valid DES key where the definition of valid is + that none of the elements are on the list of weak, semi-weak, or possibly weak keys; and that for + two keys, K1!=K2, and for three keys that K1!=K2 and K2!=K3. */ +BOOL +CryptDesValidateKey( + TPM2B_SYM_KEY *desKey // IN: key to validate + ) +{ + UINT64 k[3]; + int i; + int keys = (desKey->t.size + 7) / 8; + BYTE *pk = desKey->t.buffer; + BOOL ok; + // + // Note: 'keys' is the number of keys, not the maximum index for 'k' + ok = ((keys == 2) || (keys == 3)) && ((desKey->t.size % 8) == 0); + for(i = 0; ok && i < keys; pk += 8, i++) + { + k[i] = CryptSetOddByteParity(BYTE_ARRAY_TO_UINT64(pk)); + ok = !CryptDesIsWeakKey(k[i]); + } + ok = ok && k[0] != k[1]; + if(keys == 3) + ok = ok && k[1] != k[2]; + return ok; +} +/* 10.2.9.2.4 CryptGenerateKeyDes() */ +/* This function is used to create a DES key of the appropriate size. The key will have odd parity + in the bytes. */ +TPM_RC +CryptGenerateKeyDes( + TPMT_PUBLIC *publicArea, // IN/OUT: The public area template + // for the new key. + TPMT_SENSITIVE *sensitive, // OUT: sensitive area + RAND_STATE *rand // IN: the "entropy" source for + ) +{ + // Assume that the publicArea key size has been validated and is a supported + // number of bits. + sensitive->sensitive.sym.t.size = + BITS_TO_BYTES(publicArea->parameters.symDetail.sym.keyBits.sym); +#if USE_OPENSSL_FUNCTIONS_SYMMETRIC // libtpms added begin + if (rand == NULL) + return OpenSSLCryptGenerateKeyDes(sensitive); +#endif // libtpms added end + do + { + BYTE *pK = sensitive->sensitive.sym.t.buffer; + int i = (sensitive->sensitive.sym.t.size + 7) / 8; + // Use the random number generator to generate the required number of bits + if(DRBG_Generate(rand, pK, sensitive->sensitive.sym.t.size) == 0) + return TPM_RC_NO_RESULT; + for(; i > 0; pK += 8, i--) + { + UINT64 k = BYTE_ARRAY_TO_UINT64(pK); + k = CryptSetOddByteParity(k); + UINT64_TO_BYTE_ARRAY(k, pK); + } + } while(!CryptDesValidateKey(&sensitive->sensitive.sym)); + return TPM_RC_SUCCESS; +} +#endif diff --git a/src/tpm2/crypto/openssl/CryptEccKeyExchange.c b/src/tpm2/crypto/openssl/CryptEccKeyExchange.c new file mode 100644 index 0000000..4d1fccb --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptEccKeyExchange.c @@ -0,0 +1,373 @@ +/********************************************************************************/ +/* */ +/* Functions that are used for the two-phase, ECC, key-exchange protocols */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEccKeyExchange.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.11 CryptEccKeyExchange.c */ +#include "Tpm.h" + +LIB_EXPORT TPM_RC +SM2KeyExchange( + TPMS_ECC_POINT *outZ, // OUT: the computed point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM2B_ECC_PARAMETER *dsAIn, // IN: static private TPM key + TPM2B_ECC_PARAMETER *deAIn, // IN: ephemeral private TPM key + TPMS_ECC_POINT *QsBIn, // IN: static public party B key + TPMS_ECC_POINT *QeBIn // IN: ephemeral public party B key + ); + +#if CC_ZGen_2Phase == YES +#if ALG_ECMQV +/* 10.2.11.1.1 avf1() */ +/* This function does the associated value computation required by MQV key exchange. Process: */ +/* a) Convert xQ to an integer xqi using the convention specified in Appendix C.3. */ +/* b) Calculate xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)). */ +/* c) Calculate the associate value function avf(Q) = xqm + 2ceil(f / 2) */ +/* Always returns TRUE(1). */ +static BOOL +avf1( + bigNum bnX, // IN/OUT: the reduced value + bigNum bnN // IN: the order of the curve + ) +{ + // compute f = 2^(ceil(ceil(log2(n)) / 2)) + int f = (BnSizeInBits(bnN) + 1) / 2; + // x' = 2^f + (x mod 2^f) + BnMaskBits(bnX, f); // This is mod 2*2^f but it doesn't matter because + // the next operation will SET the extra bit anyway + BnSetBit(bnX, f); + return TRUE; +} +/* 10.2.11.1.2 C_2_2_MQV() */ +/* This function performs the key exchange defined in SP800-56A 6.1.1.4 Full MQV, C(2, 2, ECC + MQV). */ +/* CAUTION: Implementation of this function may require use of essential claims in patents not owned + by TCG members. */ +/* Points QsB() and QeB() are required to be on the curve of inQsA. The function will fail, possibly + catastrophically, if this is not the case. */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT the value for dsA does not give a valid point on the curve */ +static TPM_RC +C_2_2_MQV( + TPMS_ECC_POINT *outZ, // OUT: the computed point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key + TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key + TPMS_ECC_POINT *QsB, // IN: static public party B key + TPMS_ECC_POINT *QeB // IN: ephemeral public party B key + ) +{ + CURVE_INITIALIZED(E, curveId); + const ECC_CURVE_DATA *C; + POINT(pQeA); + POINT_INITIALIZED(pQeB, QeB); + POINT_INITIALIZED(pQsB, QsB); + ECC_NUM(bnTa); + ECC_INITIALIZED(bnDeA, deA); + ECC_INITIALIZED(bnDsA, dsA); + ECC_NUM(bnN); + ECC_NUM(bnXeB); + TPM_RC retVal; + // + // Parameter checks + if(E == NULL) + ERROR_RETURN(TPM_RC_VALUE); + pAssert(outZ != NULL && pQeB != NULL && pQsB != NULL && deA != NULL + && dsA != NULL); + C = AccessCurveData(E); + // Process: + // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. + // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). + // 3. If P = O, output an error indicator. + // 4. Z=xP, where xP is the x-coordinate of P. + // Compute the public ephemeral key pQeA = [de,A]G + if((retVal = BnPointMult(pQeA, CurveGetG(C), bnDeA, NULL, NULL, E)) + != TPM_RC_SUCCESS) + goto Exit; + // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. + // tA := (ds,A + de,A avf(Xe,A)) mod n (3) + // Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n + // Ta = avf(XeA); + BnCopy(bnTa, pQeA->x); + avf1(bnTa, bnN); + // do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n + BnModMult(bnTa, bnDsA, bnTa, bnN); + // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n + BnAdd(bnTa, bnTa, bnDeA); + BnMod(bnTa, bnN); + // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). + // Put this in because almost every case of h is == 1 so skip the call when + // not necessary. + if(!BnEqualWord(CurveGetCofactor(C), 1)) + // Cofactor is not 1 so compute Ta := Ta * h mod n + BnModMult(bnTa, bnTa, CurveGetCofactor(C), CurveGetOrder(C)); + // Now that 'tA' is (h * 'tA' mod n) + // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B). + // first, compute XeB = avf(XeB) + avf1(bnXeB, bnN); + // QsB := [XeB]QsB + BnPointMult(pQsB, pQsB, bnXeB, NULL, NULL, E); + BnEccAdd(pQeB, pQeB, pQsB, E); + // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity + // If the result is not the point at infinity, return QeB + BnPointMult(pQeB, pQeB, bnTa, NULL, NULL, E); + if(BnEqualZero(pQeB->z)) + ERROR_RETURN(TPM_RC_NO_RESULT); + // Convert BIGNUM E to TPM2B E + BnPointTo2B(outZ, pQeB, E); + Exit: + CURVE_FREE(E); + return retVal; +} +#endif // ALG_ECMQV +/* 10.2.11.1.3 C_2_2_ECDH() */ +/* This function performs the two phase key exchange defined in SP800-56A, 6.1.1.2 Full Unified + Model, C(2, 2, ECC CDH). */ +static TPM_RC +C_2_2_ECDH( + TPMS_ECC_POINT *outZs, // OUT: Zs + TPMS_ECC_POINT *outZe, // OUT: Ze + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key + TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key + TPMS_ECC_POINT *QsB, // IN: static public party B key + TPMS_ECC_POINT *QeB // IN: ephemeral public party B key + ) +{ + CURVE_INITIALIZED(E, curveId); + ECC_INITIALIZED(bnAs, dsA); + ECC_INITIALIZED(bnAe, deA); + POINT_INITIALIZED(ecBs, QsB); + POINT_INITIALIZED(ecBe, QeB); + POINT(ecZ); + TPM_RC retVal; + // + // Parameter checks + if(E == NULL) + ERROR_RETURN(TPM_RC_CURVE); + pAssert(outZs != NULL && dsA != NULL && deA != NULL && QsB != NULL + && QeB != NULL); + // Do the point multiply for the Zs value ([dsA]QsB) + retVal = BnPointMult(ecZ, ecBs, bnAs, NULL, NULL, E); + if(retVal == TPM_RC_SUCCESS) + { + // Convert the Zs value. + BnPointTo2B(outZs, ecZ, E); + // Do the point multiply for the Ze value ([deA]QeB) + retVal = BnPointMult(ecZ, ecBe, bnAe, NULL, NULL, E); + if(retVal == TPM_RC_SUCCESS) + BnPointTo2B(outZe, ecZ, E); + } + Exit: + CURVE_FREE(E); + return retVal; +} +/* 10.2.11.1.4 CryptEcc2PhaseKeyExchange() */ +/* This function is the dispatch routine for the EC key exchange functions that use two ephemeral + and two static keys. */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME scheme is not defined */ +LIB_EXPORT TPM_RC +CryptEcc2PhaseKeyExchange( + TPMS_ECC_POINT *outZ1, // OUT: a computed point + TPMS_ECC_POINT *outZ2, // OUT: and optional second point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM_ALG_ID scheme, // IN: the key exchange scheme + TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key + TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key + TPMS_ECC_POINT *QsB, // IN: static public party B key + TPMS_ECC_POINT *QeB // IN: ephemeral public party B key + ) +{ + pAssert(outZ1 != NULL + && dsA != NULL && deA != NULL + && QsB != NULL && QeB != NULL); + // Initialize the output points so that they are empty until one of the + // functions decides otherwise + outZ1->x.b.size = 0; + outZ1->y.b.size = 0; + if(outZ2 != NULL) + { + outZ2->x.b.size = 0; + outZ2->y.b.size = 0; + } + switch(scheme) + { + case TPM_ALG_ECDH: + return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB); + break; +#if ALG_ECMQV + case TPM_ALG_ECMQV: + return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB); + break; +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB); + break; +#endif + default: + return TPM_RC_SCHEME; + } +} +#if ALG_SM2 +/* 10.2.11.1.5 ComputeWForSM2() */ +/* Compute the value for w used by SM2 */ +static UINT32 +ComputeWForSM2( + bigCurve E + ) +{ + // w := ceil(ceil(log2(n)) / 2) - 1 + return (BnMsb(CurveGetOrder(AccessCurveData(E))) / 2 - 1); +} +/* 10.2.11.1.6 avfSm2() */ +/* This function does the associated value computation required by SM2 key exchange. This is + different form the avf() in the international standards because it returns a value that is half + the size of the value returned by the standard avf. For example, if n is 15, Ws (w in the + standard) is 2 but the W here is 1. This means that an input value of 14 (1110b) would return a + value of 110b with the standard but 10b with the scheme in SM2. */ +static bigNum +avfSm2( + bigNum bn, // IN/OUT: the reduced value + UINT32 w // IN: the value of w + ) +{ + // a) set w := ceil(ceil(log2(n)) / 2) - 1 + // b) set x' := 2^w + ( x & (2^w - 1)) + // This is just like the avf for MQV where x' = 2^w + (x mod 2^w) + BnMaskBits(bn, w); // as with avf1, this is too big by a factor of 2 but + // it doesn't matter because we SET the extra bit + // anyway + BnSetBit(bn, w); + return bn; +} +/* SM2KeyExchange() This function performs the key exchange defined in SM2. The first step is to + compute tA = (dsA + deA avf(Xe,A)) mod n Then, compute the Z value from outZ = (h tA mod n) (QsA + + [avf(QeB().x)](QeB())). The function will compute the ephemeral public key from the ephemeral + private key. All points are required to be on the curve of inQsA. The function will fail + catastrophically if this is not the case */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT the value for dsA does not give a valid point on the curve */ +LIB_EXPORT TPM_RC +SM2KeyExchange( + TPMS_ECC_POINT *outZ, // OUT: the computed point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM2B_ECC_PARAMETER *dsAIn, // IN: static private TPM key + TPM2B_ECC_PARAMETER *deAIn, // IN: ephemeral private TPM key + TPMS_ECC_POINT *QsBIn, // IN: static public party B key + TPMS_ECC_POINT *QeBIn // IN: ephemeral public party B key + ) +{ + CURVE_INITIALIZED(E, curveId); + const ECC_CURVE_DATA *C; + ECC_INITIALIZED(dsA, dsAIn); + ECC_INITIALIZED(deA, deAIn); + POINT_INITIALIZED(QsB, QsBIn); + POINT_INITIALIZED(QeB, QeBIn); + BN_WORD_INITIALIZED(One, 1); + POINT(QeA); + ECC_NUM(XeB); + POINT(Z); + ECC_NUM(Ta); + UINT32 w; + TPM_RC retVal = TPM_RC_NO_RESULT; + // + // Parameter checks + if(E == NULL) + ERROR_RETURN(TPM_RC_CURVE); + C = AccessCurveData(E); + pAssert(outZ != NULL && dsA != NULL && deA != NULL && QsB != NULL + && QeB != NULL); + // Compute the value for w + w = ComputeWForSM2(E); + // Compute the public ephemeral key pQeA = [de,A]G + if(!BnEccModMult(QeA, CurveGetG(C), deA, E)) + goto Exit; + // tA := (ds,A + de,A avf(Xe,A)) mod n (3) + // Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n + // Ta = avf(XeA); + // do Ta = de,A * Ta = deA * avf(XeA) + BnMult(Ta, deA, avfSm2(QeA->x, w)); + // now Ta = dsA + Ta = dsA + deA * avf(XeA) + BnAdd(Ta, dsA, Ta); + BnMod(Ta, CurveGetOrder(C)); + // outZ = [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4) + // Put this in because almost every case of h is == 1 so skip the call when + // not necessary. + if(!BnEqualWord(CurveGetCofactor(C), 1)) + // Cofactor is not 1 so compute Ta := Ta * h mod n + BnModMult(Ta, Ta, CurveGetCofactor(C), CurveGetOrder(C)); + // Now that 'tA' is (h * 'tA' mod n) + // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)). + BnCopy(XeB, QeB->x); + if(!BnEccModMult2(Z, QsB, One, QeB, avfSm2(XeB, w), E)) + goto Exit; + // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity + if(!BnEccModMult(Z, Z, Ta, E)) + goto Exit; + // Convert BIGNUM E to TPM2B E + BnPointTo2B(outZ, Z, E); + retVal = TPM_RC_SUCCESS; + Exit: + CURVE_FREE(E); + return retVal; +} +#endif +#endif // CC_ZGen_2Phase diff --git a/src/tpm2/crypto/openssl/CryptEccMain.c b/src/tpm2/crypto/openssl/CryptEccMain.c new file mode 100644 index 0000000..be92831 --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptEccMain.c @@ -0,0 +1,866 @@ +/********************************************************************************/ +/* */ +/* ECC Main */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEccMain.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 10.2.11 CryptEccMain.c */ +/* 10.2.11.1 Includes and Defines */ +#include "Tpm.h" +#include "Helpers_fp.h" // libtpms added +#include "TpmToOsslMath_fp.h" // libtpms added +#if ALG_ECC +/* This version requires that the new format for ECC data be used */ +#if !USE_BN_ECC_DATA +#error "Need to SET USE_BN_ECC_DATA to YES in TpmBuildSwitches.h" +#endif +/* 10.2.11.2 Functions */ +#if SIMULATION +void +EccSimulationEnd( + void + ) +{ +#if SIMULATION + // put things to be printed at the end of the simulation here +#endif +} +#endif // SIMULATION +/* 10.2.11.2.1 CryptEccInit() */ +/* This function is called at _TPM_Init() */ +BOOL +CryptEccInit( + void + ) +{ + return TRUE; +} +/* 10.2.11.2.2 CryptEccStartup() */ +/* This function is called at TPM2_Startup(). */ +BOOL +CryptEccStartup( + void + ) +{ + return TRUE; +} +/* 10.2.11.2.3 ClearPoint2B(generic */ +/* Initialize the size values of a TPMS_ECC_POINT structure. */ +void +ClearPoint2B( + TPMS_ECC_POINT *p // IN: the point + ) +{ + if(p != NULL) + { + p->x.t.size = 0; + p->y.t.size = 0; + } +} +/* 10.2.11.2.4 CryptEccGetParametersByCurveId() */ +/* This function returns a pointer to the curve data that is associated with the indicated + curveId. If there is no curve with the indicated ID, the function returns NULL. This function is + in this module so that it can be called by GetCurve() data. */ +/* Return Values Meaning */ +/* NULL curve with the indicated TPM_ECC_CURVE is not implemented */ +/* non-NULL pointer to the curve data */ +LIB_EXPORT const ECC_CURVE * +CryptEccGetParametersByCurveId( + TPM_ECC_CURVE curveId // IN: the curveID + ) +{ + int i; + for(i = 0; i < ECC_CURVE_COUNT; i++) + { + if(eccCurves[i].curveId == curveId) + return &eccCurves[i]; + } + return NULL; +} +/* 10.2.11.2.5 CryptEccGetKeySizeForCurve() */ +/* This function returns the key size in bits of the indicated curve */ +LIB_EXPORT UINT16 +CryptEccGetKeySizeForCurve( + TPM_ECC_CURVE curveId // IN: the curve + ) +{ + const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); + UINT16 keySizeInBits; + // + keySizeInBits = (curve != NULL) ? curve->keySizeBits : 0; + return keySizeInBits; +} +/* 10.2.11.2.6 GetCurveData() */ +/* This function returns the a pointer for the parameter data associated with a curve. */ +const ECC_CURVE_DATA * +GetCurveData( + TPM_ECC_CURVE curveId // IN: the curveID + ) +{ + const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); + return (curve != NULL) ? curve->curveData : NULL; +} +/* 10.2.11.2.7 CryptEccGetOID() */ +const BYTE * +CryptEccGetOID( + TPM_ECC_CURVE curveId + ) +{ + const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); + return (curve != NULL) ? curve->OID : NULL; +} +/* 10.2.11.2.7 CryptEccGetCurveByIndex() */ +/* This function returns the number of the i-th implemented curve. The normal use would be to call + this function with i starting at 0. When the i is greater than or equal to the number of + implemented curves, TPM_ECC_NONE is returned. */ +LIB_EXPORT TPM_ECC_CURVE +CryptEccGetCurveByIndex( + UINT16 i + ) +{ + if(i >= ECC_CURVE_COUNT) + return TPM_ECC_NONE; + return eccCurves[i].curveId; +} +/* 10.2.11.2.8 CryptEccGetParameter() */ +/* This function returns an ECC curve parameter. The parameter is selected by a single character + designator from the set of {PNABXYH}. */ +/* Return Values Meaning */ +/* TRUE curve exists and parameter returned */ +/* FALSE curve does not exist or parameter selector */ +LIB_EXPORT BOOL +CryptEccGetParameter( + TPM2B_ECC_PARAMETER *out, // OUT: place to put parameter + char p, // IN: the parameter selector + TPM_ECC_CURVE curveId // IN: the curve id + ) +{ + const ECC_CURVE_DATA *curve = GetCurveData(curveId); + bigConst parameter = NULL; + if(curve != NULL) + { + switch(p) + { + case 'p': + parameter = CurveGetPrime(curve); + break; + case 'n': + parameter = CurveGetOrder(curve); + break; + case 'a': + parameter = CurveGet_a(curve); + break; + case 'b': + parameter = CurveGet_b(curve); + break; + case 'x': + parameter = CurveGetGx(curve); + break; + case 'y': + parameter = CurveGetGy(curve); + break; + case 'h': + parameter = CurveGetCofactor(curve); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + } + // If not debugging and we get here with parameter still NULL, had better + // not try to convert so just return FALSE instead. + return (parameter != NULL) ? BnTo2B(parameter, &out->b, 0) : 0; +} +/* 10.2.11.2.9 CryptCapGetECCCurve() */ +/* This function returns the list of implemented ECC curves. */ +/* Return Values Meaning */ +/* YES if no more ECC curve is available */ +/* NO if there are more ECC curves not reported */ +TPMI_YES_NO +CryptCapGetECCCurve( + TPM_ECC_CURVE curveID, // IN: the starting ECC curve + UINT32 maxCount, // IN: count of returned curves + TPML_ECC_CURVE *curveList // OUT: ECC curve list + ) +{ + TPMI_YES_NO more = NO; + UINT16 i; + UINT32 count = ECC_CURVE_COUNT; + TPM_ECC_CURVE curve; + // Initialize output property list + curveList->count = 0; + // The maximum count of curves we may return is MAX_ECC_CURVES + if(maxCount > MAX_ECC_CURVES) maxCount = MAX_ECC_CURVES; + // Scan the eccCurveValues array + for(i = 0; i < count; i++) + { + curve = CryptEccGetCurveByIndex(i); + // If curveID is less than the starting curveID, skip it + if(curve < curveID) + continue; + if (!CryptEccIsCurveRuntimeUsable(curve)) // libtpms added: runtime filter supported curves + continue; + if(curveList->count < maxCount) + { + // If we have not filled up the return list, add more curves to + // it + curveList->eccCurves[curveList->count] = curve; + curveList->count++; + } + else + { + // If the return list is full but we still have curves + // available, report this and stop iterating + more = YES; + break; + } + } + return more; +} +/* 10.2.11.2.10 CryptGetCurveSignScheme() */ +/* This function will return a pointer to the scheme of the curve. */ +const TPMT_ECC_SCHEME * +CryptGetCurveSignScheme( + TPM_ECC_CURVE curveId // IN: The curve selector + ) +{ + const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); + if(curve != NULL) + return &(curve->sign); + else + return NULL; +} +/* 10.2.11.2.11 CryptGenerateR() */ +/* This function computes the commit random value for a split signing scheme. */ +/* If c is NULL, it indicates that r is being generated for TPM2_Commit(). If c is not NULL, the TPM + will validate that the gr.commitArray bit associated with the input value of c is SET. If not, + the TPM returns FALSE and no r value is generated. */ +/* Return Values Meaning */ +/* TRUE r value computed */ +/* FALSE no r value computed */ +BOOL +CryptGenerateR( + TPM2B_ECC_PARAMETER *r, // OUT: the generated random value + UINT16 *c, // IN/OUT: count value. + TPMI_ECC_CURVE curveID, // IN: the curve for the value + TPM2B_NAME *name // IN: optional name of a key to + // associate with 'r' + ) +{ + // This holds the marshaled g_commitCounter. + TPM2B_TYPE(8B, 8); + TPM2B_8B cntr = {{8,{0}}}; + UINT32 iterations; + TPM2B_ECC_PARAMETER n; + UINT64 currentCount = gr.commitCounter; + UINT16 t1; + // + if(!CryptEccGetParameter(&n, 'n', curveID)) + return FALSE; + // If this is the commit phase, use the current value of the commit counter + if(c != NULL) + { + // if the array bit is not set, can't use the value. + if(!TEST_BIT((*c & COMMIT_INDEX_MASK), gr.commitArray)) + return FALSE; + // If it is the sign phase, figure out what the counter value was + // when the commitment was made. + // + // When gr.commitArray has less than 64K bits, the extra + // bits of 'c' are used as a check to make sure that the + // signing operation is not using an out of range count value + t1 = (UINT16)currentCount; + // If the lower bits of c are greater or equal to the lower bits of t1 + // then the upper bits of t1 must be one more than the upper bits + // of c + if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK)) + // Since the counter is behind, reduce the current count + currentCount = currentCount - (COMMIT_INDEX_MASK + 1); + t1 = (UINT16)currentCount; + if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK)) + return FALSE; + // set the counter to the value that was + // present when the commitment was made + currentCount = (currentCount & 0xffffffffffff0000ULL) | *c; /* libtpms changed */ + } + // Marshal the count value to a TPM2B buffer for the KDF + cntr.t.size = sizeof(currentCount); + UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer); + // Now can do the KDF to create the random value for the signing operation + // During the creation process, we may generate an r that does not meet the + // requirements of the random value. + // want to generate a new r. + r->t.size = n.t.size; + for(iterations = 1; iterations < 1000000;) + { + int i; + + CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gr.commitNonce.b, COMMIT_STRING, + (TPM2B *)name, &cntr.b, n.t.size * 8, // libtpms ubsan + r->t.buffer, &iterations, FALSE); // libtpms changed + + // "random" value must be less than the prime + if(UnsignedCompareB(r->b.size, r->b.buffer, n.t.size, n.t.buffer) >= 0) + continue; + + // in this implementation it is required that at least bit + // in the upper half of the number be set + for(i = n.t.size / 2; i >= 0; i--) + if(r->b.buffer[i] != 0) + return TRUE; + } + return FALSE; +} +/* 10.2.11.2.12 CryptCommit() */ +/* This function is called when the count value is committed. The gr.commitArray value associated + with the current count value is SET and g_commitCounter is incremented. The low-order 16 bits of + old value of the counter is returned. */ +UINT16 +CryptCommit( + void + ) +{ + UINT16 oldCount = (UINT16)gr.commitCounter; + gr.commitCounter++; + SET_BIT(oldCount & COMMIT_INDEX_MASK, gr.commitArray); + return oldCount; +} +/* 10.2.11.2.13 CryptEndCommit() */ +/* This function is called when the signing operation using the committed value is completed. It + clears the gr.commitArray bit associated with the count value so that it can't be used again. */ +void +CryptEndCommit( + UINT16 c // IN: the counter value of the commitment + ) +{ + ClearBit((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray)); +} +/* 10.2.11.2.14 CryptEccGetParameters() */ +/* This function returns the ECC parameter details of the given curve */ +/* Return Values Meaning */ +/* TRUE success */ +/* FALSE unsupported ECC curve ID */ +BOOL +CryptEccGetParameters( + TPM_ECC_CURVE curveId, // IN: ECC curve ID + TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameters + ) +{ + const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); + const ECC_CURVE_DATA *data; + BOOL found = curve != NULL; + if(found) + { + data = curve->curveData; + parameters->curveID = curve->curveId; + parameters->keySize = curve->keySizeBits; + parameters->kdf = curve->kdf; + parameters->sign = curve->sign; + /* BnTo2B(data->prime, ¶meters->p.b, 0); */ + BnTo2B(data->prime, ¶meters->p.b, parameters->p.t.size); + BnTo2B(data->a, ¶meters->a.b, parameters->p.t.size /* libtpms changed for HLK */); + BnTo2B(data->b, ¶meters->b.b, parameters->p.t.size /* libtpms changed for HLK */); + BnTo2B(data->base.x, ¶meters->gX.b, parameters->p.t.size); + BnTo2B(data->base.y, ¶meters->gY.b, parameters->p.t.size); + BnTo2B(data->order, ¶meters->n.b, 0); + BnTo2B(data->h, ¶meters->h.b, 0); + } + return found; +} +/* 10.2.11.2.15 BnGetCurvePrime() */ +/* This function is used to get just the prime modulus associated with a curve */ +const bignum_t * +BnGetCurvePrime( + TPM_ECC_CURVE curveId + ) +{ + const ECC_CURVE_DATA *C = GetCurveData(curveId); + return (C != NULL) ? CurveGetPrime(C) : NULL; +} +/* 10.2.11.2.16 BnGetCurveOrder() */ +/* This function is used to get just the curve order */ +const bignum_t * +BnGetCurveOrder( + TPM_ECC_CURVE curveId + ) +{ + const ECC_CURVE_DATA *C = GetCurveData(curveId); + return (C != NULL) ? CurveGetOrder(C) : NULL; +} +/* 10.2.11.2.17 BnIsOnCurve() */ +/* This function checks if a point is on the curve. */ +BOOL +BnIsOnCurve( + pointConst Q, + const ECC_CURVE_DATA *C + ) +{ + BN_VAR(right, (MAX_ECC_KEY_BITS * 3)); + BN_VAR(left, (MAX_ECC_KEY_BITS * 2)); + bigConst prime = CurveGetPrime(C); + // + // Show that point is on the curve y^2 = x^3 + ax + b; + // Or y^2 = x(x^2 + a) + b + // y^2 + BnMult(left, Q->y, Q->y); + BnMod(left, prime); + // x^2 + BnMult(right, Q->x, Q->x); + // x^2 + a + BnAdd(right, right, CurveGet_a(C)); + // BnMod(right, CurveGetPrime(C)); + // x(x^2 + a) + BnMult(right, right, Q->x); + // x(x^2 + a) + b + BnAdd(right, right, CurveGet_b(C)); + BnMod(right, prime); + if(BnUnsignedCmp(left, right) == 0) + return TRUE; + else + return FALSE; +} +/* 10.2.11.2.18 BnIsValidPrivateEcc() */ +/* Checks that 0 < x < q */ +BOOL +BnIsValidPrivateEcc( + bigConst x, // IN: private key to check + bigCurve E // IN: the curve to check + ) +{ + BOOL retVal; + retVal = (!BnEqualZero(x) + && (BnUnsignedCmp(x, CurveGetOrder(AccessCurveData(E))) < 0)); + return retVal; +} +LIB_EXPORT BOOL +CryptEccIsValidPrivateKey( + TPM2B_ECC_PARAMETER *d, + TPM_ECC_CURVE curveId + ) +{ + BN_INITIALIZED(bnD, MAX_ECC_PARAMETER_BYTES * 8, d); + return !BnEqualZero(bnD) && (BnUnsignedCmp(bnD, BnGetCurveOrder(curveId)) < 0); +} +/* 10.2.11.2.19 BnPointMul() */ +/* This function does a point multiply of the form R = [d]S + [u]Q where the parameters are bigNum + values. If S is NULL and d is not NULL, then it computes R = [d]G + [u]Q or just R = [d]G if u + and Q are NULL. If skipChecks is TRUE, then the function will not verify that the inputs are + correct for the domain. This would be the case when the values were created by the CryptoEngine() + code. It will return TPM_RC_NO_RESULT if the resulting point is the point at infinity. */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT result of multiplication is a point at infinity */ +/* TPM_RC_ECC_POINT S or Q is not on the curve */ +/* TPM_RC_VALUE d or u is not < n */ +TPM_RC +BnPointMult( + bigPoint R, // OUT: computed point + pointConst S, // IN: optional point to multiply by 'd' + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: optional second point + bigConst u, // IN: optional second scalar + bigCurve E // IN: curve parameters + ) +{ + BOOL OK; + // + TEST(TPM_ALG_ECDH); + // Need one scalar + OK = (d != NULL || u != NULL); + // If S is present, then d has to be present. If S is not + // present, then d may or may not be present + OK = OK && (((S == NULL) == (d == NULL)) || (d != NULL)); + // either both u and Q have to be provided or neither can be provided (don't + // know what to do if only one is provided. + OK = OK && ((u == NULL) == (Q == NULL)); + OK = OK && (E != NULL); + if(!OK) + return TPM_RC_VALUE; + OK = (S == NULL) || BnIsOnCurve(S, AccessCurveData(E)); + OK = OK && ((Q == NULL) || BnIsOnCurve(Q, AccessCurveData(E))); + if(!OK) + return TPM_RC_ECC_POINT; + if((d != NULL) && (S == NULL)) + S = CurveGetG(AccessCurveData(E)); + // If only one scalar, don't need Shamir's trick + if((d == NULL) || (u == NULL)) + { + if(d == NULL) + OK = BnEccModMult(R, Q, u, E); + else + OK = BnEccModMult(R, S, d, E); + } + else + { + OK = BnEccModMult2(R, S, d, Q, u, E); + } + return (OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT); +} +/* 10.2.11.2.20 BnEccGetPrivate() */ +/* This function gets random values that are the size of the key plus 64 bits. The value is reduced + (mod (q - 1)) and incremented by 1 (q is the order of the curve. This produces a value (d) such + that 1 <= d < q. This is the method of FIPS 186-4 Section B.4.1 'Key Pair Generation Using Extra + Random Value Meaning */ +/* TRUE success */ +/* FALSE failure generating private key */ +#if !USE_OPENSSL_FUNCTIONS_EC // libtpms added +BOOL +BnEccGetPrivate( + bigNum dOut, // OUT: the qualified random value + const ECC_CURVE_DATA *C, // IN: curve for which the private key + // needs to be appropriate + RAND_STATE *rand // IN: state for DRBG + ) +{ + bigConst order = CurveGetOrder(C); + BOOL OK; + UINT32 orderBits = BnSizeInBits(order); + UINT32 orderBytes = BITS_TO_BYTES(orderBits); + BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64); + BN_VAR(nMinus1, MAX_ECC_KEY_BITS); + // + OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand); + OK = OK && BnSubWord(nMinus1, order, 1); + OK = OK && BnMod(bnExtraBits, nMinus1); + OK = OK && BnAddWord(dOut, bnExtraBits, 1); + return OK && !g_inFailureMode; +} +#else // libtpms added begin +BOOL +BnEccGetPrivate( + bigNum dOut, // OUT: the qualified random value + const ECC_CURVE_DATA *C, // IN: curve for which the private key + const EC_GROUP *G, // IN: the EC_GROUP to use; must be != NULL for rand == NULL + BOOL noLeadingZeros, // IN: require that all bytes in the private key be set + // result may not have leading zero bytes + // needs to be appropriate + RAND_STATE *rand // IN: state for DRBG + ) +{ + bigConst order = CurveGetOrder(C); + BOOL OK; + UINT32 orderBits = BnSizeInBits(order); + UINT32 orderBytes = BITS_TO_BYTES(orderBits); + UINT32 requestedBits = 0; + BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64); + BN_VAR(nMinus1, MAX_ECC_KEY_BITS); + + if (rand == NULL) { + if (noLeadingZeros) + requestedBits = orderBits; + + return OpenSSLEccGetPrivate(dOut, G, requestedBits); + } + + // + OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand); + OK = OK && BnSubWord(nMinus1, order, 1); + OK = OK && BnMod(bnExtraBits, nMinus1); + OK = OK && BnAddWord(dOut, bnExtraBits, 1); + return OK && !g_inFailureMode; +} +#endif // USE_OPENSSL_FUNCTIONS_EC libtpms added end +/* 10.2.11.2.21 BnEccGenerateKeyPair() */ +/* This function gets a private scalar from the source of random bits and does the point multiply to + get the public key. */ +#if !USE_OPENSSL_FUNCTIONS_EC // libtpms added + +BOOL +BnEccGenerateKeyPair( + bigNum bnD, // OUT: private scalar + bn_point_t *ecQ, // OUT: public point + bigCurve E, // IN: curve for the point + RAND_STATE *rand // IN: DRBG state to use + ) +{ + BOOL OK = FALSE; + // Get a private scalar + OK = BnEccGetPrivate(bnD, AccessCurveData(E), rand); + // Do a point multiply + OK = OK && BnEccModMult(ecQ, NULL, bnD, E); + if(!OK) + BnSetWord(ecQ->z, 0); + else + BnSetWord(ecQ->z, 1); + return OK; +} + +#else // libtpms added begin + +/* In this version of BnEccGenerateKeyPair we take a dual approach to constant + time requirements: For curves whose order is at the byte boundary, e.g. + NIST P224/P256/P384, we make sure that bnD has all bytes set (no leading zeros) + so that OpenSSL BIGNUM code will not reduce the number of bytes and the + subsequent BnEccModMult() would run faster for a shoter value. For all other + curves whose order is not at the byte boundary, e.g. NIST P521, we simply + always add the order of the curve to bnD and call BnEccModMult() with the + result bnD1, which leads to the same result. */ +BOOL +BnEccGenerateKeyPair( + bigNum bnD, // OUT: private scalar + bn_point_t *ecQ, // OUT: public point + bigCurve E, // IN: curve for the point + RAND_STATE *rand // IN: DRBG state to use + ) +{ + BOOL OK = FALSE; + bigConst order = CurveGetOrder(AccessCurveData(E)); + UINT32 orderBits = BnSizeInBits(order); + BOOL atByteBoundary = (orderBits & 7) == 0; + BOOL noLeadingZeros = atByteBoundary; + ECC_NUM(bnD1); + + // We request that bnD not have leading zeros if it is at byte-boundary, + // like for example it is the case for NIST P256. + OK = BnEccGetPrivate(bnD, AccessCurveData(E), E->G, noLeadingZeros, rand); + if (!atByteBoundary) { + // for NIST P521 we can add the order to bnD to ensure we have + // a constant amount of bytes; the result is the same as if we + // were doing the BnEccModMult() calculation with bnD. + OK = OK && BnAdd(bnD1, bnD, order); + OK = OK && BnEccModMult(ecQ, NULL, bnD1, E); + } else { + OK = OK && BnEccModMult(ecQ, NULL, bnD, E); + } + + if(!OK) + BnSetWord(ecQ->z, 0); + else + BnSetWord(ecQ->z, 1); + return OK; +} + +#endif // libtpms added end + +/* 10.2.11.2.21 CryptEccNewKeyPair */ +/* This function creates an ephemeral ECC. It is ephemeral in that is expected that the private part + of the key will be discarded */ +LIB_EXPORT TPM_RC +CryptEccNewKeyPair( + TPMS_ECC_POINT *Qout, // OUT: the public point + TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar + TPM_ECC_CURVE curveId // IN: the curve for the key + ) +{ + CURVE_INITIALIZED(E, curveId); + POINT(ecQ); + ECC_NUM(bnD); + BOOL OK; + if(E == NULL) + return TPM_RC_CURVE; + TEST(TPM_ALG_ECDH); + OK = BnEccGenerateKeyPair(bnD, ecQ, E, NULL); + if(OK) + { + BnPointTo2B(Qout, ecQ, E); + BnTo2B(bnD, &dOut->b, Qout->x.t.size); + } + else + { + Qout->x.t.size = Qout->y.t.size = dOut->t.size = 0; + } + CURVE_FREE(E); + return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; +} +/* 10.2.11.2.22 CryptEccPointMultiply() */ +/* This function computes 'R := [dIn]G + [uIn]QIn. Where dIn and uIn are scalars, G and QIn are + points on the specified curve and G is the default generator of the curve. */ +/* The xOut and yOut parameters are optional and may be set to NULL if not used. */ +/* It is not necessary to provide uIn if QIn is specified but one of uIn and dIn must be + provided. If dIn and QIn are specified but uIn is not provided, then R = [dIn]QIn. */ +/* If the multiply produces the point at infinity, the TPM_RC_NO_RESULT is returned. */ +/* The sizes of xOut and yOut' will be set to be the size of the degree of the curve */ +/* It is a fatal error if dIn and uIn are both unspecified (NULL) or if Qin or Rout is + unspecified. */ +/* Error Returns Meaning */ +/* TPM_RC_ECC_POINT the point Pin or Qin is not on the curve */ +/* TPM_RC_NO_RESULT the product point is at infinity */ +/* TPM_RC_CURVE bad curve */ +/* TPM_RC_VALUE dIn or uIn out of range */ +LIB_EXPORT TPM_RC +CryptEccPointMultiply( + TPMS_ECC_POINT *Rout, // OUT: the product point R + TPM_ECC_CURVE curveId, // IN: the curve to use + TPMS_ECC_POINT *Pin, // IN: first point (can be null) + TPM2B_ECC_PARAMETER *dIn, // IN: scalar value for [dIn]Qin + // the Pin + TPMS_ECC_POINT *Qin, // IN: point Q + TPM2B_ECC_PARAMETER *uIn // IN: scalar value for the multiplier + // of Q + ) +{ + CURVE_INITIALIZED(E, curveId); + POINT_INITIALIZED(ecP, Pin); + ECC_INITIALIZED(bnD, dIn); // If dIn is null, then bnD is null + ECC_INITIALIZED(bnU, uIn); + POINT_INITIALIZED(ecQ, Qin); + POINT(ecR); + TPM_RC retVal; + // + retVal = BnPointMult(ecR, ecP, bnD, ecQ, bnU, E); + if(retVal == TPM_RC_SUCCESS) + BnPointTo2B(Rout, ecR, E); + else + ClearPoint2B(Rout); + CURVE_FREE(E); + return retVal; +} +/* 10.2.11.2.23 CryptEccIsPointOnCurve() */ +/* This function is used to test if a point is on a defined curve. It does this by checking that y^2 + mod p = x^3 + a*x + b mod p */ +/* It is a fatal error if Q is not specified (is NULL). */ +/* Return Values Meaning */ +/* TRUE point is on curve */ +/* FALSE point is not on curve or curve is not supported */ +LIB_EXPORT BOOL +CryptEccIsPointOnCurve( + TPM_ECC_CURVE curveId, // IN: the curve selector + TPMS_ECC_POINT *Qin // IN: the point. + ) +{ + const ECC_CURVE_DATA *C = GetCurveData(curveId); + POINT_INITIALIZED(ecQ, Qin); + BOOL OK; + // + pAssert(Qin != NULL); + OK = (C != NULL && (BnIsOnCurve(ecQ, C))); + return OK; +} +/* 10.2.11.2.24 CryptEccGenerateKey() */ +/* This function generates an ECC key pair based on the input parameters. This routine uses KDFa() + to produce candidate numbers. The method is according to FIPS 186-3, section B.1.2 "Key Pair + Generation by Testing Candidates." According to the method in FIPS 186-3, the resulting private + value d should be 1 <= d < n where n is the order of the base point. */ +/* It is a fatal error if Qout, dOut, is not provided (is NULL). */ +/* If the curve is not supported If seed is not provided, then a random number will be used for the + key */ +/* Error Returns Meaning */ +/* TPM_RC_CURVE curve is not supported */ +/* TPM_RC_NO_RESULT could not verify key with signature (FIPS only) */ +LIB_EXPORT TPM_RC +CryptEccGenerateKey( + TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for + // the new key. The public key + // area will be replaced computed + // ECC public key + TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be + // updated to contain the private + // ECC key and the symmetric + // encryption key + RAND_STATE *rand // IN: if not NULL, the deterministic + // RNG state + ) +{ + CURVE_INITIALIZED(E, publicArea->parameters.eccDetail.curveID); + ECC_NUM(bnD); + POINT(ecQ); + BOOL OK; + TPM_RC retVal; + TEST(TPM_ALG_ECDSA); // ECDSA is used to verify each key + // Validate parameters + if(E == NULL) + ERROR_RETURN(TPM_RC_CURVE); + publicArea->unique.ecc.x.t.size = 0; + publicArea->unique.ecc.y.t.size = 0; + sensitive->sensitive.ecc.t.size = 0; + OK = BnEccGenerateKeyPair(bnD, ecQ, E, rand); + if(OK) + { + BnPointTo2B(&publicArea->unique.ecc, ecQ, E); + BnTo2B(bnD, &sensitive->sensitive.ecc.b, publicArea->unique.ecc.x.t.size); + } +#if FIPS_COMPLIANT + // See if PWCT is required + if(OK && (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))) + { + ECC_NUM(bnT); + ECC_NUM(bnS); + TPM2B_DIGEST digest; + TEST(TPM_ALG_ECDSA); + digest.t.size = MIN(sensitive->sensitive.ecc.t.size, sizeof(digest.t.buffer)); + // Get a random value to sign using the built in DRBG state + DRBG_Generate(NULL, digest.t.buffer, digest.t.size); + if(g_inFailureMode) + return TPM_RC_FAILURE; + BnSignEcdsa(bnT, bnS, E, bnD, &digest, NULL); + // and make sure that we can validate the signature + OK = BnValidateSignatureEcdsa(bnT, bnS, E, ecQ, &digest) == TPM_RC_SUCCESS; + } +#endif + retVal = (OK) ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; + Exit: + CURVE_FREE(E); + return retVal; +} + +// libtpms added begin +// Support for some curves may be compiled in but they may not be +// supported by openssl's crypto library. +LIB_EXPORT BOOL +CryptEccIsCurveRuntimeUsable( + TPMI_ECC_CURVE curveId + ) +{ + CURVE_INITIALIZED(E, curveId); + if (E == NULL) + return FALSE; + CURVE_FREE(E); + return TRUE; +} +// libtpms added end + +#endif // TPM_ALG_ECC diff --git a/src/tpm2/crypto/openssl/CryptEccSignature.c b/src/tpm2/crypto/openssl/CryptEccSignature.c new file mode 100644 index 0000000..a325a46 --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptEccSignature.c @@ -0,0 +1,1043 @@ +/********************************************************************************/ +/* */ +/* ECC Signatures */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptEccSignature.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.12 CryptEccSignature.c */ +/* 10.2.12.1 Includes and Defines */ +#include "Tpm.h" +#include "CryptEccSignature_fp.h" +#include "TpmToOsslMath_fp.h" // libtpms added +#if ALG_ECC +/* 10.2.12.2 Utility Functions */ +/* 10.2.12.2.1 EcdsaDigest() */ +/* Function to adjust the digest so that it is no larger than the order of the curve. This is used + for ECDSA sign and verification. */ +#if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added +static bigNum +EcdsaDigest( + bigNum bnD, // OUT: the adjusted digest + const TPM2B_DIGEST *digest, // IN: digest to adjust + bigConst max // IN: value that indicates the maximum + // number of bits in the results + ) +{ + int bitsInMax = BnSizeInBits(max); + int shift; + // + if(digest == NULL) + BnSetWord(bnD, 0); + else + { + BnFromBytes(bnD, digest->t.buffer, + (NUMBYTES)MIN(digest->t.size, BITS_TO_BYTES(bitsInMax))); + shift = BnSizeInBits(bnD) - bitsInMax; + if(shift > 0) + BnShiftRight(bnD, bnD, shift); + } + return bnD; +} +#endif // libtpms added +/* 10.2.12.2.2 BnSchnorrSign() */ +/* This contains the Schnorr signature computation. It is used by both ECDSA and Schnorr + signing. The result is computed as: [s = k + r * d (mod n)] where */ +/* a) s is the signature */ +/* b) k is a random value */ +/* c) r is the value to sign */ +/* d) d is the private EC key */ +/* e) n is the order of the curve */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT the result of the operation was zero or r (mod n) is zero */ +static TPM_RC +BnSchnorrSign( + bigNum bnS, // OUT: s component of the signature + bigConst bnK, // IN: a random value + bigNum bnR, // IN: the signature 'r' value + bigConst bnD, // IN: the private key + bigConst bnN // IN: the order of the curve + ) +{ + // Need a local temp value to store the intermediate computation because product + // size can be larger than will fit in bnS. + BN_VAR(bnT1, MAX_ECC_PARAMETER_BYTES * 2 * 8); + // + // Reduce bnR without changing the input value + BnDiv(NULL, bnT1, bnR, bnN); + if(BnEqualZero(bnT1)) + return TPM_RC_NO_RESULT; + // compute s = (k + r * d)(mod n) + // r * d + BnMult(bnT1, bnT1, bnD); + // k * r * d + BnAdd(bnT1, bnT1, bnK); + // k + r * d (mod n) + BnDiv(NULL, bnS, bnT1, bnN); + return (BnEqualZero(bnS)) ? TPM_RC_NO_RESULT : TPM_RC_SUCCESS; +} +/* 10.2.12.3 Signing Functions */ +/* 10.2.12.3.1 BnSignEcdsa() */ +/* This function implements the ECDSA signing algorithm. The method is described in the comments + below. This version works with internal numbers. */ +#if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added +TPM_RC +BnSignEcdsa( + bigNum bnR, // OUT: r component of the signature + bigNum bnS, // OUT: s component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigNum bnD, // IN: private signing key + const TPM2B_DIGEST *digest, // IN: the digest to sign + RAND_STATE *rand // IN: used in debug of signing + ) +{ + ECC_NUM(bnK); + ECC_NUM(bnIk); + BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8); + POINT(ecR); + bigConst order = CurveGetOrder(AccessCurveData(E)); + TPM_RC retVal = TPM_RC_SUCCESS; + INT32 tries = 10; + BOOL OK = FALSE; + // + pAssert(digest != NULL); + // The algorithm as described in "Suite B Implementer's Guide to FIPS + // 186-3(ECDSA)" + // 1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a + // per-message secret number and its inverse modulo n. Since n is prime, + // the output will be invalid only if there is a failure in the RBG. + // 2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar + // multiplication (see [Routines]), where G is the base point included in + // the set of domain parameters. + // 3. Compute r = xR mod n. If r = 0, then return to Step 1. 1. + // 4. Use the selected hash function to compute H = Hash(M). + // 5. Convert the bit string H to an integer e as described in Appendix B.2. + // 6. Compute s = (k^-1 * (e + d * r)) mod q. If s = 0, return to Step 1.2. + // 7. Return (r, s). + // In the code below, q is n (that it, the order of the curve is p) + do // This implements the loop at step 6. If s is zero, start over. + { + for(; tries > 0; tries--) + { + // Step 1 and 2 -- generate an ephemeral key and the modular inverse + // of the private key. + if(!BnEccGenerateKeyPair(bnK, ecR, E, rand)) + continue; + // x coordinate is mod p. Make it mod q + BnMod(ecR->x, order); + // Make sure that it is not zero; + if(BnEqualZero(ecR->x)) + continue; + // write the modular reduced version of r as part of the signature + BnCopy(bnR, ecR->x); + // Make sure that a modular inverse exists and try again if not + OK = (BnModInverse(bnIk, bnK, order)); + if(OK) + break; + } + if(!OK) + goto Exit; + EcdsaDigest(bnE, digest, order); + // now have inverse of K (bnIk), e (bnE), r (bnR), d (bnD) and + // CurveGetOrder(E) + // Compute s = k^-1 (e + r*d)(mod q) + // first do s = r*d mod q + BnModMult(bnS, bnR, bnD, order); + // s = e + s = e + r * d + BnAdd(bnS, bnE, bnS); + // s = k^(-1)s (mod n) = k^(-1)(e + r * d)(mod n) + BnModMult(bnS, bnIk, bnS, order); + // If S is zero, try again + } while(BnEqualZero(bnS)); + Exit: + return retVal; +} +#else // !USE_OPENSSL_FUNCTIONS_ECDSA libtpms added begin +TPM_RC +BnSignEcdsa( + bigNum bnR, // OUT: r component of the signature + bigNum bnS, // OUT: s component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigNum bnD, // IN: private signing key + const TPM2B_DIGEST *digest, // IN: the digest to sign + RAND_STATE *rand // IN: used in debug of signing + ) +{ + ECDSA_SIG *sig = NULL; + EC_KEY *eckey; + int retVal; + const BIGNUM *r; + const BIGNUM *s; + BIGNUM *d = BN_new(); + + d = BigInitialized(d, bnD); + + eckey = EC_KEY_new(); + + if (d == NULL || eckey == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + + if (EC_KEY_set_group(eckey, E->G) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + if (EC_KEY_set_private_key(eckey, d) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + sig = ECDSA_do_sign(digest->b.buffer, digest->b.size, eckey); + if (sig == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + + ECDSA_SIG_get0(sig, &r, &s); + OsslToTpmBn(bnR, r); + OsslToTpmBn(bnS, s); + + retVal = TPM_RC_SUCCESS; + + Exit: + BN_clear_free(d); + EC_KEY_free(eckey); + ECDSA_SIG_free(sig); + + return retVal; +} +#endif // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added end +#if ALG_ECDAA +/* 10.2.12.3.2 BnSignEcdaa() */ +/* This function performs s = r + T * d mod q where */ +/* a) 'r is a random, or pseudo-random value created in the commit phase */ +/* b) nonceK is a TPM-generated, random value 0 < nonceK < n */ +/* c) T is mod q of Hash(nonceK || digest), and */ +/* d) d is a private key. */ +/* The signature is the tuple (nonceK, s) */ +/* Regrettably, the parameters in this function kind of collide with the parameter names used in + ECSCHNORR making for a lot of confusion. In particular, the k value in this function is value in + this function u */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME unsupported hash algorithm */ +/* TPM_RC_NO_RESULT cannot get values from random number generator */ +static TPM_RC +BnSignEcdaa( + TPM2B_ECC_PARAMETER *nonceK, // OUT: nonce component of the signature + bigNum bnS, // OUT: s component of the signature + bigCurve E, // IN: the curve used in signing + bigNum bnD, // IN: the private key + const TPM2B_DIGEST *digest, // IN: the value to sign (mod q) + TPMT_ECC_SCHEME *scheme, // IN: signing scheme (contains the + // commit count value). + OBJECT *eccKey, // IN: The signing key + RAND_STATE *rand // IN: a random number state + ) +{ + TPM_RC retVal; + TPM2B_ECC_PARAMETER r; + HASH_STATE state; + TPM2B_DIGEST T; + BN_MAX(bnT); + // + NOT_REFERENCED(rand); + if(!CryptGenerateR(&r, &scheme->details.ecdaa.count, + eccKey->publicArea.parameters.eccDetail.curveID, + &eccKey->name)) + retVal = TPM_RC_VALUE; + else + { + // This allocation is here because 'r' doesn't have a value until + // CrypGenerateR() is done. + ECC_INITIALIZED(bnR, &r); + do + { + // generate nonceK such that 0 < nonceK < n + // use bnT as a temp. +#if USE_OPENSSL_FUNCTIONS_EC // libtpms added begin + if(!BnEccGetPrivate(bnT, AccessCurveData(E), E->G, false, rand)) +#else // libtpms added end + if(!BnEccGetPrivate(bnT, AccessCurveData(E), rand)) +#endif // libtpms added + { + retVal = TPM_RC_NO_RESULT; + break; + } + BnTo2B(bnT, &nonceK->b, 0); + T.t.size = CryptHashStart(&state, scheme->details.ecdaa.hashAlg); + if(T.t.size == 0) + { + retVal = TPM_RC_SCHEME; + } + else + { + CryptDigestUpdate2B(&state, &nonceK->b); + CryptDigestUpdate2B(&state, &digest->b); + CryptHashEnd2B(&state, &T.b); + BnFrom2B(bnT, &T.b); + // libtpms: Note: T is NOT a concern for constant-timeness + // Watch out for the name collisions in this call!! + retVal = BnSchnorrSign(bnS, bnR, bnT, bnD, + AccessCurveData(E)->order); + } + } while(retVal == TPM_RC_NO_RESULT); + // Because the rule is that internal state is not modified if the command + // fails, only end the commit if the command succeeds. + // NOTE that if the result of the Schnorr computation was zero + // it will probably not be worthwhile to run the same command again because + // the result will still be zero. This means that the Commit command will + // need to be run again to get a new commit value for the signature. + if(retVal == TPM_RC_SUCCESS) + CryptEndCommit(scheme->details.ecdaa.count); + } + return retVal; +} +#endif // ALG_ECDAA +#if ALG_ECSCHNORR +/* 10.2.12.3.3 SchnorrReduce() */ +/* Function to reduce a hash result if it's magnitude is to large. The size of number is set so that + it has no more bytes of significance than the reference value. If the resulting number can have + more bits of significance than the reference. */ +static void +SchnorrReduce( + TPM2B *number, // IN/OUT: Value to reduce + bigConst reference // IN: the reference value + ) +{ + UINT16 maxBytes = (UINT16)BITS_TO_BYTES(BnSizeInBits(reference)); + if(number->size > maxBytes) + number->size = maxBytes; +} +/* 10.2.12.3.4 SchnorrEcc() */ +/* This function is used to perform a modified Schnorr signature. */ +/* This function will generate a random value k and compute */ +/* a) (xR, yR) = [k]G */ +/* b) r = hash(xR || P)(mod q) */ +/* c) rT = truncated r */ +/* d) s= k + rT * ds (mod q) */ +/* e) return the tuple rT, s */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT failure in the Schnorr sign process */ +/* TPM_RC_SCHEME hashAlg can't produce zero-length digest */ +static TPM_RC +BnSignEcSchnorr( + bigNum bnR, // OUT: r component of the signature + bigNum bnS, // OUT: s component of the signature + bigCurve E, // IN: the curve used in signing + bigNum bnD, // IN: the signing key + const TPM2B_DIGEST *digest, // IN: the digest to sign + TPM_ALG_ID hashAlg, // IN: signing scheme (contains a hash) + RAND_STATE *rand // IN: non-NULL when testing + ) +{ + HASH_STATE hashState; + UINT16 digestSize + = CryptHashGetDigestSize(hashAlg); + TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_KEY_BYTES)); + TPM2B_T T2b; + TPM2B *e = &T2b.b; + TPM_RC retVal = TPM_RC_NO_RESULT; + const ECC_CURVE_DATA *C; + bigConst order; + bigConst prime; + ECC_NUM(bnK); + POINT(ecR); + // + // Parameter checks + if(E == NULL) + ERROR_RETURN(TPM_RC_VALUE); + C = AccessCurveData(E); + order = CurveGetOrder(C); + prime = CurveGetOrder(C); + // If the digest does not produce a hash, then null the signature and return + // a failure. + if(digestSize == 0) + { + BnSetWord(bnR, 0); + BnSetWord(bnS, 0); + ERROR_RETURN(TPM_RC_SCHEME); + } + do + { + // Generate a random key pair + if(!BnEccGenerateKeyPair(bnK, ecR, E, rand)) + break; + // Convert R.x to a string + BnTo2B(ecR->x, e, (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(prime))); + // f) compute r = Hash(e || P) (mod n) + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate2B(&hashState, e); + CryptDigestUpdate2B(&hashState, &digest->b); + e->size = CryptHashEnd(&hashState, digestSize, e->buffer); + // Reduce the hash size if it is larger than the curve order + SchnorrReduce(e, order); + // Convert hash to number + BnFrom2B(bnR, e); + // libtpms: Note: e is NOT a concern for constant-timeness + // Do the Schnorr computation + retVal = BnSchnorrSign(bnS, bnK, bnR, bnD, CurveGetOrder(C)); + } while(retVal == TPM_RC_NO_RESULT); + Exit: + return retVal; +} +#endif // ALG_ECSCHNORR +#if ALG_SM2 +#ifdef _SM2_SIGN_DEBUG +/* 10.2.12.3.5 BnHexEqual() */ +/* This function compares a bignum value to a hex string. */ +/* Return Value Meaning */ +/* TRUE(1) values equal */ +/* FALSE(0) values not equal */ +static BOOL +BnHexEqual( + bigNum bn, //IN: big number value + const char *c //IN: character string number + ) +{ + ECC_NUM(bnC); + BnFromHex(bnC, c); + return (BnUnsignedCmp(bn, bnC) == 0); +} +#endif // _SM2_SIGN_DEBUG +/* 10.2.12.3.5 BnSignEcSm2() */ +/* This function signs a digest using the method defined in SM2 Part 2. The method in the standard + will add a header to the message to be signed that is a hash of the values that define the + key. This then hashed with the message to produce a digest (e) that is signed. This function + signs e. */ +/* Error Returns Meaning */ +/* TPM_RC_VALUE bad curve */ +static TPM_RC +BnSignEcSm2( + bigNum bnR, // OUT: r component of the signature + bigNum bnS, // OUT: s component of the signature + bigCurve E, // IN: the curve used in signing + bigNum bnD, // IN: the private key + const TPM2B_DIGEST *digest, // IN: the digest to sign + RAND_STATE *rand // IN: random number generator (mostly for + // debug) + ) +{ + BN_MAX_INITIALIZED(bnE, digest); // Don't know how big digest might be + ECC_NUM(bnN); + ECC_NUM(bnK); + ECC_NUM(bnT); // temp + POINT(Q1); + bigConst order = (E != NULL) + ? CurveGetOrder(AccessCurveData(E)) : NULL; +// libtpms added begin + UINT32 orderBits = BnSizeInBits(order); + BOOL atByteBoundary = (orderBits & 7) == 0; + ECC_NUM(bnK1); +// libtpms added end + + // +#ifdef _SM2_SIGN_DEBUG + BnFromHex(bnE, "B524F552CD82B8B028476E005C377FB1" + "9A87E6FC682D48BB5D42E3D9B9EFFE76"); + BnFromHex(bnD, "128B2FA8BD433C6C068C8D803DFF7979" + "2A519A55171B1B650C23661D15897263"); +#endif + // A3: Use random number generator to generate random number 1 <= k <= n-1; + // NOTE: Ax: numbers are from the SM2 standard + loop: + { + // Get a random number 0 < k < n + // libtpms modified begin + // + // We take a dual approach here. One for curves whose order is not at + // the byte boundary, e.g. NIST P521, we get a random number bnK and add + // the order to that number to have bnK1. This will not spill over into + // a new byte and we can then use bnK1 to do the do the BnEccModMult + // with a constant number of bytes. For curves whose order is at the + // byte boundary we require that the random number bnK comes back with + // a requested number of bytes. + if (!atByteBoundary) { + BnGenerateRandomInRange(bnK, order, rand); + BnAdd(bnK1, bnK, order); +#ifdef _SM2_SIGN_DEBUG + BnFromHex(bnK1, "6CB28D99385C175C94F94E934817663F" + "C176D925DD72B727260DBAAE1FB2F96F"); +#endif + // A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according + // to details specified in 4.2.7 in Part 1 of this document, transform the + // data type of x1 into an integer; + if(!BnEccModMult(Q1, NULL, bnK1, E)) + goto loop; + } else { + BnGenerateRandomInRangeAllBytes(bnK, order, rand); +#ifdef _SM2_SIGN_DEBUG + BnFromHex(bnK, "6CB28D99385C175C94F94E934817663F" + "C176D925DD72B727260DBAAE1FB2F96F"); +#endif + if(!BnEccModMult(Q1, NULL, bnK, E)) + goto loop; + } // libtpms modified end + // A5: Figure out r = (e + x1) mod n, + BnAdd(bnR, bnE, Q1->x); + BnMod(bnR, order); +#ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41" + "94F79FB1EED2CAA55BACDB49C4E755D1")); +#endif + // if r=0 or r+k=n, return to A3; + if(BnEqualZero(bnR)) + goto loop; + BnAdd(bnT, bnK, bnR); + if(BnUnsignedCmp(bnT, bnN) == 0) + goto loop; + // A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n, + // if s=0, return to A3; + // compute t = (1+dA)^-1 + BnAddWord(bnT, bnD, 1); + BnModInverse(bnT, bnT, order); +#ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnT, "79BFCF3052C80DA7B939E0C6914A18CB" + "B2D96D8555256E83122743A7D4F5F956")); +#endif + // compute s = t * (k - r * dA) mod n + BnModMult(bnS, bnR, bnD, order); + // k - r * dA mod n = k + n - ((r * dA) mod n) + BnSub(bnS, order, bnS); + BnAdd(bnS, bnK, bnS); + BnModMult(bnS, bnS, bnT, order); +#ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" + "67A457872FB09EC56327A67EC7DEEBE7")); +#endif + if(BnEqualZero(bnS)) + goto loop; + } + // A7: According to details specified in 4.2.1 in Part 1 of this document, + // transform the data type of r, s into bit strings, signature of message M + // is (r, s). + // This is handled by the common return code +#ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41" + "94F79FB1EED2CAA55BACDB49C4E755D1")); + pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" + "67A457872FB09EC56327A67EC7DEEBE7")); +#endif + return TPM_RC_SUCCESS; +} +#endif // ALG_SM2 +/* 10.2.12.3.6 CryptEccSign() */ +/* This function is the dispatch function for the various ECC-based signing schemes. There is a bit + of ugliness to the parameter passing. In order to test this, we sometime would like to use a + deterministic RNG so that we can get the same signatures during testing. The easiest way to do + this for most schemes is to pass in a deterministic RNG and let it return canned values during + testing. There is a competing need for a canned parameter to use in ECDAA. To accommodate both + needs with minimal fuss, a special type of RAND_STATE is defined to carry the address of the + commit value. The setup and handling of this is not very different for the caller than what was + in previous versions of the code. */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME scheme is not supported */ +LIB_EXPORT TPM_RC +CryptEccSign( + TPMT_SIGNATURE *signature, // OUT: signature + OBJECT *signKey, // IN: ECC key to sign the hash + const TPM2B_DIGEST *digest, // IN: digest to sign + TPMT_ECC_SCHEME *scheme, // IN: signing scheme + RAND_STATE *rand + ) +{ + CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID); + ECC_INITIALIZED(bnD, &signKey->sensitive.sensitive.ecc.b); + ECC_NUM(bnR); + ECC_NUM(bnS); + const ECC_CURVE_DATA *C; + TPM_RC retVal = TPM_RC_SCHEME; + // + NOT_REFERENCED(scheme); + if(E == NULL) + ERROR_RETURN(TPM_RC_VALUE); + C = AccessCurveData(E); + signature->signature.ecdaa.signatureR.t.size + = sizeof(signature->signature.ecdaa.signatureR.t.buffer); + signature->signature.ecdaa.signatureS.t.size + = sizeof(signature->signature.ecdaa.signatureS.t.buffer); + TEST(signature->sigAlg); + switch(signature->sigAlg) + { + case TPM_ALG_ECDSA: + retVal = BnSignEcdsa(bnR, bnS, E, bnD, digest, rand); + break; +#if ALG_ECDAA + case TPM_ALG_ECDAA: + retVal = BnSignEcdaa(&signature->signature.ecdaa.signatureR, bnS, E, + bnD, digest, scheme, signKey, rand); + bnR = NULL; + break; +#endif +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + retVal = BnSignEcSchnorr(bnR, bnS, E, bnD, digest, + signature->signature.ecschnorr.hash, + rand); + break; +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + retVal = BnSignEcSm2(bnR, bnS, E, bnD, digest, rand); + break; +#endif + default: + break; + } + // If signature generation worked, convert the results. + if(retVal == TPM_RC_SUCCESS) + { + NUMBYTES orderBytes = + (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(C))); + if(bnR != NULL) + BnTo2B(bnR, &signature->signature.ecdaa.signatureR.b, orderBytes); + if(bnS != NULL) + BnTo2B(bnS, &signature->signature.ecdaa.signatureS.b, orderBytes); + } + Exit: + CURVE_FREE(E); + return retVal; +} +#if ALG_ECDSA +/* 10.2.12.3.7 BnValidateSignatureEcdsa() */ +/* This function validates an ECDSA signature. rIn and sIn should have been checked to make sure + that they are in the range 0 < v < n */ +/* Error Returns Meaning */ +/* TPM_RC_SIGNATURE signature not valid */ +#if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added +TPM_RC +BnValidateSignatureEcdsa( + bigNum bnR, // IN: r component of the signature + bigNum bnS, // IN: s component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bn_point_t *ecQ, // IN: the public point of the key + const TPM2B_DIGEST *digest // IN: the digest that was signed + ) +{ + // Make sure that the allocation for the digest is big enough for a maximum + // digest + BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8); + POINT(ecR); + ECC_NUM(bnU1); + ECC_NUM(bnU2); + ECC_NUM(bnW); + bigConst order = CurveGetOrder(AccessCurveData(E)); + TPM_RC retVal = TPM_RC_SIGNATURE; + // Get adjusted digest + EcdsaDigest(bnE, digest, order); + // 1. If r and s are not both integers in the interval [1, n - 1], output + // INVALID. + // bnR and bnS were validated by the caller + // 2. Use the selected hash function to compute H0 = Hash(M0). + // This is an input parameter + // 3. Convert the bit string H0 to an integer e as described in Appendix B.2. + // Done at entry + // 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1. + if(!BnModInverse(bnW, bnS, order)) + goto Exit; + // 5. Compute u1 = (e' * w) mod n, and compute u2 = (r' * w) mod n. + BnModMult(bnU1, bnE, bnW, order); + BnModMult(bnU2, bnR, bnW, order); + // 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC + // scalar multiplication and EC addition (see [Routines]). If R is equal to + // the point at infinity O, output INVALID. + if(BnPointMult(ecR, CurveGetG(AccessCurveData(E)), bnU1, ecQ, bnU2, E) + != TPM_RC_SUCCESS) + goto Exit; + // 7. Compute v = Rx mod n. + BnMod(ecR->x, order); + // 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID + if(BnUnsignedCmp(ecR->x, bnR) != 0) + goto Exit; + retVal = TPM_RC_SUCCESS; + Exit: + return retVal; +} +#else // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added begin +TPM_RC +BnValidateSignatureEcdsa( + bigNum bnR, // IN: r component of the signature + bigNum bnS, // IN: s component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bn_point_t *ecQ, // IN: the public point of the key + const TPM2B_DIGEST *digest // IN: the digest that was signed + ) +{ + int retVal; + int rc; + ECDSA_SIG *sig = NULL; + EC_KEY *eckey = NULL; + BIGNUM *r = BN_new(); + BIGNUM *s = BN_new(); + EC_POINT *q = EcPointInitialized(ecQ, E); + + r = BigInitialized(r, bnR); + s = BigInitialized(s, bnS); + + sig = ECDSA_SIG_new(); + eckey = EC_KEY_new(); + + if (r == NULL || s == NULL || q == NULL || sig == NULL || eckey == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + + if (EC_KEY_set_group(eckey, E->G) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + if (EC_KEY_set_public_key(eckey, q) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + if (ECDSA_SIG_set0(sig, r, s) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + /* sig now owns r and s */ + r = NULL; + s = NULL; + + rc = ECDSA_do_verify(digest->b.buffer, digest->b.size, sig, eckey); + switch (rc) { + case 1: + retVal = TPM_RC_SUCCESS; + break; + case 0: + retVal = TPM_RC_SIGNATURE; + break; + default: + retVal = TPM_RC_FAILURE; + break; + } + + Exit: + EC_KEY_free(eckey); + ECDSA_SIG_free(sig); + EC_POINT_clear_free(q); + BN_clear_free(r); + BN_clear_free(s); + + return retVal; +} +#endif // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added end +#endif // ALG_ECDSA +#if ALG_SM2 +/* 10.2.12.3.8 BnValidateSignatureEcSm2() */ +/* This function is used to validate an SM2 signature. */ +/* Error Returns Meaning */ +/* TPM_RC_SIGNATURE signature not valid */ +static TPM_RC +BnValidateSignatureEcSm2( + bigNum bnR, // IN: r component of the signature + bigNum bnS, // IN: s component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigPoint ecQ, // IN: the public point of the key + const TPM2B_DIGEST *digest // IN: the digest that was signed + ) +{ + POINT(P); + ECC_NUM(bnRp); + ECC_NUM(bnT); + BN_MAX_INITIALIZED(bnE, digest); + BOOL OK; + bigConst order = CurveGetOrder(AccessCurveData(E)); +#ifdef _SM2_SIGN_DEBUG + // Make sure that the input signature is the test signature + pAssert(BnHexEqual(bnR, + "40F1EC59F793D9F49E09DCEF49130D41" + "94F79FB1EED2CAA55BACDB49C4E755D1")); + pAssert(BnHexEqual(bnS, + "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" + "67A457872FB09EC56327A67EC7DEEBE7")); +#endif + // b) compute t := (r + s) mod n + BnAdd(bnT, bnR, bnS); + BnMod(bnT, order); +#ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnT, + "2B75F07ED7ECE7CCC1C8986B991F441A" + "D324D6D619FE06DD63ED32E0C997C801")); +#endif + // c) verify that t > 0 + OK = !BnEqualZero(bnT); + if(!OK) + // set T to a value that should allow rest of the computations to run + // without trouble + BnCopy(bnT, bnS); + // d) compute (x, y) := [s]G + [t]Q + OK = BnEccModMult2(P, NULL, bnS, ecQ, bnT, E); +#ifdef _SM2_SIGN_DEBUG + pAssert(OK && BnHexEqual(P->x, + "110FCDA57615705D5E7B9324AC4B856D" + "23E6D9188B2AE47759514657CE25D112")); +#endif + // e) compute r' := (e + x) mod n (the x coordinate is in bnT) + OK = OK && BnAdd(bnRp, bnE, P->x); + OK = OK && BnMod(bnRp, order); + // f) verify that r' = r + OK = OK && (BnUnsignedCmp(bnR, bnRp) == 0); + + if(!OK) + return TPM_RC_SIGNATURE; + else + return TPM_RC_SUCCESS; +} +#endif // ALG_SM2 +#if ALG_ECSCHNORR +/* 10.2.12.3.9 BnValidateSignatureEcSchnorr() */ +/* This function is used to validate an EC Schnorr signature. */ +/* Error Returns Meaning */ +/* TPM_RC_SIGNATURE signature not valid */ +static TPM_RC +BnValidateSignatureEcSchnorr( + bigNum bnR, // IN: r component of the signature + bigNum bnS, // IN: s component of the signature + TPM_ALG_ID hashAlg, // IN: hash algorithm of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigPoint ecQ, // IN: the public point of the key + const TPM2B_DIGEST *digest // IN: the digest that was signed + ) +{ + BN_MAX(bnRn); + POINT(ecE); + BN_MAX(bnEx); + const ECC_CURVE_DATA *C = AccessCurveData(E); + bigConst order = CurveGetOrder(C); + UINT16 digestSize = CryptHashGetDigestSize(hashAlg); + HASH_STATE hashState; + TPM2B_TYPE(BUFFER, MAX(MAX_ECC_PARAMETER_BYTES, MAX_DIGEST_SIZE)); + TPM2B_BUFFER Ex2 = {{sizeof(Ex2.t.buffer),{ 0 }}}; + BOOL OK; + // + // E = [s]G - [r]Q + BnMod(bnR, order); + // Make -r = n - r + BnSub(bnRn, order, bnR); + // E = [s]G + [-r]Q + OK = BnPointMult(ecE, CurveGetG(C), bnS, ecQ, bnRn, E) == TPM_RC_SUCCESS; + // // reduce the x portion of E mod q + // OK = OK && BnMod(ecE->x, order); + // Convert to byte string + OK = OK && BnTo2B(ecE->x, &Ex2.b, + (NUMBYTES)(BITS_TO_BYTES(BnSizeInBits(order)))); + if(OK) + { + // Ex = h(pE.x || digest) + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate(&hashState, Ex2.t.size, Ex2.t.buffer); + CryptDigestUpdate(&hashState, digest->t.size, digest->t.buffer); + Ex2.t.size = CryptHashEnd(&hashState, digestSize, Ex2.t.buffer); + SchnorrReduce(&Ex2.b, order); + BnFrom2B(bnEx, &Ex2.b); + // see if Ex matches R + OK = BnUnsignedCmp(bnEx, bnR) == 0; + } + return (OK) ? TPM_RC_SUCCESS : TPM_RC_SIGNATURE; +} +#endif // ALG_ECSCHNORR +/* 10.2.12.3.10 CryptEccValidateSignature() */ +/* This function validates an EcDsa() or EcSchnorr() signature. The point Qin needs to have been + validated to be on the curve of curveId. */ +/* Error Returns Meaning */ +/* TPM_RC_SIGNATURE not a valid signature */ +LIB_EXPORT TPM_RC +CryptEccValidateSignature( + TPMT_SIGNATURE *signature, // IN: signature to be verified + OBJECT *signKey, // IN: ECC key signed the hash + const TPM2B_DIGEST *digest // IN: digest that was signed + ) +{ + CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID); + ECC_NUM(bnR); + ECC_NUM(bnS); + POINT_INITIALIZED(ecQ, &signKey->publicArea.unique.ecc); + bigConst order; + TPM_RC retVal; + if(E == NULL) + ERROR_RETURN(TPM_RC_VALUE); + order = CurveGetOrder(AccessCurveData(E)); + // // Make sure that the scheme is valid + switch(signature->sigAlg) + { + case TPM_ALG_ECDSA: +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +#endif +#if ALG_SM2 + case TPM_ALG_SM2: +#endif + break; + default: + ERROR_RETURN(TPM_RC_SCHEME); + break; + } + // Can convert r and s after determining that the scheme is an ECC scheme. If + // this conversion doesn't work, it means that the unmarshaling code for + // an ECC signature is broken. + BnFrom2B(bnR, &signature->signature.ecdsa.signatureR.b); + BnFrom2B(bnS, &signature->signature.ecdsa.signatureS.b); + // r and s have to be greater than 0 but less than the curve order + if(BnEqualZero(bnR) || BnEqualZero(bnS)) + ERROR_RETURN(TPM_RC_SIGNATURE); + if((BnUnsignedCmp(bnS, order) >= 0) + || (BnUnsignedCmp(bnR, order) >= 0)) + ERROR_RETURN(TPM_RC_SIGNATURE); + switch(signature->sigAlg) + { + case TPM_ALG_ECDSA: + retVal = BnValidateSignatureEcdsa(bnR, bnS, E, ecQ, digest); + break; +#if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + retVal = BnValidateSignatureEcSchnorr(bnR, bnS, + signature->signature.any.hashAlg, + E, ecQ, digest); + break; +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + retVal = BnValidateSignatureEcSm2(bnR, bnS, E, ecQ, digest); + break; +#endif + default: + FAIL(FATAL_ERROR_INTERNAL); + } + Exit: + CURVE_FREE(E); + return retVal; +} +/* 10.2.12.3.11 CryptEccCommitCompute() */ +/* This function performs the point multiply operations required by TPM2_Commit(). */ +/* If B or M is provided, they must be on the curve defined by curveId. This routine does not check + that they are on the curve and results are unpredictable if they are not. */ +/* It is a fatal error if r is NULL. If B is not NULL, then it is a fatal error if d is NULL or if K + and L are both NULL. If M is not NULL, then it is a fatal error if E is NULL. */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT if K, L or E was computed to be the point at infinity */ +/* TPM_RC_CANCELED a cancel indication was asserted during this function */ +LIB_EXPORT TPM_RC +CryptEccCommitCompute( + TPMS_ECC_POINT *K, // OUT: [d]B or [r]Q + TPMS_ECC_POINT *L, // OUT: [r]B + TPMS_ECC_POINT *E, // OUT: [r]M + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPMS_ECC_POINT *M, // IN: M (optional) + TPMS_ECC_POINT *B, // IN: B (optional) + TPM2B_ECC_PARAMETER *d, // IN: d (optional) + TPM2B_ECC_PARAMETER *r // IN: the computed r value (required) + ) +{ + CURVE_INITIALIZED(curve, curveId); // Normally initialize E as the curve, but E means + // something else in this function + ECC_INITIALIZED(bnR, r); + TPM_RC retVal = TPM_RC_SUCCESS; + // + // Validate that the required parameters are provided. + // Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do + // E := [r]Q if both M and B are NULL. + pAssert(r != NULL && E != NULL); + // Initialize the output points in case they are not computed + ClearPoint2B(K); + ClearPoint2B(L); + ClearPoint2B(E); + // Sizes of the r parameter may not be zero + pAssert(r->t.size > 0); + // If B is provided, compute K=[d]B and L=[r]B + if(B != NULL) + { + ECC_INITIALIZED(bnD, d); + POINT_INITIALIZED(pB, B); + POINT(pK); + POINT(pL); + // + pAssert(d != NULL && K != NULL && L != NULL); + if(!BnIsOnCurve(pB, AccessCurveData(curve))) + ERROR_RETURN(TPM_RC_VALUE); + // do the math for K = [d]B + if((retVal = BnPointMult(pK, pB, bnD, NULL, NULL, curve)) != TPM_RC_SUCCESS) + goto Exit; + // Convert BN K to TPM2B K + BnPointTo2B(K, pK, curve); + // compute L= [r]B after checking for cancel + if(_plat__IsCanceled()) + ERROR_RETURN(TPM_RC_CANCELED); + // compute L = [r]B + if(!BnIsValidPrivateEcc(bnR, curve)) + ERROR_RETURN(TPM_RC_VALUE); + if((retVal = BnPointMult(pL, pB, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS) + goto Exit; + // Convert BN L to TPM2B L + BnPointTo2B(L, pL, curve); + } + if((M != NULL) || (B == NULL)) + { + POINT_INITIALIZED(pM, M); + POINT(pE); + // + // Make sure that a place was provided for the result + pAssert(E != NULL); + // if this is the third point multiply, check for cancel first + if((B != NULL) && _plat__IsCanceled()) + ERROR_RETURN(TPM_RC_CANCELED); + // If M provided, then pM will not be NULL and will compute E = [r]M. + // However, if M was not provided, then pM will be NULL and E = [r]G + // will be computed + if((retVal = BnPointMult(pE, pM, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS) + goto Exit; + // Convert E to 2B format + BnPointTo2B(E, pE, curve); + } + Exit: + CURVE_FREE(curve); + return retVal; +} +#endif // TPM_ALG_ECC diff --git a/src/tpm2/crypto/openssl/CryptHash.c b/src/tpm2/crypto/openssl/CryptHash.c new file mode 100644 index 0000000..cb5bd0f --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptHash.c @@ -0,0 +1,871 @@ +/********************************************************************************/ +/* */ +/* Implementation of cryptographic functions for hashing. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptHash.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.13 CryptHash.c */ +/* 10.2.13.1 Description */ +/* This file contains implementation of cryptographic functions for hashing. */ +/* 10.2.13.2 Includes, Defines, and Types */ +#define _CRYPT_HASH_C_ +#include "Tpm.h" +#include "CryptHash_fp.h" +#include "CryptHash.h" +#include "OIDs.h" + +/* Instance each of the hash descriptors based on the implemented algorithms */ + +FOR_EACH_HASH(HASH_DEF_TEMPLATE) + +/* Instance a null def. */ + + HASH_DEF NULL_Def = {{0}}; + +/* Create a table of pointers to the defined hash definitions */ + +#define HASH_DEF_ENTRY(HASH, Hash) &Hash##_Def, +PHASH_DEF HashDefArray[] = { + // for each implemented HASH, expands to: &HASH_Def, + FOR_EACH_HASH(HASH_DEF_ENTRY) + &NULL_Def +}; + +/* 10.2.13.3 Obligatory Initialization Functions */ +/* 10.2.13.3.1 CryptHashInit() */ +/* This function is called by _TPM_Init() do perform the initialization operations for the + library. */ +BOOL +CryptHashInit( + void + ) +{ + LibHashInit(); + return TRUE; +} +/* 10.2.13.3.2 CryptHashStartup() */ +/* This function is called by TPM2_Startup(). It checks that the size of the HashDefArray() is + consistent with the HASH_COUNT. */ +BOOL +CryptHashStartup( + void + ) +{ + int i = sizeof(HashDefArray) / sizeof(PHASH_DEF) - 1; + return (i == HASH_COUNT); +} +/* 10.2.13.4 Hash Information Access Functions */ +/* 10.2.13.4.1 Introduction */ +/* These functions provide access to the hash algorithm description information. */ +/* 10.2.13.4.2 CryptGetHashDef() */ +/* This function accesses the hash descriptor associated with a hash a algorithm. The function + returns a pointer to a null descriptor if hashAlg is TPM_ALG_NULL or not a defined algorithm. */ + +PHASH_DEF +CryptGetHashDef( + TPM_ALG_ID hashAlg + ) +{ +#define GET_DEF(HASH, Hash) case ALG_##HASH##_VALUE: return &Hash##_Def; + switch(hashAlg) + { + FOR_EACH_HASH(GET_DEF) + default: + return &NULL_Def; + } +#undef GET_DEF +} +/* 10.2.13.4.3 CryptHashIsValidAlg() */ +/* This function tests to see if an algorithm ID is a valid hash algorithm. If flag is true, then + TPM_ALG_NULL is a valid hash. */ +/* Return Value Meaning */ +/* TRUE(1) hashAlg is a valid, implemented hash on this TPM */ +/* FALSE(0) hashAlg is not valid for this TPM */ +BOOL +CryptHashIsValidAlg( + TPM_ALG_ID hashAlg, // IN: the algorithm to check + BOOL flag // IN: TRUE if TPM_ALG_NULL is to be treated + // as a valid hash + ) +{ + if(hashAlg == TPM_ALG_NULL) + return flag; + return CryptGetHashDef(hashAlg) != &NULL_Def; +} +/* 10.2.13.4.4 CryptHashGetAlgByIndex() */ +/* This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes + that are not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return + the first implemented hash and an index of 2 will return the last. All other index values will + return TPM_ALG_NULL. */ +/* Return Value Meaning */ +/* TPM_ALG_xxx a hash algorithm */ +/* TPM_ALG_NULL this can be used as a stop value */ +LIB_EXPORT TPM_ALG_ID +CryptHashGetAlgByIndex( + UINT32 index // IN: the index + ) +{ + TPM_ALG_ID hashAlg; + if(index >= HASH_COUNT) + hashAlg = TPM_ALG_NULL; + else + hashAlg = HashDefArray[index]->hashAlg; + return hashAlg; +} +/* 10.2.13.4.5 CryptHashGetDigestSize() */ +/* Returns the size of the digest produced by the hash. If hashAlg is not a hash algorithm, the TPM + will FAIL. */ +/* Return Value Meaning */ +/* 0 TPM_ALG_NULL */ +/* > 0 the digest size */ +LIB_EXPORT UINT16 +CryptHashGetDigestSize( + TPM_ALG_ID hashAlg // IN: hash algorithm to look up + ) +{ + return CryptGetHashDef(hashAlg)->digestSize; +} +/* 10.2.13.4.6 CryptHashGetBlockSize() */ +/* Returns the size of the block used by the hash. If hashAlg is not a hash algorithm, the TPM will + FAIL. */ +/* Return Value Meaning */ +/* 0 TPM_ALG_NULL */ +/* > 0 the digest size */ +LIB_EXPORT UINT16 +CryptHashGetBlockSize( + TPM_ALG_ID hashAlg // IN: hash algorithm to look up + ) +{ + return CryptGetHashDef(hashAlg)->blockSize; +} +/* 10.2.13.4.7 CryptHashGetOid() */ +/* This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs are full OID + values including the Tag (0x06) and length byte. */ +#if 0 // libtpms added +LIB_EXPORT const BYTE * +CryptHashGetOid( + TPM_ALG_ID hashAlg + ) +{ + return CryptGetHashDef(hashAlg)->OID; +} +#endif // libtpms added +/* 10.2.13.4.8 CryptHashGetContextAlg() */ +/* This function returns the hash algorithm associated with a hash context. */ +#if 0 // libtpms added +TPM_ALG_ID +CryptHashGetContextAlg( + PHASH_STATE state // IN: the context to check + ) +{ + return state->hashAlg; +} +#endif // libtpms added +/* 10.2.13.5 State Import and Export */ +/* 10.2.13.5.1 CryptHashCopyState */ +/* This function is used to clone a HASH_STATE. */ +#if 0 // libtpms added +LIB_EXPORT void +CryptHashCopyState( + HASH_STATE *out, // OUT: destination of the state + const HASH_STATE *in // IN: source of the state + ) +{ + pAssert(out->type == in->type); + out->hashAlg = in->hashAlg; + out->def = in->def; + if(in->hashAlg != TPM_ALG_NULL) + { + HASH_STATE_COPY(out, in); + } + if(in->type == HASH_STATE_HMAC) + { + const HMAC_STATE *hIn = (HMAC_STATE *)in; + HMAC_STATE *hOut = (HMAC_STATE *)out; + hOut->hmacKey = hIn->hmacKey; + } + return; +} +#endif // libtpms added +#if 0 // libtpms added +/* 10.2.13.5.2 CryptHashExportState() */ +/* This function is used to export a hash or HMAC hash state. This function would be called when + preparing to context save a sequence object. */ +void +CryptHashExportState( + PCHASH_STATE internalFmt, // IN: the hash state formatted for use by + // library + PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state + ) +{ + BYTE *outBuf = (BYTE *)externalFmt; + // + cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE)); + // the following #define is used to move data from an aligned internal data + // structure to a byte buffer (external format data. +#define CopyToOffset(value) \ + memcpy(&outBuf[offsetof(HASH_STATE,value)], &internalFmt->value, \ + sizeof(internalFmt->value)) + // Copy the hashAlg + CopyToOffset(hashAlg); + CopyToOffset(type); +#ifdef HASH_STATE_SMAC + if(internalFmt->type == HASH_STATE_SMAC) + { + memcpy(outBuf, internalFmt, sizeof(HASH_STATE)); + return; + + } +#endif + if(internalFmt->type == HASH_STATE_HMAC) + { + HMAC_STATE *from = (HMAC_STATE *)internalFmt; + memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)], &from->hmacKey, + sizeof(from->hmacKey)); + } + if(internalFmt->hashAlg != TPM_ALG_NULL) + HASH_STATE_EXPORT(externalFmt, internalFmt); +} +/* 10.2.13.5.3 CryptHashImportState() */ +/* This function is used to import the hash state. This function would be called to import a hash + state when the context of a sequence object was being loaded. */ +void +CryptHashImportState( + PHASH_STATE internalFmt, // OUT: the hash state formatted for use by + // the library + PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state + ) +{ + BYTE *inBuf = (BYTE *)externalFmt; + // +#define CopyFromOffset(value) \ + memcpy(&internalFmt->value, &inBuf[offsetof(HASH_STATE,value)], \ + sizeof(internalFmt->value)) + + // Copy the hashAlg of the byte-aligned input structure to the structure-aligned + // internal structure. + CopyFromOffset(hashAlg); + CopyFromOffset(type); + if(internalFmt->hashAlg != TPM_ALG_NULL) + { +#ifdef HASH_STATE_SMAC + if(internalFmt->type == HASH_STATE_SMAC) + { + memcpy(internalFmt, inBuf, sizeof(HASH_STATE)); + return; + } +#endif + internalFmt->def = CryptGetHashDef(internalFmt->hashAlg); + HASH_STATE_IMPORT(internalFmt, inBuf); + if(internalFmt->type == HASH_STATE_HMAC) + { + HMAC_STATE *to = (HMAC_STATE *)internalFmt; + memcpy(&to->hmacKey, &inBuf[offsetof(HMAC_STATE, hmacKey)], + sizeof(to->hmacKey)); + } + } +} +#endif // libtpms added +/* 10.2.13.6 State Modification Functions */ +/* 10.2.13.6.1 HashEnd() */ +/* Local function to complete a hash that uses the hashDef instead of an algorithm ID. This function + is used to complete the hash and only return a partial digest. The return value is the size of + the data copied. */ +static UINT16 +HashEnd( + PHASH_STATE hashState, // IN: the hash state + UINT32 dOutSize, // IN: the size of receive buffer + PBYTE dOut // OUT: the receive buffer + ) +{ + BYTE temp[MAX_DIGEST_SIZE]; + if((hashState->hashAlg == TPM_ALG_NULL) + || (hashState->type != HASH_STATE_HASH)) + dOutSize = 0; + if(dOutSize > 0) + { + hashState->def = CryptGetHashDef(hashState->hashAlg); + // Set the final size + dOutSize = MIN(dOutSize, hashState->def->digestSize); + // Complete into the temp buffer and then copy + HASH_END(hashState, temp); + // Don't want any other functions calling the HASH_END method + // directly. +#undef HASH_END + memcpy(dOut, &temp, dOutSize); + } + hashState->type = HASH_STATE_EMPTY; + return (UINT16)dOutSize; +} +/* 10.2.13.6.2 CryptHashStart() */ +/* Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect, + the value of stateSize in hashState is updated to indicate the number of bytes of state that were + saved. This function calls GetHashServer() and that function will put the TPM into failure mode + if the hash algorithm is not supported. */ +/* This function does not use the sequence parameter. If it is necessary to import or export + context, this will start the sequence in a local state and export the state to the input + buffer. Will need to add a flag to the state structure to indicate that it needs to be imported + before it can be used. (BLEH). */ +/* Return Value Meaning */ +/* 0 hash is TPM_ALG_NULL */ +/* >0 digest size */ +LIB_EXPORT UINT16 +CryptHashStart( + PHASH_STATE hashState, // OUT: the running hash state + TPM_ALG_ID hashAlg // IN: hash algorithm + ) +{ + UINT16 retVal; + + TEST(hashAlg); + + hashState->hashAlg = hashAlg; + if(hashAlg == TPM_ALG_NULL) + { + retVal = 0; + } + else + { + hashState->def = CryptGetHashDef(hashAlg); + HASH_START(hashState); + retVal = hashState->def->digestSize; + } +#undef HASH_START + hashState->type = HASH_STATE_HASH; + return retVal; +} +/* 10.2.13.6.3 CryptDigestUpdate() */ +/* Add data to a hash or HMAC, SMAC stack. */ +void +CryptDigestUpdate( + PHASH_STATE hashState, // IN: the hash context information + UINT32 dataSize, // IN: the size of data to be added + const BYTE *data // IN: data to be hashed + ) +{ + if(hashState->hashAlg != TPM_ALG_NULL) + { + if((hashState->type == HASH_STATE_HASH) + || (hashState->type == HASH_STATE_HMAC)) + HASH_DATA(hashState, dataSize, (BYTE *)data); +#if SMAC_IMPLEMENTED + else if(hashState->type == HASH_STATE_SMAC) + (hashState->state.smac.smacMethods.data)(&hashState->state.smac.state, + dataSize, data); +#endif // SMAC_IMPLEMENTED + else + FAIL(FATAL_ERROR_INTERNAL); + } + return; +} +/* 10.2.13.6.4 CryptHashEnd() */ +/* Complete a hash or HMAC computation. This function will place the smaller of digestSize or the + size of the digest in dOut. The number of bytes in the placed in the buffer is returned. If there + is a failure, the returned value is <= 0. */ +/* Return Value Meaning */ +/* 0 no data returned */ +/* > 0 the number of bytes in the digest or dOutSize, whichever is smaller */ +LIB_EXPORT UINT16 +CryptHashEnd( + PHASH_STATE hashState, // IN: the state of hash stack + UINT32 dOutSize, // IN: size of digest buffer + BYTE *dOut // OUT: hash digest + ) +{ + pAssert(hashState->type == HASH_STATE_HASH); + return HashEnd(hashState, dOutSize, dOut); +} +/* 10.2.13.6.5 CryptHashBlock() */ +/* Start a hash, hash a single block, update digest and return the size of the results. */ +/* The digestSize parameter can be smaller than the digest. If so, only the more significant + bytes are returned. */ +/* Return Value Meaning */ +/* >= 0 number of bytes placed in dOut */ +LIB_EXPORT UINT16 +CryptHashBlock( + TPM_ALG_ID hashAlg, // IN: The hash algorithm + UINT32 dataSize, // IN: size of buffer to hash + const BYTE *data, // IN: the buffer to hash + UINT32 dOutSize, // IN: size of the digest buffer + BYTE *dOut // OUT: digest buffer + ) +{ + HASH_STATE state; + CryptHashStart(&state, hashAlg); + CryptDigestUpdate(&state, dataSize, data); + return HashEnd(&state, dOutSize, dOut); +} +/* 10.2.13.6.6 CryptDigestUpdate2B() */ +/* This function updates a digest (hash or HMAC) with a TPM2B. */ +/* This function can be used for both HMAC and hash functions so the digestState is void so that + either state type can be passed. */ +LIB_EXPORT void +CryptDigestUpdate2B( + PHASH_STATE state, // IN: the digest state + const TPM2B *bIn // IN: 2B containing the data + ) +{ + // Only compute the digest if a pointer to the 2B is provided. + // In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change + // to the digest occurs. This function should not provide a buffer if bIn is + // not provided. + pAssert(bIn != NULL); + CryptDigestUpdate(state, bIn->size, bIn->buffer); + return; +} +/* 10.2.13.6.7 CryptHashEnd2B() */ +/* This function is the same as CryptCompleteHash() but the digest is placed in a TPM2B. This is the + most common use and this is provided for specification clarity. digest.size should be set to + indicate the number of bytes to place in the buffer */ +/* Return Value Meaning */ +/* >=0 the number of bytes placed in digest.buffer */ +LIB_EXPORT UINT16 +CryptHashEnd2B( + PHASH_STATE state, // IN: the hash state + P2B digest // IN: the size of the buffer Out: requested + // number of bytes + ) +{ + return CryptHashEnd(state, digest->size, digest->buffer); +} +/* 10.2.13.6.8 CryptDigestUpdateInt() */ +/* This function is used to include an integer value to a hash stack. The function marshals the + integer into its canonical form before calling CryptDigestUpdate(). */ +LIB_EXPORT void +CryptDigestUpdateInt( + void *state, // IN: the state of hash stack + UINT32 intSize, // IN: the size of 'intValue' in bytes + UINT64 intValue // IN: integer value to be hashed + ) +{ +#if LITTLE_ENDIAN_TPM + intValue = REVERSE_ENDIAN_64(intValue); +#endif + CryptDigestUpdate(state, intSize, &((BYTE *)&intValue)[8 - intSize]); +} +/* 10.2.13.7 HMAC Functions */ +/* 10.2.13.7.1 CryptHmacStart() */ +/* This function is used to start an HMAC using a temp hash context. The function does the + initialization of the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad. */ +/* The function returns the number of bytes in a digest produced by hashAlg. */ +/* Return Value Meaning */ +/* >= 0 number of bytes in digest produced by hashAlg (may be zero) */ +LIB_EXPORT UINT16 +CryptHmacStart( + PHMAC_STATE state, // IN/OUT: the state buffer + TPM_ALG_ID hashAlg, // IN: the algorithm to use + UINT16 keySize, // IN: the size of the HMAC key + const BYTE *key // IN: the HMAC key + ) +{ + PHASH_DEF hashDef; + BYTE * pb; + UINT32 i; + // + hashDef = CryptGetHashDef(hashAlg); + if(hashDef->digestSize != 0) + { + // If the HMAC key is larger than the hash block size, it has to be reduced + // to fit. The reduction is a digest of the hashKey. + if(keySize > hashDef->blockSize) + { + // if the key is too big, reduce it to a digest of itself + state->hmacKey.t.size = CryptHashBlock(hashAlg, keySize, key, + hashDef->digestSize, + state->hmacKey.t.buffer); + } + else + { + memcpy(state->hmacKey.t.buffer, key, keySize); + state->hmacKey.t.size = keySize; + } + // XOR the key with iPad (0x36) + pb = state->hmacKey.t.buffer; + for(i = state->hmacKey.t.size; i > 0; i--) + *pb++ ^= 0x36; + + // if the keySize is smaller than a block, fill the rest with 0x36 + for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--) + *pb++ = 0x36; + + // Increase the oPadSize to a full block + state->hmacKey.t.size = hashDef->blockSize; + + // Start a new hash with the HMAC key + // This will go in the caller's state structure and may be a sequence or not + CryptHashStart((PHASH_STATE)state, hashAlg); + CryptDigestUpdate((PHASH_STATE)state, state->hmacKey.t.size, + state->hmacKey.t.buffer); + // XOR the key block with 0x5c ^ 0x36 + for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--) + *pb++ ^= (0x5c ^ 0x36); + } + // Set the hash algorithm + state->hashState.hashAlg = hashAlg; + // Set the hash state type + state->hashState.type = HASH_STATE_HMAC; + + return hashDef->digestSize; +} +/* 10.2.13.7.2 CryptHmacEnd() */ +/* This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It will then add the oPadKey and the completed digest and return the results in dOut. It will not return more than dOutSize bytes. */ +/* Return Value Meaning */ +/* >= 0 number of bytes in dOut (may be zero) */ +LIB_EXPORT UINT16 +CryptHmacEnd( + PHMAC_STATE state, // IN: the hash state buffer + UINT32 dOutSize, // IN: size of digest buffer + BYTE *dOut // OUT: hash digest + ) +{ + BYTE temp[MAX_DIGEST_SIZE]; + PHASH_STATE hState = (PHASH_STATE)&state->hashState; + +#if SMAC_IMPLEMENTED + if(hState->type == HASH_STATE_SMAC) + return (state->hashState.state.smac.smacMethods.end) + (&state->hashState.state.smac.state, + dOutSize, + dOut); +#endif + pAssert(hState->type == HASH_STATE_HMAC); + hState->def = CryptGetHashDef(hState->hashAlg); + // Change the state type for completion processing + hState->type = HASH_STATE_HASH; + if(hState->hashAlg == TPM_ALG_NULL) + dOutSize = 0; + else + { + + // Complete the current hash + HashEnd(hState, hState->def->digestSize, temp); + // Do another hash starting with the oPad + CryptHashStart(hState, hState->hashAlg); + CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer); + CryptDigestUpdate(hState, hState->def->digestSize, temp); + } + return HashEnd(hState, dOutSize, dOut); +} +/* 10.2.13.7.3 CryptHmacStart2B() */ +/* This function starts an HMAC and returns the size of the digest that will be produced. */ +/* This function is provided to support the most common use of starting an HMAC with a TPM2B key. */ +/* The caller must provide a block of memory in which the hash sequence state is kept. The caller + should not alter the contents of this buffer until the hash sequence is completed or + abandoned. */ +/* Return Value Meaning */ +/* > 0 the digest size of the algorithm */ +/* = 0 the hashAlg was TPM_ALG_NULL */ +LIB_EXPORT UINT16 +CryptHmacStart2B( + PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used + // in HMAC update and completion + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + P2B key // IN: HMAC key + ) +{ + return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer); +} + /* 10.2.13.7.4 CryptHmacEnd2B() */ + /* This function is the same as CryptHmacEnd() but the HMAC result is returned in a TPM2B which is the most common use. */ + /* Return Value Meaning */ + /* >=0 the number of bytes placed in digest */ +LIB_EXPORT UINT16 +CryptHmacEnd2B( + PHMAC_STATE hmacState, // IN: the state of HMAC stack + P2B digest // OUT: HMAC + ) +{ + return CryptHmacEnd(hmacState, digest->size, digest->buffer); +} +/* 10.2.13.8 Mask and Key Generation Functions */ +/* 10.2.13.8.1 CryptMGF_KDF() */ +/* This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are T(n) = T(n-1) + || H(seed || counter) with the difference being that, with KDF1, counter starts at 0 but with + KDF2, counter starts at 1. The caller determines which version by setting the initial value of + counter to either 0 or 1. */ +/* Return Value Meaning */ +/* 0 hash algorithm was TPM_ALG_NULL */ +/* > 0 should be the same as mSize */ +LIB_EXPORT UINT16 +CryptMGF_KDF( + UINT32 mSize, // IN: length of the mask to be produced + BYTE *mask, // OUT: buffer to receive the mask + TPM_ALG_ID hashAlg, // IN: hash to use + UINT32 seedSize, // IN: size of the seed + BYTE *seed, // IN: seed size + UINT32 counter // IN: counter initial value + ) +{ + HASH_STATE hashState; + PHASH_DEF hDef = CryptGetHashDef(hashAlg); + UINT32 hLen; + UINT32 bytes; + // + // If there is no digest to compute return + if((hDef->digestSize == 0) || (mSize == 0)) + return 0; + if(counter != 0) + counter = 1; + hLen = hDef->digestSize; + for(bytes = 0; bytes < mSize; bytes += hLen) + { + // Start the hash and include the seed and counter + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate(&hashState, seedSize, seed); + CryptDigestUpdateInt(&hashState, 4, counter); + // Get as much as will fit. + CryptHashEnd(&hashState, MIN((mSize - bytes), hLen), + &mask[bytes]); + counter++; + } + return (UINT16)mSize; +} +/* 10.2.13.8.2 CryptKDFa() */ +/* This function performs the key generation according to Part 1 of the TPM specification. */ +/* This function returns the number of bytes generated which may be zero. */ +/* The key and keyStream pointers are not allowed to be NULL. The other pointer values may be + NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). */ +/* The once parameter is set to allow incremental generation of a large value. If this flag is + TRUE, sizeInBits will be used in the HMAC computation but only one iteration of the KDF is + performed. This would be used for XOR obfuscation so that the mask value can be generated in + digest-sized chunks rather than having to be generated all at once in an arbitrarily large + buffer and then XORed into the result. If once is TRUE, then sizeInBits must be a multiple of + 8. */ +/* Any error in the processing of this command is considered fatal. */ +/* Return Value Meaning */ +/* 0 hash algorithm is not supported or is TPM_ALG_NULL */ +/* > 0 the number of bytes in the keyStream buffer */ +LIB_EXPORT UINT16 +CryptKDFa( + TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC + const TPM2B *key, // IN: HMAC key + const TPM2B *label, // IN: a label for the KDF + const TPM2B *contextU, // IN: context U + const TPM2B *contextV, // IN: context V + UINT32 sizeInBits, // IN: size of generated key in bits + BYTE *keyStream, // OUT: key buffer + UINT32 *counterInOut, // IN/OUT: caller may provide the iteration + // counter for incremental operations to + // avoid large intermediate buffers. + UINT16 blocks // IN: If non-zero, this is the maximum number + // of blocks to be returned, regardless + // of sizeInBits + ) +{ + UINT32 counter = 0; // counter value + INT16 bytes; // number of bytes to produce + UINT16 generated; // number of bytes generated + BYTE *stream = keyStream; + HMAC_STATE hState; + UINT16 digestSize = CryptHashGetDigestSize(hashAlg); + + pAssert(key != NULL && keyStream != NULL); + + TEST(TPM_ALG_KDF1_SP800_108); + + if(digestSize == 0) + return 0; + + if(counterInOut != NULL) + counter = *counterInOut; + + // If the size of the request is larger than the numbers will handle, + // it is a fatal error. + pAssert(((sizeInBits + 7) / 8) <= INT16_MAX); + + // The number of bytes to be generated is the smaller of the sizeInBits bytes or + // the number of requested blocks. The number of blocks is the smaller of the + // number requested or the number allowed by sizeInBits. A partial block is + // a full block. + bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits); + generated = bytes; + + // Generate required bytes + for(; bytes > 0; bytes -= digestSize) + { + counter++; + // Start HMAC + if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0) + return 0; + // Adding counter + CryptDigestUpdateInt(&hState.hashState, 4, counter); + + // Adding label + if(label != NULL) + HASH_DATA(&hState.hashState, label->size, (BYTE *)label->buffer); + // Add a null. SP108 is not very clear about when the 0 is needed but to + // make this like the previous version that did not add an 0x00 after + // a null-terminated string, this version will only add a null byte + // if the label parameter did not end in a null byte, or if no label + // is present. + if((label == NULL) + || (label->size == 0) + || (label->buffer[label->size - 1] != 0)) + CryptDigestUpdateInt(&hState.hashState, 1, 0); + // Adding contextU + if(contextU != NULL) + HASH_DATA(&hState.hashState, contextU->size, contextU->buffer); + // Adding contextV + if(contextV != NULL) + HASH_DATA(&hState.hashState, contextV->size, contextV->buffer); + // Adding size in bits + CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits); + + // Complete and put the data in the buffer + CryptHmacEnd(&hState, bytes, stream); + stream = &stream[digestSize]; + } + // Masking in the KDF is disabled. If the calling function wants something + // less than even number of bytes, then the caller should do the masking + // because there is no universal way to do it here + if(counterInOut != NULL) + *counterInOut = counter; + return generated; +} +/* 10.2.13.8.3 CryptKDFe() */ +/* This function implements KDFe() as defined in TPM specification part 1. */ +/* This function returns the number of bytes generated which may be zero. */ +/* The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be + NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any + error in the processing of this command is considered fatal. */ +/* Return Value Meaning */ +/* 0 hash algorithm is not supported or is TPM_ALG_NULL */ +/* > 0 the number of bytes in the keyStream buffer */ +LIB_EXPORT UINT16 +CryptKDFe( + TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC + TPM2B *Z, // IN: Z + const TPM2B *label, // IN: a label value for the KDF + TPM2B *partyUInfo, // IN: PartyUInfo + TPM2B *partyVInfo, // IN: PartyVInfo + UINT32 sizeInBits, // IN: size of generated key in bits + BYTE *keyStream // OUT: key buffer + ) +{ + HASH_STATE hashState; + PHASH_DEF hashDef = CryptGetHashDef(hashAlg); + + UINT32 counter = 0; // counter value + UINT16 hLen; + BYTE *stream = keyStream; + INT16 bytes; // number of bytes to generate + + pAssert(keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX); + // + hLen = hashDef->digestSize; + bytes = (INT16)((sizeInBits + 7) / 8); + if(hashAlg == TPM_ALG_NULL || bytes == 0) + return 0; + + // Generate required bytes + //The inner loop of that KDF uses: + // Hash[i] := H(counter | Z | OtherInfo) (5) + // Where: + // Hash[i] the hash generated on the i-th iteration of the loop. + // H() an approved hash function + // counter a 32-bit counter that is initialized to 1 and incremented + // on each iteration + // Z the X coordinate of the product of a public ECC key and a + // different private ECC key. + // OtherInfo a collection of qualifying data for the KDF defined below. + // In this specification, OtherInfo will be constructed by: + // OtherInfo := Use | PartyUInfo | PartyVInfo + for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) + { + if(bytes < hLen) + hLen = bytes; + counter++; + // Do the hash + CryptHashStart(&hashState, hashAlg); + // Add counter + CryptDigestUpdateInt(&hashState, 4, counter); + + // Add Z + if(Z != NULL) + CryptDigestUpdate2B(&hashState, Z); + // Add label + if(label != NULL) + CryptDigestUpdate2B(&hashState, label); + // Add a null. SP108 is not very clear about when the 0 is needed but to + // make this like the previous version that did not add an 0x00 after + // a null-terminated string, this version will only add a null byte + // if the label parameter did not end in a null byte, or if no label + // is present. + if((label == NULL) + || (label->size == 0) + || (label->buffer[label->size - 1] != 0)) + CryptDigestUpdateInt(&hashState, 1, 0); + // Add PartyUInfo + if(partyUInfo != NULL) + CryptDigestUpdate2B(&hashState, partyUInfo); + + // Add PartyVInfo + if(partyVInfo != NULL) + CryptDigestUpdate2B(&hashState, partyVInfo); + + // Compute Hash. hLen was changed to be the smaller of bytes or hLen + // at the start of each iteration. + CryptHashEnd(&hashState, hLen, stream); + } + + // Mask off bits if the required bits is not a multiple of byte size + if((sizeInBits % 8) != 0) + keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); + + return (UINT16)((sizeInBits + 7) / 8); +} diff --git a/src/tpm2/crypto/openssl/CryptPrime.c b/src/tpm2/crypto/openssl/CryptPrime.c new file mode 100644 index 0000000..0de9ef2 --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptPrime.c @@ -0,0 +1,440 @@ +/********************************************************************************/ +/* */ +/* Code for prime validation. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptPrime.c 1529 2019-11-21 23:29:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 10.2.14 CryptPrime.c */ +/* 10.2.14.1 Introduction */ +/* This file contains the code for prime validation. */ + +#include "Tpm.h" +#include "CryptPrime_fp.h" +//#define CPRI_PRIME +//#include "PrimeTable.h" +#include "CryptPrimeSieve_fp.h" +extern const uint32_t s_LastPrimeInTable; +extern const uint32_t s_PrimeTableSize; +extern const uint32_t s_PrimesInTable; +extern const unsigned char s_PrimeTable[]; +extern bigConst s_CompositeOfSmallPrimes; + +/* 10.2.14.1.1 Root2() */ +/* This finds ceil(sqrt(n)) to use as a stopping point for searching the prime table. */ +static uint32_t +Root2( + uint32_t n + ) +{ + int32_t last = (int32_t)(n >> 2); + int32_t next = (int32_t)(n >> 1); + int32_t diff; + int32_t stop = 10; + // + // get a starting point + for(; next != 0; last >>= 1, next >>= 2); + last++; + do + { + next = (last + (n / last)) >> 1; + diff = next - last; + last = next; + if(stop-- == 0) + FAIL(FATAL_ERROR_INTERNAL); + } while(diff < -1 || diff > 1); + if((n / next) > (unsigned)next) + next++; + pAssert(next != 0); + pAssert(((n / next) <= (unsigned)next) && (n / (next + 1) < (unsigned)next)); + return next; +} +/* 10.2.14.1.2 IsPrimeInt() */ +/* This will do a test of a word of up to 32-bits in size. */ +BOOL +IsPrimeInt( + uint32_t n + ) +{ + uint32_t i; + uint32_t stop; + if(n < 3 || ((n & 1) == 0)) + return (n == 2); + if(n <= s_LastPrimeInTable) + { + n >>= 1; + return ((s_PrimeTable[n >> 3] >> (n & 7)) & 1); + } + // Need to search + stop = Root2(n) >> 1; + // starting at 1 is equivalent to staring at (1 << 1) + 1 = 3 + for(i = 1; i < stop; i++) + { + if((s_PrimeTable[i >> 3] >> (i & 7)) & 1) + // see if this prime evenly divides the number + if((n % ((i << 1) + 1)) == 0) + return FALSE; + } + return TRUE; +} +#if !RSA_KEY_SIEVE // libtpms added +/* 10.2.14.1.3 BnIsProbablyPrime() */ +/* This function is used when the key sieve is not implemented. This function Will try to eliminate + some of the obvious things before going on to perform MillerRabin() as a final verification of + primeness. */ +BOOL +BnIsProbablyPrime( + bigNum prime, // IN: + RAND_STATE *rand // IN: the random state just + // in case Miller-Rabin is required + ) +{ +#if RADIX_BITS > 32 + if(BnUnsignedCmpWord(prime, UINT32_MAX) <= 0) +#else + if(BnGetSize(prime) == 1) +#endif + return IsPrimeInt((uint32_t)prime->d[0]); + if(BnIsEven(prime)) + return FALSE; + if(BnUnsignedCmpWord(prime, s_LastPrimeInTable) <= 0) + { + crypt_uword_t temp = prime->d[0] >> 1; + return ((s_PrimeTable[temp >> 3] >> (temp & 7)) & 1); + } + { + BN_VAR(n, LARGEST_NUMBER_BITS); + BnGcd(n, prime, s_CompositeOfSmallPrimes); + if(!BnEqualWord(n, 1)) + return FALSE; + } + return MillerRabin(prime, rand); +} +#endif // libtpms added +/* 10.2.14.1.4 MillerRabinRounds() */ +/* Function returns the number of Miller-Rabin rounds necessary to give an error probability equal + to the security strength of the prime. These values are from FIPS 186-3. */ +UINT32 +MillerRabinRounds( + UINT32 bits // IN: Number of bits in the RSA prime + ) +{ + if(bits < 511) return 8; // don't really expect this + if(bits < 1536) return 5; // for 512 and 1K primes + return 4; // for 3K public modulus and greater +} +/* 10.2.14.1.5 MillerRabin() */ +/* This function performs a Miller-Rabin test from FIPS 186-3. It does iterations trials on the + number. In all likelihood, if the number is not prime, the first test fails. */ +/* Return Values Meaning */ +/* TRUE probably prime */ +/* FALSE composite */ +BOOL +MillerRabin( + bigNum bnW, + RAND_STATE *rand + ) +{ + BN_MAX(bnWm1); + BN_PRIME(bnM); + BN_PRIME(bnB); + BN_PRIME(bnZ); + BOOL ret = FALSE; // Assumed composite for easy exit + unsigned int a; + unsigned int j; + int wLen; + int i; + int iterations = MillerRabinRounds(BnSizeInBits(bnW)); + // + INSTRUMENT_INC(MillerRabinTrials[PrimeIndex]); + + pAssert(bnW->size > 1); + // Let a be the largest integer such that 2^a divides w1. + BnSubWord(bnWm1, bnW, 1); + pAssert(bnWm1->size != 0); + + // Since w is odd (w-1) is even so start at bit number 1 rather than 0 + // Get the number of bits in bnWm1 so that it doesn't have to be recomputed + // on each iteration. + i = (int)(bnWm1->size * RADIX_BITS); + // Now find the largest power of 2 that divides w1 + for(a = 1; + (a < (bnWm1->size * RADIX_BITS)) && + (BnTestBit(bnWm1, a) == 0); + a++); + // 2. m = (w1) / 2^a + BnShiftRight(bnM, bnWm1, a); + // 3. wlen = len (w). + wLen = BnSizeInBits(bnW); + // 4. For i = 1 to iterations do + for(i = 0; i < iterations; i++) + { + // 4.1 Obtain a string b of wlen bits from an RBG. + // Ensure that 1 < b < w1. + // 4.2 If ((b <= 1) or (b >= w1)), then go to step 4.1. + while(BnGetRandomBits(bnB, wLen, rand) && ((BnUnsignedCmpWord(bnB, 1) <= 0) + || (BnUnsignedCmp(bnB, bnWm1) >= 0))); + if(g_inFailureMode) + return FALSE; + + // 4.3 z = b^m mod w. + // if ModExp fails, then say this is not + // prime and bail out. + BnModExp(bnZ, bnB, bnM, bnW); + + // 4.4 If ((z == 1) or (z = w == 1)), then go to step 4.7. + if((BnUnsignedCmpWord(bnZ, 1) == 0) + || (BnUnsignedCmp(bnZ, bnWm1) == 0)) + goto step4point7; + // 4.5 For j = 1 to a 1 do. + for(j = 1; j < a; j++) + { + // 4.5.1 z = z^2 mod w. + BnModMult(bnZ, bnZ, bnZ, bnW); + // 4.5.2 If (z = w1), then go to step 4.7. + if(BnUnsignedCmp(bnZ, bnWm1) == 0) + goto step4point7; + // 4.5.3 If (z = 1), then go to step 4.6. + if(BnEqualWord(bnZ, 1)) + goto step4point6; + } + // 4.6 Return COMPOSITE. + step4point6: + INSTRUMENT_INC(failedAtIteration[i]); + goto end; + // 4.7 Continue. Comment: Increment i for the do-loop in step 4. + step4point7: + continue; + } + // 5. Return PROBABLY PRIME + ret = TRUE; + end: + return ret; +} +#if ALG_RSA +/* 10.2.14.1.6 RsaCheckPrime() */ +/* This will check to see if a number is prime and appropriate for an RSA prime. */ +/* This has different functionality based on whether we are using key sieving or not. If not, the + number checked to see if it is divisible by the public exponent, then the number is adjusted + either up or down in order to make it a better candidate. It is then checked for being probably + prime. */ +/* If sieving is used, the number is used to root a sieving process. */ +TPM_RC +RsaCheckPrime( + bigNum prime, + UINT32 exponent, + RAND_STATE *rand + ) +{ +#if !RSA_KEY_SIEVE + TPM_RC retVal = TPM_RC_SUCCESS; + UINT32 modE = BnModWord(prime, exponent); + NOT_REFERENCED(rand); + if(modE == 0) + // evenly divisible so add two keeping the number odd + BnAddWord(prime, prime, 2); + // want 0 != (p - 1) mod e + // which is 1 != p mod e + else if(modE == 1) + // subtract 2 keeping number odd and insuring that + // 0 != (p - 1) mod e + BnSubWord(prime, prime, 2); + if(BnIsProbablyPrime(prime, rand) == 0) + ERROR_RETURN(g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_VALUE); + Exit: + return retVal; +#else + return PrimeSelectWithSieve(prime, exponent, rand); +#endif +} +/* + * RsaAdjustPrimeCandidate_PreRev155 is the pre-rev.155 algorithm used; we + * still have to use it for old seeds to maintain backwards compatibility. + */ +static void +RsaAdjustPrimeCandidate_PreRev155( + bigNum prime + ) +{ + UINT16 highBytes; + crypt_uword_t *msw = &prime->d[prime->size - 1]; +#define MASK (MAX_CRYPT_UWORD >> (RADIX_BITS - 16)) + highBytes = *msw >> (RADIX_BITS - 16); + // This is fixed point arithmetic on 16-bit values + highBytes = ((UINT32)highBytes * (UINT32)0x4AFB) >> 16; + highBytes += 0xB505; + *msw = ((crypt_uword_t)(highBytes) << (RADIX_BITS - 16)) + (*msw & MASK); + prime->d[0] |= 1; +} + +/* 10.2.14.1.7 RsaAdjustPrimeCandidate() */ + +/* For this math, we assume that the RSA numbers are fixed-point numbers with the decimal point to + the left of the most significant bit. This approach helps make it clear what is happening with + the MSb of the values. The two RSA primes have to be large enough so that their product will be a + number with the necessary number of significant bits. For example, we want to be able to multiply + two 1024-bit numbers to produce a number with 2048 significant bits. If we accept any 1024-bit + prime that has its MSb set, then it is possible to produce a product that does not have the MSb + SET. For example, if we use tiny keys of 16 bits and have two 8-bit primes of 0x80, then the + public key would be 0x4000 which is only 15-bits. So, what we need to do is made sure that each + of the primes is large enough so that the product of the primes is twice as large as each + prime. A little arithmetic will show that the only way to do this is to make sure that each of + the primes is no less than root(2)/2. That's what this functions does. This function adjusts the + candidate prime so that it is odd and >= root(2)/2. This allows the product of these two numbers + to be .5, which, in fixed point notation means that the most significant bit is 1. For this + routine, the root(2)/2 (0.7071067811865475) approximated with 0xB505 which is, in fixed point, + 0.7071075439453125 or an error of 0.000108%. Just setting the upper two bits would give a value > + 0.75 which is an error of > 6%. Given the amount of time all the other computations take, + reducing the error is not much of a cost, but it isn't totally required either. */ +/* This function can be replaced with a function that just sets the two most significant bits of + each prime candidate without introducing any computational issues. */ + +static void +RsaAdjustPrimeCandidate_New( + bigNum prime + ) +{ + UINT32 msw; + UINT32 adjusted; + + // If the radix is 32, the compiler should turn this into a simple assignment + msw = prime->d[prime->size - 1] >> ((RADIX_BITS == 64) ? 32 : 0); + // Multiplying 0xff...f by 0x4AFB gives 0xff..f - 0xB5050...0 + adjusted = (msw >> 16) * 0x4AFB; + adjusted += ((msw & 0xFFFF) * 0x4AFB) >> 16; + adjusted += 0xB5050000UL; +#if RADIX_BITS == 64 + // Save the low-order 32 bits + prime->d[prime->size - 1] &= 0xFFFFFFFFUL; + // replace the upper 32-bits + prime->d[prime->size -1] |= ((crypt_uword_t)adjusted << 32); +#else + prime->d[prime->size - 1] = (crypt_uword_t)adjusted; +#endif + // make sure the number is odd + prime->d[0] |= 1; +} + + +LIB_EXPORT void +RsaAdjustPrimeCandidate( + bigNum prime, + SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added + ) +{ + switch (seedCompatLevel) { + case SEED_COMPAT_LEVEL_ORIGINAL: + RsaAdjustPrimeCandidate_PreRev155(prime); + break; + case SEED_COMPAT_LEVEL_LAST: + /* case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: */ + RsaAdjustPrimeCandidate_New(prime); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + } +} +/* 10.2.14.1.8 BnGeneratePrimeForRSA() */ +/* Function to generate a prime of the desired size with the proper attributes for an RSA prime. */ + +TPM_RC +BnGeneratePrimeForRSA( + bigNum prime, // IN/OUT: points to the BN that will get the + // random value + UINT32 bits, // IN: number of bits to get + UINT32 exponent, // IN: the exponent + RAND_STATE *rand // IN: the random state + ) +{ + BOOL found = FALSE; + // + // Make sure that the prime is large enough + pAssert(prime->allocated >= BITS_TO_CRYPT_WORDS(bits)); + // Only try to handle specific sizes of keys in order to save overhead + pAssert((bits % 32) == 0); + + prime->size = BITS_TO_CRYPT_WORDS(bits); + + while(!found) + { + // The change below is to make sure that all keys that are generated from the same + // seed value will be the same regardless of the endianness or word size of the CPU. + // DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));// old + // if(g_inFailureMode) // old + // libtpms changed begin + switch (DRBG_GetSeedCompatLevel(rand)) { + case SEED_COMPAT_LEVEL_ORIGINAL: + DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits)); + if (g_inFailureMode) + return TPM_RC_FAILURE; + break; + case SEED_COMPAT_LEVEL_LAST: + /* case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: */ + if(!BnGetRandomBits(prime, bits, rand)) // new + return TPM_RC_FAILURE; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + } + RsaAdjustPrimeCandidate(prime, DRBG_GetSeedCompatLevel(rand)); + // libtpms changed end + found = RsaCheckPrime(prime, exponent, rand) == TPM_RC_SUCCESS; + } + return TPM_RC_SUCCESS; +} + +#endif // TPM_ALG_RSA diff --git a/src/tpm2/crypto/openssl/CryptPrimeSieve.c b/src/tpm2/crypto/openssl/CryptPrimeSieve.c new file mode 100644 index 0000000..8c4e52b --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptPrimeSieve.c @@ -0,0 +1,554 @@ +/********************************************************************************/ +/* */ +/* CryptPrimeSieve */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptPrimeSieve.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 10.2.17 CryptPrimeSieve.c */ +/* 10.2.17.1 Includes and defines */ +#include "Tpm.h" +#if RSA_KEY_SIEVE +#include "CryptPrimeSieve_fp.h" +/* This determines the number of bits in the largest sieve field. */ +#define MAX_FIELD_SIZE 2048 +extern const uint32_t s_LastPrimeInTable; +extern const uint32_t s_PrimeTableSize; +extern const uint32_t s_PrimesInTable; +extern const unsigned char s_PrimeTable[]; +/* This table is set of prime markers. Each entry is the prime value for the ((n + 1) * 1024) + prime. That is, the entry in s_PrimeMarkers[1] is the value for the 2,048th prime. This is used + in the PrimeSieve() to adjust the limit for the prime search. When processing smaller prime + candidates, fewer primes are checked directly before going to Miller-Rabin. As the prime grows, + it is worth spending more time eliminating primes as, a) the density is lower, and b) the cost of + Miller-Rabin is higher. */ +const uint32_t s_PrimeMarkersCount = 6; +const uint32_t s_PrimeMarkers[] = { + 8167, 17881, 28183, 38891, 49871, 60961 }; +uint32_t primeLimit; + +/* 10.2.17.1.1 RsaAdjustPrimeLimit() */ +/* This used during the sieve process. The iterator for getting the next prime (RsaNextPrime()) will + return primes until it hits the limit (primeLimit) set up by this function. This causes the sieve + process to stop when an appropriate number of primes have been sieved. */ + +void +RsaAdjustPrimeLimit( + uint32_t requestedPrimes + ) +{ + if(requestedPrimes == 0 || requestedPrimes > s_PrimesInTable) + requestedPrimes = s_PrimesInTable; + requestedPrimes = (requestedPrimes - 1) / 1024; + if(requestedPrimes < s_PrimeMarkersCount) + primeLimit = s_PrimeMarkers[requestedPrimes]; + else + primeLimit = s_LastPrimeInTable - 2; // libtpms: Fix for 3072 bit keys to avoid mark=5 + primeLimit >>= 1; +} + +/* 10.2.17.1.2 RsaNextPrime() */ +/* This the iterator used during the sieve process. The input is the last prime returned (or any + starting point) and the output is the next higher prime. The function returns 0 when the + primeLimit is reached. */ +uint32_t +RsaNextPrime( + uint32_t lastPrime + ) +{ + if(lastPrime == 0) + return 0; + lastPrime >>= 1; + for(lastPrime += 1; lastPrime <= primeLimit; lastPrime++) + { + if(((s_PrimeTable[lastPrime >> 3] >> (lastPrime & 0x7)) & 1) == 1) + return ((lastPrime << 1) + 1); + } + return 0; +} +/* This table contains a previously sieved table. It has the bits for 3, 5, and 7 removed. Because + of the factors, it needs to be aligned to 105 and has a repeat of 105. */ +const BYTE seedValues[] = { + 0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30, 0x6c, + 0x99, 0x96, 0x4c, 0x53, 0xa2, 0x2d, 0x52, 0x96, + 0x49, 0xcb, 0xb4, 0x61, 0xd8, 0x32, 0x2d, 0x99, + 0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, 0x96, 0x69, + 0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89, 0xb6, + 0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61, 0xcb, + 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x91, 0xb2, 0x4c, + 0x5a, 0xa6, 0x0d, 0xc3, 0x96, 0x69, 0xc9, 0x34, + 0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, 0x4c, 0x1b, + 0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4, 0x45, + 0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b, 0xa6, + 0x25, 0xd3, 0x94, 0x68, 0x8b, 0x94, 0x65, 0xd2, + 0x32, 0x6d, 0x18, 0xb6, 0x4c, 0x4b, 0xa6, 0x29, + 0xd1}; +#define USE_NIBBLE +#ifndef USE_NIBBLE +static const BYTE bitsInByte[256] = { + 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, + 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, + 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, + 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, + 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, + 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, + 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 +}; +#define BitsInByte(x) bitsInByte[(unsigned char)x] +#else +const BYTE bitsInNibble[16] = { + 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, + 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04}; +#define BitsInByte(x) \ + (bitsInNibble[(unsigned char)(x) & 0xf] \ + + bitsInNibble[((unsigned char)(x) >> 4) & 0xf]) +#endif + +/* 10.2.17.1.3 BitsInArry() */ +/* This function counts the number of bits set in an array of bytes. */ +static int +BitsInArray( + const unsigned char *a, // IN: A pointer to an array of bytes + unsigned int aSize // IN: the number of bytes to sum + ) +{ + int j = 0; + for(; aSize; a++, aSize--) + j += BitsInByte(*a); + return j; +} + +/* 10.2.17.1.4 FindNthSetBit() */ +/* This function finds the nth SET bit in a bit array. The n parameter is between 1 and the number + of bits in the array (always a multiple of 8). If called when the array does not have n bits set, + it will return -1 */ +/* Return Values Meaning */ +/* <0 no bit is set or no bit with the requested number is set */ +/* >=0 the number of the bit in the array that is the nth set */ +int +FindNthSetBit( + const UINT16 aSize, // IN: the size of the array to check + const BYTE *a, // IN: the array to check + const UINT32 n // IN, the number of the SET bit + ) +{ + UINT16 i; + int retValue; + UINT32 sum = 0; + BYTE sel; + //find the bit + for(i = 0; (i < (int)aSize) && (sum < n); i++) + sum += BitsInByte(a[i]); + i--; + // The chosen bit is in the byte that was just accessed + // Compute the offset to the start of that byte + retValue = i * 8 - 1; + sel = a[i]; + // Subtract the bits in the last byte added. + sum -= BitsInByte(sel); + // Now process the byte, one bit at a time. + for(; (sel != 0) && (sum != n); retValue++, sel = sel >> 1) + sum += (sel & 1) != 0; + return (sum == n) ? retValue : -1; +} +typedef struct +{ + UINT16 prime; + UINT16 count; +} SIEVE_MARKS; +const SIEVE_MARKS sieveMarks[5] = { + {31, 7}, {73, 5}, {241, 4}, {1621, 3}, {UINT16_MAX, 2}}; + +/* 10.2.17.1.5 PrimeSieve() */ +/* This function does a prime sieve over the input field which has as its starting address the value + in bnN. Since this initializes the Sieve using a precomputed field with the bits associated with + 3, 5 and 7 already turned off, the value of pnN may need to be adjusted by a few counts to allow + the precomputed field to be used without modification. */ +/* To get better performance, one could address the issue of developing the composite numbers. When + the size of the prime gets large, the time for doing the divisions goes up, noticeably. It could + be better to develop larger composite numbers even if they need to be bigNum's themselves. The + object would be to reduce the number of times that the large prime is divided into a few large + divides and then use smaller divides to get to the final 16 bit (or smaller) remainders. */ +UINT32 +PrimeSieve( + bigNum bnN, // IN/OUT: number to sieve + UINT32 fieldSize, // IN: size of the field area in bytes + BYTE *field // IN: field + ) +{ + UINT32 i; + UINT32 j; + UINT32 fieldBits = fieldSize * 8; + UINT32 r; + BYTE *pField; + INT32 iter; + UINT32 adjust; + UINT32 mark = 0; + UINT32 count = sieveMarks[0].count; + UINT32 stop = sieveMarks[0].prime; + UINT32 composite; + UINT32 pList[8]; + UINT32 next; + pAssert(field != NULL && bnN != NULL); + // If the remainder is odd, then subtracting the value will give an even number, + // but we want an odd number, so subtract the 105+rem. Otherwise, just subtract + // the even remainder. + adjust = (UINT32)BnModWord(bnN, 105); + if(adjust & 1) + adjust += 105; + // Adjust the input number so that it points to the first number in a + // aligned field. + BnSubWord(bnN, bnN, adjust); + // pAssert(BnModWord(bnN, 105) == 0); + pField = field; + for(i = fieldSize; i >= sizeof(seedValues); + pField += sizeof(seedValues), i -= sizeof(seedValues)) + { + memcpy(pField, seedValues, sizeof(seedValues)); + } + if(i != 0) + memcpy(pField, seedValues, i); + // Cycle through the primes, clearing bits + // Have already done 3, 5, and 7 + iter = 7; +#define NEXT_PRIME(iter) (iter = RsaNextPrime(iter)) + // Get the next N primes where N is determined by the mark in the sieveMarks + while((composite = NEXT_PRIME(iter)) != 0) + { + next = 0; + i = count; + pList[i--] = composite; + for(; i > 0; i--) + { + next = NEXT_PRIME(iter); + pList[i] = next; + if(next != 0) + composite *= next; + } + // Get the remainder when dividing the base field address + // by the composite + composite = (UINT32)BnModWord(bnN, composite); + // 'composite' is divisible by the composite components. for each of the + // composite components, divide 'composite'. That remainder (r) is used to + // pick a starting point for clearing the array. The stride is equal to the + // composite component. Note, the field only contains odd numbers. If the + // field were expanded to contain all numbers, then half of the bits would + // have already been cleared. We can save the trouble of clearing them a + // second time by having a stride of 2*next. Or we can take all of the even + // numbers out of the field and use a stride of 'next' + for(i = count; i > 0; i--) + { + next = pList[i]; + if(next == 0) + goto done; + r = composite % next; + // these computations deal with the fact that we have picked a field-sized + // range that is aligned to a 105 count boundary. The problem is, this field + // only contains odd numbers. If we take our prime guess and walk through all + // the numbers using that prime as the 'stride', then every other 'stride' is + // going to be an even number. So, we are actually counting by 2 * the stride + // We want the count to start on an odd number at the start of our field. That + // is, we want to assume that we have counted up to the edge of the field by + // the 'stride' and now we are going to start flipping bits in the field as we + // continue to count up by 'stride'. If we take the base of our field and + // divide by the stride, we find out how much we find out how short the last + // count was from reaching the edge of the bit field. Say we get a quotient of + // 3 and remainder of 1. This means that after 3 strides, we are 1 short of + // the start of the field and the next stride will either land within the + // field or step completely over it. The confounding factor is that our field + // only contains odd numbers and our stride is actually 2 * stride. If the + // quoitent is even, then that means that when we add 2 * stride, we are going + // to hit another even number. So, we have to know if we need to back off + // by 1 stride before we start counting by 2 * stride. + // We can tell from the remainder whether we are on an even or odd + // stride when we hit the beginning of the table. If we are on an odd stride + // (r & 1), we would start half a stride in (next - r)/2. If we are on an + // even stride, we need 0.5 strides (next - r/2) because the table only has + // odd numbers. If the remainder happens to be zero, then the start of the + // table is on stride so no adjustment is necessary. + + if(r & 1) j = (next - r) / 2; + else if(r == 0) j = 0; + else j = next - (r / 2); + for(; j < fieldBits; j += next) + ClearBit(j, field, fieldSize); + } + if(next >= stop) + { + mark++; + count = sieveMarks[mark].count; + stop = sieveMarks[mark].prime; + } + } + done: + INSTRUMENT_INC(totalFieldsSieved[PrimeIndex]); + i = BitsInArray(field, fieldSize); + INSTRUMENT_ADD(bitsInFieldAfterSieve[PrimeIndex], i); + INSTRUMENT_ADD(emptyFieldsSieved[PrimeIndex], (i == 0)); + return i; +} +#ifdef SIEVE_DEBUG +static uint32_t fieldSize = 210; + +/* 10.2.17.1.6 SetFieldSize() */ +/* Function to set the field size used for prime generation. Used for tuning. */ +uint32_t +SetFieldSize( + uint32_t newFieldSize + ) +{ + if(newFieldSize == 0 || newFieldSize > MAX_FIELD_SIZE) + fieldSize = MAX_FIELD_SIZE; + else + fieldSize = newFieldSize; + return fieldSize; +} +#endif // SIEVE_DEBUG + +/* 10.2.17.1.7 PrimeSelectWithSieve() */ +/* This function will sieve the field around the input prime candidate. If the sieve field is not + empty, one of the one bits in the field is chosen for testing with Miller-Rabin. If the value is + prime, pnP is updated with this value and the function returns success. If this value is not + prime, another pseudo-random candidate is chosen and tested. This process repeats until all + values in the field have been checked. If all bits in the field have been checked and none is + prime, the function returns FALSE and a new random value needs to be chosen. */ +/* Error Returns Meaning */ +/* TPM_RC_FAILURE TPM in failure mode, probably due to entropy source */ +/* TPM_RC_SUCCESS candidate is probably prime */ +/* TPM_RC_NO_RESULT candidate is not prime and couldn't find and alternative in the field */ +LIB_EXPORT TPM_RC +PrimeSelectWithSieve( + bigNum candidate, // IN/OUT: The candidate to filter + UINT32 e, // IN: the exponent + RAND_STATE *rand // IN: the random number generator state + ) +{ + BYTE field[MAX_FIELD_SIZE]; + UINT32 first; + UINT32 ones; + INT32 chosen; + BN_PRIME(test); + UINT32 modE; +#ifndef SIEVE_DEBUG + UINT32 fieldSize = MAX_FIELD_SIZE; +#endif + UINT32 primeSize; + // + // Adjust the field size and prime table list to fit the size of the prime + // being tested. This is done to try to optimize the trade-off between the + // dividing done for sieving and the time for Miller-Rabin. When the size + // of the prime is large, the cost of Miller-Rabin is fairly high, as is the + // cost of the sieving. However, the time for Miller-Rabin goes up considerably + // faster than the cost of dividing by a number of primes. + primeSize = BnSizeInBits(candidate); + + if(primeSize <= 512) + { + RsaAdjustPrimeLimit(1024); // Use just the first 1024 primes + } + else if(primeSize <= 1024) + { + RsaAdjustPrimeLimit(4096); // Use just the first 4K primes + } + else + { + RsaAdjustPrimeLimit(0); // Use all available + } + + // Save the low-order word to use as a search generator and make sure that + // it has some interesting range to it + first = (UINT32)(candidate->d[0] | 0x80000000); + + // Sieve the field + ones = PrimeSieve(candidate, fieldSize, field); + pAssert(ones > 0 && ones < (fieldSize * 8)); + for(; ones > 0; ones--) + { + // Decide which bit to look at and find its offset + chosen = FindNthSetBit((UINT16)fieldSize, field, ((first % ones) + 1)); + + if((chosen < 0) || (chosen >= (INT32)(fieldSize * 8))) + FAIL(FATAL_ERROR_INTERNAL); + + // Set this as the trial prime + BnAddWord(test, candidate, (crypt_uword_t)(chosen * 2)); + + // The exponent might not have been one of the tested primes so + // make sure that it isn't divisible and make sure that 0 != (p-1) mod e + // Note: This is the same as 1 != p mod e + modE = (UINT32)BnModWord(test, e); + if((modE != 0) && (modE != 1) && MillerRabin(test, rand)) + { + BnCopy(candidate, test); + return TPM_RC_SUCCESS; + } + // Clear the bit just tested + ClearBit(chosen, field, fieldSize); + } + // Ran out of bits and couldn't find a prime in this field + INSTRUMENT_INC(noPrimeFields[PrimeIndex]); + return (g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_NO_RESULT); +} + +#if RSA_INSTRUMENT +static char a[256]; +char * +PrintTuple( + UINT32 *i + ) +{ + sprintf(a, "{%d, %d, %d}", i[0], i[1], i[2]); + return a; +} +#define CLEAR_VALUE(x) memset(x, 0, sizeof(x)) + +void +RsaSimulationEnd( + void + ) +{ + int i; + UINT32 averages[3]; + UINT32 nonFirst = 0; + if((PrimeCounts[0] + PrimeCounts[1] + PrimeCounts[2]) != 0) + { + printf("Primes generated = %s\n", PrintTuple(PrimeCounts)); + printf("Fields sieved = %s\n", PrintTuple(totalFieldsSieved)); + printf("Fields with no primes = %s\n", PrintTuple(noPrimeFields)); + printf("Primes checked with Miller-Rabin = %s\n", + PrintTuple(MillerRabinTrials)); + for(i = 0; i < 3; i++) + averages[i] = (totalFieldsSieved[i] + != 0 ? bitsInFieldAfterSieve[i] / totalFieldsSieved[i] + : 0); + printf("Average candidates in field %s\n", PrintTuple(averages)); + for(i = 1; i < (sizeof(failedAtIteration) / sizeof(failedAtIteration[0])); + i++) + nonFirst += failedAtIteration[i]; + printf("Miller-Rabin failures not in first round = %d\n", nonFirst); + } + CLEAR_VALUE(PrimeCounts); + CLEAR_VALUE(totalFieldsSieved); + CLEAR_VALUE(noPrimeFields); + CLEAR_VALUE(MillerRabinTrials); + CLEAR_VALUE(bitsInFieldAfterSieve); +} +void +GetSieveStats( + uint32_t *trials, + uint32_t *emptyFields, + uint32_t *averageBits + ) +{ + uint32_t totalBits; + uint32_t fields; + *trials = MillerRabinTrials[0] + MillerRabinTrials[1] + MillerRabinTrials[2]; + *emptyFields = noPrimeFields[0] + noPrimeFields[1] + noPrimeFields[2]; + fields = totalFieldsSieved[0] + totalFieldsSieved[1] + + totalFieldsSieved[2]; + totalBits = bitsInFieldAfterSieve[0] + bitsInFieldAfterSieve[1] + + bitsInFieldAfterSieve[2]; + if(fields != 0) + *averageBits = totalBits / fields; + else + *averageBits = 0; + CLEAR_VALUE(PrimeCounts); + CLEAR_VALUE(totalFieldsSieved); + CLEAR_VALUE(noPrimeFields); + CLEAR_VALUE(MillerRabinTrials); + CLEAR_VALUE(bitsInFieldAfterSieve); +} +#endif +#endif // RSA_KEY_SIEVE +#if !RSA_INSTRUMENT +//*** RsaSimulationEnd() +// Stub for call when not doing instrumentation. +#if 0 // libtpms added +void +RsaSimulationEnd( + void + ) +{ + return; +} +#endif // libtpms added +#endif diff --git a/src/tpm2/crypto/openssl/CryptRand.c b/src/tpm2/crypto/openssl/CryptRand.c new file mode 100644 index 0000000..5bf0643 --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptRand.c @@ -0,0 +1,881 @@ +/********************************************************************************/ +/* */ +/* DRBG with a behavior according to SP800-90A */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptRand.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "PRNG_TestVectors.h" +const BYTE DRBG_NistTestVector_Entropy[] = {DRBG_TEST_INITIATE_ENTROPY}; +const BYTE DRBG_NistTestVector_GeneratedInterm[] = + {DRBG_TEST_GENERATED_INTERM}; +const BYTE DRBG_NistTestVector_EntropyReseed[] = + {DRBG_TEST_RESEED_ENTROPY}; +const BYTE DRBG_NistTestVector_Generated[] = {DRBG_TEST_GENERATED}; + +/* 10.2.16.2.2 Derivation Function Defines and Structures */ +#define DF_COUNT (DRBG_KEY_SIZE_WORDS / DRBG_IV_SIZE_WORDS + 1) +#if DRBG_KEY_SIZE_BITS != 128 && DRBG_KEY_SIZE_BITS != 256 +# error "CryptRand.c only written for AES with 128- or 256-bit keys." +#endif + +typedef struct +{ + DRBG_KEY_SCHEDULE keySchedule; + DRBG_IV iv[DF_COUNT]; + DRBG_IV out1; + DRBG_IV buf; + int contents; +} DF_STATE, *PDF_STATE; +/* 10.2.16.2.3 DfCompute() */ +/* This function does the incremental update of the derivation function state. It encrypts the iv + value and XOR's the results into each of the blocks of the output. This is equivalent to + processing all of input data for each output block. */ +static void +DfCompute( + PDF_STATE dfState + ) +{ + int i; + int iv; + crypt_uword_t *pIv; + crypt_uword_t temp[DRBG_IV_SIZE_WORDS] = {0}; + // + for(iv = 0; iv < DF_COUNT; iv++) + { + pIv = (crypt_uword_t *)&dfState->iv[iv].words[0]; + for(i = 0; i < DRBG_IV_SIZE_WORDS; i++) + { + temp[i] ^= pIv[i] ^ dfState->buf.words[i]; + } + DRBG_ENCRYPT(&dfState->keySchedule, &temp, pIv); + } + for(i = 0; i < DRBG_IV_SIZE_WORDS; i++) + dfState->buf.words[i] = 0; + dfState->contents = 0; +} +/* 10.2.16.2.4 DfStart() */ +/* This initializes the output blocks with an encrypted counter value and initializes the key + schedule. */ +static void +DfStart( + PDF_STATE dfState, + uint32_t inputLength + ) +{ + BYTE init[8]; + int i; + UINT32 drbgSeedSize = sizeof(DRBG_SEED); + const BYTE dfKey[DRBG_KEY_SIZE_BYTES] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +#if DRBG_KEY_SIZE_BYTES > 16 + ,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f +#endif + }; + memset(dfState, 0, sizeof(DF_STATE)); + DRBG_ENCRYPT_SETUP(&dfKey[0], DRBG_KEY_SIZE_BITS, &dfState->keySchedule); + // Create the first chaining values + for(i = 0; i < DF_COUNT; i++) + ((BYTE *)&dfState->iv[i])[3] = (BYTE)i; + DfCompute(dfState); + // initialize the first 64 bits of the IV in a way that doesn't depend + // on the size of the words used. + UINT32_TO_BYTE_ARRAY(inputLength, init); + UINT32_TO_BYTE_ARRAY(drbgSeedSize, &init[4]); + memcpy(&dfState->iv[0], init, 8); + dfState->contents = 4; +} +/* 10.2.16.2.5 DfUpdate() */ +/* This updates the state with the input data. A byte at a time is moved into the state buffer until + it is full and then that block is encrypted by DfCompute(). */ +static void +DfUpdate( + PDF_STATE dfState, + int size, + const BYTE *data + ) +{ + while(size > 0) + { + int toFill = DRBG_IV_SIZE_BYTES - dfState->contents; + if(size < toFill) + toFill = size; + // Copy as many bytes as there are or until the state buffer is full + memcpy(&dfState->buf.bytes[dfState->contents], data, toFill); + // Reduce the size left by the amount copied + size -= toFill; + // Advance the data pointer by the amount copied + data += toFill; + // increase the buffer contents count by the amount copied + dfState->contents += toFill; + pAssert(dfState->contents <= DRBG_IV_SIZE_BYTES); + // If we have a full buffer, do a computation pass. + if(dfState->contents == DRBG_IV_SIZE_BYTES) + DfCompute(dfState); + } +} +/* 10.2.16.2.6 DfEnd() */ +/* This function is called to get the result of the derivation function computation. If the buffer + is not full, it is padded with zeros. The output buffer is structured to be the same as a + DRBG_SEED value so that the function can return a pointer to the DRBG_SEED value in the DF_STATE + structure. */ +static DRBG_SEED * +DfEnd( + PDF_STATE dfState + ) +{ + // Since DfCompute is always called when a buffer is full, there is always + // space in the buffer for the terminator + dfState->buf.bytes[dfState->contents++] = 0x80; + // If the buffer is not full, pad with zeros + while(dfState->contents < DRBG_IV_SIZE_BYTES) + dfState->buf.bytes[dfState->contents++] = 0; + // Do a final state update + DfCompute(dfState); + return (DRBG_SEED *)&dfState->iv; +} +/* 10.2.16.2.7 DfBuffer() */ +/* Function to take an input buffer and do the derivation function to produce a DRBG_SEED value that + can be used in DRBG_Reseed(); */ +static DRBG_SEED * +DfBuffer( + DRBG_SEED *output, // OUT: receives the result + int size, // IN: size of the buffer to add + BYTE *buf // IN: address of the buffer + ) +{ + DF_STATE dfState; + if(size == 0 || buf == NULL) + return NULL; + // Initialize the derivation function + DfStart(&dfState, size); + DfUpdate(&dfState, size, buf); + DfEnd(&dfState); + memcpy(output, &dfState.iv[0], sizeof(DRBG_SEED)); + return output; +} +/* 10.2.16.2.8 DRBG_GetEntropy() */ +/* Even though this implementation never fails, it may get blocked indefinitely long in the call to + get entropy from the platform (DRBG_GetEntropy32()). This function is only used during + instantiation of the DRBG for manufacturing and on each start-up after an non-orderly + shutdown. */ +/* Return Values Meaning */ +/* TRUE Requested entropy returned */ +/* FALSE Entropy Failure */ +BOOL +DRBG_GetEntropy( + UINT32 requiredEntropy, // IN: requested number of bytes of full + // entropy + BYTE *entropy // OUT: buffer to return collected entropy + ) +{ +#if !USE_DEBUG_RNG + UINT32 obtainedEntropy; + INT32 returnedEntropy; + // If in debug mode, always use the self-test values for initialization + if(IsSelfTest()) + { +#endif + // If doing simulated DRBG, then check to see if the + // entropyFailure condition is being tested + if(!IsEntropyBad())/* This function increments the IV value by 1. It is used by EncryptDRBG(). */ + { + // In self-test, the caller should be asking for exactly the seed + // size of entropy. + pAssert(requiredEntropy == sizeof(DRBG_NistTestVector_Entropy)); + memcpy(entropy, DRBG_NistTestVector_Entropy, + sizeof(DRBG_NistTestVector_Entropy)); + } +#if !USE_DEBUG_RNG + } + else if(!IsEntropyBad()) + { + // Collect entropy + // Note: In debug mode, the only "entropy" value ever returned + // is the value of the self-test vector. + for(returnedEntropy = 1, obtainedEntropy = 0; + obtainedEntropy < requiredEntropy && !IsEntropyBad(); + obtainedEntropy += returnedEntropy) + { + returnedEntropy = _plat__GetEntropy(&entropy[obtainedEntropy], + requiredEntropy - obtainedEntropy); + if(returnedEntropy <= 0) + SetEntropyBad(); + } + } +#endif + return !IsEntropyBad(); +} + +void +IncrementIv( + DRBG_IV *iv + ) +{ + BYTE *ivP = ((BYTE *)iv) + DRBG_IV_SIZE_BYTES; + while((--ivP >= (BYTE *)iv) && ((*ivP = ((*ivP + 1) & 0xFF)) == 0)); +} +/* 10.2.16.2.10 EncryptDRBG() */ +/* This does the encryption operation for the DRBG. It will encrypt the input state counter (IV) + using the state key. Into the output buffer for as many times as it takes to generate the + required number of bytes. */ +static BOOL +EncryptDRBG( + BYTE *dOut, + UINT32 dOutBytes, + DRBG_KEY_SCHEDULE *keySchedule, + DRBG_IV *iv, + UINT32 *lastValue // Points to the last output value + ) +{ +#if FIPS_COMPLIANT + // For FIPS compliance, the DRBG has to do a continuous self-test to make sure that + // no two consecutive values are the same. This overhead is not incurred if the TPM + // is not required to be FIPS compliant + // + UINT32 temp[DRBG_IV_SIZE_BYTES / sizeof(UINT32)]; + int i; + BYTE *p; + for(; dOutBytes > 0;) + { + // Increment the IV before each encryption (this is what makes this + // different from normal counter-mode encryption + IncrementIv(iv); + DRBG_ENCRYPT(keySchedule, iv, temp); + // Expect a 16 byte block +#if DRBG_IV_SIZE_BITS != 128 +#error "Unsuppored IV size in DRBG" +#endif + if((lastValue[0] == temp[0]) + && (lastValue[1] == temp[1]) + && (lastValue[2] == temp[2]) + && (lastValue[3] == temp[3]) + ) + { + LOG_FAILURE(FATAL_ERROR_ENTROPY); + return FALSE; + } + lastValue[0] = temp[0]; + lastValue[1] = temp[1]; + lastValue[2] = temp[2]; + lastValue[3] = temp[3]; + i = MIN(dOutBytes, DRBG_IV_SIZE_BYTES); + dOutBytes -= i; + for(p = (BYTE *)temp; i > 0; i--) + *dOut++ = *p++; + } +#else // version without continuous self-test + NOT_REFERENCED(lastValue); + for(; dOutBytes >= DRBG_IV_SIZE_BYTES; + dOut = &dOut[DRBG_IV_SIZE_BYTES], dOutBytes -= DRBG_IV_SIZE_BYTES) + { + // Increment the IV + IncrementIv(iv); + DRBG_ENCRYPT(keySchedule, iv, dOut); + } + // If there is a partial, generate into a block-sized + // temp buffer and copy to the output. + if(dOutBytes != 0) + { + BYTE temp[DRBG_IV_SIZE_BYTES]; + // Increment the IV + IncrementIv(iv); + DRBG_ENCRYPT(keySchedule, iv, temp); + memcpy(dOut, temp, dOutBytes); + } +#endif + return TRUE; +} +/* 10.2.16.2.11 DRBG_Update() */ +/* This function performs the state update function. According to SP800-90A, a temp value is created + by doing CTR mode encryption of providedData and replacing the key and IV with these values. The + one difference is that, with counter mode, the IV is incremented after each block is encrypted + and in this operation, the counter is incremented before each block is encrypted. This function + implements an optimized version of the algorithm in that it does the update of the + drbgState->seed in place and then providedData is XORed into drbgState->seed to complete the + encryption of providedData. This works because the IV is the last thing that gets encrypted. */ +static BOOL +DRBG_Update( + DRBG_STATE *drbgState, // IN:OUT state to update + DRBG_KEY_SCHEDULE *keySchedule, // IN: the key schedule (optional) + DRBG_SEED *providedData // IN: additional data + ) +{ + UINT32 i; + BYTE *temp = (BYTE *)&drbgState->seed; + DRBG_KEY *key = pDRBG_KEY(&drbgState->seed); + DRBG_IV *iv = pDRBG_IV(&drbgState->seed); + DRBG_KEY_SCHEDULE localKeySchedule; + memset(&localKeySchedule, 0, sizeof(localKeySchedule)); /* libtpms added: coverity */ + // + pAssert(drbgState->magic == DRBG_MAGIC); + // If an key schedule was not provided, make one + if(keySchedule == NULL) + { + if(DRBG_ENCRYPT_SETUP((BYTE *)key, + DRBG_KEY_SIZE_BITS, &localKeySchedule) != 0) + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return FALSE; + } + keySchedule = &localKeySchedule; + } + // Encrypt the temp value + EncryptDRBG(temp, sizeof(DRBG_SEED), keySchedule, iv, + drbgState->lastValue); + if(providedData != NULL) + { + BYTE *pP = (BYTE *)providedData; + for(i = DRBG_SEED_SIZE_BYTES; i != 0; i--) + *temp++ ^= *pP++; + } + // Since temp points to the input key and IV, we are done and + // don't need to copy the resulting 'temp' to drbgState->seed + return TRUE; +} +/* 10.2.16.2.12 DRBG_Reseed() */ +/* This function is used when reseeding of the DRBG is required. If entropy is provided, it is used + in lieu of using hardware entropy. */ +/* NOTE: the provided entropy must be the required size. */ +/* Return Values Meaning */ +/* TRUE reseed succeeded */ +/* FALSE reseed failed, probably due to the entropy generation */ +BOOL +DRBG_Reseed( + DRBG_STATE *drbgState, // IN: the state to update + DRBG_SEED *providedEntropy, // IN: entropy + DRBG_SEED *additionalData // IN: + ) +{ + DRBG_SEED seed; + pAssert((drbgState != NULL) && (drbgState->magic == DRBG_MAGIC)); + if(providedEntropy == NULL) + { + providedEntropy = &seed; + if(!DRBG_GetEntropy(sizeof(DRBG_SEED), (BYTE *)providedEntropy)) + return FALSE; + } + if(additionalData != NULL) + { + unsigned int i; + // XOR the provided data into the provided entropy + for(i = 0; i < sizeof(DRBG_SEED); i++) + ((BYTE *)providedEntropy)[i] ^= ((BYTE *)additionalData)[i]; + } + DRBG_Update(drbgState, NULL, providedEntropy); + drbgState->reseedCounter = 1; + return TRUE; +} +/* 10.2.16.2.13 DRBG_SelfTest() */ +/* This is run when the DRBG is instantiated and at startup */ +/* Return Values Meaning */ +/* FALSE test failed */ +/* TRUE test OK */ +BOOL +DRBG_SelfTest( + void + ) +{ + BYTE buf[sizeof(DRBG_NistTestVector_Generated)]; + DRBG_SEED seed; + UINT32 i; + BYTE *p; + DRBG_STATE testState; + // + pAssert(!IsSelfTest()); + SetSelfTest(); + SetDrbgTested(); + // Do an instantiate + if(!DRBG_Instantiate(&testState, 0, NULL)) + return FALSE; +#if DRBG_DEBUG_PRINT + dbgDumpMemBlock(pDRBG_KEY(&testState), DRBG_KEY_SIZE_BYTES, + "Key after Instantiate"); + dbgDumpMemBlock(pDRBG_IV(&testState), DRBG_IV_SIZE_BYTES, + "Value after Instantiate"); +#endif + if(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0) + return FALSE; +#if DRBG_DEBUG_PRINT + dbgDumpMemBlock(pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES, + "Key after 1st Generate"); + dbgDumpMemBlock(pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES, + "Value after 1st Generate"); +#endif + if(memcmp(buf, DRBG_NistTestVector_GeneratedInterm, sizeof(buf)) != 0) + return FALSE; + memcpy(seed.bytes, DRBG_NistTestVector_EntropyReseed, sizeof(seed)); + DRBG_Reseed(&testState, &seed, NULL); +#if DRBG_DEBUG_PRINT + dbgDumpMemBlock((BYTE *)pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES, + "Key after 2nd Generate"); + dbgDumpMemBlock((BYTE *)pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES, + "Value after 2nd Generate"); + dbgDumpMemBlock(buf, sizeof(buf), "2nd Generated"); +#endif + if(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0) + return FALSE; + if(memcmp(buf, DRBG_NistTestVector_Generated, sizeof(buf)) != 0) + return FALSE; + ClearSelfTest(); + DRBG_Uninstantiate(&testState); + for(p = (BYTE *)&testState, i = 0; i < sizeof(DRBG_STATE); i++) + { + if(*p++) + return FALSE; + } + // Simulate hardware failure to make sure that we get an error when + // trying to instantiate + SetEntropyBad(); + if(DRBG_Instantiate(&testState, 0, NULL)) + return FALSE; + ClearEntropyBad(); + return TRUE; +} +/* 10.2.16.3 Public Interface */ + +/* 10.2.16.3.1 Description */ +/* The functions in this section are the interface to the RNG. These are the functions that are used + by TPM.lib. */ + +/* 10.2.16.3.2 CryptRandomStir() */ +/* This function is used to cause a reseed. A DRBG_SEED amount of entropy is collected from the + hardware and then additional data is added. */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT failure of the entropy generator */ +LIB_EXPORT TPM_RC +CryptRandomStir( + UINT16 additionalDataSize, + BYTE *additionalData + ) +{ +#if !USE_DEBUG_RNG + DRBG_SEED tmpBuf; + DRBG_SEED dfResult; + // + // All reseed with outside data starts with a buffer full of entropy + if(!DRBG_GetEntropy(sizeof(tmpBuf), (BYTE *)&tmpBuf)) + return TPM_RC_NO_RESULT; + DRBG_Reseed(&drbgDefault, &tmpBuf, + DfBuffer(&dfResult, additionalDataSize, additionalData)); + drbgDefault.reseedCounter = 1; + return TPM_RC_SUCCESS; +#else + // If doing debug, use the input data as the initial setting for the RNG state + // so that the test can be reset at any time. + // Note: If this is called with a data size of 0 or less, nothing happens. The + // presumption is that, in a debug environment, the caller will have specific + // values for initialization, so this check is just a simple way to prevent + // inadvertent programming errors from screwing things up. This doesn't use an + // pAssert() because the non-debug version of this function will accept these + // parameters as meaning that there is no additionalData and only hardware + // entropy is used. + if((additionalDataSize > 0) && (additionalData != NULL)) + { + memset(drbgDefault.seed.bytes, 0, sizeof(drbgDefault.seed.bytes)); + memcpy(drbgDefault.seed.bytes, additionalData, + MIN(additionalDataSize, sizeof(drbgDefault.seed.bytes))); + } + drbgDefault.reseedCounter = 1; + return TPM_RC_SUCCESS; +#endif +} +/* 10.2.16.3.3 CryptRandomGenerate() */ +/* Generate a randomSize number or random bytes. */ +LIB_EXPORT UINT16 +CryptRandomGenerate( + UINT16 randomSize, + BYTE *buffer + ) +{ + return DRBG_Generate((RAND_STATE *)&drbgDefault, buffer, randomSize); +} +/* 10.2.16.3.4 DRBG_InstantiateSeededKdf() */ +/* Function used to instantiate a KDF-based RNG. This is used for derivations. This function always + returns TRUE. */ +LIB_EXPORT BOOL +DRBG_InstantiateSeededKdf( + KDF_STATE *state, // OUT: buffer to hold the state + TPM_ALG_ID hashAlg, // IN: hash algorithm + TPM_ALG_ID kdf, // IN: the KDF to use + TPM2B *seed, // IN: the seed to use + const TPM2B *label, // IN: a label for the generation process. + TPM2B *context, // IN: the context value + UINT32 limit // IN: Maximum number of bits from the KDF + ) +{ + state->magic = KDF_MAGIC; + state->limit = limit; + state->seed = seed; + state->hash = hashAlg; + state->kdf = kdf; + state->label = label; + state->context = context; + state->digestSize = CryptHashGetDigestSize(hashAlg); + state->counter = 0; + state->residual.t.size = 0; + return TRUE; +} +/* 10.2.16.3.5 DRBG_AdditionalData() */ +/* Function to reseed the DRBG with additional entropy. This is normally called before computing the + protection value of a primary key in the Endorsement hierarchy. */ +LIB_EXPORT void +DRBG_AdditionalData( + DRBG_STATE *drbgState, // IN:OUT state to update + TPM2B *additionalData // IN: value to incorporate + ) +{ + DRBG_SEED dfResult; + if(drbgState->magic == DRBG_MAGIC) + { + DfBuffer(&dfResult, additionalData->size, additionalData->buffer); + DRBG_Reseed(drbgState, &dfResult, NULL); + } +} +/* 10.2.16.3.6 DRBG_InstantiateSeeded() */ +/* This function is used to instantiate a random number generator from seed values. The nominal use + of this generator is to create sequences of pseudo-random numbers from a seed value. */ +/* Returns + TPM_RC_FAILURE DRBG self-test failure +*/ +LIB_EXPORT TPM_RC +DRBG_InstantiateSeeded( + DRBG_STATE *drbgState, // IN/OUT: buffer to hold the state + const TPM2B *seed, // IN: the seed to use + const TPM2B *purpose, // IN: a label for the generation process. + const TPM2B *name, // IN: name of the object + const TPM2B *additional, // IN: additional data + SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added + ) +{ + DF_STATE dfState; + int totalInputSize; + // DRBG should have been tested, but... + if(!IsDrbgTested() && !DRBG_SelfTest()) + { + LOG_FAILURE(FATAL_ERROR_SELF_TEST); + return TPM_RC_FAILURE; + } + // Initialize the DRBG state + memset(drbgState, 0, sizeof(DRBG_STATE)); + drbgState->magic = DRBG_MAGIC; + drbgState->seedCompatLevel = seedCompatLevel; // libtpms added + // Size all of the values + totalInputSize = (seed != NULL) ? seed->size : 0; + totalInputSize += (purpose != NULL) ? purpose->size : 0; + totalInputSize += (name != NULL) ? name->size : 0; + totalInputSize += (additional != NULL) ? additional->size : 0; + // Initialize the derivation + DfStart(&dfState, totalInputSize); + // Run all the input strings through the derivation function + if(seed != NULL) + DfUpdate(&dfState, seed->size, seed->buffer); + if(purpose != NULL) + DfUpdate(&dfState, purpose->size, purpose->buffer); + if(name != NULL) + DfUpdate(&dfState, name->size, name->buffer); + if(additional != NULL) + DfUpdate(&dfState, additional->size, additional->buffer); + // Used the derivation function output as the "entropy" input. This is not + // how it is described in SP800-90A but this is the equivalent function + DRBG_Reseed(((DRBG_STATE *)drbgState), DfEnd(&dfState), NULL); + return TPM_RC_SUCCESS; +} +/* 10.2.16.3.7 CryptRandStartup() */ +/* This function is called when TPM_Startup() is executed. */ +/* TRUE instantiation succeeded */ /* kgold */ +/* FALSE instantiation failed */ +LIB_EXPORT BOOL +CryptRandStartup( + void + ) +{ +#if ! _DRBG_STATE_SAVE + // If not saved in NV, re-instantiate on each startup + return DRBG_Instantiate(&drbgDefault, 0, NULL); +#else + // If the running state is saved in NV, NV has to be loaded before it can + // be updated + if(go.drbgState.magic == DRBG_MAGIC) + return DRBG_Reseed(&go.drbgState, NULL, NULL); + else + return DRBG_Instantiate(&go.drbgState, 0, NULL); +#endif +} +/* 10.2.16.3.8 CryptRandInit() */ +/* This function is called when _TPM_Init() is being processed */ +LIB_EXPORT BOOL +CryptRandInit( + void + ) +{ +#if !USE_DEBUG_RNG + _plat__GetEntropy(NULL, 0); +#endif + return DRBG_SelfTest(); +} +// libtpms added begin +LIB_EXPORT SEED_COMPAT_LEVEL +DRBG_GetSeedCompatLevel( + RAND_STATE *state + ) +{ + if(state == NULL) + { + return SEED_COMPAT_LEVEL_LAST; + } + else if(state->drbg.magic == DRBG_MAGIC) + { + DRBG_STATE *drbgState = (DRBG_STATE *)state; + + return drbgState->seedCompatLevel; + } + else + { + return SEED_COMPAT_LEVEL_LAST; + } +} +// libtpms added end +/* 10.2.16.5 DRBG_Generate() */ +/* This function generates a random sequence according SP800-90A. If random is not NULL, then + randomSize bytes of random values are generated. If random is NULL or randomSize is zero, then + the function returns TRUE without generating any bits or updating the reseed counter. This + function returns 0 if a reseed is required. Otherwise, it returns the number of bytes produced + which could be less than the number requested if the request is too large.("too large" is + implementation dependent.) */ +LIB_EXPORT UINT16 +DRBG_Generate( + RAND_STATE *state, + BYTE *random, // OUT: buffer to receive the random values + UINT16 randomSize // IN: the number of bytes to generate + ) +{ + if(state == NULL) + state = (RAND_STATE *)&drbgDefault; + if(random == NULL) + return 0; + + // If the caller used a KDF state, generate a sequence from the KDF not to + // exceed the limit. + if(state->kdf.magic == KDF_MAGIC) + { + KDF_STATE *kdf = (KDF_STATE *)state; + UINT32 counter = (UINT32)kdf->counter; + INT32 bytesLeft = randomSize; + + // If the number of bytes to be returned would put the generator + // over the limit, then return 0 + if((((kdf->counter * kdf->digestSize) + randomSize) * 8) > kdf->limit) + return 0; + // Process partial and full blocks until all requested bytes provided + while(bytesLeft > 0) + { + // If there is any residual data in the buffer, copy it to the output + // buffer + if(kdf->residual.t.size > 0) + { + INT32 size; + // + // Don't use more of the residual than will fit or more than are + // available + size = MIN(kdf->residual.t.size, bytesLeft); + // Copy some or all of the residual to the output. The residual is + // at the end of the buffer. The residual might be a full buffer. + MemoryCopy(random, + &kdf->residual.t.buffer + [kdf->digestSize - kdf->residual.t.size], size); + // Advance the buffer pointer + random += size; + // Reduce the number of bytes left to get + bytesLeft -= size; + // And reduce the residual size appropriately + kdf->residual.t.size -= (UINT16)size; + } + else + { + UINT16 blocks = (UINT16)(bytesLeft / kdf->digestSize); + // + // Get the number of required full blocks + if(blocks > 0) + { + UINT16 size = blocks * kdf->digestSize; + // Get some number of full blocks and put them in the return buffer + CryptKDFa(kdf->hash, kdf->seed, kdf->label, kdf->context, NULL, + kdf->limit, random, &counter, blocks); + // reduce the size remaining to be moved and advance the pointer + bytesLeft -= size; + random += size; + } + else + { + // Fill the residual buffer with a full block and then loop to + // top to get part of it copied to the output. + kdf->residual.t.size = CryptKDFa(kdf->hash, kdf->seed, + kdf->label, kdf->context, NULL, + kdf->limit, + kdf->residual.t.buffer, + &counter, 1); + } + } + } + kdf->counter = counter; + return randomSize; + } + else if(state->drbg.magic == DRBG_MAGIC) + { + DRBG_STATE *drbgState = (DRBG_STATE *)state; + DRBG_KEY_SCHEDULE keySchedule; + DRBG_SEED *seed = &drbgState->seed; + memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */ + if(drbgState->reseedCounter >= CTR_DRBG_MAX_REQUESTS_PER_RESEED) + { + if(drbgState == &drbgDefault) + { + DRBG_Reseed(drbgState, NULL, NULL); + if(IsEntropyBad() && !IsSelfTest()) + return 0; + } + else + { + // If this is a PRNG then the only way to get + // here is if the SW has run away. + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return 0; + } + } + // if the allowed number of bytes in a request is larger than the + // less than the number of bytes that can be requested, then check +#if UINT16_MAX >= CTR_DRBG_MAX_BYTES_PER_REQUEST + if(randomSize > CTR_DRBG_MAX_BYTES_PER_REQUEST) + randomSize = CTR_DRBG_MAX_BYTES_PER_REQUEST; +#endif + // Create encryption schedule + if(DRBG_ENCRYPT_SETUP((BYTE *)pDRBG_KEY(seed), + DRBG_KEY_SIZE_BITS, &keySchedule) != 0) + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return 0; + } + // Generate the random data + EncryptDRBG(random, randomSize, &keySchedule, pDRBG_IV(seed), + drbgState->lastValue); + // Do a key update + DRBG_Update(drbgState, &keySchedule, NULL); + // Increment the reseed counter + drbgState->reseedCounter += 1; + } + else + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return 0; // libtpms changed from FALSE + } + return randomSize; +} +/* 10.2.16.6 DRBG_Instantiate() */ +/* This is CTR_DRBG_Instantiate_algorithm() from [SP 800-90A 10.2.1.3.1]. This is called when a the + TPM DRBG is to be instantiated. This is called to instantiate a DRBG used by the TPM for normal + operations. */ +/* Return Values Meaning */ +/* TRUE instantiation succeeded */ +/* FALSE instantiation failed */ +LIB_EXPORT BOOL +DRBG_Instantiate( + DRBG_STATE *drbgState, // OUT: the instantiated value + UINT16 pSize, // IN: Size of personalization string + BYTE *personalization // IN: The personalization string + ) +{ + DRBG_SEED seed; + DRBG_SEED dfResult; + // + pAssert((pSize == 0) || (pSize <= sizeof(seed)) || (personalization != NULL)); + // If the DRBG has not been tested, test when doing an instantiation. Since + // Instantiation is called during self test, make sure we don't get stuck in a + // loop. + if(!IsDrbgTested() && !IsSelfTest() && !DRBG_SelfTest()) + return FALSE; + // If doing a self test, DRBG_GetEntropy will return the NIST + // test vector value. + if(!DRBG_GetEntropy(sizeof(seed), (BYTE *)&seed)) + return FALSE; + // set everything to zero + memset(drbgState, 0, sizeof(DRBG_STATE)); + drbgState->magic = DRBG_MAGIC; + // Steps 1, 2, 3, 6, 7 of SP 800-90A 10.2.1.3.1 are exactly what + // reseeding does. So, do a reduction on the personalization value (if any) + // and do a reseed. + DRBG_Reseed(drbgState, &seed, DfBuffer(&dfResult, pSize, personalization)); + return TRUE; +} +/* 10.2.16.7 DRBG_Uninstantiate() */ +/* This is Uninstantiate_function() from [SP 800-90A 9.4]. */ +/* Error Returns Meaning */ +/* TPM_RC_VALUE not a valid state */ +LIB_EXPORT TPM_RC +DRBG_Uninstantiate( + DRBG_STATE *drbgState // IN/OUT: working state to erase + ) +{ + if((drbgState == NULL) || (drbgState->magic != DRBG_MAGIC)) + return TPM_RC_VALUE; + memset(drbgState, 0, sizeof(DRBG_STATE)); + return TPM_RC_SUCCESS; +} + diff --git a/src/tpm2/crypto/openssl/CryptRsa.c b/src/tpm2/crypto/openssl/CryptRsa.c new file mode 100644 index 0000000..4ed0438 --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptRsa.c @@ -0,0 +1,1634 @@ +/********************************************************************************/ +/* */ +/* Implementation of cryptographic primitives for RSA */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptRsa.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.17 CryptRsa.c */ +/* 10.2.17.1 Introduction */ +/* This file contains implementation of cryptographic primitives for RSA. Vendors may replace the + implementation in this file with their own library functions. */ +/* 10.2.17.2 Includes */ +/* Need this define to get the private defines for this function */ +#define CRYPT_RSA_C +#include "Tpm.h" +#include "Helpers_fp.h" // libtpms added + +#include // libtpms added + +#if ALG_RSA +/* 10.2.17.3 Obligatory Initialization Functions */ +/* 10.2.17.3.1 CryptRsaInit() */ +/* Function called at _TPM_Init(). */ +BOOL +CryptRsaInit( + void + ) +{ + return TRUE; +} +/* 10.2.17.3.2 CryptRsaStartup() */ +/* Function called at TPM2_Startup() */ +BOOL +CryptRsaStartup( + void + ) +{ + return TRUE; +} +/* 10.2.17.4 Internal Functions */ +void +RsaInitializeExponent( + privateExponent_t *pExp + ) +{ +#if CRT_FORMAT_RSA == NO + BN_INIT(pExp->D); +#else + BN_INIT(pExp->Q); + BN_INIT(pExp->dP); + BN_INIT(pExp->dQ); + BN_INIT(pExp->qInv); +#endif +} +/* 10.2.17.4.1 ComputePrivateExponent() */ +/* This function computes the private exponent from the primes. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure */ +static BOOL +ComputePrivateExponent( + bigNum P, // IN: first prime (size is 1/2 of bnN) + bigNum Q, // IN: second prime (size is 1/2 of bnN) + bigNum E, // IN: the public exponent + bigNum N, // IN: the public modulus + privateExponent_t *pExp // OUT: + ) +{ + BOOL pOK; + BOOL qOK; +#if CRT_FORMAT_RSA == NO + BN_RSA(bnPhi); + // + RsaInitializeExponent(pExp); + // Get compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1 + pOK = BnCopy(bnPhi, N); + pOK = pOK && BnSub(bnPhi, bnPhi, P); + pOK = pOK && BnSub(bnPhi, bnPhi, Q); + pOK = pOK && BnAddWord(bnPhi, bnPhi, 1); + // Compute the multiplicative inverse d = 1/e mod Phi + pOK = pOK && BnModInverse((bigNum)&pExp->D, E, bnPhi); + qOK = pOK; +#else + BN_PRIME(temp); + bigNum pT; + // + NOT_REFERENCED(N); + RsaInitializeExponent(pExp); + BnCopy((bigNum)&pExp->Q, Q); + // make p the larger value so that m2 is always less than p + if(BnUnsignedCmp(P, Q) < 0) + { + pT = P; + P = Q; + Q = pT; + } + //dP = (1/e) mod (p-1) = d mod (p-1) + pOK = BnSubWord(temp, P, 1); + pOK = pOK && BnModInverse((bigNum)&pExp->dP, E, temp); + //dQ = (1/e) mod (q-1) = d mod (q-1) + qOK = BnSubWord(temp, Q, 1); + qOK = qOK && BnModInverse((bigNum)&pExp->dQ, E, temp); + // qInv = (1/q) mod p + if(pOK && qOK) + pOK = qOK = BnModInverse((bigNum)&pExp->qInv, Q, P); +#endif + if(!pOK) + BnSetWord(P, 0); + if(!qOK) + BnSetWord(Q, 0); + return pOK && qOK; +} +/* 10.2.17.4.2 RsaPrivateKeyOp() */ +/* This function is called to do the exponentiation with the private key. Compile options allow use + of the simple (but slow) private exponent, or the more complex but faster CRT method. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure */ +static BOOL +RsaPrivateKeyOp( + bigNum inOut, // IN/OUT: number to be exponentiated + bigNum N, // IN: public modulus (can be NULL if CRT) + bigNum P, // IN: one of the primes (can be NULL if not CRT) + privateExponent_t *pExp + ) +{ + BOOL OK; +#if CRT_FORMAT_RSA == NO + (P); + OK = BnModExp(inOut, inOut, (bigNum)&pExp->D, N); +#else + BN_RSA(M1); + BN_RSA(M2); + BN_RSA(M); + BN_RSA(H); + bigNum Q = (bigNum)&pExp->Q; + NOT_REFERENCED(N); + // Make P the larger prime. + // NOTE that when the CRT form of the private key is created, dP will always + // be computed using the larger of p and q so the only thing needed here is that + // the primes be selected so that they agree with dP. + if(BnUnsignedCmp(P, Q) < 0) + { + bigNum T = P; + P = Q; + Q = T; + } + // m1 = cdP mod p + OK = BnModExp(M1, inOut, (bigNum)&pExp->dP, P); + // m2 = cdQ mod q + OK = OK && BnModExp(M2, inOut, (bigNum)&pExp->dQ, Q); + // h = qInv * (m1 - m2) mod p = qInv * (m1 + P - m2) mod P because Q < P + // so m2 < P + OK = OK && BnSub(H, P, M2); + OK = OK && BnAdd(H, H, M1); + OK = OK && BnModMult(H, H, (bigNum)&pExp->qInv, P); + // m = m2 + h * q + OK = OK && BnMult(M, H, Q); + OK = OK && BnAdd(inOut, M2, M); +#endif + return OK; +} +/* 10.2.17.4.3 RSAEP() */ +/* This function performs the RSAEP operation defined in PKCS#1v2.1. It is an exponentiation of a + value (m) with the public exponent (e), modulo the public (n). */ +/* Error Returns Meaning */ +/* TPM_RC_VALUE number to exponentiate is larger than the modulus */ +#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added +static TPM_RC +RSAEP( + TPM2B *dInOut, // IN: size of the encrypted block and the size of + // the encrypted value. It must be the size of + // the modulus. + // OUT: the encrypted data. Will receive the + // decrypted value + OBJECT *key // IN: the key to use + ) +{ + TPM2B_TYPE(4BYTES, 4); + TPM2B_4BYTES(e) = {{4, {(BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 24) & 0xff), + (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 16) & 0xff), + (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 8) & 0xff), + (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT)& 0xff)}}}; + // + if(key->publicArea.parameters.rsaDetail.exponent != 0) + UINT32_TO_BYTE_ARRAY(key->publicArea.parameters.rsaDetail.exponent, + e.t.buffer); + return ModExpB(dInOut->size, dInOut->buffer, dInOut->size, dInOut->buffer, + e.t.size, e.t.buffer, key->publicArea.unique.rsa.t.size, + key->publicArea.unique.rsa.t.buffer); +} +/* 10.2.17.4.4 RSADP() */ +/* This function performs the RSADP operation defined in PKCS#1v2.1. It is an exponentiation of a + value (c) with the private exponent (d), modulo the public modulus (n). The decryption is in + place. */ +/* This function also checks the size of the private key. If the size indicates that only a prime + value is present, the key is converted to being a private exponent. */ +/* Error Returns Meaning */ +/* TPM_RC_SIZE the value to decrypt is larger than the modulus */ +static TPM_RC +RSADP( + TPM2B *inOut, // IN/OUT: the value to encrypt + OBJECT *key // IN: the key + ) +{ + BN_RSA_INITIALIZED(bnM, inOut); + BN_RSA_INITIALIZED(bnN, &key->publicArea.unique.rsa); + BN_RSA_INITIALIZED(bnP, &key->sensitive.sensitive.rsa); + if(BnUnsignedCmp(bnM, bnN) >= 0) + return TPM_RC_SIZE; + // private key operation requires that private exponent be loaded + // During self-test, this might not be the case so load it up if it hasn't + // already done + // been done + if(!key->attributes.privateExp) + CryptRsaLoadPrivateExponent(key); + if(!RsaPrivateKeyOp(bnM, bnN, bnP, &key->privateExponent)) + FAIL(FATAL_ERROR_INTERNAL); + BnTo2B(bnM, inOut, inOut->size); + return TPM_RC_SUCCESS; +} +/* 10.2.17.4.5 OaepEncode() */ +/* This function performs OAEP padding. The size of the buffer to receive the OAEP padded data must + equal the size of the modulus */ +/* Error Returns Meaning */ +/* TPM_RC_VALUE hashAlg is not valid or message size is too large */ +static TPM_RC +OaepEncode( + TPM2B *padded, // OUT: the pad data + TPM_ALG_ID hashAlg, // IN: algorithm to use for padding + const TPM2B *label, // IN: null-terminated string (may be NULL) + TPM2B *message, // IN: the message being padded + RAND_STATE *rand // IN: the random number generator to use + ) +{ + INT32 padLen; + INT32 dbSize; + INT32 i; + BYTE mySeed[MAX_DIGEST_SIZE]; + BYTE *seed = mySeed; + UINT16 hLen = CryptHashGetDigestSize(hashAlg); + BYTE mask[MAX_RSA_KEY_BYTES]; + BYTE *pp; + BYTE *pm; + TPM_RC retVal = TPM_RC_SUCCESS; + pAssert(padded != NULL && message != NULL); + // A value of zero is not allowed because the KDF can't produce a result + // if the digest size is zero. + if(hLen == 0) + return TPM_RC_VALUE; + // Basic size checks + // make sure digest isn't too big for key size + if(padded->size < (2 * hLen) + 2) + ERROR_RETURN(TPM_RC_HASH); + // and that message will fit messageSize <= k - 2hLen - 2 + if(message->size > (padded->size - (2 * hLen) - 2)) + ERROR_RETURN(TPM_RC_VALUE); + // Hash L even if it is null + // Offset into padded leaving room for masked seed and byte of zero + pp = &padded->buffer[hLen + 1]; + if(CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer, + hLen, pp) != hLen) + ERROR_RETURN(TPM_RC_FAILURE); + // concatenate PS of k mLen 2hLen 2 + padLen = padded->size - message->size - (2 * hLen) - 2; + MemorySet(&pp[hLen], 0, padLen); + pp[hLen + padLen] = 0x01; + padLen += 1; + memcpy(&pp[hLen + padLen], message->buffer, message->size); + // The total size of db = hLen + pad + mSize; + dbSize = hLen + padLen + message->size; + // If testing, then use the provided seed. Otherwise, use values + // from the RNG + CryptRandomGenerate(hLen, mySeed); + DRBG_Generate(rand, mySeed, (UINT16)hLen); + // mask = MGF1 (seed, nSize hLen 1) + CryptMGF_KDF(dbSize, mask, hashAlg, hLen, seed, 0); + // Create the masked db + pm = mask; + for(i = dbSize; i > 0; i--) + *pp++ ^= *pm++; + pp = &padded->buffer[hLen + 1]; + // Run the masked data through MGF1 + if(CryptMGF_KDF(hLen, &padded->buffer[1], hashAlg, dbSize, pp, 0) != (unsigned)hLen) + ERROR_RETURN(TPM_RC_VALUE); + // Now XOR the seed to create masked seed + pp = &padded->buffer[1]; + pm = seed; + for(i = hLen; i > 0; i--) + *pp++ ^= *pm++; + // Set the first byte to zero + padded->buffer[0] = 0x00; + Exit: + return retVal; +} +/* 10.2.17.4.6 OaepDecode() */ +/* This function performs OAEP padding checking. The size of the buffer to receive the recovered + data. If the padding is not valid, the dSize size is set to zero and the function returns + TPM_RC_VALUE. */ +/* The dSize parameter is used as an input to indicate the size available in the buffer. If + insufficient space is available, the size is not changed and the return code is TPM_RC_VALUE. */ +/* Error Returns Meaning */ +/* TPM_RC_VALUE the value to decode was larger than the modulus, or the padding is wrong or the + buffer to receive the results is too small */ +static TPM_RC +OaepDecode( + TPM2B *dataOut, // OUT: the recovered data + TPM_ALG_ID hashAlg, // IN: algorithm to use for padding + const TPM2B *label, // IN: null-terminated string (may be NULL) + TPM2B *padded // IN: the padded data + ) +{ + UINT32 i; + BYTE seedMask[MAX_DIGEST_SIZE]; + UINT32 hLen = CryptHashGetDigestSize(hashAlg); + BYTE mask[MAX_RSA_KEY_BYTES]; + BYTE *pp; + BYTE *pm; + TPM_RC retVal = TPM_RC_SUCCESS; + // Strange size (anything smaller can't be an OAEP padded block) + // Also check for no leading 0 + if((padded->size < (unsigned)((2 * hLen) + 2)) || (padded->buffer[0] != 0)) + ERROR_RETURN(TPM_RC_VALUE); + // Use the hash size to determine what to put through MGF1 in order + // to recover the seedMask + CryptMGF_KDF(hLen, seedMask, hashAlg, padded->size - hLen - 1, + &padded->buffer[hLen + 1], 0); + // Recover the seed into seedMask + pAssert(hLen <= sizeof(seedMask)); + pp = &padded->buffer[1]; + pm = seedMask; + for(i = hLen; i > 0; i--) + *pm++ ^= *pp++; + // Use the seed to generate the data mask + CryptMGF_KDF(padded->size - hLen - 1, mask, hashAlg, hLen, seedMask, 0); + // Use the mask generated from seed to recover the padded data + pp = &padded->buffer[hLen + 1]; + pm = mask; + for(i = (padded->size - hLen - 1); i > 0; i--) + *pm++ ^= *pp++; + // Make sure that the recovered data has the hash of the label + // Put trial value in the seed mask + if((CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer, + hLen, seedMask)) != hLen) + FAIL(FATAL_ERROR_INTERNAL); + if(memcmp(seedMask, mask, hLen) != 0) + ERROR_RETURN(TPM_RC_VALUE); + // find the start of the data + pm = &mask[hLen]; + for(i = (UINT32)padded->size - (2 * hLen) - 1; i > 0; i--) + { + if(*pm++ != 0) + break; + } + // If we ran out of data or didn't end with 0x01, then return an error + if(i == 0 || pm[-1] != 0x01) + ERROR_RETURN(TPM_RC_VALUE); + // pm should be pointing at the first part of the data + // and i is one greater than the number of bytes to move + i--; + if(i > dataOut->size) + // Special exit to preserve the size of the output buffer + return TPM_RC_VALUE; + memcpy(dataOut->buffer, pm, i); + dataOut->size = (UINT16)i; + Exit: + if(retVal != TPM_RC_SUCCESS) + dataOut->size = 0; + return retVal; +} +/* 10.2.17.4.7 PKCS1v1_5Encode() */ +/* This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */ +/* Error Returns Meaning */ +/* TPM_RC_VALUE message size is too large */ +static TPM_RC +RSAES_PKCS1v1_5Encode( + TPM2B *padded, // OUT: the pad data + TPM2B *message, // IN: the message being padded + RAND_STATE *rand + ) +{ + UINT32 ps = padded->size - message->size - 3; + // + if(message->size > padded->size - 11) + return TPM_RC_VALUE; + // move the message to the end of the buffer + memcpy(&padded->buffer[padded->size - message->size], message->buffer, + message->size); + // Set the first byte to 0x00 and the second to 0x02 + padded->buffer[0] = 0; + padded->buffer[1] = 2; + // Fill with random bytes + DRBG_Generate(rand, &padded->buffer[2], (UINT16)ps); + // Set the delimiter for the random field to 0 + padded->buffer[2 + ps] = 0; + // Now, the only messy part. Make sure that all the 'ps' bytes are non-zero + // In this implementation, use the value of the current index + for(ps++; ps > 1; ps--) + { + if(padded->buffer[ps] == 0) + padded->buffer[ps] = 0x55; // In the < 0.5% of the cases that the + // random value is 0, just pick a value to + // put into the spot. + } + return TPM_RC_SUCCESS; +} +/* 10.2.17.4.8 RSAES_Decode() */ +/* This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */ +/* Error Returns Meaning */ +/* TPM_RC_FAIL decoding error or results would no fit into provided buffer */ +static TPM_RC +RSAES_Decode( + TPM2B *message, // OUT: the recovered message + TPM2B *coded // IN: the encoded message + ) +{ + BOOL fail = FALSE; + UINT16 pSize; + fail = (coded->size < 11); + fail = (coded->buffer[0] != 0x00) | fail; + fail = (coded->buffer[1] != 0x02) | fail; + for(pSize = 2; pSize < coded->size; pSize++) + { + if(coded->buffer[pSize] == 0) + break; + } + pSize++; + // Make sure that pSize has not gone over the end and that there are at least 8 + // bytes of pad data. + fail = (pSize > coded->size) | fail; + fail = ((pSize - 2) <= 8) | fail; + if((message->size < (UINT16)(coded->size - pSize)) || fail) + return TPM_RC_VALUE; + message->size = coded->size - pSize; + memcpy(message->buffer, &coded->buffer[pSize], coded->size - pSize); + return TPM_RC_SUCCESS; +} +#endif // libtpms added +/* 10.2.17.4.13 CryptRsaPssSaltSize() */ +/* This function computes the salt size used in PSS. It is broken out so that the X509 code can get + the same value that is used by the encoding function in this module. */ +INT16 +CryptRsaPssSaltSize( + INT16 hashSize, + INT16 outSize +) +{ + INT16 saltSize; + // + // (Mask Length) = (outSize - hashSize - 1); + // Max saltSize is (Mask Length) - 1 + saltSize = (outSize - hashSize - 1) - 1; + // Use the maximum salt size allowed by FIPS 186-4 + if (saltSize > hashSize) + saltSize = hashSize; + else if (saltSize < 0) + saltSize = 0; + return saltSize; +} + +#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added +/* 10.2.17.4.9 PssEncode() */ +/* This function creates an encoded block of data that is the size of modulus. The function uses the + maximum salt size that will fit in the encoded block. */ +/* Returns TPM_RC_SUCCESS or goes into failure mode. */ +static TPM_RC +PssEncode( + TPM2B *out, // OUT: the encoded buffer + TPM_ALG_ID hashAlg, // IN: hash algorithm for the encoding + TPM2B *digest, // IN: the digest + RAND_STATE *rand // IN: random number source + ) +{ + UINT32 hLen = CryptHashGetDigestSize(hashAlg); + BYTE salt[MAX_RSA_KEY_BYTES - 1]; + UINT16 saltSize; + BYTE *ps = salt; + BYTE *pOut; + UINT16 mLen; + HASH_STATE hashState; + // These are fatal errors indicating bad TPM firmware + pAssert(out != NULL && hLen > 0 && digest != NULL); + // Get the size of the mask + mLen = (UINT16)(out->size - hLen - 1); + // Maximum possible salt size is mask length - 1 + saltSize = mLen - 1; + // Use the maximum salt size allowed by FIPS 186-4 + if(saltSize > hLen) + saltSize = (UINT16)hLen; + //using eOut for scratch space + // Set the first 8 bytes to zero + pOut = out->buffer; + memset(pOut, 0, 8); + // Get set the salt + DRBG_Generate(rand, salt, saltSize); + // Create the hash of the pad || input hash || salt + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate(&hashState, 8, pOut); + CryptDigestUpdate2B(&hashState, digest); + CryptDigestUpdate(&hashState, saltSize, salt); + CryptHashEnd(&hashState, hLen, &pOut[out->size - hLen - 1]); + // Create a mask + if(CryptMGF_KDF(mLen, pOut, hashAlg, hLen, &pOut[mLen], 0) != mLen) + FAIL(FATAL_ERROR_INTERNAL); + // Since this implementation uses key sizes that are all even multiples of + // 8, just need to make sure that the most significant bit is CLEAR + *pOut &= 0x7f; + // Before we mess up the pOut value, set the last byte to 0xbc + pOut[out->size - 1] = 0xbc; + // XOR a byte of 0x01 at the position just before where the salt will be XOR'ed + pOut = &pOut[mLen - saltSize - 1]; + *pOut++ ^= 0x01; + // XOR the salt data into the buffer + for(; saltSize > 0; saltSize--) + *pOut++ ^= *ps++; + // and we are done + return TPM_RC_SUCCESS; +} +/* 10.2.17.4.10 PssDecode() */ +/* This function checks that the PSS encoded block was built from the provided digest. If the check + is successful, TPM_RC_SUCCESS is returned. Any other value indicates an error. */ +/* This implementation of PSS decoding is intended for the reference TPM implementation and is not + at all generalized. It is used to check signatures over hashes and assumptions are made about + the sizes of values. Those assumptions are enforce by this implementation. This implementation + does allow for a variable size salt value to have been used by the creator of the signature. */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME hashAlg is not a supported hash algorithm */ +/* TPM_RC_VALUE decode operation failed */ +static TPM_RC +PssDecode( + TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding + TPM2B *dIn, // In: the digest to compare + TPM2B *eIn // IN: the encoded data + ) +{ + UINT32 hLen = CryptHashGetDigestSize(hashAlg); + BYTE mask[MAX_RSA_KEY_BYTES]; + BYTE *pm = mask; + BYTE *pe; + BYTE pad[8] = {0}; + UINT32 i; + UINT32 mLen; + BYTE fail; + TPM_RC retVal = TPM_RC_SUCCESS; + HASH_STATE hashState; + // These errors are indicative of failures due to programmer error + pAssert(dIn != NULL && eIn != NULL); + pe = eIn->buffer; + // check the hash scheme + if(hLen == 0) + ERROR_RETURN(TPM_RC_SCHEME); + // most significant bit must be zero + fail = pe[0] & 0x80; + // last byte must be 0xbc + fail |= pe[eIn->size - 1] ^ 0xbc; + // Use the hLen bytes at the end of the buffer to generate a mask + // Doesn't start at the end which is a flag byte + mLen = eIn->size - hLen - 1; + CryptMGF_KDF(mLen, mask, hashAlg, hLen, &pe[mLen], 0); + // Clear the MSO of the mask to make it consistent with the encoding. + mask[0] &= 0x7F; + pAssert(mLen <= sizeof(mask)); + // XOR the data into the mask to recover the salt. This sequence + // advances eIn so that it will end up pointing to the seed data + // which is the hash of the signature data + for(i = mLen; i > 0; i--) + *pm++ ^= *pe++; + // Find the first byte of 0x01 after a string of all 0x00 + for(pm = mask, i = mLen; i > 0; i--) + { + if(*pm == 0x01) + break; + else + fail |= *pm++; + } + // i should not be zero + fail |= (i == 0); + // if we have failed, will continue using the entire mask as the salt value so + // that the timing attacks will not disclose anything (I don't think that this + // is a problem for TPM applications but, usually, we don't fail so this + // doesn't cost anything). + if(fail) + { + i = mLen; + pm = mask; + } + else + { + pm++; + i--; + } + // i contains the salt size and pm points to the salt. Going to use the input + // hash and the seed to recreate the hash in the lower portion of eIn. + CryptHashStart(&hashState, hashAlg); + // add the pad of 8 zeros + CryptDigestUpdate(&hashState, 8, pad); + // add the provided digest value + CryptDigestUpdate(&hashState, dIn->size, dIn->buffer); + // and the salt + CryptDigestUpdate(&hashState, i, pm); + // get the result + fail |= (CryptHashEnd(&hashState, hLen, mask) != hLen); + // Compare all bytes + for(pm = mask; hLen > 0; hLen--) + // don't use fail = because that could skip the increment and compare + // operations after the first failure and that gives away timing + // information. + fail |= *pm++ ^ *pe++; + retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS; + Exit: + return retVal; +} +/* 10.2.17.4.16 MakeDerTag() */ +/* Construct the DER value that is used in RSASSA */ +/* Return Value Meaning */ +/* > 0 size of value */ +/* <= 0 no hash exists */ +INT16 +MakeDerTag( + TPM_ALG_ID hashAlg, + INT16 sizeOfBuffer, + BYTE *buffer + ) +{ + // 0x30, 0x31, // SEQUENCE (2 elements) 1st + // 0x30, 0x0D, // SEQUENCE (2 elements) + // 0x06, 0x09, // HASH OID + // 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + // 0x05, 0x00, // NULL + // 0x04, 0x20 // OCTET STRING + HASH_DEF *info = CryptGetHashDef(hashAlg); + INT16 oidSize; + // If no OID, can't do encode + VERIFY(info != NULL); + oidSize = 2 + (info->OID)[1]; + // make sure this fits in the buffer + VERIFY(sizeOfBuffer >= (oidSize + 8)); + *buffer++ = 0x30; // 1st SEQUENCE + // Size of the 1st SEQUENCE is 6 bytes + size of the hash OID + size of the + // digest size + *buffer++ = (BYTE)(6 + oidSize + info->digestSize); // + *buffer++ = 0x30; // 2nd SEQUENCE + // size is 4 bytes of overhead plus the side of the OID + *buffer++ = (BYTE)(2 + oidSize); + MemoryCopy(buffer, info->OID, oidSize); + buffer += oidSize; + *buffer++ = 0x05; // Add a NULL + *buffer++ = 0x00; + + *buffer++ = 0x04; + *buffer++ = (BYTE)(info->digestSize); + return oidSize + 8; + Error: + return 0; + +} + +/* 10.2.17.4.17 RSASSA_Encode() */ +/* Encode a message using PKCS1v1.5 method. */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME hashAlg is not a supported hash algorithm */ +/* TPM_RC_SIZE eOutSize is not large enough */ +/* TPM_RC_VALUE hInSize does not match the digest size of hashAlg */ +static TPM_RC +RSASSA_Encode( + TPM2B *pOut, // IN:OUT on in, the size of the public key + // on out, the encoded area + TPM_ALG_ID hashAlg, // IN: hash algorithm for PKCS1v1_5 + TPM2B *hIn // IN: digest value to encode + ) +{ + BYTE DER[20]; + BYTE *der = DER; + INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER); + BYTE *eOut; + INT32 fillSize; + TPM_RC retVal = TPM_RC_SUCCESS; + + // Can't use this scheme if the algorithm doesn't have a DER string defined. + if(derSize == 0) + ERROR_RETURN(TPM_RC_SCHEME); + + // If the digest size of 'hashAl' doesn't match the input digest size, then + // the DER will misidentify the digest so return an error + if(CryptHashGetDigestSize(hashAlg) != hIn->size) + ERROR_RETURN(TPM_RC_VALUE); + fillSize = pOut->size - derSize - hIn->size - 3; + eOut = pOut->buffer; + + // Make sure that this combination will fit in the provided space + if(fillSize < 8) + ERROR_RETURN(TPM_RC_SIZE); + + // Start filling + *eOut++ = 0; // initial byte of zero + *eOut++ = 1; // byte of 0x01 + for(; fillSize > 0; fillSize--) + *eOut++ = 0xff; // bunch of 0xff + *eOut++ = 0; // another 0 + for(; derSize > 0; derSize--) + *eOut++ = *der++; // copy the DER + der = hIn->buffer; + for(fillSize = hIn->size; fillSize > 0; fillSize--) + *eOut++ = *der++; // copy the hash + Exit: + return retVal; +} + +/* 10.2.17.4.18 RSASSA_Decode() */ +/* This function performs the RSASSA decoding of a signature. */ +/* Error Returns Meaning */ +/* TPM_RC_VALUE decode unsuccessful */ +/* TPM_RC_SCHEME haslAlg is not supported */ +static TPM_RC +RSASSA_Decode( + TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding + TPM2B *hIn, // In: the digest to compare + TPM2B *eIn // IN: the encoded data + ) +{ + BYTE fail; + BYTE DER[20]; + BYTE *der = DER; + INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER); + BYTE *pe; + INT32 hashSize = CryptHashGetDigestSize(hashAlg); + INT32 fillSize; + TPM_RC retVal; + BYTE *digest; + UINT16 digestSize; + + pAssert(hIn != NULL && eIn != NULL); + pe = eIn->buffer; + + // Can't use this scheme if the algorithm doesn't have a DER string + // defined or if the provided hash isn't the right size + if(derSize == 0 || (unsigned)hashSize != hIn->size) + ERROR_RETURN(TPM_RC_SCHEME); + + // Make sure that this combination will fit in the provided space + // Since no data movement takes place, can just walk though this + // and accept nearly random values. This can only be called from + // CryptValidateSignature() so eInSize is known to be in range. + fillSize = eIn->size - derSize - hashSize - 3; + + // Start checking (fail will become non-zero if any of the bytes do not have + // the expected value. + fail = *pe++; // initial byte of zero + fail |= *pe++ ^ 1; // byte of 0x01 + for(; fillSize > 0; fillSize--) + fail |= *pe++ ^ 0xff; // bunch of 0xff + fail |= *pe++; // another 0 + for(; derSize > 0; derSize--) + fail |= *pe++ ^ *der++; // match the DER + digestSize = hIn->size; + digest = hIn->buffer; + for(; digestSize > 0; digestSize--) + fail |= *pe++ ^ *digest++; // match the hash + retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS; + Exit: + return retVal; +} +#endif // libtpms added + +/* 10.2.17.4.13 CryptRsaSelectScheme() */ +/* This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to + select a scheme between input and object default. This function assume the RSA object is + loaded. If a default scheme is defined in object, the default scheme should be chosen, otherwise, + the input scheme should be chosen. In the case that both the object and scheme are not + TPM_ALG_NULL, then if the schemes are the same, the input scheme will be chosen. if the scheme + are not compatible, a NULL pointer will be returned. */ +/* The return pointer may point to a TPM_ALG_NULL scheme. */ +TPMT_RSA_DECRYPT* +CryptRsaSelectScheme( + TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key + TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme + ) +{ + OBJECT *rsaObject; + TPMT_ASYM_SCHEME *keyScheme; + TPMT_RSA_DECRYPT *retVal = NULL; + // Get sign object pointer + rsaObject = HandleToObject(rsaHandle); + keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme; + // if the default scheme of the object is TPM_ALG_NULL, then select the + // input scheme + if(keyScheme->scheme == TPM_ALG_NULL) + { + retVal = scheme; + } + // if the object scheme is not TPM_ALG_NULL and the input scheme is + // TPM_ALG_NULL, then select the default scheme of the object. + else if(scheme->scheme == TPM_ALG_NULL) + { + // if input scheme is NULL + retVal = (TPMT_RSA_DECRYPT *)keyScheme; + } + // get here if both the object scheme and the input scheme are + // not TPM_ALG_NULL. Need to insure that they are the same. + // IMPLEMENTATION NOTE: This could cause problems if future versions have + // schemes that have more values than just a hash algorithm. A new function + // (IsSchemeSame()) might be needed then. + else if(keyScheme->scheme == scheme->scheme + && keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg) + { + retVal = scheme; + } + // two different, incompatible schemes specified will return NULL + return retVal; +} +/* 10.2.17.4.14 CryptRsaLoadPrivateExponent() */ +/* Error Returns Meaning */ +/* TPM_RC_BINDING public and private parts of rsaKey are not matched */ +TPM_RC +CryptRsaLoadPrivateExponent( + OBJECT *rsaKey // IN: the RSA key object + ) +{ + BN_RSA_INITIALIZED(bnN, &rsaKey->publicArea.unique.rsa); + BN_PRIME_INITIALIZED(bnP, &rsaKey->sensitive.sensitive.rsa); + BN_RSA(bnQ); + BN_PRIME(bnQr); + BN_WORD_INITIALIZED(bnE, (rsaKey->publicArea.parameters.rsaDetail.exponent == 0) + ? RSA_DEFAULT_PUBLIC_EXPONENT + : rsaKey->publicArea.parameters.rsaDetail.exponent); + TPM_RC retVal = TPM_RC_SUCCESS; + if(!rsaKey->attributes.privateExp) + { + TEST(TPM_ALG_NULL); + // Make sure that the bigNum used for the exponent is properly initialized + RsaInitializeExponent(&rsaKey->privateExponent); + // Find the second prime by division + BnDiv(bnQ, bnQr, bnN, bnP); + if(!BnEqualZero(bnQr)) + ERROR_RETURN(TPM_RC_BINDING); + // Compute the private exponent and return it if found + if(!ComputePrivateExponent(bnP, bnQ, bnE, bnN, + &rsaKey->privateExponent)) + ERROR_RETURN(TPM_RC_BINDING); + } + Exit: + rsaKey->attributes.privateExp = (retVal == TPM_RC_SUCCESS); + return retVal; +} +#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added +/* 10.2.17.4.15 CryptRsaEncrypt() */ +/* This is the entry point for encryption using RSA. Encryption is use of the public exponent. The + padding parameter determines what padding will be used. */ +/* The cOutSize parameter must be at least as large as the size of the key. */ +/* If the padding is RSA_PAD_NONE, dIn is treated as a number. It must be lower in value than the + key modulus. */ +/* NOTE: If dIn has fewer bytes than cOut, then we don't add low-order zeros to dIn to make it the + size of the RSA key for the call to RSAEP. This is because the high order bytes of dIn might have + a numeric value that is greater than the value of the key modulus. If this had low-order zeros + added, it would have a numeric value larger than the modulus even though it started out with a + lower numeric value. */ +/* Error Returns Meaning */ +/* TPM_RC_VALUE cOutSize is too small (must be the size of the modulus) */ +/* TPM_RC_SCHEME padType is not a supported scheme */ +LIB_EXPORT TPM_RC +CryptRsaEncrypt( + TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data + TPM2B *dIn, // IN: the data to encrypt + OBJECT *key, // IN: the key used for encryption + TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash + // if needed + const TPM2B *label, // IN: in case it is needed + RAND_STATE *rand // IN: random number generator + // state (mostly for testing) + ) +{ + TPM_RC retVal = TPM_RC_SUCCESS; + TPM2B_PUBLIC_KEY_RSA dataIn; + // + // if the input and output buffers are the same, copy the input to a scratch + // buffer so that things don't get messed up. + if(dIn == &cOut->b) + { + MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer)); + dIn = &dataIn.b; + } + // All encryption schemes return the same size of data + cOut->t.size = key->publicArea.unique.rsa.t.size; + TEST(scheme->scheme); + switch(scheme->scheme) + { + case TPM_ALG_NULL: // 'raw' encryption + { + INT32 i; + INT32 dSize = dIn->size; + // dIn can have more bytes than cOut as long as the extra bytes + // are zero. Note: the more significant bytes of a number in a byte + // buffer are the bytes at the start of the array. + for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++); + dSize -= i; + if(dSize > cOut->t.size) + ERROR_RETURN(TPM_RC_VALUE); + // Pad cOut with zeros if dIn is smaller + memset(cOut->t.buffer, 0, cOut->t.size - dSize); + // And copy the rest of the value + memcpy(&cOut->t.buffer[cOut->t.size - dSize], &dIn->buffer[i], dSize); + // If the size of dIn is the same as cOut dIn could be larger than + // the modulus. If it is, then RSAEP() will catch it. + } + break; + case TPM_ALG_RSAES: + retVal = RSAES_PKCS1v1_5Encode(&cOut->b, dIn, rand); + break; + case TPM_ALG_OAEP: + retVal = OaepEncode(&cOut->b, scheme->details.oaep.hashAlg, label, dIn, + rand); + break; + default: + ERROR_RETURN(TPM_RC_SCHEME); + break; + } + // All the schemes that do padding will come here for the encryption step + // Check that the Encoding worked + if(retVal == TPM_RC_SUCCESS) + // Padding OK so do the encryption + retVal = RSAEP(&cOut->b, key); + Exit: + return retVal; +} +/* 10.2.17.4.16 CryptRsaDecrypt() */ +/* This is the entry point for decryption using RSA. Decryption is use of the private exponent. The + padType parameter determines what padding was used. */ +/* Error Returns Meaning */ +/* TPM_RC_SIZE cInSize is not the same as the size of the public modulus of key; or numeric value of + the encrypted data is greater than the modulus */ +/* TPM_RC_VALUE dOutSize is not large enough for the result */ +/* TPM_RC_SCHEME padType is not supported */ +LIB_EXPORT TPM_RC +CryptRsaDecrypt( + TPM2B *dOut, // OUT: the decrypted data + TPM2B *cIn, // IN: the data to decrypt + OBJECT *key, // IN: the key to use for decryption + TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme + const TPM2B *label // IN: in case it is needed for the scheme + ) +{ + TPM_RC retVal; + // Make sure that the necessary parameters are provided + pAssert(cIn != NULL && dOut != NULL && key != NULL); + // Size is checked to make sure that the encrypted value is the right size + if(cIn->size != key->publicArea.unique.rsa.t.size) + ERROR_RETURN(TPM_RC_SIZE); + TEST(scheme->scheme); + // For others that do padding, do the decryption in place and then + // go handle the decoding. + retVal = RSADP(cIn, key); + if(retVal == TPM_RC_SUCCESS) + { + // Remove padding + switch(scheme->scheme) + { + case TPM_ALG_NULL: + if(dOut->size < cIn->size) + return TPM_RC_VALUE; + MemoryCopy2B(dOut, cIn, dOut->size); + break; + case TPM_ALG_RSAES: + retVal = RSAES_Decode(dOut, cIn); + break; + case TPM_ALG_OAEP: + retVal = OaepDecode(dOut, scheme->details.oaep.hashAlg, label, cIn); + break; + default: + retVal = TPM_RC_SCHEME; + break; + } + } + Exit: + return retVal; +} +/* 10.2.17.4.17 CryptRsaSign() */ +/* This function is used to generate an RSA signature of the type indicated in scheme. */ +/* Error Returns Meaning */ +/* TPM_RC_SCHEME scheme or hashAlg are not supported */ +/* TPM_RC_VALUE hInSize does not match hashAlg (for RSASSA) */ +LIB_EXPORT TPM_RC +CryptRsaSign( + TPMT_SIGNATURE *sigOut, + OBJECT *key, // IN: key to use + TPM2B_DIGEST *hIn, // IN: the digest to sign + RAND_STATE *rand // IN: the random number generator + // to use (mostly for testing) + ) +{ + TPM_RC retVal = TPM_RC_SUCCESS; + UINT16 modSize; + // parameter checks + pAssert(sigOut != NULL && key != NULL && hIn != NULL); + modSize = key->publicArea.unique.rsa.t.size; + // for all non-null signatures, the size is the size of the key modulus + sigOut->signature.rsapss.sig.t.size = modSize; + TEST(sigOut->sigAlg); + switch(sigOut->sigAlg) + { + case TPM_ALG_NULL: + sigOut->signature.rsapss.sig.t.size = 0; + return TPM_RC_SUCCESS; + case TPM_ALG_RSAPSS: + retVal = PssEncode(&sigOut->signature.rsapss.sig.b, + sigOut->signature.rsapss.hash, &hIn->b, rand); + break; + case TPM_ALG_RSASSA: + retVal = RSASSA_Encode(&sigOut->signature.rsassa.sig.b, + sigOut->signature.rsassa.hash, &hIn->b); + break; + default: + retVal = TPM_RC_SCHEME; + } + if(retVal == TPM_RC_SUCCESS) + { + // Do the encryption using the private key + retVal = RSADP(&sigOut->signature.rsapss.sig.b, key); + } + return retVal; +} +/* 10.2.17.4.18 CryptRsaValidateSignature() */ +/* This function is used to validate an RSA signature. If the signature is valid TPM_RC_SUCCESS is + returned. If the signature is not valid, TPM_RC_SIGNATURE is returned. Other return codes + indicate either parameter problems or fatal errors. */ +/* Error Returns Meaning */ +/* TPM_RC_SIGNATURE the signature does not check */ +/* TPM_RC_SCHEME unsupported scheme or hash algorithm */ +LIB_EXPORT TPM_RC +CryptRsaValidateSignature( + TPMT_SIGNATURE *sig, // IN: signature + OBJECT *key, // IN: public modulus + TPM2B_DIGEST *digest // IN: The digest being validated + ) +{ + TPM_RC retVal; + // + // Fatal programming errors + pAssert(key != NULL && sig != NULL && digest != NULL); + switch(sig->sigAlg) + { + case TPM_ALG_RSAPSS: + case TPM_ALG_RSASSA: + break; + default: + return TPM_RC_SCHEME; + } + // Errors that might be caused by calling parameters + if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size) + ERROR_RETURN(TPM_RC_SIGNATURE); + TEST(sig->sigAlg); + // Decrypt the block + retVal = RSAEP(&sig->signature.rsassa.sig.b, key); + if(retVal == TPM_RC_SUCCESS) + { + switch(sig->sigAlg) + { + case TPM_ALG_RSAPSS: + retVal = PssDecode(sig->signature.any.hashAlg, &digest->b, + &sig->signature.rsassa.sig.b); + break; + case TPM_ALG_RSASSA: + retVal = RSASSA_Decode(sig->signature.any.hashAlg, &digest->b, + &sig->signature.rsassa.sig.b); + break; + default: + return TPM_RC_SCHEME; + } + } + Exit: + return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS; +} +#endif // libtpms added +#if SIMULATION && USE_RSA_KEY_CACHE +extern int s_rsaKeyCacheEnabled; +int GetCachedRsaKey(OBJECT *key, RAND_STATE *rand); +#define GET_CACHED_KEY(key, rand) \ + (s_rsaKeyCacheEnabled && GetCachedRsaKey(key, rand)) +#else +#define GET_CACHED_KEY(key, rand) +#endif +/* 10.2.17.4.19 CryptRsaGenerateKey() */ +/* Generate an RSA key from a provided seed */ +/* Error Returns Meaning */ +/* TPM_RC_CANCELED operation was canceled */ +/* TPM_RC_RANGE public exponent is not supported */ +/* TPM_RC_VALUE could not find a prime using the provided parameters */ +LIB_EXPORT TPM_RC +CryptRsaGenerateKey( + OBJECT *rsaKey, // IN/OUT: The object structure in which + // the key is created. + RAND_STATE *rand // IN: if not NULL, the deterministic + // RNG state + ) +{ + UINT32 i; + BN_PRIME(bnP); // These four declarations initialize the number to 0 + BN_PRIME(bnQ); + BN_RSA(bnD); + BN_RSA(bnN); + BN_WORD(bnE); + UINT32 e; + int keySizeInBits; + TPMT_PUBLIC *publicArea = &rsaKey->publicArea; + TPMT_SENSITIVE *sensitive = &rsaKey->sensitive; + TPM_RC retVal = TPM_RC_NO_RESULT; + // + // Need to make sure that the caller did not specify an exponent that is + // not supported + e = publicArea->parameters.rsaDetail.exponent; + if(e == 0) + e = RSA_DEFAULT_PUBLIC_EXPONENT; + if(e < 65537) + ERROR_RETURN(TPM_RC_RANGE); + if(e != RSA_DEFAULT_PUBLIC_EXPONENT && !IsPrimeInt(e)) + ERROR_RETURN(TPM_RC_RANGE); + BnSetWord(bnE, e); + // Check that e is prime + // check for supported key size. + keySizeInBits = publicArea->parameters.rsaDetail.keyBits; + if(((keySizeInBits % 1024) != 0) + || (keySizeInBits > MAX_RSA_KEY_BITS) // this might be redundant, but... + || (keySizeInBits == 0)) + ERROR_RETURN(TPM_RC_VALUE); + // Set the prime size for instrumentation purposes + INSTRUMENT_SET(PrimeIndex, PRIME_INDEX(keySizeInBits / 2)); +#if SIMULATION && USE_RSA_KEY_CACHE + if(GET_CACHED_KEY(rsaKey, rand)) + return TPM_RC_SUCCESS; +#endif + // Make sure that key generation has been tested + TEST(TPM_ALG_NULL); +#if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin + if (rand == NULL) + return OpenSSLCryptRsaGenerateKey(rsaKey, e, keySizeInBits); +#endif // libtpms added end + // Need to initialize the privateExponent structure + RsaInitializeExponent(&rsaKey->privateExponent); + // The prime is computed in P. When a new prime is found, Q is checked to + // see if it is zero. If so, P is copied to Q and a new P is found. + // When both P and Q are non-zero, the modulus and + // private exponent are computed and a trial encryption/decryption is + // performed. If the encrypt/decrypt fails, assume that at least one of the + // primes is composite. Since we don't know which one, set Q to zero and start + // over and find a new pair of primes. + for(i = 1; (retVal != TPM_RC_SUCCESS) && (i != 100); i++) + { + if(_plat__IsCanceled()) + ERROR_RETURN(TPM_RC_CANCELED); + BnGeneratePrimeForRSA(bnP, keySizeInBits / 2, e, rand); + INSTRUMENT_INC(PrimeCounts[PrimeIndex]); + // If this is the second prime, make sure that it differs from the + // first prime by at least 2^100 + if(BnEqualZero(bnQ)) + { + // copy p to q and compute another prime in p + BnCopy(bnQ, bnP); + continue; + } + // Make sure that the difference is at least 100 bits. Need to do it this + // way because the big numbers are only positive values + if(BnUnsignedCmp(bnP, bnQ) < 0) + BnSub(bnD, bnQ, bnP); + else + BnSub(bnD, bnP, bnQ); + if(BnMsb(bnD) < 100) + continue; + //Form the public modulus and set the unique value + BnMult(bnN, bnP, bnQ); + BnTo2B(bnN, &publicArea->unique.rsa.b, + (NUMBYTES)BITS_TO_BYTES(keySizeInBits)); + // And the prime to the sensitive area + BnTo2B(bnP, &sensitive->sensitive.rsa.b, + (NUMBYTES)BITS_TO_BYTES(keySizeInBits) / 2); + // Make sure everything came out right. The MSb of the values must be + // one + if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0) + || ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0)) + FAIL(FATAL_ERROR_INTERNAL); + // Make sure that we can form the private exponent values + if(ComputePrivateExponent(bnP, bnQ, bnE, bnN, &rsaKey->privateExponent) + != TRUE) + { + // If ComputePrivateExponent could not find an inverse for + // Q, then copy P and recompute P. This might + // cause both to be recomputed if P is also zero + if(BnEqualZero(bnQ)) + BnCopy(bnQ, bnP); + continue; + } + retVal = TPM_RC_SUCCESS; + // Do a trial encryption decryption if this is a signing key + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + { + BN_RSA(temp1); + BN_RSA(temp2); + BnGenerateRandomInRange(temp1, bnN, rand); + // Encrypt with public exponent... + BnModExp(temp2, temp1, bnE, bnN); + // ... then decrypt with private exponent + RsaPrivateKeyOp(temp2, bnN, bnP, &rsaKey->privateExponent); + // If the starting and ending values are not the same, + // start over )-; + if(BnUnsignedCmp(temp2, temp1) != 0) + { + BnSetWord(bnQ, 0); + retVal = TPM_RC_NO_RESULT; + } + } + } + Exit: + if(retVal == TPM_RC_SUCCESS) + rsaKey->attributes.privateExp = SET; + return retVal; +} + +#if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin +LIB_EXPORT TPM_RC +CryptRsaEncrypt( + TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data + TPM2B *dIn, // IN: the data to encrypt + OBJECT *key, // IN: the key used for encryption + TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash + // if needed + const TPM2B *label, // IN: in case it is needed + RAND_STATE *rand // IN: random number generator + // state (mostly for testing) + ) +{ + TPM_RC retVal; + TPM2B_PUBLIC_KEY_RSA dataIn; + TPM2B_PUBLIC_KEY_RSA scratch; + size_t outlen; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md; + const char *digestname; + unsigned char *tmp = NULL; + // + // if the input and output buffers are the same, copy the input to a scratch + // buffer so that things don't get messed up. + if(dIn == &cOut->b) + { + MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer)); + dIn = &dataIn.b; + } + // All encryption schemes return the same size of data + pAssert(sizeof(cOut->t.buffer) >= key->publicArea.unique.rsa.t.size); + cOut->t.size = key->publicArea.unique.rsa.t.size; + TEST(scheme->scheme); + + retVal = InitOpenSSLRSAPublicKey(key, &pkey); + if (retVal != TPM_RC_SUCCESS) + return retVal; + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL || + EVP_PKEY_encrypt_init(ctx) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + switch(scheme->scheme) + { + case TPM_ALG_NULL: // 'raw' encryption + { + INT32 i; + INT32 dSize = dIn->size; + // dIn can have more bytes than cOut as long as the extra bytes + // are zero. Note: the more significant bytes of a number in a byte + // buffer are the bytes at the start of the array. + for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++); + dSize -= i; + scratch.t.size = cOut->t.size; + pAssert(scratch.t.size <= sizeof(scratch.t.buffer)); + if(dSize > scratch.t.size) + ERROR_RETURN(TPM_RC_VALUE); + // Pad cOut with zeros if dIn is smaller + memset(scratch.t.buffer, 0, scratch.t.size - dSize); + // And copy the rest of the value; value is then right-aligned + memcpy(&scratch.t.buffer[scratch.t.size - dSize], &dIn->buffer[i], dSize); + + dIn = &scratch.b; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + break; + case TPM_ALG_RSAES: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + break; + case TPM_ALG_OAEP: + digestname = GetDigestNameByHashAlg(scheme->details.oaep.hashAlg); + if (digestname == NULL) + ERROR_RETURN(TPM_RC_VALUE); + + md = EVP_get_digestbyname(digestname); + if (md == NULL || + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + if (label->size > 0) { + tmp = malloc(label->size); + if (tmp == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + memcpy(tmp, label->buffer, label->size); + } + // label->size == 0 is supported + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, tmp, label->size) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + tmp = NULL; + break; + default: + ERROR_RETURN(TPM_RC_SCHEME); + break; + } + + outlen = cOut->t.size; + + if (EVP_PKEY_encrypt(ctx, cOut->t.buffer, &outlen, + dIn->buffer, dIn->size) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + cOut->t.size = outlen; + + Exit: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + free(tmp); + + return retVal; +} + +LIB_EXPORT TPM_RC +CryptRsaDecrypt( + TPM2B *dOut, // OUT: the decrypted data + TPM2B *cIn, // IN: the data to decrypt + OBJECT *key, // IN: the key to use for decryption + TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme + const TPM2B *label // IN: in case it is needed for the scheme + ) +{ + TPM_RC retVal; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md = NULL; + const char *digestname; + size_t outlen; + unsigned char *tmp = NULL; + unsigned char buffer[MAX_RSA_KEY_BYTES]; + + // Make sure that the necessary parameters are provided + pAssert(cIn != NULL && dOut != NULL && key != NULL); + // Size is checked to make sure that the encrypted value is the right size + if(cIn->size != key->publicArea.unique.rsa.t.size) + ERROR_RETURN(TPM_RC_SIZE); + TEST(scheme->scheme); + + retVal = InitOpenSSLRSAPrivateKey(key, &pkey); + if (retVal != TPM_RC_SUCCESS) + return retVal; + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL || + EVP_PKEY_decrypt_init(ctx) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + switch(scheme->scheme) + { + case TPM_ALG_NULL: // 'raw' encryption + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + break; + case TPM_ALG_RSAES: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + break; + case TPM_ALG_OAEP: + digestname = GetDigestNameByHashAlg(scheme->details.oaep.hashAlg); + if (digestname == NULL) + ERROR_RETURN(TPM_RC_VALUE); + + md = EVP_get_digestbyname(digestname); + if (md == NULL || + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + if (label->size > 0) { + tmp = malloc(label->size); + if (tmp == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + memcpy(tmp, label->buffer, label->size); + + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, tmp, label->size) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + tmp = NULL; + } + break; + default: + ERROR_RETURN(TPM_RC_SCHEME); + break; + } + + /* cannot use cOut->buffer */ + outlen = sizeof(buffer); + if (EVP_PKEY_decrypt(ctx, buffer, &outlen, + cIn->buffer, cIn->size) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + if (outlen > dOut->size) + ERROR_RETURN(TPM_RC_FAILURE); + + memcpy(dOut->buffer, buffer, outlen); + dOut->size = outlen; + + retVal = TPM_RC_SUCCESS; + + Exit: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + free(tmp); + + return retVal; +} + +LIB_EXPORT TPM_RC +CryptRsaSign( + TPMT_SIGNATURE *sigOut, + OBJECT *key, // IN: key to use + TPM2B_DIGEST *hIn, // IN: the digest to sign + RAND_STATE *rand // IN: the random number generator + // to use (mostly for testing) + ) +{ + TPM_RC retVal = TPM_RC_SUCCESS; + UINT16 modSize; + size_t outlen; + int padding; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md; + const char *digestname; + TPMI_ALG_HASH hashAlg; + + // parameter checks + pAssert(sigOut != NULL && key != NULL && hIn != NULL); + modSize = key->publicArea.unique.rsa.t.size; + // for all non-null signatures, the size is the size of the key modulus + sigOut->signature.rsapss.sig.t.size = modSize; + TEST(sigOut->sigAlg); + + switch(sigOut->sigAlg) + { + case TPM_ALG_NULL: + sigOut->signature.rsapss.sig.t.size = 0; + return TPM_RC_SUCCESS; + case TPM_ALG_RSAPSS: + padding = RSA_PKCS1_PSS_PADDING; + hashAlg = sigOut->signature.rsapss.hash; + break; + case TPM_ALG_RSASSA: + padding = RSA_PKCS1_PADDING; + hashAlg = sigOut->signature.rsassa.hash; + break; + default: + ERROR_RETURN(TPM_RC_SCHEME); + } + + digestname = GetDigestNameByHashAlg(hashAlg); + if (digestname == NULL) + ERROR_RETURN(TPM_RC_VALUE); + + md = EVP_get_digestbyname(digestname); + if (md == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + + retVal = InitOpenSSLRSAPrivateKey(key, &pkey); + if (retVal != TPM_RC_SUCCESS) + return retVal; + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL || + EVP_PKEY_sign_init(ctx) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || + EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + /* careful with PSS padding: Use salt length = hash length (-1) if + * length(digest) + length(hash-to-sign) + 2 <= modSize + * otherwise use the max. possible salt length, which is the default (-2) + * test case: 1024 bit key PSS signing sha512 hash + */ + if (padding == RSA_PKCS1_PSS_PADDING && + EVP_MD_size(md) + hIn->b.size + 2 <= modSize && /* OSSL: RSA_padding_add_PKCS1_PSS_mgf1 */ + EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + outlen = sigOut->signature.rsapss.sig.t.size; + if (EVP_PKEY_sign(ctx, + sigOut->signature.rsapss.sig.t.buffer, &outlen, + hIn->b.buffer, hIn->b.size) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + sigOut->signature.rsapss.sig.t.size = outlen; + + Exit: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + + return retVal; +} + +LIB_EXPORT TPM_RC +CryptRsaValidateSignature( + TPMT_SIGNATURE *sig, // IN: signature + OBJECT *key, // IN: public modulus + TPM2B_DIGEST *digest // IN: The digest being validated + ) +{ + TPM_RC retVal; + int padding; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md; + const char *digestname; + + // + // Fatal programming errors + pAssert(key != NULL && sig != NULL && digest != NULL); + switch(sig->sigAlg) + { + case TPM_ALG_RSAPSS: + padding = RSA_PKCS1_PSS_PADDING; + break; + case TPM_ALG_RSASSA: + padding = RSA_PKCS1_PADDING; + break; + default: + return TPM_RC_SCHEME; + } + // Errors that might be caused by calling parameters + if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size) + ERROR_RETURN(TPM_RC_SIGNATURE); + TEST(sig->sigAlg); + + retVal = InitOpenSSLRSAPublicKey(key, &pkey); + if (retVal != TPM_RC_SUCCESS) + return retVal; + + digestname = GetDigestNameByHashAlg(sig->signature.any.hashAlg); + if (digestname == NULL) + ERROR_RETURN(TPM_RC_VALUE); + + md = EVP_get_digestbyname(digestname); + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (md == NULL || ctx == NULL || + EVP_PKEY_verify_init(ctx) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || + EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) + ERROR_RETURN(TPM_RC_FAILURE); + + if (EVP_PKEY_verify(ctx, + sig->signature.rsassa.sig.t.buffer, sig->signature.rsassa.sig.t.size, + digest->t.buffer, digest->t.size) <= 0) + ERROR_RETURN(TPM_RC_SIGNATURE); + + retVal = TPM_RC_SUCCESS; + + Exit: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + + return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS; +} +#endif // USE_OPENSSL_FUNCTIONS_RSA libtpms added end + +#endif // TPM_ALG_RSA diff --git a/src/tpm2/crypto/openssl/CryptSmac.c b/src/tpm2/crypto/openssl/CryptSmac.c new file mode 100644 index 0000000..c4b3515 --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptSmac.c @@ -0,0 +1,156 @@ +/********************************************************************************/ +/* */ +/* Message Authentication Codes Based on a Symmetric Block Cipher */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptSmac.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2018 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.20 CryptSmac.c */ +/* 10.2.20.1 Introduction */ +/* This file contains the implementation of the message authentication codes based on a symmetric + block cipher. These functions only use the single block encryption functions of the selected + symmetric cryptographic library. */ +/* 10.2.20.2 Includes, Defines, and Typedefs */ +#define _CRYPT_HASH_C_ +#include "Tpm.h" +#if SMAC_IMPLEMENTED + /* 10.2.20.2.1 CryptSmacStart() */ + /* Function to start an SMAC. */ +UINT16 +CryptSmacStart( + HASH_STATE *state, + TPMU_PUBLIC_PARMS *keyParameters, + TPM_ALG_ID macAlg, // IN: the type of MAC + TPM2B *key + ) +{ + UINT16 retVal = 0; + // + // Make sure that the key size is correct. This should have been checked + // at key load, but... + if(BITS_TO_BYTES(keyParameters->symDetail.sym.keyBits.sym) == key->size) + { + switch(macAlg) + { +#if ALG_CMAC + case TPM_ALG_CMAC: + retVal = CryptCmacStart(&state->state.smac, keyParameters, + macAlg, key); + break; +#endif + default: + break; + } + } + state->type = (retVal != 0) ? HASH_STATE_SMAC : HASH_STATE_EMPTY; + return retVal; +} +/* 10.2.20.2.2 CryptMacStart() */ +/* Function to start either an HMAC or an SMAC. Cannot reuse the CryptHmacStart() function because + of the difference in number of parameters. */ +UINT16 +CryptMacStart( + HMAC_STATE *state, + TPMU_PUBLIC_PARMS *keyParameters, + TPM_ALG_ID macAlg, // IN: the type of MAC + TPM2B *key + ) +{ + MemorySet(state, 0, sizeof(HMAC_STATE)); + if(CryptHashIsValidAlg(macAlg, FALSE)) + { + return CryptHmacStart(state, macAlg, key->size, key->buffer); + } + else if(CryptSmacIsValidAlg(macAlg, FALSE)) + { + return CryptSmacStart(&state->hashState, keyParameters, macAlg, key); + } + else + return 0; +} +/* 10.2.20.2.3 CryptMacEnd() */ +/* Dispatch to the MAC end function using a size and buffer pointer. */ +UINT16 +CryptMacEnd( + HMAC_STATE *state, + UINT32 size, + BYTE *buffer + ) +{ + UINT16 retVal = 0; + if(state->hashState.type == HASH_STATE_SMAC) + retVal = (state->hashState.state.smac.smacMethods.end)( + &state->hashState.state.smac.state, size, buffer); + else if(state->hashState.type == HASH_STATE_HMAC) + retVal = CryptHmacEnd(state, size, buffer); + state->hashState.type = HASH_STATE_EMPTY; + return retVal; +} +#if 0 /* libtpms added */ +/* 10.2.20.2.4 CryptMacEnd2B() */ +/* Dispatch to the MAC end function using a 2B. */ +UINT16 +CryptMacEnd2B ( + HMAC_STATE *state, + TPM2B *data + ) +{ + return CryptMacEnd(state, data->size, data->buffer); +} +#endif /* libtpms added */ +#endif // SMAC_IMPLEMENTED + diff --git a/src/tpm2/crypto/openssl/CryptSym.c b/src/tpm2/crypto/openssl/CryptSym.c new file mode 100644 index 0000000..c8a0497 --- /dev/null +++ b/src/tpm2/crypto/openssl/CryptSym.c @@ -0,0 +1,771 @@ +/********************************************************************************/ +/* */ +/* Symmetric block cipher modes */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: CryptSym.c 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 10.2.19 CryptSym.c */ +/* 10.2.19.1 Introduction */ +/* This file contains the implementation of the symmetric block cipher modes allowed for a + TPM. These functions only use the single block encryption functions of the selected symmetric + crypto library. */ + +/* 10.2.19.2 Includes, Defines, and Typedefs */ +#include "Tpm.h" +#include "CryptSym.h" +#include "Helpers_fp.h" // libtpms changed + + +#define KEY_BLOCK_SIZES(ALG, alg) \ + static const INT16 alg##KeyBlockSizes[] = { \ + ALG##_KEY_SIZES_BITS, -1, ALG##_BLOCK_SIZES }; + +FOR_EACH_SYM(KEY_BLOCK_SIZES) + +/* 10.2.19.3 Initialization and Data Access Functions */ +/* 10.2.19.3.1 CryptSymInit() */ +/* This function is called to do _TPM_Init() processing */ +BOOL +CryptSymInit( + void + ) +{ + return TRUE; +} +/* 10.2.19.3.2 CryptSymStartup() */ +/* This function is called to do TPM2_Startup() processing */ +BOOL +CryptSymStartup( + void + ) +{ + return TRUE; +} +/* 10.2.20.4 Data Access Functions */ +/* 10.2.20.4.1 CryptGetSymmetricBlockSize() */ +/* This function returns the block size of the algorithm. The table of bit sizes has an entry for + each allowed key size. The entry for a key size is 0 if the TPM does not implement that key + size. The key size table is delimited with a negative number (-1). After the delimiter is a list + of block sizes with each entry corresponding to the key bit size. For most symmetric algorithms, + the block size is the same regardless of the key size but this arrangement allows them to be + different. */ +/* Return Values Meaning */ +/* <= 0 cipher not supported */ +/* > 0 the cipher block size in bytes */ + +LIB_EXPORT INT16 +CryptGetSymmetricBlockSize( + TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm + UINT16 keySizeInBits // IN: the key size + ) +{ + const INT16 *sizes; + INT16 i; +#if 0 // libtpms added +#define ALG_CASE(SYM, sym) case TPM_ALG_##SYM: sizes = sym##KeyBlockSizes; break +#endif // libtpms added + switch(symmetricAlg) + { +#define GET_KEY_BLOCK_POINTER(SYM, sym) \ + case TPM_ALG_##SYM: \ + sizes = sym##KeyBlockSizes; \ + break; + // Get the pointer to the block size array + FOR_EACH_SYM(GET_KEY_BLOCK_POINTER); + + default: + return 0; + } + // Find the index of the indicated keySizeInBits + for(i = 0; *sizes >= 0; i++, sizes++) + { + if(*sizes == keySizeInBits) + break; + } + // If sizes is pointing at the end of the list of key sizes, then the desired + // key size was not found so set the block size to zero. + if(*sizes++ < 0) + return 0; + // Advance until the end of the list is found + while(*sizes++ >= 0); + // sizes is pointing to the first entry in the list of block sizes. Use the + // ith index to find the block size for the corresponding key size. + return sizes[i]; +} + +#if !USE_OPENSSL_FUNCTIONS_SYMMETRIC // libtpms added +/* 10.2.20.5 Symmetric Encryption */ +/* This function performs symmetric encryption based on the mode. */ +/* Error Returns Meaning */ +/* TPM_RC_SIZE dSize is not a multiple of the block size for an algorithm that requires it */ +/* TPM_RC_FAILURE Fatal error */ +LIB_EXPORT TPM_RC +CryptSymmetricEncrypt( + BYTE *dOut, // OUT: + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE *key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE *dIn // IN: data buffer + ) +{ + BYTE *pIv; + int i; + BYTE tmp[MAX_SYM_BLOCK_SIZE]; + BYTE *pT; + tpmCryptKeySchedule_t keySchedule; + INT16 blockSize; + TpmCryptSetSymKeyCall_t encrypt; + BYTE *iv; + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + // + memset(&keySchedule, 0, sizeof(keySchedule)); // libtpms added; coverity + pAssert(dOut != NULL && key != NULL && dIn != NULL); + if(dSize == 0) + return TPM_RC_SUCCESS; + TEST(algorithm); + blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); + if(blockSize == 0) + return TPM_RC_FAILURE; + // If the iv is provided, then it is expected to be block sized. In some cases, + // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] + // with no knowledge of the actual block size. This function will set it. + if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) + { + ivInOut->t.size = blockSize; + iv = ivInOut->t.buffer; + } + else + iv = defaultIv; + pIv = iv; + // Create encrypt key schedule and set the encryption function pointer. + switch (algorithm) + { + FOR_EACH_SYM(ENCRYPT_CASE) + + default: + return TPM_RC_SYMMETRIC; + } + switch(mode) + { +#if ALG_CTR + case TPM_ALG_CTR: + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the IV(counter) + ENCRYPT(&keySchedule, iv, tmp); + //increment the counter (counter is big-endian so start at end) + for(i = blockSize - 1; i >= 0; i--) + if((iv[i] += 1) != 0) + break; + // XOR the encrypted counter value with input and put into output + pT = tmp; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = *dIn++ ^ *pT++; + } + break; +#endif +#if ALG_OFB + case TPM_ALG_OFB: + // This is written so that dIn and dOut may be the same + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the "IV" + ENCRYPT(&keySchedule, iv, iv); + // XOR the encrypted IV into dIn to create the cipher text (dOut) + pIv = iv; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = (*pIv++ ^ *dIn++); + } + break; +#endif +#if ALG_CBC + case TPM_ALG_CBC: + // For CBC the data size must be an even multiple of the + // cipher block size + if((dSize % blockSize) != 0) + return TPM_RC_SIZE; + // XOR the data block into the IV, encrypt the IV into the IV + // and then copy the IV to the output + for(; dSize > 0; dSize -= blockSize) + { + pIv = iv; + for(i = blockSize; i > 0; i--) + *pIv++ ^= *dIn++; + ENCRYPT(&keySchedule, iv, iv); + pIv = iv; + for(i = blockSize; i > 0; i--) + *dOut++ = *pIv++; + } + break; +#endif + // CFB is not optional + case TPM_ALG_CFB: + // Encrypt the IV into the IV, XOR in the data, and copy to output + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the IV + ENCRYPT(&keySchedule, iv, iv); + pIv = iv; + for(i = (int)(dSize < blockSize) ? dSize : blockSize; i > 0; i--) + // XOR the data into the IV to create the cipher text + // and put into the output + *dOut++ = *pIv++ ^= *dIn++; + } + // If the inner loop (i loop) was smaller than blockSize, then dSize + // would have been smaller than blockSize and it is now negative. If + // it is negative, then it indicates how many bytes are needed to pad + // out the IV for the next round. + for(; dSize < 0; dSize++) + *pIv++ = 0; + break; +#if ALG_ECB + case TPM_ALG_ECB: + // For ECB the data size must be an even multiple of the + // cipher block size + if((dSize % blockSize) != 0) + return TPM_RC_SIZE; + // Encrypt the input block to the output block + for(; dSize > 0; dSize -= blockSize) + { + ENCRYPT(&keySchedule, dIn, dOut); + dIn = &dIn[blockSize]; + dOut = &dOut[blockSize]; + } + break; +#endif + default: + return TPM_RC_FAILURE; + } + return TPM_RC_SUCCESS; +} +/* 10.2.20.5.1 CryptSymmetricDecrypt() */ +/* This function performs symmetric decryption based on the mode. */ +/* Error Returns Meaning */ +/* TPM_RC_FAILURE A fatal error */ +/* TPM_RCS_SIZE dSize is not a multiple of the block size for an algorithm that requires it */ +LIB_EXPORT TPM_RC +CryptSymmetricDecrypt( + BYTE *dOut, // OUT: decrypted data + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE *key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE *dIn // IN: data buffer + ) +{ + BYTE *pIv; + int i; + BYTE tmp[MAX_SYM_BLOCK_SIZE]; + BYTE *pT; + tpmCryptKeySchedule_t keySchedule; + INT16 blockSize; + BYTE *iv; + TpmCryptSetSymKeyCall_t encrypt; + TpmCryptSetSymKeyCall_t decrypt; + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + + memset(&keySchedule, 0, sizeof(keySchedule)); // libtpms added; coverity + // These are used but the compiler can't tell because they are initialized + // in case statements and it can't tell if they are always initialized + // when needed, so... Comment these out if the compiler can tell or doesn't + // care that these are initialized before use. + encrypt = NULL; + decrypt = NULL; + pAssert(dOut != NULL && key != NULL && dIn != NULL); + if(dSize == 0) + return TPM_RC_SUCCESS; + TEST(algorithm); + blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); + if(blockSize == 0) + return TPM_RC_FAILURE; + // If the iv is provided, then it is expected to be block sized. In some cases, + // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] + // with no knowledge of the actual block size. This function will set it. + if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) + { + ivInOut->t.size = blockSize; + iv = ivInOut->t.buffer; + } + else + iv = defaultIv; + pIv = iv; + // Use the mode to select the key schedule to create. Encrypt always uses the + // encryption schedule. Depending on the mode, decryption might use either + // the decryption or encryption schedule. + switch(mode) + { +#if ALG_CBC || ALG_ECB + case TPM_ALG_CBC: // decrypt = decrypt + case TPM_ALG_ECB: + // For ECB and CBC, the data size must be an even multiple of the + // cipher block size + if((dSize % blockSize) != 0) + return TPM_RC_SIZE; + switch (algorithm) + { + FOR_EACH_SYM(DECRYPT_CASE) + default: + return TPM_RC_SYMMETRIC; + } + break; +#endif + default: + // For the remaining stream ciphers, use encryption to decrypt + switch (algorithm) + { + FOR_EACH_SYM(ENCRYPT_CASE) + default: + return TPM_RC_SYMMETRIC; + } + } + // Now do the mode-dependent decryption + switch(mode) + { +#if ALG_CBC + case TPM_ALG_CBC: + // Copy the input data to a temp buffer, decrypt the buffer into the + // output, XOR in the IV, and copy the temp buffer to the IV and repeat. + for(; dSize > 0; dSize -= blockSize) + { + pT = tmp; + for(i = blockSize; i > 0; i--) + *pT++ = *dIn++; + DECRYPT(&keySchedule, tmp, dOut); + pIv = iv; + pT = tmp; + for(i = blockSize; i > 0; i--) + { + *dOut++ ^= *pIv; + *pIv++ = *pT++; + } + } + break; +#endif + case TPM_ALG_CFB: + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the IV into the temp buffer + ENCRYPT(&keySchedule, iv, tmp); + pT = tmp; + pIv = iv; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + // Copy the current cipher text to IV, XOR + // with the temp buffer and put into the output + *dOut++ = *pT++ ^ (*pIv++ = *dIn++); + } + // If the inner loop (i loop) was smaller than blockSize, then dSize + // would have been smaller than blockSize and it is now negative + // If it is negative, then it indicates how may fill bytes + // are needed to pad out the IV for the next round. + for(; dSize < 0; dSize++) + *pIv++ = 0; + break; +#if ALG_CTR + case TPM_ALG_CTR: + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the IV(counter) + ENCRYPT(&keySchedule, iv, tmp); + //increment the counter (counter is big-endian so start at end) + for(i = blockSize - 1; i >= 0; i--) + if((iv[i] += 1) != 0) + break; + // XOR the encrypted counter value with input and put into output + pT = tmp; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = *dIn++ ^ *pT++; + } + break; +#endif +#if ALG_ECB + case TPM_ALG_ECB: + for(; dSize > 0; dSize -= blockSize) + { + DECRYPT(&keySchedule, dIn, dOut); + dIn = &dIn[blockSize]; + dOut = &dOut[blockSize]; + } + break; +#endif +#if ALG_OFB + case TPM_ALG_OFB: + // This is written so that dIn and dOut may be the same + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the "IV" + ENCRYPT(&keySchedule, iv, iv); + // XOR the encrypted IV into dIn to create the cipher text (dOut) + pIv = iv; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = (*pIv++ ^ *dIn++); + } + break; +#endif + default: + return TPM_RC_FAILURE; + } + return TPM_RC_SUCCESS; +} + +#else // libtpms added begin + +#if ALG_TDES && ALG_CTR +// Emulated TDES Counter mode since OpenSSL does not implement it +static void TDES_CTR(const BYTE *key, // IN + INT32 keySizeInBits, // IN + INT32 dSize, // IN + const BYTE *dIn, // IN + BYTE *iv, // IN + BYTE *dOut, // OUT + INT16 blockSize // IN + ) +{ + tpmCryptKeySchedule_t keySchedule; + int i; + BYTE tmp[MAX_SYM_BLOCK_SIZE]; + BYTE *pT; + + TDES_set_encrypt_key(key, keySizeInBits, + (tpmKeyScheduleTDES *)&keySchedule.tdes); + + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the IV(counter) + TDES_encrypt(iv, tmp, (tpmKeyScheduleTDES *)&keySchedule.tdes); + //increment the counter (counter is big-endian so start at end) + for(i = blockSize - 1; i >= 0; i--) + if((iv[i] += 1) != 0) + break; + // XOR the encrypted counter value with input and put into output + pT = tmp; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = *dIn++ ^ *pT++; + } +} +#endif + +/* 10.2.20.5 Symmetric Encryption */ +/* This function performs symmetric encryption based on the mode. */ +/* Error Returns Meaning */ +/* TPM_RC_SIZE dSize is not a multiple of the block size for an algorithm that requires it */ +/* TPM_RC_FAILURE Fatal error */ +LIB_EXPORT TPM_RC +CryptSymmetricEncrypt( + BYTE *dOut, // OUT: + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE *key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE *dIn // IN: data buffer + ) +{ + INT16 blockSize; + BYTE *iv; + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + evpfunc evpfn; + EVP_CIPHER_CTX *ctx = NULL; + int outlen1 = 0; + int outlen2 = 0; + BYTE *pOut = dOut; + BYTE *buffer = NULL; // for in-place encryption + UINT32 buffersize = 0; + BYTE keyToUse[MAX_SYM_KEY_BYTES]; + UINT16 keyToUseLen = (UINT16)sizeof(keyToUse); + TPM_RC retVal = TPM_RC_SUCCESS; + int ivLen; + + pAssert(dOut != NULL && key != NULL && dIn != NULL); + if(dSize == 0) + return TPM_RC_SUCCESS; + TEST(algorithm); + blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); + if(blockSize == 0) + return TPM_RC_FAILURE; + // If the iv is provided, then it is expected to be block sized. In some cases, + // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] + // with no knowledge of the actual block size. This function will set it. + if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) + { + ivInOut->t.size = blockSize; + iv = ivInOut->t.buffer; + } + else + iv = defaultIv; + + switch (mode) + { + case TPM_ALG_ECB: + case TPM_ALG_CBC: + // For ECB & CBC the data size must be an even multiple of the + // cipher block size + if((dSize % blockSize) != 0) + return TPM_RC_SIZE; + } + + evpfn = GetEVPCipher(algorithm, keySizeInBits, mode, key, + keyToUse, &keyToUseLen); + if (evpfn == NULL) + return TPM_RC_FAILURE; + + if (dIn == dOut) { + // in-place encryption; we use a temp buffer + buffersize = TPM2_ROUNDUP(dSize, blockSize); + buffer = malloc(buffersize); + if (buffer == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + + pOut = buffer; + } + +#if ALG_TDES && ALG_CTR + if (algorithm == TPM_ALG_TDES && mode == TPM_ALG_CTR) { + TDES_CTR(keyToUse, keyToUseLen * 8, dSize, dIn, iv, pOut, blockSize); + outlen1 = dSize; + ERROR_RETURN(TPM_RC_SUCCESS); + } +#endif + + ctx = EVP_CIPHER_CTX_new(); + if (!ctx || + EVP_EncryptInit_ex(ctx, evpfn(), NULL, keyToUse, iv) != 1 || + EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 || + EVP_EncryptUpdate(ctx, pOut, &outlen1, dIn, dSize) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + pAssert(outlen1 <= dSize || dSize >= outlen1 + blockSize); + + if (EVP_EncryptFinal_ex(ctx, pOut + outlen1, &outlen2) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + if (ivInOut) { + ivLen = EVP_CIPHER_CTX_iv_length(ctx); + if (ivLen < 0 || (size_t)ivLen > sizeof(ivInOut->t.buffer)) + ERROR_RETURN(TPM_RC_FAILURE); + + ivInOut->t.size = ivLen; + memcpy(ivInOut->t.buffer, EVP_CIPHER_CTX_iv(ctx), ivInOut->t.size); + } + Exit: + if (retVal == TPM_RC_SUCCESS && pOut != dOut) + memcpy(dOut, pOut, outlen1 + outlen2); + + clear_and_free(buffer, buffersize); + EVP_CIPHER_CTX_free(ctx); + + return retVal; +} + +/* 10.2.20.5.1 CryptSymmetricDecrypt() */ +/* This function performs symmetric decryption based on the mode. */ +/* Error Returns Meaning */ +/* TPM_RC_FAILURE A fatal error */ +/* TPM_RCS_SIZE dSize is not a multiple of the block size for an algorithm that requires it */ +LIB_EXPORT TPM_RC +CryptSymmetricDecrypt( + BYTE *dOut, // OUT: decrypted data + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE *key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE *dIn // IN: data buffer + ) +{ + INT16 blockSize; + BYTE *iv; + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + evpfunc evpfn; + EVP_CIPHER_CTX *ctx = NULL; + int outlen1 = 0; + int outlen2 = 0; + BYTE *buffer; + UINT32 buffersize = 0; + BYTE keyToUse[MAX_SYM_KEY_BYTES]; + UINT16 keyToUseLen = (UINT16)sizeof(keyToUse); + TPM_RC retVal = TPM_RC_SUCCESS; + int ivLen; + + // These are used but the compiler can't tell because they are initialized + // in case statements and it can't tell if they are always initialized + // when needed, so... Comment these out if the compiler can tell or doesn't + // care that these are initialized before use. + pAssert(dOut != NULL && key != NULL && dIn != NULL); + if(dSize == 0) + return TPM_RC_SUCCESS; + TEST(algorithm); + blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); + if(blockSize == 0) + return TPM_RC_FAILURE; + // If the iv is provided, then it is expected to be block sized. In some cases, + // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] + // with no knowledge of the actual block size. This function will set it. + if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) + { + ivInOut->t.size = blockSize; + iv = ivInOut->t.buffer; + } + else + iv = defaultIv; + + switch(mode) + { +#if ALG_CBC || ALG_ECB + case TPM_ALG_CBC: + case TPM_ALG_ECB: + // For ECB and CBC, the data size must be an even multiple of the + // cipher block size + if((dSize % blockSize) != 0) + return TPM_RC_SIZE; + break; +#endif + default: + break; + } + + evpfn = GetEVPCipher(algorithm, keySizeInBits, mode, key, + keyToUse, &keyToUseLen); + if (evpfn == NULL) + return TPM_RC_FAILURE; + + /* a buffer with a 'safety margin' for EVP_DecryptUpdate */ + buffersize = TPM2_ROUNDUP(dSize + blockSize, blockSize); + buffer = malloc(buffersize); + if (buffer == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + +#if ALG_TDES && ALG_CTR + if (algorithm == TPM_ALG_TDES && mode == TPM_ALG_CTR) { + TDES_CTR(keyToUse, keyToUseLen * 8, dSize, dIn, iv, buffer, blockSize); + outlen1 = dSize; + ERROR_RETURN(TPM_RC_SUCCESS); + } +#endif + + ctx = EVP_CIPHER_CTX_new(); + if (!ctx || + EVP_DecryptInit_ex(ctx, evpfn(), NULL, keyToUse, iv) != 1 || + EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 || + EVP_DecryptUpdate(ctx, buffer, &outlen1, dIn, dSize) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + pAssert((int)buffersize >= outlen1); + + if ((int)buffersize <= outlen1 /* coverity */ || + EVP_DecryptFinal(ctx, &buffer[outlen1], &outlen2) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + pAssert((int)buffersize >= outlen1 + outlen2); + + if (ivInOut) { + ivLen = EVP_CIPHER_CTX_iv_length(ctx); + if (ivLen < 0 || (size_t)ivLen > sizeof(ivInOut->t.buffer)) + ERROR_RETURN(TPM_RC_FAILURE); + + ivInOut->t.size = ivLen; + memcpy(ivInOut->t.buffer, EVP_CIPHER_CTX_iv(ctx), ivInOut->t.size); + } + + Exit: + if (retVal == TPM_RC_SUCCESS) { + pAssert(dSize >= outlen1 + outlen2); + memcpy(dOut, buffer, outlen1 + outlen2); + } + + clear_and_free(buffer, buffersize); + EVP_CIPHER_CTX_free(ctx); + + return retVal; +} + +#endif // libtpms added end + +/* 10.2.20.5.2 CryptSymKeyValidate() */ +/* Validate that a provided symmetric key meets the requirements of the TPM */ +/* Error Returns Meaning */ +/* TPM_RC_KEY_SIZE Key size specifiers do not match */ +/* TPM_RC_KEY Key is not allowed */ +TPM_RC +CryptSymKeyValidate( + TPMT_SYM_DEF_OBJECT *symDef, + TPM2B_SYM_KEY *key + ) +{ + if(key->t.size != BITS_TO_BYTES(symDef->keyBits.sym)) + return TPM_RCS_KEY_SIZE; +#if ALG_TDES + if(symDef->algorithm == TPM_ALG_TDES && !CryptDesValidateKey(key)) + return TPM_RCS_KEY; +#endif // TPM_ALG_TDES + return TPM_RC_SUCCESS; +} diff --git a/src/tpm2/crypto/openssl/ExpDCache.c b/src/tpm2/crypto/openssl/ExpDCache.c new file mode 100644 index 0000000..5aeaf14 --- /dev/null +++ b/src/tpm2/crypto/openssl/ExpDCache.c @@ -0,0 +1,200 @@ +/********************************************************************************/ +/* */ +/* Private Exponent D cache functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp., 2021 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "ExpDCache_fp.h" + +/* Implement a cache for the private exponent D so it doesn't need to be + * recalculated every time from P, Q, E and N (modulus). The cache has a + * number of entries that cache D and use P, Q, and E for lookup. + * A least-recently-used cache eviction strategy is implemented that evicts + * the oldest cache entry in case space is needed. An entry is young once + * it is added or made young when it was found via lookup. All other entries + * age by '1' when an entry is added or accessed. + */ + +struct ExpDCacheEntry { + /* The age of the entry; the higher the number the more likely it + * will be evicted soon + */ + unsigned int age; + BIGNUM *P; /* input */ + BIGNUM *N; /* input */ + BIGNUM *E; /* input */ + BIGNUM *Q; /* cached */ + BIGNUM *D; /* cached */ +}; + +#define DCACHE_NUM_ENTRIES 64 + +static struct ExpDCacheEntry ExpDCache[DCACHE_NUM_ENTRIES]; + +/* Increment the age of all cache entries that have a current age <= maxage */ +static void ExpDCacheIncrementAge(unsigned maxage) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { + if (ExpDCache[i].age <= maxage && ExpDCache[i].D != NULL) + ExpDCache[i].age++; + } +} + +/* Free the data associated with a ExpDCacheEntry and initialize it */ +static void ExpDCacheEntryFree(struct ExpDCacheEntry *dce) +{ + BN_clear_free(dce->P); + BN_free(dce->N); + BN_free(dce->E); + BN_clear_free(dce->Q); + BN_clear_free(dce->D); + memset(dce, 0, sizeof(*dce)); +} + +void ExpDCacheFree(void) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) + ExpDCacheEntryFree(&ExpDCache[i]); +} + +/* Get a ExpDCacheEntry by finding either an unused entry or evicting the oldest + * entry. The returned entry will have all NULL pointers and age 0. + */ +static struct ExpDCacheEntry *ExpDCacheEntryGet(void) +{ + size_t i, use_i = 0; + unsigned oldest_age = 0; + struct ExpDCacheEntry *dce; + + for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { + if (ExpDCache[i].D == NULL) { + /* use this free entry */ + use_i = i; + break; + } + if (ExpDCache[i].age > oldest_age) { + /* this one is currently the oldest */ + use_i = i; + oldest_age = ExpDCache[i].age; + } + } + dce = &ExpDCache[use_i]; + + ExpDCacheEntryFree(dce); + + return dce; +} + +/* Add 'D' to the ExpDCache. This function does not check for duplicates */ +void ExpDCacheAdd(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, + const BIGNUM *Q, const BIGNUM *D) +{ + struct ExpDCacheEntry *dce = ExpDCacheEntryGet(); + + /* age of 'dce' is '0' */ + dce->P = BN_dup(P); + dce->N = BN_dup(N); + dce->E = BN_dup(E); + dce->Q = BN_dup(Q); + dce->D = BN_dup(D); + + if (!dce->P || !dce->N || !dce->E || !dce->Q || !dce->D) + ExpDCacheEntryFree(dce); + else + ExpDCacheIncrementAge(~0); +} + +BIGNUM *ExpDCacheFind(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, BIGNUM **Q) +{ + size_t i; + unsigned myage; + BIGNUM *D; + + for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { + if (BN_cmp(ExpDCache[i].P, P) == 0 && BN_cmp(ExpDCache[i].N, N) == 0 && + BN_cmp(ExpDCache[i].E, E) == 0) { + /* entry found */ + myage = ExpDCache[i].age; + /* mark this entry as most recently used */ + ExpDCache[i].age = 0; + /* Increment everyone who is <= 'myage'. + * The age of this entry will be '1' after that. + */ + ExpDCacheIncrementAge(myage); + + *Q = BN_dup(ExpDCache[i].Q); + if (*Q == NULL) + return NULL; + D = BN_dup(ExpDCache[i].D); + if (D == NULL) { + BN_clear_free(*Q); + *Q = NULL; + return NULL; + } + BN_set_flags(*Q, BN_FLG_CONSTTIME); + BN_set_flags(D, BN_FLG_CONSTTIME); + return D; + } + } + + return NULL; +} diff --git a/src/tpm2/crypto/openssl/ExpDCache_fp.h b/src/tpm2/crypto/openssl/ExpDCache_fp.h new file mode 100644 index 0000000..b8ee9d7 --- /dev/null +++ b/src/tpm2/crypto/openssl/ExpDCache_fp.h @@ -0,0 +1,75 @@ +/********************************************************************************/ +/* */ +/* Private Exponent D cache functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp., 2021 */ +/* */ +/********************************************************************************/ + +#ifndef DCACHE_FP_H +#define DCACHE_FP_H + +#include + +BIGNUM *ExpDCacheFind(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, + BIGNUM **Q); + +void ExpDCacheAdd(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, + const BIGNUM *Q, const BIGNUM *D); + +void ExpDCacheFree(void); + +#endif /* DCACHE_FP_H */ + diff --git a/src/tpm2/crypto/openssl/Helpers.c b/src/tpm2/crypto/openssl/Helpers.c new file mode 100644 index 0000000..f47cdbf --- /dev/null +++ b/src/tpm2/crypto/openssl/Helpers.c @@ -0,0 +1,625 @@ +/********************************************************************************/ +/* */ +/* OpenSSL helper functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "ExpDCache_fp.h" +#include "Helpers_fp.h" +#include "TpmToOsslMath_fp.h" + +#include "config.h" + +#include +#include + +/* to enable RSA_check_key() on private keys set to != 0 */ +#ifndef DO_RSA_CHECK_KEY +#define DO_RSA_CHECK_KEY 0 +#endif + +#if USE_OPENSSL_FUNCTIONS_SYMMETRIC + +TPM_RC +OpenSSLCryptGenerateKeyDes( + TPMT_SENSITIVE *sensitive // OUT: sensitive area + ) +{ + DES_cblock *key; + size_t offset; + size_t limit; + + limit = MIN(sizeof(sensitive->sensitive.sym.t.buffer), + sensitive->sensitive.sym.t.size); + limit = TPM2_ROUNDUP(limit, sizeof(*key)); + pAssert(limit < sizeof(sensitive->sensitive.sym.t.buffer)); + + for (offset = 0; offset < limit; offset += sizeof(*key)) { + key = (DES_cblock *)&sensitive->sensitive.sym.t.buffer[offset]; + if (DES_random_key(key) != 1) + return TPM_RC_NO_RESULT; + } + return TPM_RC_SUCCESS; +} + +evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN + UINT16 keySizeInBits, // IN + TPM_ALG_ID mode, // IN + const BYTE *key, // IN + BYTE *keyToUse, // OUT same as key or stretched key + UINT16 *keyToUseLen // IN/OUT + ) +{ + int i; + UINT16 keySizeInBytes = keySizeInBits / 8; + evpfunc evpfn = NULL; + + // key size to array index: 128 -> 0, 192 -> 1, 256 -> 2 + i = (keySizeInBits >> 6) - 2; + if (i < 0 || i > 2) + return NULL; + + pAssert(*keyToUseLen >= keySizeInBytes) + memcpy(keyToUse, key, keySizeInBytes); + + switch (algorithm) { +#if ALG_AES + case TPM_ALG_AES: + *keyToUseLen = keySizeInBytes; + switch (mode) { +#if ALG_CTR + case TPM_ALG_CTR: + evpfn = (evpfunc []){EVP_aes_128_ctr, EVP_aes_192_ctr, + EVP_aes_256_ctr}[i]; + break; +#endif +#if ALG_OFB + case TPM_ALG_OFB: + evpfn = (evpfunc[]){EVP_aes_128_ofb, EVP_aes_192_ofb, + EVP_aes_256_ofb}[i]; + break; +#endif +#if ALG_CBC + case TPM_ALG_CBC: + evpfn = (evpfunc[]){EVP_aes_128_cbc, EVP_aes_192_cbc, + EVP_aes_256_cbc}[i]; + break; +#endif +#if ALG_CFB + case TPM_ALG_CFB: + evpfn = (evpfunc[]){EVP_aes_128_cfb, EVP_aes_192_cfb, + EVP_aes_256_cfb}[i]; + break; +#endif +#if ALG_ECB + case TPM_ALG_ECB: + evpfn = (evpfunc[]){EVP_aes_128_ecb, EVP_aes_192_ecb, + EVP_aes_256_ecb}[i]; + break; +#endif + } + break; +#endif +#if ALG_TDES + case TPM_ALG_TDES: + if (keySizeInBits == 128) { + pAssert(*keyToUseLen >= BITS_TO_BYTES(192)) + // stretch the key + memcpy(&keyToUse[16], &keyToUse[0], 8); + *keyToUseLen = BITS_TO_BYTES(192); + } + + switch (mode) { +#if ALG_CTR + case TPM_ALG_CTR: + evpfn = (evpfunc[]){EVP_des_ede3, EVP_des_ede3, NULL}[i]; + break; +#endif +#if ALG_OFB + case TPM_ALG_OFB: + evpfn = (evpfunc[]){EVP_des_ede3_ofb, EVP_des_ede3_ofb, NULL}[i]; + break; +#endif +#if ALG_CBC + case TPM_ALG_CBC: + evpfn = (evpfunc[]){EVP_des_ede3_cbc, EVP_des_ede3_cbc, NULL}[i]; + break; +#endif +#if ALG_CFB + case TPM_ALG_CFB: + evpfn = (evpfunc[]){EVP_des_ede3_cfb64, EVP_des_ede3_cfb64, NULL}[i]; + break; +#endif +#if ALG_ECB + case TPM_ALG_ECB: + evpfn = (evpfunc[]){EVP_des_ede3_ecb, EVP_des_ede3_ecb, NULL}[i]; + break; +#endif + } + break; +#endif + +#if ALG_SM4 + case TPM_ALG_SM4: + *keyToUseLen = keySizeInBytes; + switch (mode) { +#if ALG_CTR + case TPM_ALG_CTR: + evpfn = (evpfunc[]){EVP_sm4_ctr, NULL, NULL}[i]; + break; +#endif +#if ALG_OFB + case TPM_ALG_OFB: + evpfn = (evpfunc[]){EVP_sm4_ofb, NULL, NULL}[i]; + break; +#endif +#if ALG_CBC + case TPM_ALG_CBC: + evpfn = (evpfunc[]){EVP_sm4_cbc, NULL, NULL}[i]; + break; +#endif +#if ALG_CFB + case TPM_ALG_CFB: + evpfn = (evpfunc[]){EVP_sm4_cfb, NULL, NULL}[i]; + break; +#endif +#if ALG_ECB + case TPM_ALG_ECB: + evpfn = (evpfunc[]){EVP_sm4_ecb, NULL, NULL}[i]; + break; +#endif + } + break; +#endif + +#if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + *keyToUseLen = keySizeInBytes; + switch (mode) { +#if ALG_CTR + case TPM_ALG_CTR: + evpfn = (evpfunc []){EVP_camellia_128_ctr, EVP_camellia_192_ctr, + EVP_camellia_256_ctr}[i]; + break; +#endif +#if ALG_OFB + case TPM_ALG_OFB: + evpfn = (evpfunc[]){EVP_camellia_128_ofb, EVP_camellia_192_ofb, + EVP_camellia_256_ofb}[i]; + break; +#endif +#if ALG_CBC + case TPM_ALG_CBC: + evpfn = (evpfunc[]){EVP_camellia_128_cbc, EVP_camellia_192_cbc, + EVP_camellia_256_cbc}[i]; + break; +#endif +#if ALG_CFB + case TPM_ALG_CFB: + evpfn = (evpfunc[]){EVP_camellia_128_cfb, EVP_camellia_192_cfb, + EVP_camellia_256_cfb}[i]; + break; +#endif +#if ALG_ECB + case TPM_ALG_ECB: + evpfn = (evpfunc[]){EVP_camellia_128_ecb, EVP_camellia_192_ecb, + EVP_camellia_256_ecb}[i]; + break; +#endif + } + break; +#endif + } + + if (evpfn == NULL) + MemorySet(keyToUse, 0, *keyToUseLen); + + return evpfn; +} + +#endif // USE_OPENSSL_FUNCTIONS_SYMMETRIC + +#if USE_OPENSSL_FUNCTIONS_EC +BOOL +OpenSSLEccGetPrivate( + bigNum dOut, // OUT: the qualified random value + const EC_GROUP *G, // IN: the EC_GROUP to use + const UINT32 requestedBits // IN: if not 0, then dOut must have that many bits + ) +{ + BOOL OK = FALSE; + const BIGNUM *D; + EC_KEY *eckey = EC_KEY_new(); + UINT32 requestedBytes = BITS_TO_BYTES(requestedBits); + int repeats = 0; + int maxRepeats; + int numBytes; + + pAssert(G != NULL); + + if (!eckey) + return FALSE; + + if (EC_KEY_set_group(eckey, G) != 1) + goto Exit; + + maxRepeats = 8; + // non-byte boundary order'ed curves, like NIST P521, need more loops to + // have a result with topmost byte != 0 + if (requestedBits & 7) + maxRepeats += (9 - (requestedBits & 7)); + + while (true) { + if (EC_KEY_generate_key(eckey) == 1) { + D = EC_KEY_get0_private_key(eckey); + // if we need a certain amount of bytes and we are below a threshold + // of loops, check the number of bytes we have, otherwise take the + // result + if ((requestedBytes != 0) && (repeats < maxRepeats)) { + numBytes = BN_num_bytes(D); + if ((int)requestedBytes != numBytes) { + // result does not have enough bytes + repeats++; + continue; + } + // result is sufficient + } + OK = TRUE; + OsslToTpmBn(dOut, D); + } + break; + } + + Exit: + EC_KEY_free(eckey); + + return OK; +} +#endif // USE_OPENSSL_FUNCTIONS_EC + +#if USE_OPENSSL_FUNCTIONS_RSA + +static const struct hnames { + const char *name; + TPM_ALG_ID hashAlg; +} hnames[HASH_COUNT + 1] = { + { +#if ALG_SHA1 + .name = "sha1", + .hashAlg = ALG_SHA1_VALUE, + }, { +#endif +#if ALG_SHA256 + .name = "sha256", + .hashAlg = ALG_SHA256_VALUE, + }, { +#endif +#if ALG_SHA384 + .name = "sha384", + .hashAlg = ALG_SHA384_VALUE, + }, { +#endif +#if ALG_SHA512 + .name = "sha512", + .hashAlg = ALG_SHA512_VALUE, + }, { +#endif + .name = NULL, + } +}; +#if HASH_COUNT != ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA512 +# error Missing entry in hnames array! +#endif + +LIB_EXPORT const char * +GetDigestNameByHashAlg(const TPM_ALG_ID hashAlg) +{ + unsigned i; + + for (i = 0; i < HASH_COUNT; i++) { + if (hashAlg == hnames[i].hashAlg) + return hnames[i].name; + } + return NULL; +} + +static BOOL +ComputePrivateExponentD( + const BIGNUM *P, // IN: first prime (size is 1/2 of bnN) + const BIGNUM *Q, // IN: second prime (size is 1/2 of bnN) + const BIGNUM *E, // IN: the public exponent + const BIGNUM *N, // IN: the public modulus + BIGNUM **D // OUT: + ) +{ + BOOL pOK = FALSE; + BIGNUM *phi; + BN_CTX *ctx; + // + // compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1 + phi = BN_dup(N); + ctx = BN_CTX_new(); + if (phi && ctx) { + pOK = BN_sub(phi, phi, P); + pOK = pOK && BN_sub(phi, phi, Q); + pOK = pOK && BN_add_word(phi, 1); + // Compute the multiplicative inverse d = 1/e mod Phi + BN_set_flags(phi, BN_FLG_CONSTTIME); // phi is secret + pOK = pOK && (*D = BN_mod_inverse(NULL, E, phi, ctx)) != NULL; + } + BN_CTX_free(ctx); + BN_clear_free(phi); + + return pOK; +} + +LIB_EXPORT TPM_RC +InitOpenSSLRSAPublicKey(OBJECT *key, // IN + EVP_PKEY **pkey // OUT + ) +{ + TPM_RC retVal; + RSA *rsakey = RSA_new(); + BIGNUM *N = NULL; + BIGNUM *E = BN_new(); + BN_ULONG eval; + + *pkey = EVP_PKEY_new(); + + if (rsakey == NULL || *pkey == NULL || E == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + + if(key->publicArea.parameters.rsaDetail.exponent != 0) + eval = key->publicArea.parameters.rsaDetail.exponent; + else + eval = RSA_DEFAULT_PUBLIC_EXPONENT; + + if (BN_set_word(E, eval) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + N = BN_bin2bn(key->publicArea.unique.rsa.b.buffer, + key->publicArea.unique.rsa.b.size, NULL); + if (N == NULL || + RSA_set0_key(rsakey, N, E, NULL) != 1 || + EVP_PKEY_assign_RSA(*pkey, rsakey) == 0) + ERROR_RETURN(TPM_RC_FAILURE) + + RSA_set_flags(rsakey, RSA_FLAG_NO_BLINDING); + + retVal = TPM_RC_SUCCESS; + + Exit: + if (retVal != TPM_RC_SUCCESS) { + RSA_free(rsakey); + EVP_PKEY_free(*pkey); + *pkey = NULL; + } + + return retVal; +} + +static void DoRSACheckKey(const BIGNUM *P, const BIGNUM *Q, const BIGNUM *N, + const BIGNUM *E, const BIGNUM *D) +{ + RSA *mykey; + static int disp; + + if (!DO_RSA_CHECK_KEY) + return; + if (!disp) { + fprintf(stderr, "RSA key checking is enabled\n"); + disp = 1; + } + + mykey = RSA_new(); + RSA_set0_factors(mykey, BN_dup(P), BN_dup(Q)); + RSA_set0_key(mykey, BN_dup(N), BN_dup(E), BN_dup(D)); + if (RSA_check_key(mykey) != 1) { + fprintf(stderr, "Detected bad RSA key. STOP.\n"); + while (1); + } + RSA_free(mykey); +} + +LIB_EXPORT TPM_RC +InitOpenSSLRSAPrivateKey(OBJECT *rsaKey, // IN + EVP_PKEY **pkey // OUT + ) +{ + const BIGNUM *N = NULL; + const BIGNUM *E = NULL; + BIGNUM *P = NULL; + BIGNUM *Q = NULL; + BIGNUM *Qr = NULL; + BIGNUM *D = NULL; +#if CRT_FORMAT_RSA == YES + BIGNUM *dP = BN_new(); + BIGNUM *dQ = BN_new(); + BIGNUM *qInv = BN_new(); +#endif + RSA *key = NULL; + BN_CTX *ctx = NULL; + TPM_RC retVal = InitOpenSSLRSAPublicKey(rsaKey, pkey); + + if (retVal != TPM_RC_SUCCESS) + return retVal; + + if(!rsaKey->attributes.privateExp) + CryptRsaLoadPrivateExponent(rsaKey); + + P = BN_bin2bn(rsaKey->sensitive.sensitive.rsa.t.buffer, + rsaKey->sensitive.sensitive.rsa.t.size, NULL); + if (P == NULL) + ERROR_RETURN(TPM_RC_FAILURE) + + key = EVP_PKEY_get1_RSA(*pkey); + if (key == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + RSA_get0_key(key, &N, &E, NULL); + + D = ExpDCacheFind(P, N, E, &Q); + if (D == NULL) { + ctx = BN_CTX_new(); + Q = BN_new(); + Qr = BN_new(); + if (ctx == NULL || Q == NULL || Qr == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + /* Q = N/P; no remainder */ + BN_set_flags(P, BN_FLG_CONSTTIME); // P is secret + BN_div(Q, Qr, N, P, ctx); + if(!BN_is_zero(Qr)) + ERROR_RETURN(TPM_RC_BINDING); + BN_set_flags(Q, BN_FLG_CONSTTIME); // Q is secret + + if (ComputePrivateExponentD(P, Q, E, N, &D) == FALSE) + ERROR_RETURN(TPM_RC_FAILURE); + ExpDCacheAdd(P, N, E, Q, D); + } + if (RSA_set0_key(key, NULL, NULL, D) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + DoRSACheckKey(P, Q, N, E, D); + + D = NULL; + +#if CRT_FORMAT_RSA == YES + /* CRT parameters are not absolutely needed but may speed up ops */ + dP = BigInitialized(dP, (bigConst)&rsaKey->privateExponent.dP); + dQ = BigInitialized(dQ, (bigConst)&rsaKey->privateExponent.dQ); + qInv = BigInitialized(qInv, (bigConst)&rsaKey->privateExponent.qInv); + if (dP == NULL || dQ == NULL || qInv == NULL || + RSA_set0_crt_params(key, dP, dQ, qInv) != 1) + ERROR_RETURN(TPM_RC_FAILURE); +#endif + + retVal = TPM_RC_SUCCESS; + + Exit: + BN_CTX_free(ctx); + BN_clear_free(P); + BN_clear_free(Q); + BN_free(Qr); + RSA_free(key); // undo reference from EVP_PKEY_get1_RSA() + + if (retVal != TPM_RC_SUCCESS) { + BN_clear_free(D); +#if CRT_FORMAT_RSA == YES + BN_clear_free(dP); + BN_clear_free(dQ); + BN_clear_free(qInv); +#endif + EVP_PKEY_free(*pkey); + *pkey = NULL; + } + + return retVal; +} + +LIB_EXPORT TPM_RC +OpenSSLCryptRsaGenerateKey( + OBJECT *rsaKey, // IN/OUT: The object structure in which + // the key is created. + UINT32 e, + int keySizeInBits + ) +{ + TPMT_PUBLIC *publicArea = &rsaKey->publicArea; + TPMT_SENSITIVE *sensitive = &rsaKey->sensitive; + TPM_RC retVal = TPM_RC_SUCCESS; + int rc; + RSA *rsa = NULL; + const BIGNUM *bnP = NULL; + const BIGNUM *bnN = NULL; + BIGNUM *bnE = BN_new(); + BN_RSA(tmp); + + if (bnE == NULL || BN_set_word(bnE, e) != 1) + ERROR_RETURN(TPM_RC_FAILURE); + + // Need to initialize the privateExponent structure + RsaInitializeExponent(&rsaKey->privateExponent); + + rsa = RSA_new(); + if (rsa == NULL) + ERROR_RETURN(TPM_RC_FAILURE); + + rc = RSA_generate_key_ex(rsa, keySizeInBits, bnE, NULL); + if (rc == 0) + ERROR_RETURN(TPM_RC_NO_RESULT); + + RSA_get0_key(rsa, &bnN, NULL, NULL); + RSA_get0_factors(rsa, &bnP, NULL); + + OsslToTpmBn(tmp, bnN); + BnTo2B((bigNum)tmp, &publicArea->unique.rsa.b, 0); + + OsslToTpmBn(tmp, bnP); + BnTo2B((bigNum)tmp, &sensitive->sensitive.rsa.b, 0); + + // CryptRsaGenerateKey calls ComputePrivateExponent; we have to call + // it via CryptRsaLoadPrivateExponent + retVal = CryptRsaLoadPrivateExponent(rsaKey); + + Exit: + BN_free(bnE); + RSA_free(rsa); + + return retVal; +} + +#endif // USE_OPENSSL_FUNCTIONS_RSA diff --git a/src/tpm2/crypto/openssl/Helpers_fp.h b/src/tpm2/crypto/openssl/Helpers_fp.h new file mode 100644 index 0000000..5b9ca14 --- /dev/null +++ b/src/tpm2/crypto/openssl/Helpers_fp.h @@ -0,0 +1,117 @@ +/********************************************************************************/ +/* */ +/* OpenSSL helper functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2019 */ +/* */ +/********************************************************************************/ + +#ifndef HELPERS_FP_H +#define HELPERS_FP_H + +#include "TpmTypes.h" + +#include + +#if USE_OPENSSL_FUNCTIONS_SYMMETRIC +TPM_RC +OpenSSLCryptGenerateKeyDes( + TPMT_SENSITIVE *sensitive // OUT: sensitive area + ); + +typedef const EVP_CIPHER *(*evpfunc)(void); + +evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN + UINT16 keySizeInBits, // IN + TPM_ALG_ID mode, // IN + const BYTE *key, // IN + BYTE *keyToUse, // OUT same as key or stretched key + UINT16 *keyToUseLen // IN/OUT + ); +#endif + +#if USE_OPENSSL_FUNCTIONS_EC +BOOL OpenSSLEccGetPrivate( + bigNum dOut, // OUT: the qualified random value + const EC_GROUP *G, // IN: the EC_GROUP to use + const UINT32 requestedBits // IN: if not 0, then dOut must have that many bits + ); +#endif + +#if USE_OPENSSL_FUNCTIONS_RSA + +const char *GetDigestNameByHashAlg(const TPM_ALG_ID hashAlg); + +LIB_EXPORT TPM_RC +OpenSSLCryptRsaGenerateKey( + OBJECT *rsaKey, // IN/OUT: The object structure in which + // the key is created. + UINT32 e, + int keySizeInBits + ); + +LIB_EXPORT TPM_RC +InitOpenSSLRSAPublicKey(OBJECT *key, // IN + EVP_PKEY **pkey //OUT + ); + +LIB_EXPORT TPM_RC +InitOpenSSLRSAPrivateKey(OBJECT *rsaKey, // IN + EVP_PKEY **pkey // OUT + ); + +#endif // USE_OPENSSL_FUNCTIONS_RSA + +#endif /* HELPERS_FP_H */ diff --git a/src/tpm2/crypto/openssl/LibSupport.h b/src/tpm2/crypto/openssl/LibSupport.h new file mode 100644 index 0000000..d571b84 --- /dev/null +++ b/src/tpm2/crypto/openssl/LibSupport.h @@ -0,0 +1,98 @@ +/********************************************************************************/ +/* */ +/* select the library code that gets included in the TPM build */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: LibSupport.h 1656 2021-01-15 21:45:18Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +// 5.12 LibSupport.h +// This header file is used to select the library code that gets included in the TPM build +#ifndef _LIB_SUPPORT_H_ +#define _LIB_SUPPORT_H_ + +#if 0 // libtpms added +/* kgold added power and s390 */ +#ifndef RADIX_BITS +# if defined(__x86_64__) || defined(__x86_64) \ + || defined(__amd64__) || defined(__amd64) \ + || defined(_WIN64) || defined(_M_X64) \ + || defined(_M_ARM64) || defined(__aarch64__) \ + || defined(__powerpc64__) || defined(__PPC64__) || defined(__ppc64__) \ + || defined(__s390x__) +# define RADIX_BITS 64 +# elif defined(__i386__) || defined(__i386) || defined(i386) \ + || defined(_WIN32) || defined(_M_IX86) \ + || defined(_M_ARM) || defined(__arm__) || defined(__thumb__) \ + || defined(__powerpc__) || defined(__PPC__) +# define RADIX_BITS 32 +# else +# error Unable to determine RADIX_BITS from compiler environment +# endif +#endif // RADIX_BITS +#endif // libtpms added + +// These macros use the selected libraries to the proper include files. +#define LIB_QUOTE(_STRING_) #_STRING_ +#define LIB_INCLUDE2(_LIB_, _TYPE_) LIB_QUOTE(TpmTo##_LIB_##_TYPE_.h) +#define LIB_INCLUDE(_LIB_, _TYPE_) LIB_INCLUDE2(_LIB_, _TYPE_) +// Include the options for hashing and symmetric. Defer the load of the math package until the +// bignum parameters are defined. +#include LIB_INCLUDE(SYM_LIB, Sym) +#include LIB_INCLUDE(HASH_LIB, Hash) +#undef MIN +#undef MAX +#endif // _LIB_SUPPORT_H_ diff --git a/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c b/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c new file mode 100644 index 0000000..d27aad2 --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c @@ -0,0 +1,119 @@ +/********************************************************************************/ +/* */ +/* TPM DES Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslDesSupport.c 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* B.2.3.1. TpmToOsslDesSupport.c */ +/* B.2.3.1.1. Introduction */ +/* The functions in this file are used for initialization of the interface to the OpenSSL + library. */ +/* B.2.3.1.2. Defines and Includes */ +#include "Tpm.h" +#if (defined SYM_LIB_OSSL) && ALG_TDES +/* B.2.3.1.3. Functions */ +/* B.2.3.1.3.1. TDES_set_encyrpt_key() */ +/* This function makes creation of a TDES key look like the creation of a key for any of the other + OpenSSL block ciphers. It will create three key schedules, one for each of the DES keys. If + there are only two keys, then the third schedule is a copy of the first. */ +void +TDES_set_encrypt_key( + const BYTE *key, + UINT16 keySizeInBits, + tpmKeyScheduleTDES *keySchedule + ) +{ + DES_set_key_unchecked((const_DES_cblock *)key, &keySchedule[0]); + DES_set_key_unchecked((const_DES_cblock *)&key[8], &keySchedule[1]); + // If is two-key, copy the schedule for K1 into K3, otherwise, compute the + // the schedule for K3 + if(keySizeInBits == 128) + keySchedule[2] = keySchedule[0]; + else + DES_set_key_unchecked((const_DES_cblock *)&key[16], + &keySchedule[2]); +} +/* B.2.3.1.3.2. TDES_encyrpt() */ +/* The TPM code uses one key schedule. For TDES, the schedule contains three schedules. OpenSSL + wants the schedules referenced separately. This function does that. */ +void TDES_encrypt( + const BYTE *in, + BYTE *out, + tpmKeyScheduleTDES *ks + ) +{ + DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out, + &ks[0], &ks[1], &ks[2], + DES_ENCRYPT); +} +#if !USE_OPENSSL_FUNCTIONS_SYMMETRIC +/* B.2.3.1.3.3. TDES_decrypt() */ +/* As with TDES_encypt() this function bridges between the TPM single schedule model and the + OpenSSL three schedule model. */ +void TDES_decrypt( + const BYTE *in, + BYTE *out, + tpmKeyScheduleTDES *ks + ) +{ + DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out, + &ks[0], &ks[1], &ks[2], + DES_DECRYPT); +} +#endif // !USE_OPENSSL_FUNCTIONS_SYMMETRIC +#endif // SYM_LIB_OSSL diff --git a/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h b/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h new file mode 100644 index 0000000..4338fe6 --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslDesSupport_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 */ +/* */ +/********************************************************************************/ + +#ifndef TPMTOOSSLDESSUPPORT_FP_H +#define TPMTOOSSLDESSUPPORT_FP_H + +void +TDES_set_encrypt_key( + const BYTE *key, + UINT16 keySizeInBits, + tpmKeyScheduleTDES *keySchedule + ); +void TDES_encrypt( + const BYTE *in, + BYTE *out, + tpmKeyScheduleTDES *ks + ); +void TDES_decrypt( + const BYTE *in, + BYTE *out, + tpmKeyScheduleTDES *ks + ); + + +#endif diff --git a/src/tpm2/crypto/openssl/TpmToOsslHash.h b/src/tpm2/crypto/openssl/TpmToOsslHash.h new file mode 100644 index 0000000..9fa6479 --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslHash.h @@ -0,0 +1,219 @@ +/********************************************************************************/ +/* */ +/* Used to splice the OpenSSL() hash code into the TPM code */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslHash.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* B.2.2.1. TpmToOsslHash.h */ +/* B.2.2.1.1. Introduction */ +/* This header file is used to splice the OpenSSL hash code into the TPM code. */ +#ifndef HASH_LIB_DEFINED +#define HASH_LIB_DEFINED +#define HASH_LIB_OSSL +#include +#include + +#if ALG_SM3_256 +# if defined(OPENSSL_NO_SM3) || OPENSSL_VERSION_NUMBER < 0x10101010L +# if ALG_SM3_256 // libtpms added begin +# error This version of OpenSSL does not support SM3 +# endif // libtpms added end +# undef ALG_SM3_256 +# define ALG_SM3_256 ALG_NO +# elif OPENSSL_VERSION_NUMBER >= 0x10200000L +# include +# else +// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory, +// and they do not get installed as part of the libssl package +# define SM3_LBLOCK (64/4) + +# error Check support for this version of SM3 in OpenSSL (libtpms) +typedef struct SM3state_st { + unsigned int A, B, C, D, E, F, G, H; + unsigned int Nl, Nh; + unsigned int data[SM3_LBLOCK]; + unsigned int num; +} SM3_CTX; + +int sm3_init(SM3_CTX *c); +int sm3_update(SM3_CTX *c, const void *data, size_t len); +int sm3_final(unsigned char *md, SM3_CTX *c); +# endif // OpenSSL < 1.2 +#endif // ALG_SM3_256 + +#include + +#define HASH_ALIGNMENT RADIX_BYTES /* libtpms: keep; not sure whether needed */ + +/* B.2.2.1.2. Links to the OpenSSL HASH code */ +/* Redefine the internal name used for each of the hash state structures to the name used by the + library. These defines need to be known in all parts of the TPM so that the structure sizes can + be properly computed when needed. */ +#define tpmHashStateSHA1_t SHA_CTX +#define tpmHashStateSHA256_t SHA256_CTX +#define tpmHashStateSHA384_t SHA512_CTX +#define tpmHashStateSHA512_t SHA512_CTX +#define tpmHashStateSM3_256_t SM3_CTX +#if ALG_SM3_256 +# error "The version of OpenSSL used by this code does not support SM3" +#endif +/* The defines below are only needed when compiling CryptHash.c or CryptSmac.c. This isolation + is primarily to avoid name space collision. However, if there is a real collision, it will + likely show up when the linker tries to put things together. */ +#ifdef _CRYPT_HASH_C_ +typedef BYTE *PBYTE; +typedef const BYTE *PCBYTE; +/* Define the interface between CryptHash.c to the functions provided by the library. For each + method, define the calling parameters of the method and then define how the method is invoked in + CryptHash.c. */ +/* All hashes are required to have the same calling sequence. If they don't, create a simple + adaptation function that converts from the standard form of the call to the form used by the + specific hash (and then send a nasty letter to the person who wrote the hash function for the + library). */ +/* The macro that calls the method also defines how the parameters get swizzled between the default + form (in CryptHash.c)and the library form. */ + +#define HASH_ALIGNMENT RADIX_BYTES + +/* Initialize the hash context */ +#define HASH_START_METHOD_DEF void (HASH_START_METHOD)(PANY_HASH_STATE state) +#define HASH_START(hashState) \ + ((hashState)->def->method.start)(&(hashState)->state); +/* Add data to the hash */ +#define HASH_DATA_METHOD_DEF \ + void (HASH_DATA_METHOD)(PANY_HASH_STATE state, \ + PCBYTE buffer, \ + size_t size) +#define HASH_DATA(hashState, dInSize, dIn) \ + ((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize) +/* Finalize the hash and get the digest */ +#define HASH_END_METHOD_DEF \ + void (HASH_END_METHOD)(BYTE *buffer, PANY_HASH_STATE state) +#define HASH_END(hashState, buffer) \ + ((hashState)->def->method.end)(buffer, &(hashState)->state) +/* Copy the hash context */ +/* NOTE: For import, export, and copy, memcpy() is used since there is no reformatting necessary + between the internal and external forms. */ +#define HASH_STATE_COPY_METHOD_DEF \ + void (HASH_STATE_COPY_METHOD)(PANY_HASH_STATE to, \ + PCANY_HASH_STATE from, \ + size_t size) +#define HASH_STATE_COPY(hashStateOut, hashStateIn) \ + ((hashStateIn)->def->method.copy)(&(hashStateOut)->state, \ + &(hashStateIn)->state, \ + (hashStateIn)->def->contextSize) +/* Copy (with reformatting when necessary) an internal hash structure to an external blob */ +#define HASH_STATE_EXPORT_METHOD_DEF \ + void (HASH_STATE_EXPORT_METHOD)(BYTE *to, \ + PCANY_HASH_STATE from, \ + size_t size) +#define HASH_STATE_EXPORT(to, hashStateFrom) \ + ((hashStateFrom)->def->method.copyOut) \ + (&(((BYTE *)(to))[offsetof(HASH_STATE, state)]), \ + &(hashStateFrom)->state, \ + (hashStateFrom)->def->contextSize) +/* Copy from an external blob to an internal format (with reformatting when necessary) */ +#define HASH_STATE_IMPORT_METHOD_DEF \ + void (HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to, \ + const BYTE *from, \ + size_t size) +#define HASH_STATE_IMPORT(hashStateTo, from) \ + ((hashStateTo)->def->method.copyIn) \ + (&(hashStateTo)->state, \ + &(((const BYTE *)(from))[offsetof(HASH_STATE, state)]), \ + (hashStateTo)->def->contextSize) +/* Function aliases. The code in CryptHash.c uses the internal designation for the functions. These + need to be translated to the function names of the library. */ +#define tpmHashStart_SHA1 SHA1_Init // external name of the initialization method +#define tpmHashData_SHA1 SHA1_Update +#define tpmHashEnd_SHA1 SHA1_Final +#define tpmHashStateCopy_SHA1 memcpy +#define tpmHashStateExport_SHA1 memcpy +#define tpmHashStateImport_SHA1 memcpy +#define tpmHashStart_SHA256 SHA256_Init +#define tpmHashData_SHA256 SHA256_Update +#define tpmHashEnd_SHA256 SHA256_Final +#define tpmHashStateCopy_SHA256 memcpy +#define tpmHashStateExport_SHA256 memcpy +#define tpmHashStateImport_SHA256 memcpy +#define tpmHashStart_SHA384 SHA384_Init +#define tpmHashData_SHA384 SHA384_Update +#define tpmHashEnd_SHA384 SHA384_Final +#define tpmHashStateCopy_SHA384 memcpy +#define tpmHashStateExport_SHA384 memcpy +#define tpmHashStateImport_SHA384 memcpy +#define tpmHashStart_SHA512 SHA512_Init +#define tpmHashData_SHA512 SHA512_Update +#define tpmHashEnd_SHA512 SHA512_Final +#define tpmHashStateCopy_SHA512 memcpy +#define tpmHashStateExport_SHA512 memcpy +#define tpmHashStateImport_SHA512 memcpy +#define tpmHashStart_SM3_256 sm3_init +#define tpmHashData_SM3_256 sm3_update +#define tpmHashEnd_SM3_256 sm3_final +#define tpmHashStateCopy_SM3_256 memcpy +#define tpmHashStateExport_SM3_256 memcpy +#define tpmHashStateImport_SM3_256 memcpy + +#endif // _CRYPT_HASH_C_ +#define LibHashInit() +/* This definition would change if there were something to report */ +#define HashLibSimulationEnd() +#endif // // HASH_LIB_DEFINED + + diff --git a/src/tpm2/crypto/openssl/TpmToOsslMath.c b/src/tpm2/crypto/openssl/TpmToOsslMath.c new file mode 100644 index 0000000..18e6c23 --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslMath.c @@ -0,0 +1,736 @@ +/********************************************************************************/ +/* */ +/* TPM to OpenSSL BigNum Shim Layer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslMath.c 1598 2020-03-27 21:59:49Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* B.2.3.2. TpmToOsslMath.c */ +/* B.2.3.2.1. Introduction */ + +/* The functions in this file provide the low-level interface between the TPM code and the big + number and elliptic curve math routines in OpenSSL. */ +/* Most math on big numbers require a context. The context contains the memory in which OpenSSL + creates and manages the big number values. When a OpenSSL math function will be called that + modifies a BIGNUM value, that value must be created in an OpenSSL context. The first line of code + in such a function must be: OSSL_ENTER(); and the last operation before returning must be + OSSL_LEAVE(). OpenSSL variables can then be created with BnNewVariable(). Constant values to be + used by OpenSSL are created from the bigNum values passed to the functions in this file. Space + for the BIGNUM control block is allocated in the stack of the function and then it is initialized + by calling BigInitialized(). That function sets up the values in the BIGNUM structure and sets + the data pointer to point to the data in the bignum_t. This is only used when the value is known + to be a constant in the called function. */ +/* Because the allocations of constants is on the local stack and the OSSL_ENTER()/OSSL_LEAVE() pair + flushes everything created in OpenSSL memory, there should be no chance of a memory leak. */ + + +#include "Tpm.h" +#ifdef MATH_LIB_OSSL +#include "TpmToOsslMath_fp.h" + +/* B.2.3.2.3.1. OsslToTpmBn() */ +/* This function converts an OpenSSL BIGNUM to a TPM bignum. In this implementation it is assumed + that OpenSSL uses a different control structure but the same data layout -- an array of + native-endian words in little-endian order. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure because value will not fit or OpenSSL variable doesn't exist */ +BOOL +OsslToTpmBn( + bigNum bn, + const BIGNUM *osslBn // libtpms: added 'const' + ) +{ + VERIFY(osslBn != NULL); + // If the bn is NULL, it means that an output value pointer was NULL meaning that + // the results is simply to be discarded. + unsigned char buffer[LARGEST_NUMBER + 1]; // libtpms added + int buffer_len; // libtpms added + + if(bn != NULL) + { +#if 1 //libtpms added begin + int num_bytes; + + num_bytes = BN_num_bytes(osslBn); + VERIFY(num_bytes >= 0 && sizeof(buffer) >= (size_t)num_bytes); + buffer_len = BN_bn2bin(osslBn, buffer); /* ossl to bin */ + BnFromBytes(bn, buffer, buffer_len); /* bin to TPM */ +#else // libtpms added end + int i; + // + VERIFY((unsigned)osslBn->top <= BnGetAllocated(bn)); + for(i = 0; i < osslBn->top; i++) + bn->d[i] = osslBn->d[i]; + BnSetTop(bn, osslBn->top); +#endif // libtpms added + } + return TRUE; + Error: + return FALSE; +} + +/* B.2.3.2.3.2. BigInitialized() */ +/* This function initializes an OSSL BIGNUM from a TPM bigConst. Do not use this for values that are + passed to OpenSLL when they are not declared as const in the function prototype. Instead, use + BnNewVariable(). */ +BIGNUM * +BigInitialized( + BIGNUM *toInit, + bigConst initializer + ) +{ +#if 1 // libtpms added begin + BIGNUM *_toInit; + unsigned char buffer[LARGEST_NUMBER + 1]; + NUMBYTES buffer_len = (NUMBYTES )sizeof(buffer); +#endif // libtpms added end + + if(initializer == NULL) + FAIL(FATAL_ERROR_PARAMETER); + if(toInit == NULL || initializer == NULL) + return NULL; + +#if 1 // libtpms added begin + BnToBytes(initializer, buffer, &buffer_len); /* TPM to bin */ + _toInit = BN_bin2bn(buffer, buffer_len, NULL); /* bin to ossl */ + BN_set_flags(_toInit, BN_FLG_CONSTTIME); + BN_copy(toInit, _toInit); + BN_clear_free(_toInit); +#else // libtpms added end + toInit->d = (BN_ULONG *)&initializer->d[0]; + toInit->dmax = (int)initializer->allocated; + toInit->top = (int)initializer->size; + toInit->neg = 0; + toInit->flags = 0; +#endif + return toInit; +} + +#ifndef OSSL_DEBUG +# define BIGNUM_PRINT(label, bn, eol) +# define DEBUG_PRINT(x) +#else +# define DEBUG_PRINT(x) printf("%s", x) +# define BIGNUM_PRINT(label, bn, eol) BIGNUM_print((label), (bn), (eol)) + +static +void BIGNUM_print( + const char *label, + const BIGNUM *a, + BOOL eol + ) +{ + BN_ULONG *d; + int i; + int notZero = FALSE; + if(label != NULL) + printf("%s", label); + if(a == NULL) + { + printf("NULL"); + goto done; + } + if (a->neg) + printf("-"); + for(i = a->top, d = &a->d[i - 1]; i > 0; i--) + { + int j; + BN_ULONG l = *d--; + for(j = BN_BITS2 - 8; j >= 0; j -= 8) + { + BYTE b = (BYTE)((l >> j) & 0xFF); + notZero = notZero || (b != 0); + if(notZero) + printf("%02x", b); + } + if(!notZero) + printf("0"); + } + done: + if(eol) + printf("\n"); + return; +} +#endif + +/* B.2.3.2.3.4. BnNewVariable() */ +/* This function allocates a new variable in the provided context. If the context does not exist or + the allocation fails, it is a catastrophic failure. */ +static BIGNUM * +BnNewVariable( + BN_CTX *CTX + ) +{ + BIGNUM *new; + // + // This check is intended to protect against calling this function without + // having initialized the CTX. + if((CTX == NULL) || ((new = BN_CTX_get(CTX)) == NULL)) + FAIL(FATAL_ERROR_ALLOCATION); + return new; +} + +#if LIBRARY_COMPATIBILITY_CHECK + +BOOL +MathLibraryCompatibilityCheck( + void + ) +{ + OSSL_ENTER(); + BIGNUM *osslTemp = BnNewVariable(CTX); +#if 0 + crypt_uword_t i; +#endif + BYTE test[] = {0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, + 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; + BN_VAR(tpmTemp, sizeof(test) * 8); // allocate some space for a test value + // + // Convert the test data to a bigNum + BnFromBytes(tpmTemp, test, sizeof(test)); + // Convert the test data to an OpenSSL BIGNUM + BN_bin2bn(test, sizeof(test), osslTemp); + // Make sure the values are consistent +#if 0 + VERIFY(osslTemp->top == (int)tpmTemp->size); + for(i = 0; i < tpmTemp->size; i++) + VERIFY(osslTemp->d[i] == tpmTemp->d[i]); +#endif + OSSL_LEAVE(); + return 1; +#if 0 + Error: + return 0; +#endif +} + +#endif + +/* B.2.3.2.3.3. BnModMult() */ +/* Does multiply and divide returning the remainder of the divide. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure in operation */ + +LIB_EXPORT BOOL +BnModMult( + bigNum result, + bigConst op1, + bigConst op2, + bigConst modulus + ) +{ + OSSL_ENTER(); + BOOL OK = TRUE; + BIGNUM *bnResult = BN_NEW(); + BIGNUM *bnTemp = BN_NEW(); + BIG_INITIALIZED(bnOp1, op1); + BIG_INITIALIZED(bnOp2, op2); + BIG_INITIALIZED(bnMod, modulus); + // + VERIFY(BN_mul(bnTemp, bnOp1, bnOp2, CTX)); + VERIFY(BN_div(NULL, bnResult, bnTemp, bnMod, CTX)); + VERIFY(OsslToTpmBn(result, bnResult)); + goto Exit; + Error: + OK = FALSE; + Exit: + BN_clear_free(bnMod); // libtpms added + BN_clear_free(bnOp2); // libtpms added + BN_clear_free(bnOp1); // libtpms added + OSSL_LEAVE(); + return OK; +} + +/* B.2.3.2.3.4. BnMult() */ +/* Multiplies two numbers */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure in operation */ + +LIB_EXPORT BOOL +BnMult( + bigNum result, + bigConst multiplicand, + bigConst multiplier + ) +{ + OSSL_ENTER(); + BIGNUM *bnTemp = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bnA, multiplicand); + BIG_INITIALIZED(bnB, multiplier); + // + VERIFY(BN_mul(bnTemp, bnA, bnB, CTX)); + VERIFY(OsslToTpmBn(result, bnTemp)); + goto Exit; + Error: + OK = FALSE; + Exit: + BN_clear_free(bnB); // libtpms added + BN_clear_free(bnA); // libtpms added + OSSL_LEAVE(); + return OK; +} + +/* B.2.3.2.3.5. BnDiv() */ +/* This function divides two bigNum values. The function returns FALSE if there is an error in the + operation. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure in operation */ + +LIB_EXPORT BOOL +BnDiv( + bigNum quotient, + bigNum remainder, + bigConst dividend, + bigConst divisor + ) +{ + OSSL_ENTER(); + BIGNUM *bnQ = BN_NEW(); + BIGNUM *bnR = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bnDend, dividend); + BIG_INITIALIZED(bnSor, divisor); + // + if(BnEqualZero(divisor)) + FAIL(FATAL_ERROR_DIVIDE_ZERO); + VERIFY(BN_div(bnQ, bnR, bnDend, bnSor, CTX)); + VERIFY(OsslToTpmBn(quotient, bnQ)); + VERIFY(OsslToTpmBn(remainder, bnR)); + DEBUG_PRINT("In BnDiv:\n"); + BIGNUM_PRINT(" bnDividend: ", bnDend, TRUE); + BIGNUM_PRINT(" bnDivisor: ", bnSor, TRUE); + BIGNUM_PRINT(" bnQuotient: ", bnQ, TRUE); + BIGNUM_PRINT(" bnRemainder: ", bnR, TRUE); + goto Exit; + Error: + OK = FALSE; + Exit: + BN_clear_free(bnSor); // libtpms added + BN_clear_free(bnDend); // libtpms added + OSSL_LEAVE(); + return OK; +} + +#if ALG_RSA +#if !RSA_KEY_SIEVE // libtpms added +/* B.2.3.2.3.6. BnGcd() */ +/* Get the greatest common divisor of two numbers */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure in operation */ + +LIB_EXPORT BOOL +BnGcd( + bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: + ) +{ + OSSL_ENTER(); + BIGNUM *bnGcd = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bn1, number1); + BIG_INITIALIZED(bn2, number2); + // + BN_set_flags(bn1, BN_FLG_CONSTTIME); // number1 is secret prime number + VERIFY(BN_gcd(bnGcd, bn1, bn2, CTX)); + VERIFY(OsslToTpmBn(gcd, bnGcd)); + goto Exit; + Error: + OK = FALSE; + Exit: + BN_clear_free(bn2); // libtpms added + BN_clear_free(bn1); // libtpms added + OSSL_LEAVE(); + return OK; +} +#endif // libtpms added + +/* B.2.3.2.3.7. BnModExp() */ +/* Do modular exponentiation using bigNum values. The conversion from a bignum_t to a bigNum is + trivial as they are based on the same structure */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure in operation */ + +LIB_EXPORT BOOL +BnModExp( + bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: + ) +{ + OSSL_ENTER(); + BIGNUM *bnResult = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bnN, number); + BIG_INITIALIZED(bnE, exponent); + BIG_INITIALIZED(bnM, modulus); + // + BN_set_flags(bnE, BN_FLG_CONSTTIME); // exponent may be private + VERIFY(BN_mod_exp(bnResult, bnN, bnE, bnM, CTX)); + VERIFY(OsslToTpmBn(result, bnResult)); + goto Exit; + Error: + OK = FALSE; + Exit: + BN_clear_free(bnM); // libtpms added + BN_clear_free(bnE); // libtpms added + BN_clear_free(bnN); // libtpms added + OSSL_LEAVE(); + return OK; +} + +/* B.2.3.2.3.8. BnModInverse() */ +/* Modular multiplicative inverse */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure in operation */ + +LIB_EXPORT BOOL +BnModInverse( + bigNum result, + bigConst number, + bigConst modulus + ) +{ + OSSL_ENTER(); + BIGNUM *bnResult = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bnN, number); + BIG_INITIALIZED(bnM, modulus); + // + BN_set_flags(bnN, BN_FLG_CONSTTIME); // number may be private + VERIFY(BN_mod_inverse(bnResult, bnN, bnM, CTX) != NULL); + VERIFY(OsslToTpmBn(result, bnResult)); + goto Exit; + Error: + OK = FALSE; + Exit: + BN_clear_free(bnM); // libtpms added + BN_clear_free(bnN); // libtpms added + OSSL_LEAVE(); + return OK; +} + +#endif // TPM_ALG_RSA + +#if ALG_ECC + +/* B.2.3.2.3.9. PointFromOssl() */ +/* Function to copy the point result from an OSSL function to a bigNum */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure in operation */ +static BOOL +PointFromOssl( + bigPoint pOut, // OUT: resulting point + EC_POINT *pIn, // IN: the point to return + bigCurve E // IN: the curve + ) +{ + BIGNUM *x = NULL; + BIGNUM *y = NULL; + BOOL OK; + BN_CTX_start(E->CTX); + // + x = BN_CTX_get(E->CTX); + y = BN_CTX_get(E->CTX); + if(y == NULL) + FAIL(FATAL_ERROR_ALLOCATION); + // If this returns false, then the point is at infinity +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin + OK = EC_POINT_get_affine_coordinates(E->G, pIn, x, y, E->CTX); +#else // libtpms added begin + OK = EC_POINT_get_affine_coordinates_GFp(E->G, pIn, x, y, E->CTX); +#endif // libtpms added end + if(OK) + { + OsslToTpmBn(pOut->x, x); + OsslToTpmBn(pOut->y, y); + BnSetWord(pOut->z, 1); + } + else + BnSetWord(pOut->z, 0); + BN_CTX_end(E->CTX); + return OK; +} +/* B.2.3.2.3.10. EcPointInitialized() */ +/* Allocate and initialize a point. */ + +LIB_EXPORT EC_POINT * // libtpms: exported function +EcPointInitialized( + pointConst initializer, + bigCurve E + ) +{ + EC_POINT *P = NULL; + + if(initializer != NULL) + { + BIG_INITIALIZED(bnX, initializer->x); + BIG_INITIALIZED(bnY, initializer->y); + if(E == NULL) + FAIL(FATAL_ERROR_ALLOCATION); + P = EC_POINT_new(E->G); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin + if(!EC_POINT_set_affine_coordinates(E->G, P, bnX, bnY, E->CTX)) +#else // libtpms added end + if(!EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, E->CTX)) +#endif // libtpms added + P = NULL; + BN_clear_free(bnX); // libtpms added + BN_clear_free(bnY); // libtpms added + } + return P; +} + +/* B.2.3.2.3.11. BnCurveInitialize() */ +/* This function initializes the OpenSSL group definition */ +/* It is a fatal error if groupContext is not provided. */ +/* Return Values Meaning */ +/* NULL the TPM_ECC_CURVE is not valid */ +/* non-NULL points to a structure in groupContext */ + +LIB_EXPORT bigCurve +BnCurveInitialize( + bigCurve E, // IN: curve structure to initialize + TPM_ECC_CURVE curveId // IN: curve identifier + ) +{ + const ECC_CURVE_DATA *C = GetCurveData(curveId); + if(C == NULL) + E = NULL; + if(E != NULL) + { + // This creates the OpenSSL memory context that stays in effect as long as the + // curve (E) is defined. + OSSL_ENTER(); // if the allocation fails, the TPM fails + EC_POINT *P = NULL; + BIG_INITIALIZED(bnP, C->prime); + BIG_INITIALIZED(bnA, C->a); + BIG_INITIALIZED(bnB, C->b); + BIG_INITIALIZED(bnX, C->base.x); + BIG_INITIALIZED(bnY, C->base.y); + BIG_INITIALIZED(bnN, C->order); + BIG_INITIALIZED(bnH, C->h); + // + E->C = C; + E->CTX = CTX; + + // initialize EC group, associate a generator point and initialize the point + // from the parameter data + // Create a group structure + E->G = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, CTX); + VERIFY(E->G != NULL); + + // Allocate a point in the group that will be used in setting the + // generator. This is not needed after the generator is set. + P = EC_POINT_new(E->G); + VERIFY(P != NULL); + + // Need to use this in case Montgomery method is being used +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin + VERIFY(EC_POINT_set_affine_coordinates(E->G, P, bnX, bnY, CTX)); +#else // libtpms added end + VERIFY(EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, CTX)); +#endif // libtpms added + // Now set the generator + VERIFY(EC_GROUP_set_generator(E->G, P, bnN, bnH)); + + EC_POINT_free(P); + goto Exit_free; // libtpms changed + Error: + EC_POINT_free(P); + BnCurveFree(E); + E = NULL; + + Exit_free: // libtpms added begin + BN_clear_free(bnH); + BN_clear_free(bnN); + BN_clear_free(bnY); + BN_clear_free(bnX); + BN_clear_free(bnB); + BN_clear_free(bnA); + BN_clear_free(bnP); // libtpms added end + } +// Exit: + return E; +} + +/* B.2.3.2.3.15. BnCurveFree() */ +/* This function will free the allocated components of the curve and end the frame in which the + curve data exists */ +LIB_EXPORT void +BnCurveFree( + bigCurve E + ) +{ + if(E) + { + EC_GROUP_free(E->G); + OsslContextLeave(E->CTX); + } +} + +/* B.2.3.2.3.11. BnEccModMult() */ +/* This functi2n does a point multiply of the form R = [d]S */ +/* Return Values Meaning */ +/* FALSE failure in operation; treat as result being point at infinity */ + +LIB_EXPORT BOOL +BnEccModMult( + bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' (optional) + bigConst d, // IN: scalar for [d]S + bigCurve E + ) +{ + EC_POINT *pR = EC_POINT_new(E->G); + EC_POINT *pS = EcPointInitialized(S, E); + BIG_INITIALIZED(bnD, d); + + if(S == NULL) + EC_POINT_mul(E->G, pR, bnD, NULL, NULL, E->CTX); + else + EC_POINT_mul(E->G, pR, NULL, pS, bnD, E->CTX); + PointFromOssl(R, pR, E); + EC_POINT_clear_free(pR); // libtpms changed + EC_POINT_clear_free(pS); // libtpms changed + BN_clear_free(bnD); // libtpms added + return !BnEqualZero(R->z); +} + +/* B.2.3.2.3.13. BnEccModMult2() */ +/* This function does a point multiply of the form R = [d]G + [u]Q */ +/* FALSE failure in operation; treat as result being point at infinity */ + +LIB_EXPORT BOOL +BnEccModMult2( + bigPoint R, // OUT: computed point + pointConst S, // IN: optional point + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve + ) +{ + EC_POINT *pR = EC_POINT_new(E->G); + EC_POINT *pS = EcPointInitialized(S, E); + BIG_INITIALIZED(bnD, d); + EC_POINT *pQ = EcPointInitialized(Q, E); + BIG_INITIALIZED(bnU, u); + + if(S == NULL || S == (pointConst)&(AccessCurveData(E)->base)) + EC_POINT_mul(E->G, pR, bnD, pQ, bnU, E->CTX); + else + { + const EC_POINT *points[2]; + const BIGNUM *scalars[2]; + points[0] = pS; + points[1] = pQ; + scalars[0] = bnD; + scalars[1] = bnU; + EC_POINTs_mul(E->G, pR, NULL, 2, points, scalars, E->CTX); + } + PointFromOssl(R, pR, E); + EC_POINT_clear_free(pR); // libtpms changed + EC_POINT_clear_free(pS); // libtpms changed + EC_POINT_clear_free(pQ); // libtpms changed + BN_clear_free(bnD); // libtpms added + BN_clear_free(bnU); // libtpms added + + return !BnEqualZero(R->z); +} + +/* B.2.3.2.4. BnEccAdd() */ +/* This function does addition of two points. */ +/* Return Values Meaning */ +/* FALSE failure in operation; treat as result being point at infinity */ +LIB_EXPORT BOOL +BnEccAdd( + bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve + ) +{ + EC_POINT *pR = EC_POINT_new(E->G); + EC_POINT *pS = EcPointInitialized(S, E); + EC_POINT *pQ = EcPointInitialized(Q, E); + // + EC_POINT_add(E->G, pR, pS, pQ, E->CTX); + PointFromOssl(R, pR, E); + EC_POINT_clear_free(pR); // libtpms changed + EC_POINT_clear_free(pS); // libtpms changed + EC_POINT_clear_free(pQ); // libtpms changed + return !BnEqualZero(R->z); +} + +#endif // ALG_ECC +#endif // MATH_LIB_OSSL diff --git a/src/tpm2/crypto/openssl/TpmToOsslMath.h b/src/tpm2/crypto/openssl/TpmToOsslMath.h new file mode 100644 index 0000000..47333c7 --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslMath.h @@ -0,0 +1,164 @@ +/********************************************************************************/ +/* */ +/* TPM to OpenSSL BigNum Shim Layer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslMath.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* B.2.2.1. TpmToOsslMath.h */ +/* B.2.2.1.1. Introduction */ +/* This file contains the structure definitions used for ECC in the OpenSSL version of the + code. These definitions would change, based on the library. The ECC-related structures that cross + the TPM interface are defined in TpmTypes.h */ + +#ifndef MATH_LIB_DEFINED +#define MATH_LIB_DEFINED +#define MATH_LIB_OSSL +#include +#include + +#define SYMMETRIC_ALIGNMENT RADIX_BYTES + +#if 0 // libtpms added +#if OPENSSL_VERSION_NUMBER >= 0x10200000L +// Check the bignum_st definition in crypto/bn/bn_lcl.h and either update the +// version check or provide the new definition for this version. +# error Untested OpenSSL version +#elif OPENSSL_VERSION_NUMBER >= 0x10100000L +// from crypto/bn/bn_lcl.h +struct bignum_st { + BN_ULONG *d; + int top; + + int dmax; + int neg; + int flags; +}; +#if 0 // libtpms added +# define EC_POINT_get_affine_coordinates EC_POINT_get_affine_coordinates_GFp +# define EC_POINT_set_affine_coordinates EC_POINT_set_affine_coordinates_GFp +#endif // libtpms added +#endif // OPENSSL_VERSION_NUMBER +#endif // libtpms added + +#include +#if USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added begin +#include +#endif // libtpms added end + +/* B.2.2.2.2. Macros and Defines */ +/* Make sure that the library is using the correct size for a crypt word */ + +#if defined THIRTY_TWO_BIT && (RADIX_BITS != 32) \ + || ((defined SIXTY_FOUR_BIT_LONG || defined SIXTY_FOUR_BIT) \ + && (RADIX_BITS != 64)) +# error Ossl library is using different radix +#endif + +/* Allocate a local BIGNUM value. For the allocation, a bigNum structure is created as is a local + BIGNUM. The bigNum is initialized and then the BIGNUM is set to reference the local value. */ + +#define BIG_VAR(name, bits) \ + BN_VAR(name##Bn, (bits)); \ + BIGNUM *_##name = BN_new(); /* libtpms */ \ + BIGNUM *name = BigInitialized(_##name, /* libtpms */ \ + BnInit(name##Bn, \ + BYTES_TO_CRYPT_WORDS(sizeof(_##name##Bn.d)))) + +/* Allocate a BIGNUM and initialize with the values in a bigNum initializer */ + +#define BIG_INITIALIZED(name, initializer) \ + BIGNUM *_##name = BN_new(); /* libtpms */ \ + BIGNUM *name = BigInitialized(_##name, initializer) /* libtpms */ + +typedef struct +{ + const ECC_CURVE_DATA *C; // the TPM curve values + EC_GROUP *G; // group parameters + BN_CTX *CTX; // the context for the math (this might not be + // the context in which the curve was created>; +} OSSL_CURVE_DATA; +typedef OSSL_CURVE_DATA *bigCurve; +#define AccessCurveData(E) ((E)->C) + +#include "TpmToOsslSupport_fp.h" + +#define OSSL_ENTER() BN_CTX *CTX = OsslContextEnter() +#define OSSL_LEAVE() OsslContextLeave(CTX) + +/* Start and end a context that spans multiple ECC functions. This is used so that the group for the + curve can persist across multiple frames. */ + +#define CURVE_INITIALIZED(name, initializer) \ + OSSL_CURVE_DATA _##name; \ + bigCurve name = BnCurveInitialize(&_##name, initializer) + +#define CURVE_FREE(name) BnCurveFree(name) + +/* Start and end a local stack frame within the context of the curve frame */ +#if 0 /* kgold not used */ +#define ECC_ENTER() BN_CTX *CTX = OsslPushContext(E->CTX) +#define ECC_LEAVE() OsslPopContext(CTX) +#endif +#define BN_NEW() BnNewVariable(CTX) + + +/* This definition would change if there were something to report */ +#define MathLibSimulationEnd() +#endif // MATH_LIB_DEFINED + + diff --git a/src/tpm2/crypto/openssl/TpmToOsslMath_fp.h b/src/tpm2/crypto/openssl/TpmToOsslMath_fp.h new file mode 100644 index 0000000..7c42e71 --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslMath_fp.h @@ -0,0 +1,152 @@ +/********************************************************************************/ +/* */ +/* TPM to OpenSSL BigNum Shim Layer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslMath_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef TPMTOOSSLMATH_FP_H +#define TPMTOOSSLMATH_FP_H + +#include + +BOOL +OsslToTpmBn( + bigNum bn, + const BIGNUM *osslBn // libtpms added 'const' + ); +BIGNUM * +BigInitialized( + BIGNUM *toInit, + bigConst initializer + ); +// libtpms added begin +EC_POINT * +EcPointInitialized( + pointConst initializer, + bigCurve E + ); +// libtpms added end +LIB_EXPORT BOOL +BnModMult( + bigNum result, + bigConst op1, + bigConst op2, + bigConst modulus + ); +LIB_EXPORT BOOL +BnMult( + bigNum result, + bigConst multiplicand, + bigConst multiplier + ); +LIB_EXPORT BOOL +BnDiv( + bigNum quotient, + bigNum remainder, + bigConst dividend, + bigConst divisor + ); +LIB_EXPORT BOOL +BnGcd( + bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: + ); +LIB_EXPORT BOOL +BnModExp( + bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: + ); +LIB_EXPORT BOOL +BnModInverse( + bigNum result, + bigConst number, + bigConst modulus + ); +bigCurve +BnCurveInitialize( + bigCurve E, // IN: curve structure to initialize + TPM_ECC_CURVE curveId // IN: curve identifier + ); +LIB_EXPORT BOOL +BnEccModMult( + bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' (optional) + bigConst d, // IN: scalar for [d]S + bigCurve E + ); +LIB_EXPORT BOOL +BnEccModMult2( + bigPoint R, // OUT: computed point + pointConst S, // IN: optional point + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve + ); +LIB_EXPORT BOOL +BnEccAdd( + bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve + ); + +#endif diff --git a/src/tpm2/crypto/openssl/TpmToOsslSupport.c b/src/tpm2/crypto/openssl/TpmToOsslSupport.c new file mode 100644 index 0000000..921b02f --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslSupport.c @@ -0,0 +1,129 @@ +/********************************************************************************/ +/* */ +/* Initialization of the Interface to the OpenSSL Library. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslSupport.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* B.2.3.3. TpmToOsslSupport.c */ +/* B.2.3.3.1. Introduction */ +/* The functions in this file are used for initialization of the interface to the OpenSSL + library. */ +/* B.2.3.3.2. Defines and Includes */ +#include "Tpm.h" + +#if defined(HASH_LIB_OSSL) || defined(MATH_LIB_OSSL) || defined(SYM_LIB_OSSL) + +/* Used to pass the pointers to the correct sub-keys */ +typedef const BYTE *desKeyPointers[3]; +/* B.2.3.3.2.1. SupportLibInit() */ +/* This does any initialization required by the support library. */ +LIB_EXPORT int +SupportLibInit( + void + ) +{ + return TRUE; +} +/* B.2.3.3.2.2. OsslContextEnter() */ +/* This function is used to initialize an OpenSSL context at the start of a function that will + call to an OpenSSL math function. */ +BN_CTX * +OsslContextEnter( + void + ) +{ + BN_CTX *CTX = BN_CTX_new(); + return OsslPushContext(CTX); +} +/* B.2.3.3.2.3. OsslContextLeave() */ +/* This is the companion function to OsslContextEnter(). */ +void +OsslContextLeave( + BN_CTX *CTX + ) +{ + OsslPopContext(CTX); + BN_CTX_free(CTX); +} + +/* B.2.3.3.2.4. OsslPushContext() */ +/* This function is used to create a frame in a context. All values allocated within this context after the frame is started will be automatically freed when the context (OsslPopContext() */ +BN_CTX * +OsslPushContext( + BN_CTX *CTX + ) +{ + if(CTX == NULL) + FAIL(FATAL_ERROR_ALLOCATION); + BN_CTX_start(CTX); + return CTX; +} + +/* B.2.3.3.2.5. OsslPopContext() */ +/* This is the companion function to OsslPushContext(). */ +void +OsslPopContext( + BN_CTX *CTX + ) +{ + // BN_CTX_end can't be called with NULL. It will blow up. + if(CTX != NULL) + BN_CTX_end(CTX); +} + +#endif // HASH_LIB_OSSL || MATH_LIB_OSSL || SYM_LIB_OSSL diff --git a/src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h b/src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h new file mode 100644 index 0000000..c8d7b5a --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h @@ -0,0 +1,83 @@ +/********************************************************************************/ +/* */ +/* Initialization of the Interface to the OpenSSL Library */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslSupport_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#ifndef TPMTOOSSLSUPPORT_FP_H +#define TPMTOOSSLSUPPORT_FP_H + +BN_CTX * +OsslContextEnter( + void + ); +void +OsslContextLeave( + BN_CTX *context + ); +BN_CTX * +OsslPushContext( + BN_CTX *CTX + ); +void +OsslPopContext( + BN_CTX *CTX + ); + + +#endif diff --git a/src/tpm2/crypto/openssl/TpmToOsslSym.h b/src/tpm2/crypto/openssl/TpmToOsslSym.h new file mode 100644 index 0000000..521204f --- /dev/null +++ b/src/tpm2/crypto/openssl/TpmToOsslSym.h @@ -0,0 +1,197 @@ +/********************************************************************************/ +/* */ +/* Splice the OpenSSL() library into the TPM code. */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: TpmToOsslSym.h 1619 2020-05-19 16:51:47Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* B.2.3.2. TpmToOsslSym.h */ +/* B.2.3.2.1. Introduction */ +/* This header file is used to splice the OpenSSL() library into the TPM code. */ +/* The support required of a library are a hash module, a block cipher module and portions of a big + number library. All of the library-dependent headers should have the same guard to that only the + first one gets defined. */ + +#ifndef SYM_LIB_DEFINED +#define SYM_LIB_DEFINED +#define SYM_LIB_OSSL +#include +#if ALG_TDES +#include +#endif + +#if ALG_SM4 +# if defined(OPENSSL_NO_SM4) || OPENSSL_VERSION_NUMBER < 0x10101010L +# undef ALG_SM4 +# define ALG_SM4 ALG_NO +# elif OPENSSL_VERSION_NUMBER >= 0x10200000L +# include +# else +// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory, +// and they do not get installed as part of the libssl package + +# define SM4_KEY_SCHEDULE 32 + +typedef struct SM4_KEY_st { + uint32_t rk[SM4_KEY_SCHEDULE]; +} SM4_KEY; + +int SM4_set_key(const uint8_t *key, SM4_KEY *ks); +void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); +void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); +# endif // OpenSSL < 1.2 +#endif // ALG_SM4 + +#if ALG_CAMELLIA +#include +#endif +#include +#include + +/* B.2.2.3.2. Links to the OpenSSL symmetric algorithms */ +// The Crypt functions that call the block encryption function use the parameters in the order: +// a) keySchedule +// b) in buffer +// c) out buffer Since open SSL uses the order in encryptoCall_t above, need to swizzle the values +// to the order required by the library. + +#define SWIZZLE(keySchedule, in, out) \ + (const BYTE *)(in), (BYTE *)(out), (void *)(keySchedule) + +// Define the order of parameters to the library functions that do block encryption and decryption. + +typedef void(*TpmCryptSetSymKeyCall_t)( + const BYTE *in, + BYTE *out, + void *keySchedule + ); + +#define SYM_ALIGNMENT 4 /* libtpms: keep old value */ + +/* B.2.2.3.3. Links to the OpenSSL AES code */ +/* Macros to set up the encryption/decryption key schedules */ + +#define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) \ + AES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES *)(schedule)) +#define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule) \ + AES_set_decrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES *)(schedule)) + +/* Macros to alias encryption calls to specific algorithms. This should be used + sparingly. Currently, only used by CryptSym.c and CryptRand.c */ +/* When using these calls, to call the AES block encryption code, the caller should use: + TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)); */ + +#define TpmCryptEncryptAES AES_encrypt +#define TpmCryptDecryptAES AES_decrypt +#define tpmKeyScheduleAES AES_KEY + +/* B.2.2.3.4. Links to the OpenSSL DES code */ + +#if ALG_TDES && 0 // libtpms changed +#include "TpmToOsslDesSupport_fp.h" +#endif + +#define TpmCryptSetEncryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) +#define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) + +/* Macros to alias encryption calls to specific algorithms. This should be used + sparingly. Currently, only used by CryptRand.c */ + +#define TpmCryptEncryptTDES TDES_encrypt +#define TpmCryptDecryptTDES TDES_decrypt +#define tpmKeyScheduleTDES DES_key_schedule + +#if ALG_TDES // libtpms added begin +#include "TpmToOsslDesSupport_fp.h" +#endif // libtpms added end + +/* B.2.2.3.5. Links to the OpenSSL SM4 code */ +/* Macros to set up the encryption/decryption key schedules */ + +#define TpmCryptSetEncryptKeySM4(key, keySizeInBits, schedule) \ + SM4_set_key((key), (tpmKeyScheduleSM4 *)(schedule)) +#define TpmCryptSetDecryptKeySM4(key, keySizeInBits, schedule) \ + SM4_set_key((key), (tpmKeyScheduleSM4 *)(schedule)) +/* Macros to alias encryption calls to specific algorithms. This should be used sparingly. */ + +#define TpmCryptEncryptSM4 SM4_encrypt +#define TpmCryptDecryptSM4 SM4_decrypt +#define tpmKeyScheduleSM4 SM4_KEY + +/* B.2.2.3.6. Links to the OpenSSL CAMELLIA code */ +/* Macros to set up the encryption/decryption key schedules */ + +#define TpmCryptSetEncryptKeyCAMELLIA(key, keySizeInBits, schedule) \ + Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA *)(schedule)) +#define TpmCryptSetDecryptKeyCAMELLIA(key, keySizeInBits, schedule) \ + Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA *)(schedule)) + +/* Macros to alias encryption calls to specific algorithms. This should be used sparingly. */ + +#define TpmCryptEncryptCAMELLIA Camellia_encrypt +#define TpmCryptDecryptCAMELLIA Camellia_decrypt +#define tpmKeyScheduleCAMELLIA CAMELLIA_KEY + +/* Forward reference */ + +// kgold typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; + +/* This definition would change if there were something to report */ +#define SymLibSimulationEnd() +#endif // SYM_LIB_DEFINED diff --git a/src/tpm2/crypto/openssl/consttime.txt b/src/tpm2/crypto/openssl/consttime.txt new file mode 100644 index 0000000..6dd8328 --- /dev/null +++ b/src/tpm2/crypto/openssl/consttime.txt @@ -0,0 +1,76 @@ +The following (top level) OpenSSL public BIGNUM functions check for +the BN_FLG_CONSTTIME: + +bn_blind.c: + BN_BLINDING_new() + +bn_exp.c: + BN_exp : must not be set for input bignums +! BN_mod_exp : SHOULD be set for any one of input bignums (only) if m is odd + BN_mod_exp_recp: must NOT be set for input bignums + BN_mod_exp_mont: SHOULD be set for any one of input bignums + BN_mod_exp_mont_word: must NOT be set for input bignums + BN_mod_exp_simple: must NOT bet set for input bignums + +bn_gcd.c: +! BN_mod_inverse: SHOULD be set for any one of input bignums + +bn_lib: + BN_num_bits +! BN_copy + +bn_mont.c: + BN_MONT_CTX_set + +bn.h: +! BN_num_bytes: Calls BN_num_bits + + +Relevant files and functions in the files: +Helpers.c + ComputePrivateExponentD: + - BN_dup: -> BN_copy: YES, BN_FLG_CONSTTIME set by caller on P and Q + - BN_sub: no + - BN_add_word: no + - BN_mod_inverse: YES, DONE + InitOpenSSLRSAPublicKey: + - BN_set_word: no + - BN_bin2bn: no + InitOpenSSLRSAPrivateKey: + - BN_bin2bn: no + - BN_div: -> BN_copy: YES, DONE + - BN_is_zero: no + +TpmToOsslMath: + OsslToTpmBn: + - BN_num_bytes: need not + - BN_bn2bin: -> BN_num_bytes: need not + BigInitialized: + - BN_bin2bn: no + - BN_copy: YES, DONE + BnModMult: + - BN_mul: no + - BN_div: -> BN_copy: ? + BnMult: + - BN_mul: no + BnDiv: + - BN_div: -> BN_copy: ? + BnGcd: /* FUNCTION IS NOT USED */ + - BN_gcd: -> BN_copy, BN_num_bits: YES, DONE + BnModExp: + - BN_mod_exp: YES, DONE + BnModInverse: + - BN_mod_inverse: YES, DONE + + +Elliptic curve signing : + +CryptEccMain.c: + BnEccGenerateKeyPair: + - BnEccModMult: YES, DONE (we have control over random number bnD) + called by BnSignEcSchnorr + called by BnSignEcdsa (if OpenSSL function not used) + +CryptEccSignature.c: + BnEccSignSM2: + - BnEccModMult: YES, DONE (we have control over random number bnK) diff --git a/src/tpm2/crypto/openssl/consttime.txt' b/src/tpm2/crypto/openssl/consttime.txt' new file mode 100644 index 0000000..b667086 --- /dev/null +++ b/src/tpm2/crypto/openssl/consttime.txt' @@ -0,0 +1,58 @@ +The following OpenSSL public BIGNUM functions check for the BN_FLG_CONSTTIME: + +bn_blind.c: + BN_BLINDING_new() + +bn_exp.c: + BN_exp : must not be set for input bignums +! BN_mod_exp : SHOULD be set for any one of input bignums (only) if m is odd + BN_mod_exp_recp: must NOT be set for input bignums + BN_mod_exp_mont: SHOULD be set for any one of input bignums + BN_mod_exp_mont_word: must NOT be set for input bignums + BN_mod_exp_simple: must NOT bet set for input bignums + +bn_gcd.c: +! BN_mod_inverse: SHOULD be set for any one of input bignums + +bn_lib: + BN_num_bits +! BN_copy + +bn_mont.c: + BN_MONT_CTX_set + +bn.h: +! BN_num_bytes: Calls BN_num_bits + + +Relevant files and functions in the files: +Helpers.c + - BN_dup: + - BN_sub: + - BN_add_word: + - BN_mod_inverse: yes + - BN_set_word: + - BN_bin2bn: + - BN_div: + - BN_is_zero: + +TpmToOsslMath: + OsslToTpmBn: + - BN_num_bytes: + - BN_bn2bin: + BigInitialized: + - BN_bin2bn: + - BN_copy: + BnModMult: + - BN_mul: + - BN_div: + BnMult: + - BN_mul: + BnDiv: + - BN_div: + BnGcd: + - BN_gcd: + BnModExp: + - BN_mod_exp: YES + BnModInverse: + - BN_mod_inverse: YES diff --git a/src/tpm2/gensymtestsdata.sh b/src/tpm2/gensymtestsdata.sh new file mode 100755 index 0000000..1c51c2f --- /dev/null +++ b/src/tpm2/gensymtestsdata.sh @@ -0,0 +1,195 @@ +#!/bin/bash + +function do_aes() { + local data="$1" + local osslflag="$2" + + for keysize in 128 192 256; do + tmp=AES_KEY_${keysize} + key=$(eval echo \$$tmp) + for mode in ecb cbc cfb ofb ctr; do + cipher="aes-${keysize}-${mode}" + bs=$((128 / 8)) + iv="" + ivparm="" + case $mode in + ecb) + ;; + ctr) + v=255 + for ((c=0; c < bs; c++)); do + iv="$(printf "%02x" $v)${iv}" + v=$((v - 1)) + done + ivparm="-iv ${iv}" + ;; + *) + for ((c=0; c < bs; c++)); do + iv="${iv}$(printf "%02x" $c)" + done + ivparm="-iv ${iv}" + ;; + esac + echo -n "$cipher: " + openssl enc -e -K "${key}" ${ivparm} -${cipher} -in <(echo -en "$data") ${osslflag} | \ + od -t x1 -w128 -An | \ + sed -n 's/ \([a-f0-9]\{2\}\)/ 0x\1/pg' + done + done +} + +function do_camellia() { + local data="$1" + local osslflag="$2" + + for keysize in 128 192 256; do + tmp=CAMELLIA_KEY_${keysize} + key=$(eval echo \$$tmp) + for mode in ecb cbc cfb ofb ctr; do + cipher="camellia-${keysize}-${mode}" + bs=$((128 / 8)) + iv="" + ivparm="" + case $mode in + ecb) + ;; + ctr) + v=255 + for ((c=0; c < bs; c++)); do + iv="$(printf "%02x" $v)${iv}" + v=$((v - 1)) + done + ivparm="-iv ${iv}" + ;; + *) + for ((c=0; c < bs; c++)); do + iv="${iv}$(printf "%02x" $c)" + done + ivparm="-iv ${iv}" + ;; + esac + echo -n "$cipher: " + openssl enc -e -K "${key}" ${ivparm} -${cipher} -in <(echo -en "$data") ${osslflag} | \ + od -t x1 -w128 -An | \ + sed -n 's/ \([a-f0-9]\{2\}\)/ 0x\1/pg' + done + done +} + +function do_tdes() { + local data="$1" + local osslflag="$2" + + for keysize in 128 192; do + tmp=TDES_KEY_${keysize} + key=$(eval echo \$$tmp) + for mode in ecb cbc cfb ofb; do + cipher="des-ede3-${mode}" + iv="" + ivparm="" + bs=8 + case $mode in + ecb) + ;; + *) + for ((c=0; c < bs; c++)); do + iv="${iv}$(printf "%02x" $c)" + done + ivparm="-iv ${iv}" + ;; + esac + echo -n "$cipher [${keysize}]: " + case $mode in + ecb|cbc) + if [[ "${osslflag}" =~ "nopad" ]]; then + echo " Not supported without padding to blocksize" + continue + fi + ;; + esac + openssl enc -e -K "${key}" ${ivparm} -${cipher} -in <(echo -en "$data") ${osslflag} | \ + od -t x1 -w128 -An | \ + sed -n 's/ \([a-f0-9]\{2\}\)/ 0x\1/pg' + done + done +} + +function do_sm4() { + local data="$1" + local osslflag="$2" + + for keysize in 128; do + tmp=SM4_KEY_${keysize} + key=$(eval echo \$$tmp) + for mode in ecb cbc cfb ofb ctr; do + cipher="sm4-${mode}" + bs=$((128 / 8)) + iv="" + ivparm="" + case $mode in + ecb) + ;; + ctr) + v=255 + for ((c=0; c < bs; c++)); do + iv="$(printf "%02x" $v)${iv}" + v=$((v - 1)) + done + ivparm="-iv ${iv}" + ;; + *) + for ((c=0; c < bs; c++)); do + iv="${iv}$(printf "%02x" $c)" + done + ivparm="-iv ${iv}" + ;; + esac + echo -n "$cipher: " + openssl enc -e -K "${key}" ${ivparm} -${cipher} -in <(echo -en "$data") ${osslflag} | \ + od -t x1 -w128 -An | \ + sed -n 's/ \([a-f0-9]\{2\}\)/ 0x\1/pg' + done + done +} + + +AES_KEY_128='2b7e151628aed2a6abf7158809cf4f3c' +AES_KEY_192='8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' +AES_KEY_256='603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' +AES_DATA_IN='\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51' + +echo "----- AES -----" +do_aes "${AES_DATA_IN}" "" +echo "---------------" + +# We need to extend the 128 bit key to be 192 bit key otherwise 3rd schedule is all zeroes +TDES_KEY_128=${AES_KEY_128}${AES_KEY_128:0:16} +TDES_KEY_192=${AES_KEY_192} +TDES_DATA_IN=${AES_DATA_IN} + +echo "----- TDES -----" +do_tdes "${TDES_DATA_IN}" "" +echo "----------------" + + +echo "---- TDES (short input) -----" +do_tdes "\x31\x32\x33\x34\x35" "-nopad" +echo "----------------" + +CAMELLIA_KEY_128=${AES_KEY_128} +CAMELLIA_KEY_192=${AES_KEY_192} +CAMELLIA_KEY_256=${AES_KEY_256} +CAMELLIA_DATA_IN=${AES_DATA_IN} + +echo "----- CAMELLIA -----" +do_camellia "${CAMELLIA_DATA_IN}" "" +echo "--------------------" + +if [ -n "$(openssl enc -ciphers | grep sm4)" ]; then + SM4_KEY_128='0123456789abcdeffedcba9876543210' + SM4_DATA_IN='\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb' + + echo "-------- SM4 -------" + do_sm4 "${SM4_DATA_IN}" "" + echo "--------------------" +fi diff --git a/src/tpm2/swap.h b/src/tpm2/swap.h new file mode 100644 index 0000000..42a2440 --- /dev/null +++ b/src/tpm2/swap.h @@ -0,0 +1,120 @@ +/********************************************************************************/ +/* */ +/* Swap */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: swap.h 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ +/* */ +/********************************************************************************/ + +#ifndef SWAP_H +#define SWAP_H + +#if LITTLE_ENDIAN_TPM +#define TO_BIG_ENDIAN_UINT16(i) REVERSE_ENDIAN_16(i) +#define FROM_BIG_ENDIAN_UINT16(i) REVERSE_ENDIAN_16(i) +#define TO_BIG_ENDIAN_UINT32(i) REVERSE_ENDIAN_32(i) +#define FROM_BIG_ENDIAN_UINT32(i) REVERSE_ENDIAN_32(i) +#define TO_BIG_ENDIAN_UINT64(i) REVERSE_ENDIAN_64(i) +#define FROM_BIG_ENDIAN_UINT64(i) REVERSE_ENDIAN_64(i) +#else +#define TO_BIG_ENDIAN_UINT16(i) (i) +#define FROM_BIG_ENDIAN_UINT16(i) (i) +#define TO_BIG_ENDIAN_UINT32(i) (i) +#define FROM_BIG_ENDIAN_UINT32(i) (i) +#define TO_BIG_ENDIAN_UINT64(i) (i) +#define FROM_BIG_ENDIAN_UINT64(i) (i) +#endif +#if AUTO_ALIGN == NO +/* The aggregation macros for machines that do not allow unaligned access or for little-endian + machines. Aggregate bytes into an UINT */ +#define BYTE_ARRAY_TO_UINT8(b) (uint8_t)((b)[0]) +#define BYTE_ARRAY_TO_UINT16(b) ByteArrayToUint16((BYTE *)(b)) +#define BYTE_ARRAY_TO_UINT32(b) ByteArrayToUint32((BYTE *)(b)) +#define BYTE_ARRAY_TO_UINT64(b) ByteArrayToUint64((BYTE *)(b)) +#define UINT8_TO_BYTE_ARRAY(i, b) ((b)[0] = (uint8_t)(i)) +#define UINT16_TO_BYTE_ARRAY(i, b) Uint16ToByteArray((i), (BYTE *)(b)) +#define UINT32_TO_BYTE_ARRAY(i, b) Uint32ToByteArray((i), (BYTE *)(b)) +#define UINT64_TO_BYTE_ARRAY(i, b) Uint64ToByteArray((i), (BYTE *)(b)) +#else // AUTO_ALIGN +#if BIG_ENDIAN_TPM +/* The big-endian macros for machines that allow unaligned memory access Aggregate a byte + array into a UINT */ +#define BYTE_ARRAY_TO_UINT8(b) *((uint8_t *)(b)) +#define BYTE_ARRAY_TO_UINT16(b) *((uint16_t *)(b)) +#define BYTE_ARRAY_TO_UINT32(b) *((uint32_t *)(b)) +#define BYTE_ARRAY_TO_UINT64(b) *((uint64_t *)(b)) +/* Disaggregate a UINT into a byte array */ +#define UINT8_TO_BYTE_ARRAY(i, b) {*((uint8_t *)(b)) = (i);} +#define UINT16_TO_BYTE_ARRAY(i, b) {*((uint16_t *)(b)) = (i);} +#define UINT32_TO_BYTE_ARRAY(i, b) {*((uint32_t *)(b)) = (i);} +#define UINT64_TO_BYTE_ARRAY(i, b) {*((uint64_t *)(b)) = (i);} +#else +/* the little endian macros for machines that allow unaligned memory access the big-endian macros + for machines that allow unaligned memory access Aggregate a byte array into a UINT */ +#define BYTE_ARRAY_TO_UINT8(b) *((uint8_t *)(b)) +#define BYTE_ARRAY_TO_UINT16(b) REVERSE_ENDIAN_16(*((uint16_t *)(b))) +#define BYTE_ARRAY_TO_UINT32(b) REVERSE_ENDIAN_32(*((uint32_t *)(b))) +#define BYTE_ARRAY_TO_UINT64(b) REVERSE_ENDIAN_64(*((uint64_t *)(b))) +/* Disaggregate a UINT into a byte array */ +#define UINT8_TO_BYTE_ARRAY(i, b) {*((uint8_t *)(b)) = (i);} +#define UINT16_TO_BYTE_ARRAY(i, b) {*((uint16_t *)(b)) = REVERSE_ENDIAN_16(i);} +#define UINT32_TO_BYTE_ARRAY(i, b) {*((uint32_t *)(b)) = REVERSE_ENDIAN_32(i);} +#define UINT64_TO_BYTE_ARRAY(i, b) {*((uint64_t *)(b)) = REVERSE_ENDIAN_64(i);} +#endif // BIG_ENDIAN_TPM +#endif // AUTO_ALIGN == NO + + +#endif diff --git a/src/tpm_debug.c b/src/tpm_debug.c new file mode 100644 index 0000000..7c1efdf --- /dev/null +++ b/src/tpm_debug.c @@ -0,0 +1,134 @@ +/********************************************************************************/ +/* */ +/* TPM Debug Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_debug.c 4179 2010-11-10 20:10:24Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#include "tpm_debug.h" +#undef printf + +#if 0 + +int swallow_rc = 0; + +int tpm_swallow_printf_args(const char *format, ...) +{ + format = format; /* to silence compiler */ + return 0; +} + +#else + +void TPM_PrintFourLimit(const char *string, + const unsigned char *buff, size_t buflen) +{ + if (buff != NULL) { + switch (buflen) { + case 0: + TPMLIB_LogPrintf("%s (no data)\n", string); + break; + case 1: + TPMLIB_LogPrintf("%s %02x\n", + string, + buff[0]); + break; + case 2: + TPMLIB_LogPrintf("%s %02x %02x\n", + string, + buff[0], + buff[1]); + break; + case 3: + TPMLIB_LogPrintf("%s %02x %02x %02x\n", + string, + buff[0], + buff[1], + buff[2]); + break; + default: + TPMLIB_LogPrintf("%s %02x %02x %02x %02x\n", + string, + buff[0], + buff[1], + buff[2], + buff[3]); + } + } + else { + TPMLIB_LogPrintf("%s null\n", string); + } + return; +} + +/* TPM_PrintFour() prints a prefix plus 4 bytes of a buffer */ + +void TPM_PrintFour(const char *string, const unsigned char* buff) +{ + TPM_PrintFourLimit(string, buff, 4); +} + +#endif + +/* TPM_PrintAll() prints 'string', the length, and then the entire byte array + */ + +void TPM_PrintAll(const char *string, const unsigned char* buff, uint32_t length) +{ + uint32_t i; + int indent; + + if (buff != NULL) { + indent = TPMLIB_LogPrintf("%s length %u\n", string, length); + if (indent < 0) + return; + + for (i = 0 ; i < length ; i++) { + if (i && !( i % 16 )) + TPMLIB_LogPrintfA(0, "\n"); + + if (!(i % 16)) + TPMLIB_LogPrintf(" %.2X ", buff[i]); + else + TPMLIB_LogPrintfA(0, "%.2X ", buff[i]); + } + TPMLIB_LogPrintfA(0, "\n"); + } else { + TPMLIB_LogPrintf("%s null\n", string); + } + return; +} diff --git a/src/tpm_debug.h b/src/tpm_debug.h new file mode 100644 index 0000000..a9671d6 --- /dev/null +++ b/src/tpm_debug.h @@ -0,0 +1,71 @@ +/********************************************************************************/ +/* */ +/* TPM Debug Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_debug.h 4179 2010-11-10 20:10:24Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_DEBUG_H +#define TPM_DEBUG_H + +#include "tpm_types.h" +#include "tpm_library_intern.h" + +/* prototypes */ + +void TPM_PrintFour(const char *string, const unsigned char* buff); +void TPM_PrintFourLimit(const char *string, + const unsigned char* buff, size_t bufflen); +void TPM_PrintAll(const char *string, const unsigned char* buff, uint32_t length); + +#if 0 +#ifndef TPM_DEBUG /* if debug is turned off */ + +/* dummy function to match the printf prototype */ +int tpm_swallow_printf_args(const char *format, ...); + +/* assign to this dummy value to eliminate "statement has no effect" warnings */ +extern int swallow_rc; + +/* redefine printf to null */ +#define printf swallow_rc = swallow_rc && tpm_swallow_printf_args +#define TPM_PrintFour(arg1, arg2) + +#endif /* TPM_DEBUG */ +#endif + +#define printf(...) TPMLIB_LogPrintf(__VA_ARGS__); + +#endif diff --git a/src/tpm_library.c b/src/tpm_library.c new file mode 100644 index 0000000..5dd8fa4 --- /dev/null +++ b/src/tpm_library.c @@ -0,0 +1,677 @@ +/********************************************************************************/ +/* */ +/* LibTPM interface functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_library.c 4615 2011-08-30 15:35:24Z stefanb $ */ +/* */ +/* (c) Copyright IBM Corporation 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#include +#include +#if defined __FreeBSD__ +# define _WITH_DPRINTF +#endif +#include +#include +#include +#include +#include +#include + +#ifdef USE_FREEBL_CRYPTO_LIBRARY +# include +#endif + +#ifdef USE_OPENSSL_CRYPTO_LIBRARY +# include +# include +#endif + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_library.h" +#include "tpm_library_intern.h" +#include "tpm_nvfilename.h" +#include "tpm_tis.h" + +static const struct tags_and_indices { + const char *starttag; + const char *endtag; +} tags_and_indices[] = { + [TPMLIB_BLOB_TYPE_INITSTATE] = + { + .starttag = TPMLIB_INITSTATE_START_TAG, + .endtag = TPMLIB_INITSTATE_END_TAG, + }, +}; + +static const struct tpm_interface *const tpm_iface[] = { +#if WITH_TPM1 + &TPM12Interface, +#else + &DisabledInterface, +#endif +#if WITH_TPM2 + &TPM2Interface, +#else + &DisabledInterface, +#endif + NULL, +}; + +static int debug_fd = -1; +static unsigned debug_level = 0; +static char *debug_prefix = NULL; + +static struct sized_buffer cached_blobs[TPMLIB_STATE_SAVE_STATE + 1]; + +static int tpmvers_choice = 0; /* default is TPM1.2 */ +static TPM_BOOL tpmvers_locked = FALSE; + +uint32_t TPMLIB_GetVersion(void) +{ + return TPM_LIBRARY_VERSION; +} + +TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion ver) +{ + /* TPMLIB_Terminate will reset previous choice */ + if (tpmvers_locked) + return TPM_FAIL; + + switch (ver) { +#if WITH_TPM1 + case TPMLIB_TPM_VERSION_1_2: + if (tpmvers_choice != 0) + ClearAllCachedState(); + + tpmvers_choice = 0; // entry 0 in tpm_iface + return TPM_SUCCESS; +#endif +#if WITH_TPM2 + case TPMLIB_TPM_VERSION_2: + if (tpmvers_choice != 1) + ClearAllCachedState(); + + tpmvers_choice = 1; // entry 1 in tpm_iface + return TPM_SUCCESS; +#endif + default: + return TPM_FAIL; + } +} + +TPM_RESULT TPMLIB_MainInit(void) +{ + if (!tpm_iface[tpmvers_choice]) { + return TPM_FAIL; + } + + tpmvers_locked = TRUE; + + return tpm_iface[tpmvers_choice]->MainInit(); +} + +void TPMLIB_Terminate(void) +{ + tpm_iface[tpmvers_choice]->Terminate(); + + tpmvers_locked = FALSE; +} + +/* + * Send a command to the TPM. The command buffer must hold a well formatted + * TPM command and the command_size indicate the size of the command. + * The respbuffer parameter may be provided by the user and grow if + * the respbufsize size indicator is determined to be too small for the + * response. In that case a new buffer will be allocated and the size of that + * buffer returned in the respbufsize parameter. resp_size describes the + * size of the actual response within the respbuffer. + */ +TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size, + uint32_t *respbufsize, + unsigned char *command, uint32_t command_size) +{ + return tpm_iface[tpmvers_choice]->Process(respbuffer, + resp_size, respbufsize, + command, command_size); +} + +/* + * Get the volatile state from the TPM. This function will return the + * buffer and the length of the buffer to the caller in case everything + * went alright. + */ +TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer, + uint32_t *buflen) +{ + return tpm_iface[tpmvers_choice]->VolatileAllStore(buffer, buflen); +} + +/* + * Have the TPM cancel an ongoing command + */ +TPM_RESULT TPMLIB_CancelCommand(void) +{ + return tpm_iface[tpmvers_choice]->CancelCommand(); +} + +/* + * Get a property of the TPM. The functions currently only + * return compile-time #defines but this may change in future + * versions where we may return parameters with which the TPM + * was created (rather than compiled). + */ +TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop, + int *result) +{ + switch (prop) { + case TPMPROP_TPM_BUFFER_MAX: + *result = TPM_BUFFER_MAX; + break; + + default: + return tpm_iface[tpmvers_choice]->GetTPMProperty(prop, result); + } + + return TPM_SUCCESS; +} + +char *TPMLIB_GetInfo(enum TPMLIB_InfoFlags flags) +{ + return tpm_iface[tpmvers_choice]->GetInfo(flags); +} + +TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st, + const unsigned char *buffer, uint32_t buflen) +{ + return tpm_iface[tpmvers_choice]->SetState(st, buffer, buflen); +} + +TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen) +{ + return tpm_iface[tpmvers_choice]->GetState(st, buffer, buflen); +} + +TPM_RESULT TPM_IO_Hash_Start(void) +{ + return tpm_iface[tpmvers_choice]->HashStart(); +} + +TPM_RESULT TPM_IO_Hash_Data(const unsigned char *data, uint32_t data_length) +{ + return tpm_iface[tpmvers_choice]->HashData(data, data_length); +} + +TPM_RESULT TPM_IO_Hash_End(void) +{ + return tpm_iface[tpmvers_choice]->HashEnd(); +} + +TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished) +{ + return tpm_iface[tpmvers_choice]->TpmEstablishedGet(tpmEstablished); +} + +TPM_RESULT TPM_IO_TpmEstablished_Reset(void) +{ + return tpm_iface[tpmvers_choice]->TpmEstablishedReset(); +} + +uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size, + uint32_t *min_size, + uint32_t *max_size) +{ + return tpm_iface[tpmvers_choice]->SetBufferSize(wanted_size, + min_size, + max_size); +} + +TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st, + unsigned int flags) +{ + return tpm_iface[tpmvers_choice]->ValidateState(st, flags); +} + +static struct libtpms_callbacks libtpms_cbs; + +struct libtpms_callbacks *TPMLIB_GetCallbacks(void) +{ + return &libtpms_cbs; +} + +TPM_RESULT TPMLIB_RegisterCallbacks(struct libtpms_callbacks *callbacks) +{ + int max_size = sizeof(struct libtpms_callbacks); + + /* restrict the size of the structure to what we know currently + future versions may know more callbacks */ + if (callbacks->sizeOfStruct < max_size) + max_size = callbacks->sizeOfStruct; + + /* clear the internal callback structure and copy the user provided + callbacks into it */ + memset(&libtpms_cbs, 0x0, sizeof(libtpms_cbs)); + memcpy(&libtpms_cbs, callbacks, max_size); + + return TPM_SUCCESS; +} + +static int is_base64ltr(char c) +{ + return ((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || + c == '+' || + c == '/' || + c == '='); +} + +#ifdef USE_OPENSSL_CRYPTO_LIBRARY +static unsigned char *TPMLIB_OpenSSL_Base64Decode(char *input, + unsigned int outputlen) +{ + BIO *b64, *bmem; + unsigned char *res = NULL; + int n; + + b64 = BIO_new(BIO_f_base64()); + if (!b64) { + return NULL; + } + + bmem = BIO_new_mem_buf(input, strlen(input)); + if (!bmem) { + BIO_free(b64); + goto cleanup; + } + bmem = BIO_push(b64, bmem); + BIO_set_flags(bmem, BIO_FLAGS_BASE64_NO_NL); + + res = malloc(outputlen); + if (!res) { + TPMLIB_LogError("Could not allocate %u bytes.\n", outputlen); + goto cleanup; + } + + n = BIO_read(bmem, res, outputlen); + if (n <= 0) { + free(res); + res = NULL; + goto cleanup; + } + +cleanup: + BIO_free_all(bmem); + + return res; +} +#endif + +/* + * Base64 decode the string starting at 'start' and the last + * valid character may be a 'end'. The length of the decoded string + * is returned in *length. + */ +static unsigned char *TPMLIB_Base64Decode(const char *start, const char *end, + size_t *length) +{ + unsigned char *ret = NULL; + char *input = NULL, *d; + const char *s; + char c; + unsigned int numbase64chars = 0; + + if (end < start) + return NULL; + + while (end > start && !is_base64ltr(*end)) + end--; + + end++; + + input = malloc(end - start + 1); + if (!input) { + TPMLIB_LogError("Could not allocate %u bytes.\n", + (unsigned int)(end - start + 1)); + return NULL; + } + + /* copy from source string skipping '\n' and '\r' and using + '=' to calculate the exact length */ + d = input; + s = start; + + while (s < end) { + c = *s; + if (is_base64ltr(c)) { + *d = c; + d++; + if (c != '=') { + numbase64chars++; + } + } else if (c == 0) { + break; + } + s++; + } + *d = 0; + + *length = (numbase64chars / 4) * 3; + switch (numbase64chars % 4) { + case 2: + case 3: + *length += (numbase64chars % 4) - 1; + break; + case 0: + break; + case 1: + fprintf(stderr,"malformed base64\n"); + goto err_exit; + break; + } + +#ifdef USE_FREEBL_CRYPTO_LIBRARY + ret = (unsigned char *)PL_Base64Decode(input, 0, NULL); +#endif + +#ifdef USE_OPENSSL_CRYPTO_LIBRARY + ret = TPMLIB_OpenSSL_Base64Decode(input, *length); +#endif + +err_exit: + free(input); + + return ret; +} + +static unsigned char *TPMLIB_GetPlaintext(const char *stream, + const char *starttag, + const char *endtag, + size_t *length) +{ + char *start, *end; + unsigned char *plaintext = NULL; + + start = strstr(stream, starttag); + if (start) { + start += strlen(starttag); + while (isspace((int)*start)) + start++; + end = strstr(start, endtag); + if (end) { + plaintext = TPMLIB_Base64Decode(start, --end, length); + } + } + return plaintext; +} + +TPM_RESULT TPMLIB_DecodeBlob(const char *buffer, enum TPMLIB_BlobType type, + unsigned char **result, size_t *result_len) +{ + TPM_RESULT res = TPM_SUCCESS; + + *result = TPMLIB_GetPlaintext(buffer, + tags_and_indices[type].starttag, + tags_and_indices[type].endtag, + result_len); + + if (*result == NULL) { + res = TPM_FAIL; + } + + return res; +} + +void TPMLIB_SetDebugFD(int fd) +{ + debug_fd = fd; +} + +void TPMLIB_SetDebugLevel(unsigned level) +{ + debug_level = level; +} + +TPM_RESULT TPMLIB_SetDebugPrefix(const char *prefix) +{ + free(debug_prefix); + + if (prefix) { + debug_prefix = strdup(prefix); + if (!debug_prefix) + return TPM_FAIL; + } else { + debug_prefix = NULL; + } + + return TPM_SUCCESS; +} + +int TPMLIB_LogPrintf(const char *format, ...) +{ + unsigned level = debug_level, i; + va_list args; + char buffer[256]; + int n; + + if (!debug_fd || !debug_level) + return -1; + + va_start(args, format); + n = vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + + if (n < 0 || n >= (int)sizeof(buffer)) + return -1; + + level--; + + i = 0; + while (1) { + if (buffer[i] == 0) + return -1; + if (buffer[i] != ' ') + break; + if (i == level) + return -1; + i++; + } + + if (debug_prefix) + dprintf(debug_fd, "%s", debug_prefix); + dprintf(debug_fd, "%s", buffer); + + return i; +} + +/* + * TPMLIB_LogPrintfA: Printf to the logfd without indentation check + * + * @indent: how many spaces to indent; indent of ~0 forces logging + * with indent 0 even if not debug_level is set + * @format: format to use for formatting the following parameters + * @...: varargs + */ +void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...) +{ + va_list args; + char spaces[20]; + int fd; + + if (indent != (unsigned int)~0) { + if (!debug_fd || !debug_level) + return; + fd = debug_fd; + } else { + indent = 0; + fd = (debug_fd >= 0) ? debug_fd : STDERR_FILENO; + } + + if (indent) { + if (indent > sizeof(spaces) - 1) + indent = sizeof(spaces) - 1; + memset(spaces, ' ', indent); + spaces[indent] = 0; + dprintf(fd, "%s", spaces); + } + + va_start(args, format); + vdprintf(fd, format, args); + va_end(args); +} + +/* + * TPMLIB_LogArray: Display an array of data + * + * @indent: how many spaces to indent; indent of ~0 forces logging + * with indent 0 even if not debug_level is set + * @data: the data to print + * @datalen: length of the data + */ +void TPMLIB_LogArray(unsigned int indent, const unsigned char *data, + size_t datalen) +{ + char line[80]; + size_t i, o = 0; + + for (i = 0; i < datalen; i++) { + snprintf(&line[o], sizeof(line) - o, "%02x ", data[i]); + o += 3; + if (o >= 16 * 3) { + TPMLIB_LogPrintfA(indent, "%s\n", line); + o = 0; + } + } + if (o > 0) { + TPMLIB_LogPrintfA(indent, "%s\n", line); + } +} + +void ClearCachedState(enum TPMLIB_StateType st) +{ + free(cached_blobs[st].buffer); + cached_blobs[st].buffer = NULL; + cached_blobs[st].buflen = 0; +} + +void ClearAllCachedState(void) +{ + ClearCachedState(TPMLIB_STATE_VOLATILE); + ClearCachedState(TPMLIB_STATE_PERMANENT); + ClearCachedState(TPMLIB_STATE_SAVE_STATE); +} + +/* + * Set buffer for cached state; we allow setting an empty cached state + * by the caller passing a NULL pointer for the buffer. + */ +void SetCachedState(enum TPMLIB_StateType st, + unsigned char *buffer, uint32_t buflen) +{ + free(cached_blobs[st].buffer); + cached_blobs[st].buffer = buffer; + cached_blobs[st].buflen = buffer ? buflen : BUFLEN_EMPTY_BUFFER; +} + +void GetCachedState(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen, + bool *is_empty_buffer) +{ + /* caller owns blob now */ + *buffer = cached_blobs[st].buffer; + *buflen = cached_blobs[st].buflen; + *is_empty_buffer = (*buflen == BUFLEN_EMPTY_BUFFER); + cached_blobs[st].buffer = NULL; + cached_blobs[st].buflen = 0; +} + +bool HasCachedState(enum TPMLIB_StateType st) +{ + return (cached_blobs[st].buffer != NULL || cached_blobs[st].buflen != 0); +} + +TPM_RESULT CopyCachedState(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen, + bool *is_empty_buffer) +{ + TPM_RESULT ret = TPM_SUCCESS; + + /* buflen may indicate an empty buffer */ + *buflen = cached_blobs[st].buflen; + *is_empty_buffer = (*buflen == BUFLEN_EMPTY_BUFFER); + + if (cached_blobs[st].buffer) { + *buffer = malloc(*buflen); + if (!*buffer) { + TPMLIB_LogError("Could not allocate %u bytes.\n", *buflen); + ret = TPM_SIZE; + } else { + memcpy(*buffer, cached_blobs[st].buffer, *buflen); + } + } else { + *buffer = NULL; + } + + return ret; +} + +const char *TPMLIB_StateTypeToName(enum TPMLIB_StateType st) +{ + switch (st) { + case TPMLIB_STATE_PERMANENT: + return TPM_PERMANENT_ALL_NAME; + case TPMLIB_STATE_VOLATILE: + return TPM_VOLATILESTATE_NAME; + case TPMLIB_STATE_SAVE_STATE: + return TPM_SAVESTATE_NAME; + } + return NULL; +} + +enum TPMLIB_StateType TPMLIB_NameToStateType(const char *name) +{ + if (!name) + return 0; + if (!strcmp(name, TPM_PERMANENT_ALL_NAME)) + return TPMLIB_STATE_PERMANENT; + if (!strcmp(name, TPM_VOLATILESTATE_NAME)) + return TPMLIB_STATE_VOLATILE; + if (!strcmp(name, TPM_SAVESTATE_NAME)) + return TPMLIB_STATE_SAVE_STATE; + return 0; +} diff --git a/src/tpm_library_conf.h b/src/tpm_library_conf.h new file mode 100644 index 0000000..43e07e3 --- /dev/null +++ b/src/tpm_library_conf.h @@ -0,0 +1,172 @@ +/********************************************************************************/ +/* */ +/* LibTPM compile-time choices (#defines) */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_library_conf.h 4589 2011-07-05 12:22:40Z stefanb $ */ +/* */ +/* (c) Copyright IBM Corporation 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ +#ifndef TPM_LIBRARY_CONF_H +#define TPM_LIBRARY_CONF_H + +/* Note: None of these defines should be used directly; rather, + * the TPMLIB_GetTPMProperty() call should be used to + * query their value. + * Since tpm_constants.h defines some default values if none + * other are defined, this header should be included before + * tpm_constants.h is included. + */ + +/* need to restrict the maximum size of keys to cap the below blobs */ +#define TPM_RSA_KEY_LENGTH_MAX 2048 + +/* maximum size of the IO buffer used for requests and responses */ +#define TPM_BUFFER_MAX 4096 + +/* + * Below the following acronyms are used to identify what + * #define influences which one of the state blobs the TPM + * produces. + * + * PA : permanentall + * SS : savestate + * VA : volatileall + * + * BAL: contributes to the ballooning of the state blob + */ + +/* + * Do not touch these #define's anymore. They are fixed forever + * and define the properties of the TPM library and have a + * direct influence on the size requirements of the TPM's block + * store and the organization of data inside that block store. + */ +/* + * Every 2048 bit key in volatile space accounts for an + * increase of maximum of 559 bytes (PCR_INFO_LONG, tied to PCRs). + */ +#define TPM_KEY_HANDLES 20 /* SS, VA, BAL */ + +/* + * Every 2048 bit key on which the owner evict key flag is set + * accounts for an increase of 559 bytes of the permanentall + * blob. + */ +#define TPM_OWNER_EVICT_KEY_HANDLES 10 /* PA, BAL */ + +/* + * The largest auth session is DSAP; each such session consumes 119 bytes + */ +#define TPM_MIN_AUTH_SESSIONS 16 /* SS, VA, BAL */ + +/* + * Every transport session accounts for an increase of 78 bytes + */ +#define TPM_MIN_TRANS_SESSIONS 16 /* SS, VA, BAL */ +/* + * Every DAA session accounts for an increase of 844 bytes. + */ +#define TPM_MIN_DAA_SESSIONS 2 /* SS, VA, BAL */ + +#define TPM_MIN_SESSION_LIST 128 /* SS, VA */ +#define TPM_MIN_COUNTERS 8 /* PA */ +#define TPM_NUM_FAMILY_TABLE_ENTRY_MIN 16 /* PA */ +#define TPM_NUM_DELEGATE_TABLE_ENTRY_MIN 4 /* PA */ + +/* + * NB: above #defines directly influence the largest size of the + * 'permanentall', 'savestate' and 'volatileall' data. If these + * #define's allow the below space requirements to be exceeded, the + * TPM may go into shutdown mode, something we would definitely + * like to prevent. We are mostly concerned about the size of + * the 'permanentall' blob, which is capped by TPM_MAX_NV_SPACE, + * and that of the 'savestate' blob, which is capped by + * TPM_MAX_SAVESTATE_SPACE. + */ + +#define TPM_SPACE_SAFETY_MARGIN (4 * 1024) + +/* + * As of V0.5.1 (may have increased since then): + * permanent space + 10 keys = 7920 bytes + * full volatile space = 17223 bytes + * full savestate space = 16992 bytes + */ + +/* + * For the TPM_MAX_NV_SPACE we cannot provide a safety margin here + * since the TPM will allow NVRAM spaces to allocate everything. + * So, we tell the user in TPMLIB_GetTPMProperty that it's 20kb. This + * gives us some safety margin for the future. + */ +#define TPM_PERMANENT_ALL_BASE_SIZE (2334 /* incl. SRK, EK */ + \ + 2048 /* extra space */) + +#define TPM_MAX_NV_DEFINED_SIZE (2048 /* min. NVRAM spaces */ + \ + 26*1024 /* extra NVRAM space */ ) + +#define TPM_MAX_NV_SPACE (TPM_PERMANENT_ALL_BASE_SIZE + \ + TPM_OWNER_EVICT_KEY_HANDLES * 559 + \ + TPM_MAX_NV_DEFINED_SIZE) + +#define TPM_MAX_SAVESTATE_SPACE (972 + /* base size */ \ + TPM_KEY_HANDLES * 559 + \ + TPM_MIN_TRANS_SESSIONS * 78 + \ + TPM_MIN_DAA_SESSIONS * 844 + \ + TPM_MIN_AUTH_SESSIONS * 119 + \ + TPM_SPACE_SAFETY_MARGIN) + +#define TPM_MAX_VOLATILESTATE_SPACE (1203 + /* base size */ \ + TPM_KEY_HANDLES * 559 + \ + TPM_MIN_TRANS_SESSIONS * 78 + \ + TPM_MIN_DAA_SESSIONS * 844 + \ + TPM_MIN_AUTH_SESSIONS * 119 + \ + TPM_SPACE_SAFETY_MARGIN) + +/* + * The timeouts in microseconds. + * + * The problem with the timeouts is that on a heavily utilized + * virtualized platform, the processing of the TPM's commands will + * take much longer than on a system that's not very busy. So, we + * now choose values that are very high so that we don't hit timeouts + * in TPM drivers just because the system is busy. However, hitting + * timeouts on a very busy system may be inevitable... + */ + +#define TPM_SMALL_DURATION ( 50 * 1000 * 1000) +#define TPM_MEDIUM_DURATION (100 * 1000 * 1000) +#define TPM_LONG_DURATION (300 * 1000 * 1000) + + +#endif /* TPM_LIBRARY_CONF_H */ diff --git a/src/tpm_library_intern.h b/src/tpm_library_intern.h new file mode 100644 index 0000000..92c3722 --- /dev/null +++ b/src/tpm_library_intern.h @@ -0,0 +1,149 @@ +/********************************************************************************/ +/* */ +/* LibTPM internal interface functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_library_intern.h 4432 2011-02-11 15:30:31Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2011. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ +#ifndef TPM_LIBRARY_INTERN_H +#define TPM_LIBRARY_INTERN_H + +#include +#include "compiler.h" +#include "tpm_library.h" + +#define ROUNDUP(VAL, SIZE) \ + ( ( (VAL) + (SIZE) - 1 ) / (SIZE) ) * (SIZE) + +#define _STRINGIFY(x) #x +#define STRINGIFY(x) _STRINGIFY(x) + +struct libtpms_callbacks *TPMLIB_GetCallbacks(void); + +/* additional TPM 2 error codes from TPM 1.2 */ +#define TPM_RC_BAD_PARAMETER 0x03 +#define TPM_RC_BAD_VERSION 0x2e + +/* + * TPM functionality must all be accessible with this interface + */ +struct tpm_interface { + TPM_RESULT (*MainInit)(void); + void (*Terminate)(void); + uint32_t (*SetBufferSize)(uint32_t wanted_size, uint32_t *min_size, + uint32_t *max_size); + TPM_RESULT (*Process)(unsigned char **respbuffer, uint32_t *resp_size, + uint32_t *respbufsize, + unsigned char *command, uint32_t command_size); + TPM_RESULT (*VolatileAllStore)(unsigned char **buffer, uint32_t *buflen); + TPM_RESULT (*CancelCommand)(void); + TPM_RESULT (*GetTPMProperty)(enum TPMLIB_TPMProperty prop, + int *result); + char *(*GetInfo)(enum TPMLIB_InfoFlags flags); + TPM_RESULT (*TpmEstablishedGet)(TPM_BOOL *tpmEstablished); + TPM_RESULT (*TpmEstablishedReset)(void); + TPM_RESULT (*HashStart)(void); + TPM_RESULT (*HashData)(const unsigned char *data, + uint32_t data_length); + TPM_RESULT (*HashEnd)(void); + TPM_RESULT (*ValidateState)(enum TPMLIB_StateType st, + unsigned int flags); + TPM_RESULT (*SetState)(enum TPMLIB_StateType st, + const unsigned char *buffer, uint32_t buflen); + TPM_RESULT (*GetState)(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen); +}; + +extern const struct tpm_interface DisabledInterface; +extern const struct tpm_interface TPM12Interface; +extern const struct tpm_interface TPM2Interface; + +/* prototypes for TPM 1.2 */ +TPM_RESULT TPM12_IO_Hash_Start(void); +TPM_RESULT TPM12_IO_Hash_Data(const unsigned char *data, + uint32_t data_length); +TPM_RESULT TPM12_IO_Hash_End(void); +TPM_RESULT TPM12_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished); + +uint32_t TPM12_GetBufferSize(void); + +TPM_RESULT TPM12_IO_TpmEstablished_Reset(void); + +/* internal logging function */ +int TPMLIB_LogPrintf(const char *format, ...); +void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...) \ + ATTRIBUTE_FORMAT(2, 3); +void TPMLIB_LogArray(unsigned int indent, const unsigned char *data, + size_t datalen); + +#define TPMLIB_LogError(format, ...) \ + TPMLIB_LogPrintfA(~0, "libtpms: "format, __VA_ARGS__) +#define TPMLIB_LogTPM12Error(format, ...) \ + TPMLIB_LogPrintfA(~0, "libtpms/tpm12: "format, __VA_ARGS__) +#define TPMLIB_LogTPM2Error(format, ...) \ + TPMLIB_LogPrintfA(~0, "libtpms/tpm2: "format, __VA_ARGS__) + +/* prototypes for TPM2 */ +TPM_RESULT TPM2_IO_Hash_Start(void); +TPM_RESULT TPM2_IO_Hash_Data(const unsigned char *data, + uint32_t data_length); +TPM_RESULT TPM2_IO_Hash_End(void); +TPM_RESULT TPM2_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished); +TPM_RESULT TPM2_IO_TpmEstablished_Reset(void); + +struct sized_buffer { + unsigned char *buffer; + uint32_t buflen; +#define BUFLEN_EMPTY_BUFFER 0xFFFFFFFF +}; + +void ClearCachedState(enum TPMLIB_StateType st); +void ClearAllCachedState(void); +void SetCachedState(enum TPMLIB_StateType st, + unsigned char *buffer, uint32_t buflen); +void GetCachedState(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen, + bool *is_empty_buffer); +bool HasCachedState(enum TPMLIB_StateType st); +TPM_RESULT CopyCachedState(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen, + bool *is_empty_buffer); + +const char *TPMLIB_StateTypeToName(enum TPMLIB_StateType st); +enum TPMLIB_StateType TPMLIB_NameToStateType(const char *name); + +uint32_t TPM2_GetBufferSize(void); +TPM_RESULT TPM2_PersistentAllStore(unsigned char **buf, uint32_t *buflen); + +#endif /* TPM_LIBRARY_INTERN_H */ diff --git a/src/tpm_memory.c b/src/tpm_memory.c new file mode 100644 index 0000000..ce78a3e --- /dev/null +++ b/src/tpm_memory.c @@ -0,0 +1,130 @@ +/********************************************************************************/ +/* */ +/* TPM Memory Allocation */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_memory.c 4609 2011-08-26 19:27:38Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include + +#include "tpm_debug.h" +#include "tpm_error.h" + +#include "tpm_memory.h" + +/* TPM_Malloc() is a general purpose wrapper around malloc() + */ + +TPM_RESULT TPM_Malloc(unsigned char **buffer, uint32_t size) +{ + TPM_RESULT rc = 0; + + /* assertion test. The coding style requires that all allocated pointers are initialized to + NULL. A non-NULL value indicates either a missing initialization or a pointer reuse (a + memory leak). */ + if (rc == 0) { + if (*buffer != NULL) { + printf("TPM_Malloc: Error (fatal), *buffer %p should be NULL before malloc\n", *buffer); + rc = TPM_FAIL; + } + } + /* verify that the size is not "too large" */ + if (rc == 0) { + if (size > TPM_ALLOC_MAX) { + printf("TPM_Malloc: Error, size %u greater than maximum allowed\n", size); + rc = TPM_SIZE; + } + } + /* verify that the size is not 0, this would be implementation defined and should never occur */ + if (rc == 0) { + if (size == 0) { + printf("TPM_Malloc: Error (fatal), size is zero\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + *buffer = malloc(size); + if (*buffer == NULL) { + printf("TPM_Malloc: Error allocating %u bytes\n", size); + rc = TPM_SIZE; + } + } + return rc; +} + +/* TPM_Realloc() is a general purpose wrapper around realloc() + */ + +TPM_RESULT TPM_Realloc(unsigned char **buffer, + uint32_t size) +{ + TPM_RESULT rc = 0; + unsigned char *tmpptr = NULL; + + /* verify that the size is not "too large" */ + if (rc == 0) { + if (size > TPM_ALLOC_MAX) { + printf("TPM_Realloc: Error, size %u greater than maximum allowed\n", size); + rc = TPM_SIZE; + } + } + if (rc == 0) { + tmpptr = realloc(*buffer, size); + if (tmpptr == NULL) { + printf("TPM_Realloc: Error reallocating %u bytes\n", size); + rc = TPM_SIZE; + } + } + if (rc == 0) { + *buffer = tmpptr; + } + return rc; +} + +/* TPM_Free() is the companion to the TPM allocation functions. It is not used internally. The + intent is for use by an application that links directly to a TPM and wants to free memory + allocated by the TPM. + + It avoids a potential problem if the application uses a different allocation library, perhaps one + that wraps the functions to detect overflows or memory leaks. +*/ + +void TPM_Free(unsigned char *buffer) +{ + free(buffer); + return; +} + diff --git a/src/tpm_nvfile.c b/src/tpm_nvfile.c new file mode 100644 index 0000000..d9049e8 --- /dev/null +++ b/src/tpm_nvfile.c @@ -0,0 +1,418 @@ +/********************************************************************************/ +/* */ +/* NVRAM File Abstraction Layer */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_nvfile.c 4664 2012-01-03 22:15:08Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* This module abstracts out all NVRAM read and write operations. + + This implementation uses standard, portable C files. + + The basic high level abstractions are: + + TPM_NVRAM_LoadData(); + TPM_NVRAM_StoreData(); + TPM_NVRAM_DeleteName(); + + They take a 'name' that is mapped to a rooted file name. +*/ + +#include +#include +#include +#include + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_memory.h" + +#include "tpm_nvfile.h" + +#ifdef TPM_LIBTPMS_CALLBACKS +#include "tpm_library_intern.h" +#include "tpm_library.h" +#endif + + +/* local prototypes */ + +static TPM_RESULT TPM_NVRAM_GetFilenameForName(char *filename, + size_t filename_len, + uint32_t tpm_number, + const char *name); + + +/* A file name in NVRAM is composed of 3 parts: + + 1 - 'state_directory' is the rooted path to the TPM state home directory + 2 = 'tpm_number' is the TPM instance, 00 for a single TPM + 2 - the file name + + For the IBM cryptographic coprocessor version, the root path is hard coded. + + For the Linux and Windows versions, the path comes from an environment variable. This variable is + used once in TPM_NVRAM_Init(). + + One root path is used for all virtual TPM's, so it can be a static variable. +*/ + +char state_directory[FILENAME_MAX]; + +/* TPM_NVRAM_Init() is called once at startup. It does any NVRAM required initialization. + + This function sets some static variables that are used by all TPM's. +*/ + +TPM_RESULT TPM_NVRAM_Init(void) +{ + TPM_RESULT rc = 0; + char *tpm_state_path = NULL; + size_t length; + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + /* call user-provided function if available, otherwise execute + default behavior */ + if (cbs->tpm_nvram_init) { + rc = cbs->tpm_nvram_init(); + return rc; + } +#endif + + printf(" TPM_NVRAM_Init:\n"); +#ifdef TPM_NV_DISK + /* TPM_NV_DISK TPM emulation stores in local directory determined by environment variable. */ + if (rc == 0) { + tpm_state_path = getenv("TPM_PATH"); + if (tpm_state_path == NULL) { + printf("TPM_NVRAM_Init: Error (fatal), TPM_PATH environment variable not set\n"); + rc = TPM_FAIL; + } + } +#endif + /* check that the directory name plus a file name will not overflow FILENAME_MAX */ + if (rc == 0) { + length = strlen(tpm_state_path); + if ((length + TPM_FILENAME_MAX) > FILENAME_MAX) { + printf("TPM_NVRAM_Init: Error (fatal), TPM state path name %s too large\n", + tpm_state_path); + rc = TPM_FAIL; + } + } + if (rc == 0) { + strcpy(state_directory, tpm_state_path); + printf("TPM_NVRAM_Init: Rooted state path %s\n", state_directory); + } + return rc; +} + +/* Load 'data' of 'length' from the 'name'. + + 'data' must be freed after use. + + Returns + 0 on success. + TPM_RETRY and NULL,0 on non-existent file (non-fatal, first time start up) + TPM_FAIL on failure to load (fatal), since it should never occur +*/ + +TPM_RESULT TPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ + uint32_t *length, + uint32_t tpm_number, + const char *name) +{ + TPM_RESULT rc = 0; + long lrc; + size_t src; + int irc; + FILE *file = NULL; + char filename[FILENAME_MAX]; /* rooted file name from name */ + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs; + bool is_empty_buffer; + + /* try to get state blob set with TPMLIB_SetState() */ + GetCachedState(TPMLIB_NameToStateType(name), data, length, &is_empty_buffer); + if (is_empty_buffer) + return TPM_RETRY; + if (*data) + return TPM_SUCCESS; + + cbs = TPMLIB_GetCallbacks(); + + /* call user-provided function if available, otherwise execute + default behavior */ + if (cbs->tpm_nvram_loaddata) { + rc = cbs->tpm_nvram_loaddata(data, length, tpm_number, name); + return rc; + } +#endif + + printf(" TPM_NVRAM_LoadData: From file %s\n", name); + *data = NULL; + *length = 0; + /* open the file */ + if (rc == 0) { + /* map name to the rooted filename */ + rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename), + tpm_number, name); + } + if (rc == 0) { + printf(" TPM_NVRAM_LoadData: Opening file %s\n", filename); + file = fopen(filename, "rb"); /* closed @1 */ + if (file == NULL) { /* if failure, determine cause */ + if (errno == ENOENT) { + printf("TPM_NVRAM_LoadData: No such file %s\n", filename); + rc = TPM_RETRY; /* first time start up */ + } + else { + printf("TPM_NVRAM_LoadData: Error (fatal) opening %s for read, %s\n", + filename, strerror(errno)); + rc = TPM_FAIL; + } + } + } + /* determine the file length */ + if (rc == 0) { + irc = fseek(file, 0L, SEEK_END); /* seek to end of file */ + if (irc == -1L) { + printf("TPM_NVRAM_LoadData: Error (fatal) fseek'ing %s, %s\n", + filename, strerror(errno)); + rc = TPM_FAIL; + } + } + if (rc == 0) { + lrc = ftell(file); /* get position in the stream */ + if (lrc == -1L) { + printf("TPM_NVRAM_LoadData: Error (fatal) ftell'ing %s, %s\n", + filename, strerror(errno)); + rc = TPM_FAIL; + } + else { + *length = (uint32_t)lrc; /* save the length */ + } + } + if (rc == 0) { + irc = fseek(file, 0L, SEEK_SET); /* seek back to the beginning of the file */ + if (irc == -1L) { + printf("TPM_NVRAM_LoadData: Error (fatal) fseek'ing %s, %s\n", + filename, strerror(errno)); + rc = TPM_FAIL; + } + } + /* allocate a buffer for the actual data */ + if ((rc == 0) && *length != 0) { + printf(" TPM_NVRAM_LoadData: Reading %u bytes of data\n", *length); + rc = TPM_Malloc(data, *length); + if (rc != 0) { + printf("TPM_NVRAM_LoadData: Error (fatal) allocating %u bytes\n", *length); + rc = TPM_FAIL; + } + } + /* read the contents of the file into the data buffer */ + if ((rc == 0) && *length != 0) { + src = fread(*data, 1, *length, file); + if (src != *length) { + printf("TPM_NVRAM_LoadData: Error (fatal), data read of %u only read %lu\n", + *length, (unsigned long)src); + rc = TPM_FAIL; + } + } + /* close the file */ + if (file != NULL) { + printf(" TPM_NVRAM_LoadData: Closing file %s\n", filename); + irc = fclose(file); /* @1 */ + if (irc != 0) { + printf("TPM_NVRAM_LoadData: Error (fatal) closing file %s\n", filename); + rc = TPM_FAIL; + } + else { + printf(" TPM_NVRAM_LoadData: Closed file %s\n", filename); + } + } + return rc; +} + +/* TPM_NVRAM_StoreData stores 'data' of 'length' to the rooted 'filename' + + Returns + 0 on success + TPM_FAIL for other fatal errors +*/ + +TPM_RESULT TPM_NVRAM_StoreData(const unsigned char *data, + uint32_t length, + uint32_t tpm_number, + const char *name) +{ + TPM_RESULT rc = 0; + uint32_t lrc; + int irc; + FILE *file = NULL; + char filename[FILENAME_MAX]; /* rooted file name from name */ + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + /* call user-provided function if available, otherwise execute + default behavior */ + if (cbs->tpm_nvram_storedata) { + rc = cbs->tpm_nvram_storedata(data, length, tpm_number, name); + return rc; + } +#endif + + printf(" TPM_NVRAM_StoreData: To name %s\n", name); + if (rc == 0) { + /* map name to the rooted filename */ + rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename), + tpm_number, name); + } + if (rc == 0) { + /* open the file */ + printf(" TPM_NVRAM_StoreData: Opening file %s\n", filename); + file = fopen(filename, "wb"); /* closed @1 */ + if (file == NULL) { + printf("TPM_NVRAM_StoreData: Error (fatal) opening %s for write failed, %s\n", + filename, strerror(errno)); + rc = TPM_FAIL; + } + } + /* write the data to the file */ + if (rc == 0) { + printf(" TPM_NVRAM_StoreData: Writing %u bytes of data\n", length); + lrc = fwrite(data, 1, length, file); + if (lrc != length) { + printf("TPM_NVRAM_StoreData: Error (fatal), data write of %u only wrote %u\n", + length, lrc); + rc = TPM_FAIL; + } + } + if (file != NULL) { + printf(" TPM_NVRAM_StoreData: Closing file %s\n", filename); + irc = fclose(file); /* @1 */ + if (irc != 0) { + printf("TPM_NVRAM_StoreData: Error (fatal) closing file\n"); + rc = TPM_FAIL; + } + else { + printf(" TPM_NVRAM_StoreData: Closed file %s\n", filename); + } + } + return rc; +} + + +/* TPM_NVRAM_GetFilenameForName() constructs a rooted file name from the name. + + The filename is of the form: + + state_directory/tpm_number.name +*/ + +static TPM_RESULT TPM_NVRAM_GetFilenameForName(char *filename, /* output: rooted filename */ + size_t filename_len, + uint32_t tpm_number, + const char *name) /* input: abstract name */ +{ + int n; + TPM_RESULT rc = TPM_FAIL; + + printf(" TPM_NVRAM_GetFilenameForName: For name %s\n", name); + n = snprintf(filename, filename_len, + "%s/%02lx.%s", state_directory, (unsigned long)tpm_number, + name); + if (n < 0) { + printf(" TPM_NVRAM_GetFilenameForName: Error (fatal), snprintf failed\n"); + } else if ((size_t)n >= filename_len) { + printf(" TPM_NVRAM_GetFilenameForName: Error (fatal), buffer too small\n"); + } else { + printf(" TPM_NVRAM_GetFilenameForName: File name %s\n", filename); + rc = TPM_SUCCESS; + } + return rc; +} + +/* TPM_NVRAM_DeleteName() deletes the 'name' from NVRAM + + Returns: + 0 on success, or if the file does not exist and mustExist is FALSE + TPM_FAIL if the file could not be removed, since this should never occur and there is + no recovery + + NOTE: Not portable code, but supported by Linux and Windows +*/ + +TPM_RESULT TPM_NVRAM_DeleteName(uint32_t tpm_number, + const char *name, + TPM_BOOL mustExist) +{ + TPM_RESULT rc = 0; + int irc; + char filename[FILENAME_MAX]; /* rooted file name from name */ + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + /* call user-provided function if available, otherwise execute + default behavior */ + if (cbs->tpm_nvram_deletename) { + rc = cbs->tpm_nvram_deletename(tpm_number, name, mustExist); + return rc; + } +#endif + + printf(" TPM_NVRAM_DeleteName: Name %s\n", name); + /* map name to the rooted filename */ + if (rc == 0) { + rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename), + tpm_number, name); + } + if (rc == 0) { + irc = remove(filename); + if ((irc != 0) && /* if the remove failed */ + (mustExist || /* if any error is a failure, or */ + (errno != ENOENT))) { /* if error other than no such file */ + printf("TPM_NVRAM_DeleteName: Error, (fatal) file remove failed, errno %d\n", + errno); + rc = TPM_FAIL; + } + } + return rc; +} + diff --git a/src/tpm_nvfile.h b/src/tpm_nvfile.h new file mode 100644 index 0000000..69b5823 --- /dev/null +++ b/src/tpm_nvfile.h @@ -0,0 +1,71 @@ +/********************************************************************************/ +/* */ +/* NVRAM Utilities */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_nvfile.h 4623 2011-09-28 15:15:09Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2010. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_NVFILE_H +#define TPM_NVFILE_H + +#include "tpm_types.h" + +/* characters in the TPM base file name, 14 for file name, slash, NUL terminator, etc. + + This macro is used once during initialization to ensure that the TPM_PATH environment variable + length will not cause the rooted file name to overflow file name buffers. +*/ + +#define TPM_FILENAME_MAX 20 + +TPM_RESULT TPM_NVRAM_Init(void); + +/* + Basic abstraction for read and write +*/ + +TPM_RESULT TPM_NVRAM_LoadData(unsigned char **data, + uint32_t *length, + uint32_t tpm_number, + const char *name); +TPM_RESULT TPM_NVRAM_StoreData(const unsigned char *data, + uint32_t length, + uint32_t tpm_number, + const char *name); +TPM_RESULT TPM_NVRAM_DeleteName(uint32_t tpm_number, + const char *name, + TPM_BOOL mustExist); + +#endif diff --git a/src/tpm_tpm12_interface.c b/src/tpm_tpm12_interface.c new file mode 100644 index 0000000..6e3cde6 --- /dev/null +++ b/src/tpm_tpm12_interface.c @@ -0,0 +1,530 @@ +/********************************************************************************/ +/* */ +/* LibTPM TPM 1.2 call interface functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2015. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm12/tpm_init.h" +#include "tpm_library_intern.h" +#include "tpm12/tpm_process.h" +#include "tpm12/tpm_startup.h" +#include "tpm12/tpm_global.h" +#include "tpm12/tpm_permanent.h" +#include "tpm_nvfile.h" + +static TPM_RESULT TPM12_MainInit(void) +{ + return TPM_MainInit(); +} + +static void TPM12_Terminate(void) +{ + TPM_Global_Delete(tpm_instances[0]); + free(tpm_instances[0]); + tpm_instances[0] = NULL; +} + +static TPM_RESULT TPM12_Process(unsigned char **respbuffer, uint32_t *resp_size, + uint32_t *respbufsize, + unsigned char *command, uint32_t command_size) +{ + *resp_size = 0; + return TPM_ProcessA(respbuffer, resp_size, respbufsize, + command, command_size); +} + +static TPM_RESULT TPM12_VolatileAllStore(unsigned char **buffer, + uint32_t *buflen) +{ + TPM_RESULT rc; + TPM_STORE_BUFFER tsb; + TPM_Sbuffer_Init(&tsb); + uint32_t total; + +#ifdef TPM_DEBUG + assert(tpm_instances[0] != NULL); +#endif + + rc = TPM_VolatileAll_Store(&tsb, tpm_instances[0]); + + if (rc == TPM_SUCCESS) { + /* caller now owns the buffer and needs to free it */ + TPM_Sbuffer_GetAll(&tsb, buffer, buflen, &total); + } else { + TPM_Sbuffer_Delete(&tsb); + *buflen = 0; + *buffer = NULL; + } + + return rc; +} + +static TPM_RESULT TPM12_CancelCommand(void) +{ + return TPM_FAIL; /* not supported */ +} + + +static TPM_RESULT TPM12_GetTPMProperty(enum TPMLIB_TPMProperty prop, + int *result) +{ + switch (prop) { + case TPMPROP_TPM_RSA_KEY_LENGTH_MAX: + *result = TPM_RSA_KEY_LENGTH_MAX; + break; + + case TPMPROP_TPM_KEY_HANDLES: + *result = TPM_KEY_HANDLES; + break; + + case TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES: + *result = TPM_OWNER_EVICT_KEY_HANDLES; + break; + + case TPMPROP_TPM_MIN_AUTH_SESSIONS: + *result = TPM_MIN_AUTH_SESSIONS; + break; + + case TPMPROP_TPM_MIN_TRANS_SESSIONS: + *result = TPM_MIN_TRANS_SESSIONS; + break; + + case TPMPROP_TPM_MIN_DAA_SESSIONS: + *result = TPM_MIN_DAA_SESSIONS; + break; + + case TPMPROP_TPM_MIN_SESSION_LIST: + *result = TPM_MIN_SESSION_LIST; + break; + + case TPMPROP_TPM_MIN_COUNTERS: + *result = TPM_MIN_COUNTERS; + break; + + case TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN: + *result = TPM_NUM_FAMILY_TABLE_ENTRY_MIN; + break; + + case TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN: + *result = TPM_NUM_DELEGATE_TABLE_ENTRY_MIN; + break; + + case TPMPROP_TPM_SPACE_SAFETY_MARGIN: + *result = TPM_SPACE_SAFETY_MARGIN; + break; + + case TPMPROP_TPM_MAX_NV_SPACE: + /* fill up 20 kb.; this provides some safety margin (currently + >4Kb) for possible future expansion of this blob */ + *result = ROUNDUP(TPM_MAX_NV_SPACE, 20 * 1024); + break; + + case TPMPROP_TPM_MAX_SAVESTATE_SPACE: + *result = TPM_MAX_SAVESTATE_SPACE; + break; + + case TPMPROP_TPM_MAX_VOLATILESTATE_SPACE: + *result = TPM_MAX_VOLATILESTATE_SPACE; + break; + + default: + return TPM_FAIL; + } + + return TPM_SUCCESS; +} + +/* + * TPM12_GetInfo: + * + * @flags: logical or of flags that query for information + * + * Return a JSON document with contents queried for by the user's passed flags + */ +static char *TPM12_GetInfo(enum TPMLIB_InfoFlags flags) +{ + const char *tpmspec = + "\"TPMSpecification\":{" + "\"family\":\"1.2\"," + "\"level\":2," + "\"revision\":116" + "}"; + const char *tpmattrs = + "\"TPMAttributes\":{" + "\"manufacturer\":\"id:00001014\"," + "\"version\":\"id:00740001\"," /* 146.1 */ + "\"model\":\"swtpm\"" + "}"; + char *fmt = NULL, *buffer; + bool printed = false; + + if (!(buffer = strdup("{%s%s%s}"))) + return NULL; + + if ((flags & TPMLIB_INFO_TPMSPECIFICATION)) { + fmt = buffer; + buffer = NULL; + if (asprintf(&buffer, fmt, "", tpmspec, "%s%s%s") < 0) + goto error; + free(fmt); + printed = true; + } + if ((flags & TPMLIB_INFO_TPMATTRIBUTES)) { + fmt = buffer; + buffer = NULL; + if (asprintf(&buffer, fmt, printed ? "," : "", + tpmattrs, "%s%s%s") < 0) + goto error; + free(fmt); + printed = true; + } + + /* nothing else to add */ + fmt = buffer; + buffer = NULL; + if (asprintf(&buffer, fmt, "", "", "") < 0) + goto error; + free(fmt); + + return buffer; + +error: + free(fmt); + free(buffer); + + return NULL; +} + +static uint32_t tpm12_buffersize = TPM_BUFFER_MAX; + +static uint32_t TPM12_SetBufferSize(uint32_t wanted_size, + uint32_t *min_size, + uint32_t *max_size) +{ + if (min_size) + *min_size = TPM_BUFFER_MIN; + if (max_size) + *max_size = TPM_BUFFER_MAX; + + if (wanted_size == 0) + return tpm12_buffersize; + + if (wanted_size > TPM_BUFFER_MAX) + wanted_size = TPM_BUFFER_MAX; + else if (wanted_size < TPM_BUFFER_MIN) + wanted_size = TPM_BUFFER_MIN; + + tpm12_buffersize = wanted_size; + + return tpm12_buffersize; +} + +uint32_t TPM12_GetBufferSize(void) +{ + return TPM12_SetBufferSize(0, NULL, NULL); +} + +static TPM_RESULT TPM12_ValidateState(enum TPMLIB_StateType st, + unsigned int flags) +{ + TPM_RESULT ret = TPM_SUCCESS; + tpm_state_t tpm_state; + enum TPMLIB_StateType sts[] = { + TPMLIB_STATE_PERMANENT, + TPMLIB_STATE_VOLATILE, + TPMLIB_STATE_SAVE_STATE, + 0, + }; + enum TPMLIB_StateType c_st; + unsigned i; + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + if (cbs->tpm_nvram_init) { + ret = cbs->tpm_nvram_init(); + if (ret != TPM_SUCCESS) + return ret; + } +#endif + + ret = TPM_Global_Init(&tpm_state); + tpm_state.tpm_number = 0; + + if (ret == TPM_SUCCESS) { + /* permanent state needs to be there and loaded first */ + ret = TPM_PermanentAll_NVLoad(&tpm_state); + } + + for (i = 0; sts[i] && ret == TPM_SUCCESS; i++) { + c_st = st & sts[i]; + + /* 'cached' state is known to 'work', so skip it */ + if (!c_st || HasCachedState(c_st)) + continue; + + switch (c_st) { + case TPMLIB_STATE_PERMANENT: + break; + case TPMLIB_STATE_VOLATILE: + ret = TPM_VolatileAll_NVLoad(&tpm_state); + break; + case TPMLIB_STATE_SAVE_STATE: + ret = TPM_SaveState_NVLoad(&tpm_state); + break; + } + } + + TPM_Global_Delete(&tpm_state); + + return ret; +} + +static TPM_RESULT _TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer, + tpm_state_t *tpm_state) +{ + const unsigned char *buffer = NULL; + uint32_t buflen; + + return TPM_PermanentAll_Store(sbuffer, &buffer, &buflen, tpm_state); +} + +/* + * TPM_PermanentAll_NVLoad_Preserve + * + * @tpm_state: The tpm_state to load the permanent state into + * + * Call TPM_PermanentAll_NVLoad and preserve any cached data that a call + * to TPM_PermanentAll_NVLoad (TPM_NVRAM_LoadData) may otherwise consume + * and remove if it was available. + */ +static TPM_RESULT TPM_PermanentAll_NVLoad_Preserve(tpm_state_t *tpm_state) +{ + TPM_RESULT ret; + unsigned char *buffer = NULL; + uint32_t buffer_len; + bool is_empty_buffer; + + ret = CopyCachedState(TPMLIB_STATE_PERMANENT, + &buffer, &buffer_len, &is_empty_buffer); + if (ret == TPM_SUCCESS) { + ret = TPM_PermanentAll_NVLoad(tpm_state); + + /* restore a previous empty buffer or any valid buffer */ + if (is_empty_buffer || buffer != NULL) + SetCachedState(TPMLIB_STATE_PERMANENT, buffer, buffer_len); + } + + return ret; +} + +/* + * Get the state blob of the given type. If we TPM is not running, we + * get the cached state blobs, if available, otherwise we try to read + * it from files. In case the TPM is running, we get it from the running + * TPM. + */ +static TPM_RESULT TPM12_GetState(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen) +{ + TPM_RESULT ret = TPM_FAIL; + TPM_STORE_BUFFER tsb; + uint32_t total; + + /* TPM not running ? */ + if (tpm_instances[0] == NULL) { + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + bool is_empty_buffer; + + /* try cached blob before file */ + ret = CopyCachedState(st, buffer, buflen, &is_empty_buffer); + if (ret != TPM_SUCCESS || *buffer != NULL || is_empty_buffer) + return ret; + + if (cbs->tpm_nvram_init) { + ret = cbs->tpm_nvram_init(); + if (ret != TPM_SUCCESS) + return ret; + + ret = TPM_NVRAM_LoadData(buffer, buflen, 0, + TPMLIB_StateTypeToName(st)); + } else { + ret = TPM_FAIL; + } + return ret; + } + + TPM_Sbuffer_Init(&tsb); + + switch (st) { + case TPMLIB_STATE_PERMANENT: + ret = _TPM_PermanentAll_Store(&tsb, tpm_instances[0]); + break; + case TPMLIB_STATE_VOLATILE: + ret = TPM_VolatileAll_Store(&tsb, tpm_instances[0]); + break; + case TPMLIB_STATE_SAVE_STATE: + ret = TPM_SaveState_Store(&tsb, tpm_instances[0]); + break; + } + + if (ret == TPM_SUCCESS) { + /* caller now owns the buffer and needs to free it */ + TPM_Sbuffer_GetAll(&tsb, buffer, buflen, &total); + } else { + TPM_Sbuffer_Delete(&tsb); + *buflen = 0; + *buffer = NULL; + } + + return ret; +} + +/* + * Set the state the TPM 1.2 will use upon next TPM_MainInit(). The TPM 1.2 + * must not have been started, yet, or it must have been terminated for this + * function to set the state. + * + * @st: The TPMLIB_StateType describing the type of blob in the buffer + * @buffer: pointer to the buffer containing the state blob; NULL pointer clears + * previous state + * @buflen: length of the buffer + */ +static TPM_RESULT TPM12_SetState(enum TPMLIB_StateType st, + const unsigned char *buffer, uint32_t buflen) +{ + TPM_RESULT ret = TPM_SUCCESS; + unsigned char *stream = NULL, *orig_stream = NULL; + uint32_t stream_size = buflen; + tpm_state_t *tpm_state = NULL; + + if (buffer == NULL) { + SetCachedState(st, NULL, 0); + return TPM_SUCCESS; + } + + if (tpm_instances[0]) + return TPM_INVALID_POSTINIT; + + if (ret == TPM_SUCCESS) { + stream = malloc(buflen); + if (!stream) { + TPMLIB_LogError("Could not allocate %u bytes.\n", buflen); + ret = TPM_SIZE; + } + } + + if (ret == TPM_SUCCESS) { + orig_stream = stream; + memcpy(stream, buffer, buflen); + + tpm_state = malloc(sizeof(tpm_state_t)); + if (!tpm_state) { + TPMLIB_LogError("Could not allocated %zu bytes.\n", + sizeof(tpm_state_t)); + ret = TPM_SIZE; + } + } + + if (ret == TPM_SUCCESS) { + ret = TPM_Global_Init(tpm_state); + } + + /* test whether we can accept the blob */ + if (ret == TPM_SUCCESS) { + tpm_state->tpm_number = 0; + + switch (st) { + case TPMLIB_STATE_PERMANENT: + ret = TPM_PermanentAll_Load(tpm_state, &stream, &stream_size); + break; + case TPMLIB_STATE_VOLATILE: + /* permanent state needs to be there and loaded first */ + ret = TPM_PermanentAll_NVLoad_Preserve(tpm_state); + if (ret == TPM_SUCCESS) + ret = TPM_VolatileAll_Load(tpm_state, &stream, &stream_size); + break; + case TPMLIB_STATE_SAVE_STATE: + ret = TPM_PermanentAll_NVLoad_Preserve(tpm_state); + if (ret == TPM_SUCCESS) + ret = TPM_SaveState_Load(tpm_state, &stream, &stream_size); + break; + } + if (ret) + ClearAllCachedState(); + } + + /* cache the blob for the TPM_MainInit() to pick it up */ + if (ret == TPM_SUCCESS) { + SetCachedState(st, orig_stream, buflen); + } else { + free(orig_stream); + } + + TPM_Global_Delete(tpm_state); + free(tpm_state); + + return ret; +} + +const struct tpm_interface TPM12Interface = { + .MainInit = TPM12_MainInit, + .Terminate = TPM12_Terminate, + .Process = TPM12_Process, + .VolatileAllStore = TPM12_VolatileAllStore, + .CancelCommand = TPM12_CancelCommand, + .GetTPMProperty = TPM12_GetTPMProperty, + .GetInfo = TPM12_GetInfo, + .TpmEstablishedGet = TPM12_IO_TpmEstablished_Get, + .TpmEstablishedReset = TPM12_IO_TpmEstablished_Reset, + .HashStart = TPM12_IO_Hash_Start, + .HashData = TPM12_IO_Hash_Data, + .HashEnd = TPM12_IO_Hash_End, + .SetBufferSize = TPM12_SetBufferSize, + .ValidateState = TPM12_ValidateState, + .SetState = TPM12_SetState, + .GetState = TPM12_GetState, +}; diff --git a/src/tpm_tpm12_tis.c b/src/tpm_tpm12_tis.c new file mode 100644 index 0000000..0253cba --- /dev/null +++ b/src/tpm_tpm12_tis.c @@ -0,0 +1,280 @@ +/********************************************************************************/ +/* */ +/* TPM TIS I/O */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_tis.c 4505 2011-03-20 17:43:27Z kgoldman $ */ +/* */ +/* (c) Copyright IBM Corporation 2006, 2011. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +/* + This file implements the TPM TIS interface out-of-band commands. +*/ + +#include +#include + +#include "tpm12/tpm_crypto.h" +#include "tpm12/tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm12/tpm_digest.h" +#include "tpm12/tpm_global.h" +#include "tpm12/tpm_pcr.h" +#include "tpm12/tpm_permanent.h" +#include "tpm12/tpm_platform.h" +#include "tpm12/tpm_process.h" +#include "tpm12/tpm_transport.h" + +#include "tpm_tis.h" + +/* These commands do not test for TPM_ContinueSelfTest: + + The following operations MUST be available after TPM_Init and before a call to + TPM_ContinueSelfTest 1.9. TPM_HASH_START / TPM_HASH_DATA / TPM_HASH_END */ + +/* TPM_IO_Hash_Start() implements the LPC bus TPM_HASH_START command + */ +TPM_RESULT TPM12_IO_Hash_Start(void) +{ + TPM_RESULT rc = 0; + tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ + TPM_PCRVALUE zeroPCR; + TPM_BOOL altered = FALSE; /* TRUE if the structure has been changed */ + + printf("\nTPM_IO_Hash_Start: Ordinal Entry\n"); + TPM_Digest_Init(zeroPCR); + + /* Prior to receiving the TPM_HASH_START command the TPM must have received a TPM_Startup + command. If the TPM receives a TPM_HASH_START after a TPM_Init but before a startup command, + the TPM treats this as an error */ + if (rc == 0) { + if (tpm_state->tpm_stany_flags.postInitialise) { + printf("TPM_IO_Hash_Start: Error, postInitialise is TRUE\n"); + rc = TPM_INVALID_POSTINIT; + } + } + /* NOTE: Done by caller + (1) If no TPM_ACCESS_x.activeLocality field is set, the TPM MUST set the + TPM_ACCESS_x.activeLocality field to indicate Locality 4. Any currently executing command + MUST be aborted per and subject to Section 11.2.3. */ + /* NOTE: Done by caller + (2) If TPM_ACCESS_x.activeLocality is set, and if the TPM_ACCESS_x.activeLocality field is + not 4, the TPM MUST ignore this command. */ + /* NOTE: Done by caller + (3) The TPM MUST clear the write FIFO. */ + if (rc == 0) { + /* (4) If there is an exclusive transport session, it MUST be invalidated. */ + if (tpm_state->tpm_stany_flags.transportExclusive != 0) { /* active exclusive */ + rc = TPM_TransportSessions_TerminateHandle + (tpm_state->tpm_stclear_data.transSessions, + tpm_state->tpm_stany_flags.transportExclusive, + &(tpm_state->tpm_stany_flags.transportExclusive)); + } + } + if (rc == 0) { + /* (5) Set the TPM_PERMANENT_FLAGS->tpmEstablished flag to TRUE (1). Note: see description of + Bit Field: tpmEstablishment in 11.2.11 Access Register. */ + TPM_SetCapability_Flag(&altered, + &(tpm_state->tpm_permanent_flags.tpmEstablished), + TRUE); + } + if (rc == 0) { + /* (6) Set the TPM_STANY_FLAGS->TOSPresent flag to TRUE (1). */ + tpm_state->tpm_stany_flags.TOSPresent = TRUE; + /* (7) Set PCRs per column labeled TPM_HASH_START in Table 5: PCR Initial and Reset Values. + (PCR 17-22 to zero, others unchanged */ + TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 17, zeroPCR); + TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 18, zeroPCR); + TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 19, zeroPCR); + TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 20, zeroPCR); + TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 21, zeroPCR); + TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 22, zeroPCR); + /* (8) Ignore any data component of the TPM_HASH_START LPC command. */ + /* (9) Allocate tempLocation of a size required to perform the SHA-1 operation. */ + /* (10) Initialize tempLocation per SHA-1. */ + rc = TPM_SHA1InitCmd(&(tpm_state->sha1_context_tis)); + } + rc = TPM_PermanentAll_NVStore(tpm_state, + altered, + rc); + /* + 1) Upon any error in the above steps the TPM: + a) MUST enter Failure Mode. + NOTE: Done by caller + b) MUST release locality. + */ + if (rc != 0) { + printf("TPM_IO_Hash_Start: Error, (fatal)\n"); + printf(" TPM_IO_Hash_Start: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + return rc; +} + +/* TPM_IO_Hash_Data() implements the LPC bus TPM_HASH_DATA command + */ +TPM_RESULT TPM12_IO_Hash_Data(const unsigned char *data, + uint32_t data_length) +{ + TPM_RESULT rc = 0; + tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ + + printf("\nTPM_IO_Hash_Data: Ordinal Entry\n"); + /* (1) Transform tempLocation per SHA-1 with data received from this command. */ + /* (2) Repeat for each TPM_HASH_DATA LPC command received. */ + if (rc == 0) { + if (tpm_state->sha1_context_tis == NULL) { + printf("TPM_IO_Hash_Data: Error, no existing SHA1 thread\n"); + rc = TPM_SHA_THREAD; + } + } + if (rc == 0) { + rc = TPM_SHA1UpdateCmd(tpm_state->sha1_context_tis, data, data_length); + } + /* + 1) Upon any error in the above steps the TPM: + a) MUST enter Failure Mode. + NOTE: Done by caller + b) MUST release locality. + */ + if (rc != 0) { + printf("TPM_IO_Hash_Data: Error, (fatal)\n"); + printf(" TPM_IO_Hash_Data: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + return rc; +} + +/* TPM_IO_Hash_End() implements the LPC bus TPM_HASH_END command + */ +TPM_RESULT TPM12_IO_Hash_End(void) +{ + TPM_RESULT rc = 0; + TPM_PCRVALUE zeroPCR; + TPM_DIGEST extendDigest; + tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ + + printf("\nTPM_IO_Hash_End: Ordinal Entry\n"); + if (rc == 0) { + if (tpm_state->sha1_context_tis == NULL) { + printf("TPM_IO_Hash_End: Error, no existing SHA1 thread\n"); + rc = TPM_SHA_THREAD; + } + } + /* (1) Ignore any data sent with the command. */ + /* (2) Perform finalize operation on tempLocation per SHA-1. */ + if (rc == 0) { + rc = TPM_SHA1FinalCmd(extendDigest, tpm_state->sha1_context_tis); + } + /* (3) Perform an “extend” operation, as defined in the TPM_Extend command, of the value within + tempLocation into PCR[Locality 4]. */ + if (rc == 0) { + /* In the previous line above, “PCR[Locality 4]” within and before the SHA-1 function is + TPM_PCRVALUE = 0 (i.e., 20 bytes of all zeros). */ + TPM_Digest_Init(zeroPCR); /* initial PCR value */ + /* PCR[Locality 4] = SHA-1( PCR[Locality 4] || tempLoc) */ + rc = TPM_SHA1(tpm_state->tpm_stclear_data.PCRS[TPM_LOCALITY_4_PCR], + TPM_DIGEST_SIZE, zeroPCR, + TPM_DIGEST_SIZE, extendDigest, + 0, NULL); + } + /* NOTE: Done by caller + (4) Clear TPM_ACCESS_x.activeLocality for Locality 4. */ + /* + 1) Upon any error in the above steps the TPM: + a) MUST enter Failure Mode. + NOTE: Done by caller + b) MUST release locality. + */ + if (rc != 0) { + printf("TPM_IO_Hash_End: Error, (fatal)\n"); + printf(" TPM_IO_Hash_End: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + TPM_SHA1Delete(&(tpm_state->sha1_context_tis)); + return rc; +} + +TPM_RESULT TPM12_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished) +{ + TPM_RESULT rc = 0; + tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ + + if (rc == 0) { + *tpmEstablished = tpm_state->tpm_permanent_flags.tpmEstablished; + } + /* + 1) Upon any error in the above steps the TPM: + a) MUST enter Failure Mode. + NOTE: Done by caller + b) MUST release locality. + */ + if (rc != 0) { + printf("TPM_IO_TpmEstablished_Get: Error, (fatal)\n"); + printf(" TPM_IO_TpmEstablished_Get: Set testState to %u \n", TPM_TEST_STATE_FAILURE); + tpm_state->testState = TPM_TEST_STATE_FAILURE; + } + return 0; +} + +TPM_RESULT TPM12_IO_TpmEstablished_Reset(void) +{ + TPM_RESULT returnCode = 0; + tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ + + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_IO_GetLocality(&(tpm_state->tpm_stany_flags.localityModifier), + tpm_state->tpm_number); + } + + /* 1. Validate the assertion of locality 3 or locality 4 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, /* BYTE bitmap */ + tpm_state->tpm_stany_flags.localityModifier); + } + /* 2. Set TPM_PERMANENT_FLAGS -> tpmEstablished to FALSE */ + if (returnCode == TPM_SUCCESS) { + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.tpmEstablished), /* flag */ + FALSE); /* value */ + + } + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + + return returnCode; +} diff --git a/src/tpm_tpm2_interface.c b/src/tpm_tpm2_interface.c new file mode 100644 index 0000000..8d8117e --- /dev/null +++ b/src/tpm_tpm2_interface.c @@ -0,0 +1,690 @@ +/********************************************************************************/ +/* */ +/* LibTPM TPM 2 call interface functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2015. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#define _GNU_SOURCE +#include +#include +#include +#include + +#ifndef LIB_EXPORT +#define LIB_EXPORT +#endif +#include "tpm2/Tpm.h" +#include "tpm2/Manufacture_fp.h" +#include "tpm2/Platform_fp.h" +#include "tpm2/ExecCommand_fp.h" +#include "tpm2/TpmTcpProtocol.h" +#include "tpm2/Simulator_fp.h" +#include "tpm2/_TPM_Hash_Data_fp.h" +#include "tpm2/_TPM_Init_fp.h" +#include "tpm2/StateMarshal.h" +#include "tpm2/PlatformACT.h" +#include "tpm2/PlatformData.h" +#include "tpm2/Volatile.h" +#include "tpm2/crypto/openssl/ExpDCache_fp.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_nvfile.h" // TPM_NVRAM_Loaddata() +#include "tpm_error.h" +#include "tpm_library_intern.h" +#include "tpm_nvfilename.h" + +extern BOOL g_inFailureMode; +static BOOL reportedFailureCommand; + +/* + * Check whether the main NVRAM file exists. Return TRUE if it doesn, FALSE otherwise + */ +static TPM_BOOL _TPM2_CheckNVRAMFileExists(bool *has_nvram_loaddata_callback) +{ +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + const char *name = TPM_PERMANENT_ALL_NAME; + unsigned char *data = NULL; + uint32_t length = 0; + uint32_t tpm_number = 0; + TPM_RESULT ret; + + *has_nvram_loaddata_callback = cbs->tpm_nvram_loaddata != NULL; + if (cbs->tpm_nvram_loaddata) { + ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name); + free(data); + /* a file exists once NOT TPM_RETRY is returned */ + if (ret != TPM_RETRY) + return TRUE; + } +#else + *has_nvram_loaddata_callback = FALSE; +#endif /* TPM_LIBTPMS_CALLBACKS */ + + return FALSE; +} + +static TPM_RESULT TPM2_MainInit(void) +{ + TPM_RESULT ret = TPM_SUCCESS; + bool has_cached_state; + bool has_nvram_file; + bool has_nvram_loaddata_callback; + + g_inFailureMode = FALSE; + reportedFailureCommand = FALSE; + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + if (cbs->tpm_io_init) { + ret = cbs->tpm_io_init(); + if (ret != TPM_SUCCESS) + return ret; + } + + if (cbs->tpm_nvram_init) { + ret = cbs->tpm_nvram_init(); + if (ret != TPM_SUCCESS) + return ret; + } +#endif /* TPM_LIBTPMS_CALLBACKS */ + + _rpc__Signal_PowerOff(); + + has_cached_state = HasCachedState(TPMLIB_STATE_PERMANENT); + has_nvram_file = _TPM2_CheckNVRAMFileExists(&has_nvram_loaddata_callback); + + if (!has_cached_state) { + if (!has_nvram_file) { + ret = _plat__NVEnable(NULL); + if (ret) + TPMLIB_LogTPM2Error( + "%s: _plat__NVEnable(NULL) failed: %d\n", + __func__, ret); + if (TPM_Manufacture(TRUE) < 0 || g_inFailureMode) { + TPMLIB_LogTPM2Error("%s: TPM_Manufacture(TRUE) failed or TPM in " + "failure mode\n", __func__); + reportedFailureCommand = TRUE; + } + } + } else if (!has_nvram_loaddata_callback) { + ret = _plat__NVEnable_NVChipFile(NULL); + if (ret) + TPMLIB_LogTPM2Error("%s: _plat__NVEnable_File(NULL) failed: %d\n", + __func__, ret); + } + + _rpc__Signal_PowerOn(FALSE); + + _rpc__Signal_NvOn(); + + if (ret == TPM_SUCCESS) { + if (g_inFailureMode) + ret = TPM_RC_FAILURE; + } + + if (ret == TPM_SUCCESS && has_cached_state) { + NvCommit(); + } + + return ret; +} + +static void TPM2_Terminate(void) +{ + TPM_TearDown(); + + _rpc__Signal_PowerOff(); + ExpDCacheFree(); +} + +static TPM_RESULT TPM2_Process(unsigned char **respbuffer, uint32_t *resp_size, + uint32_t *respbufsize, + unsigned char *command, uint32_t command_size) +{ + uint8_t locality = 0; + _IN_BUFFER req; + _OUT_BUFFER resp; + unsigned char *tmp; + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + if (cbs->tpm_io_getlocality) { + TPM_MODIFIER_INDICATOR locty; + + locality = cbs->tpm_io_getlocality(&locty, 0); + + locality = locty; + } +#endif /* TPM_LIBTPMS_CALLBACKS */ + + req.BufferSize = command_size; + req.Buffer = command; + + /* have the TPM 2 write directly into the response buffer */ + if (*respbufsize < TPM_BUFFER_MAX || !*respbuffer) { + tmp = realloc(*respbuffer, TPM_BUFFER_MAX); + if (!tmp) { + TPMLIB_LogTPM2Error("Could not allocated %u bytes.\n", + TPM_BUFFER_MAX); + return TPM_SIZE; + } + *respbuffer = tmp; + *respbufsize = TPM_BUFFER_MAX; + } + resp.BufferSize = *respbufsize; + resp.Buffer = *respbuffer; + + /* + * signals for cancellation have to come after we start processing + */ + _rpc__Signal_CancelOff(); + + _rpc__Send_Command(locality, req, &resp); + + /* it may come back with a different buffer, especially in failure mode */ + if (resp.Buffer != *respbuffer) { + if (resp.BufferSize > *respbufsize) + resp.BufferSize = *respbufsize; + memcpy(*respbuffer, resp.Buffer, resp.BufferSize); + } + + *resp_size = resp.BufferSize; + + if (g_inFailureMode && !reportedFailureCommand) { + reportedFailureCommand = TRUE; + TPMLIB_LogTPM2Error("%s: Entered failure mode through command:\n", + __func__); + TPMLIB_LogArray(~0, command, command_size); + } + + return TPM_SUCCESS; +} + +TPM_RESULT TPM2_PersistentAllStore(unsigned char **buf, + uint32_t *buflen) +{ + BYTE *buffer; + INT32 size; + unsigned char *nbuffer; + TPM_RESULT ret = TPM_SUCCESS; + UINT32 written = 0; + + *buflen = NV_MEMORY_SIZE + 32 * 1024; + *buf = NULL; + + /* the marshal functions do not indicate insufficient + buffer; to make sure we didn't run out of buffer, + we check that enough room for the biggest type of + chunk (64k) is available and try again. */ + do { + *buflen += 66 * 1024; + + nbuffer = realloc(*buf, *buflen); + if (nbuffer == NULL) { + free(*buf); + *buf = NULL; + ret = TPM_SIZE; + written = 0; + break; + } + + *buf = buffer = nbuffer; + size = *buflen; + written = PERSISTENT_ALL_Marshal(&buffer, &size); + } while (size < 66 * 1024); + + *buflen = written; + + return ret; +} + +static TPM_RESULT TPM2_VolatileAllStore(unsigned char **buffer, + uint32_t *buflen) +{ + TPM_RESULT rc = 0; + INT32 size = NV_MEMORY_SIZE; + UINT16 written; + unsigned char *statebuffer = NULL; + + *buffer = NULL; + statebuffer = malloc(size); + if (!statebuffer) { + TPMLIB_LogTPM2Error("Could not allocate %u bytes.\n", size); + return TPM_SIZE; + } + + /* statebuffer will change */ + *buffer = statebuffer; + + written = VolatileSave(&statebuffer, &size); + if (written >= size) { + free(*buffer); + *buffer = NULL; + rc = TPM_FAIL; + } else { + *buflen = written; + } + + return rc; +} + +static TPM_RESULT TPM2_CancelCommand(void) +{ + _rpc__Signal_CancelOn(); + + return TPM_SUCCESS; +} + +static TPM_RESULT TPM2_GetTPMProperty(enum TPMLIB_TPMProperty prop, + int *result) +{ + switch (prop) { + case TPMPROP_TPM_RSA_KEY_LENGTH_MAX: + *result = MAX_RSA_KEY_BITS; + break; + + case TPMPROP_TPM_KEY_HANDLES: + *result = MAX_HANDLE_NUM; + break; + + /* not supported for TPM 2 */ + case TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES: + case TPMPROP_TPM_MIN_AUTH_SESSIONS: + case TPMPROP_TPM_MIN_TRANS_SESSIONS: + case TPMPROP_TPM_MIN_DAA_SESSIONS: + case TPMPROP_TPM_MIN_SESSION_LIST: + case TPMPROP_TPM_MIN_COUNTERS: + case TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN: + case TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN: + case TPMPROP_TPM_SPACE_SAFETY_MARGIN: + case TPMPROP_TPM_MAX_NV_SPACE: + case TPMPROP_TPM_MAX_SAVESTATE_SPACE: + case TPMPROP_TPM_MAX_VOLATILESTATE_SPACE: + + default: + return TPM_FAIL; + } + + return TPM_SUCCESS; +} + +/* + * TPM2_GetInfo: + * + * @flags: logical or of flags that query for information + * + * Return a JSON document with contents queried for by the user's passed flags + */ +static char *TPM2_GetInfo(enum TPMLIB_InfoFlags flags) +{ + const char *tpmspec = + "\"TPMSpecification\":{" + "\"family\":\"2.0\"," + "\"level\":" STRINGIFY(SPEC_LEVEL_NUM) "," + "\"revision\":" STRINGIFY(SPEC_VERSION) + "}"; + const char *tpmattrs_temp = + "\"TPMAttributes\":{" + "\"manufacturer\":\"id:00001014\"," + "\"version\":\"id:%08X\"," + "\"model\":\"swtpm\"" + "}"; + const char *tpmfeatures_temp = + "\"TPMFeatures\":{" + "\"RSAKeySizes\":[%s]," + "\"CamelliaKeySizes\":[%s]" + "}"; + char *fmt = NULL, *buffer; + bool printed = false; + char *tpmattrs = NULL; + char *tpmfeatures = NULL; + char rsakeys[32]; + char camelliakeys[16]; + size_t n; + + if (!(buffer = strdup("{%s%s%s}"))) + return NULL; + + if ((flags & TPMLIB_INFO_TPMSPECIFICATION)) { + fmt = buffer; + buffer = NULL; + if (asprintf(&buffer, fmt, "", tpmspec, "%s%s%s") < 0) + goto error; + free(fmt); + printed = true; + } + + if ((flags & TPMLIB_INFO_TPMATTRIBUTES)) { + fmt = buffer; + buffer = NULL; + if (asprintf(&tpmattrs, tpmattrs_temp, FIRMWARE_V1) < 0) + goto error; + if (asprintf(&buffer, fmt, printed ? "," : "", + tpmattrs, "%s%s%s") < 0) + goto error; + free(fmt); + printed = true; + } + + if ((flags & TPMLIB_INFO_TPMFEATURES)) { + fmt = buffer; + buffer = NULL; + n = snprintf(rsakeys, sizeof(rsakeys), "%s2048%s%s", + RSA_1024 ? "1024," : "", + RSA_3072 ? ",3072" : "", + RSA_4096 ? ",4096" : ""); + if (n >= sizeof(rsakeys)) + goto error; + n = snprintf(camelliakeys, sizeof(camelliakeys), "%s%s%s", + CAMELLIA_128 ? "128" : "", + CAMELLIA_192 ? ",192" : "", + CAMELLIA_256 ? ",256" : ""); + if (n >= sizeof(camelliakeys)) + goto error; + if (asprintf(&tpmfeatures, tpmfeatures_temp, + rsakeys, camelliakeys) < 0) + goto error; + if (asprintf(&buffer, fmt, printed ? "," : "", + tpmfeatures, "%s%s%s") < 0) + goto error; + free(fmt); + printed = true; + } + + /* nothing else to add */ + fmt = buffer; + buffer = NULL; + if (asprintf(&buffer, fmt, "", "", "") < 0) + goto error; + + free(fmt); + free(tpmattrs); + free(tpmfeatures); + + return buffer; + +error: + free(fmt); + free(buffer); + free(tpmattrs); + free(tpmfeatures); + + return NULL; +} + +static uint32_t tpm2_buffersize = TPM_BUFFER_MAX; + +static uint32_t TPM2_SetBufferSize(uint32_t wanted_size, + uint32_t *min_size, + uint32_t *max_size) +{ + const uint32_t min = MAX_CONTEXT_SIZE + 128; + const uint32_t max = TPM_BUFFER_MAX; + + if (min_size) + *min_size = min; + if (max_size) + *max_size = max; + + if (wanted_size == 0) + return tpm2_buffersize; + + if (wanted_size > max) + wanted_size = max; + else if (wanted_size < min) + wanted_size = min; + + tpm2_buffersize = wanted_size; + + return tpm2_buffersize; +} + +uint32_t TPM2_GetBufferSize(void) +{ + return TPM2_SetBufferSize(0, NULL, NULL); +} + +/* + * Validate the state blobs to check whether they can be + * successfully used by a TPM_INIT. +*/ +static TPM_RESULT TPM2_ValidateState(enum TPMLIB_StateType st, + unsigned int flags) +{ + TPM_RESULT ret = TPM_SUCCESS; + TPM_RC rc = TPM_RC_SUCCESS; + unsigned char *data = NULL; + uint32_t length; + unsigned char bak_NV[NV_MEMORY_SIZE]; + INT32 size; + BYTE *buffer; + BOOL restored; + + /* make backup of current NvChip memory */ + memcpy(bak_NV, s_NV, sizeof(bak_NV)); + +#ifdef TPM_LIBTPMS_CALLBACKS + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + + if (cbs->tpm_nvram_init) { + ret = cbs->tpm_nvram_init(); + if (ret != TPM_SUCCESS) + return ret; + } + +#endif + + if ((rc == TPM_RC_SUCCESS) && + (st & (TPMLIB_STATE_PERMANENT | TPMLIB_STATE_SAVE_STATE))) { + +#ifdef TPM_LIBTPMS_CALLBACKS + if (cbs->tpm_nvram_loaddata) { + ret = cbs->tpm_nvram_loaddata(&data, &length, 0, + TPM_PERMANENT_ALL_NAME); + if (ret != TPM_SUCCESS) + return ret; + } +#endif + + if (!data) + return TPM_FAIL; + + buffer = data; + size = length; + rc = PERSISTENT_ALL_Unmarshal(&buffer, &size); + free(data); + } + + if ((rc == TPM_RC_SUCCESS) && + (st & TPMLIB_STATE_VOLATILE)) { + rc = VolatileLoad(&restored); + } + + ret = rc; + + return ret; +} + +/* + * Get the state blob of the given type. If the TPM is not running, we + * get the cached state blobs, if available, otherwise we try to read + * it from files. In case the TPM is running, we get it from the running + * TPM. + */ +static TPM_RESULT TPM2_GetState(enum TPMLIB_StateType st, + unsigned char **buffer, uint32_t *buflen) +{ + TPM_RESULT ret = TPM_FAIL; + + if (!_rpc__Signal_IsPowerOn()) { + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + bool is_empty_buffer; + + ret = CopyCachedState(st, buffer, buflen, &is_empty_buffer); + if (ret != TPM_SUCCESS || *buffer != NULL || is_empty_buffer) + return ret; + + if (cbs->tpm_nvram_init) { + ret = cbs->tpm_nvram_init(); + if (ret != TPM_SUCCESS) + return ret; + + /* we can call the TPM 1.2 function here ... */ + ret = TPM_NVRAM_LoadData(buffer, buflen, 0, + TPMLIB_StateTypeToName(st)); + } else { + ret = TPM_FAIL; + } + return ret; + } + + /* from the running TPM */ + switch (st) { + case TPMLIB_STATE_PERMANENT: + ret = TPM2_PersistentAllStore(buffer, buflen); + break; + case TPMLIB_STATE_VOLATILE: + ret = TPM2_VolatileAllStore(buffer, buflen); + break; + case TPMLIB_STATE_SAVE_STATE: + *buffer = NULL; + *buflen = 0; + ret = 0; + break; + } + + return ret; +} + +/* + * Set the state the TPM 2 will use upon next TPM_MainInit(). The TPM 2 + * must not have been started, yet, or it must have been terminated for this + * function to set the state. + * + * @st: The TPMLIB_StateType describing the type of blob in the buffer + * @buffer: pointer to the buffer containing the state blob; NULL pointer clears + * previous state + * @buflen: length of the buffer + */ +static TPM_RESULT TPM2_SetState(enum TPMLIB_StateType st, + const unsigned char *buffer, uint32_t buflen) +{ + TPM_RESULT ret = TPM_SUCCESS; + TPM_RC rc = TPM_RC_SUCCESS; + BYTE *stream = NULL, *orig_stream = NULL; + INT32 stream_size = buflen; + unsigned char *permanent = NULL, *ptr; + INT32 permanent_len; + + if (buffer == NULL) { + SetCachedState(st, NULL, 0); + return TPM_SUCCESS; + } + + if (_rpc__Signal_IsPowerOn()) + return TPM_INVALID_POSTINIT; + + if (ret == TPM_SUCCESS) { + stream = malloc(buflen); + if (!stream) + ret = TPM_SIZE; + } + + if (ret == TPM_SUCCESS) { + orig_stream = stream; + memcpy(stream, buffer, buflen); + } + + /* test whether we can accept the blob */ + if (ret == TPM_SUCCESS) { + switch (st) { + case TPMLIB_STATE_PERMANENT: + rc = PERSISTENT_ALL_Unmarshal(&stream, &stream_size); + break; + case TPMLIB_STATE_VOLATILE: + /* load permanent state first */ + rc = TPM2_GetState(TPMLIB_STATE_PERMANENT, + &permanent, (uint32_t *)&permanent_len); + if (rc == TPM_RC_SUCCESS) { + ptr = permanent; + rc = PERSISTENT_ALL_Unmarshal(&ptr, &permanent_len); + if (rc == TPM_RC_SUCCESS) + rc = VolatileState_Load(&stream, &stream_size); + } + break; + case TPMLIB_STATE_SAVE_STATE: + if (buffer != NULL) + rc = TPM_BAD_TYPE; + break; + } + ret = rc; + if (ret != TPM_SUCCESS) + ClearAllCachedState(); + } + + /* cache the blob for the TPM_MainInit() to pick it up */ + if (ret == TPM_SUCCESS) { + SetCachedState(st, orig_stream, buflen); + } else { + free(orig_stream); + } + free(permanent); + + return ret; +} + +const struct tpm_interface TPM2Interface = { + .MainInit = TPM2_MainInit, + .Terminate = TPM2_Terminate, + .Process = TPM2_Process, + .VolatileAllStore = TPM2_VolatileAllStore, + .CancelCommand = TPM2_CancelCommand, + .GetTPMProperty = TPM2_GetTPMProperty, + .GetInfo = TPM2_GetInfo, + .TpmEstablishedGet = TPM2_IO_TpmEstablished_Get, + .TpmEstablishedReset = TPM2_IO_TpmEstablished_Reset, + .HashStart = TPM2_IO_Hash_Start, + .HashData = TPM2_IO_Hash_Data, + .HashEnd = TPM2_IO_Hash_End, + .SetBufferSize = TPM2_SetBufferSize, + .ValidateState = TPM2_ValidateState, + .SetState = TPM2_SetState, + .GetState = TPM2_GetState, +}; diff --git a/src/tpm_tpm2_tis.c b/src/tpm_tpm2_tis.c new file mode 100644 index 0000000..08623eb --- /dev/null +++ b/src/tpm_tpm2_tis.c @@ -0,0 +1,108 @@ +/********************************************************************************/ +/* */ +/* TPM TIS I/O */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2015. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include + +#include + +#include "tpm2/Tpm.h" +#include "tpm2/TpmTypes.h" +#include "tpm2/TpmBuildSwitches.h" +#include "tpm2/_TPM_Hash_Start_fp.h" +#include "tpm2/_TPM_Hash_Data_fp.h" +#include "tpm2/_TPM_Hash_End_fp.h" +#include "tpm2/TpmTcpProtocol.h" +#include "tpm2/Platform_fp.h" +#include "tpm2/Simulator_fp.h" + +#define TPM_HAVE_TPM2_DECLARATIONS +#include "tpm_library_intern.h" +#include "tpm_error.h" + +TPM_RESULT TPM2_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished) +{ + *tpmEstablished = _rpc__Signal_GetTPMEstablished(); + + return TPM_SUCCESS; +} + +TPM_RESULT TPM2_IO_TpmEstablished_Reset(void) +{ + TPM_RESULT ret = TPM_SUCCESS; + struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); + TPM_MODIFIER_INDICATOR locality = 0; + uint32_t tpm_number = 0; + + if (cbs->tpm_io_getlocality) { + cbs->tpm_io_getlocality(&locality, tpm_number); + } + + _plat__LocalitySet(locality); + + if (locality == 3 || locality == 4) { + _rpc__Signal_ResetTPMEstablished(); + } else { + ret = TPM_BAD_LOCALITY; + } + + return ret; +} + +TPM_RESULT TPM2_IO_Hash_Start(void) +{ + _TPM_Hash_Start(); + + _rpc__Signal_SetTPMEstablished(); + + return TPM_SUCCESS; +} + +TPM_RESULT TPM2_IO_Hash_Data(const unsigned char *data, + uint32_t data_length) +{ + _TPM_Hash_Data(data_length, (unsigned char *)data); + + return TPM_SUCCESS; +} + +TPM_RESULT TPM2_IO_Hash_End(void) +{ + _TPM_Hash_End(); + + return TPM_SUCCESS; +} -- cgit v1.2.3