diff options
Diffstat (limited to '')
-rw-r--r-- | src/tpm12/tpm_process.c | 6051 |
1 files changed, 6051 insertions, 0 deletions
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 <stdlib.h> +#include <string.h> +#include <stdio.h> + +#ifdef TPM_POSIX +#include <sys/types.h> +#include <unistd.h> +#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; +} |