blob: c38d1ec210bfbc7536404e7dd4ab75364953e3ad [file] [log] [blame]
/********************************************************************************/
/* */
/* TSS Primary API for TPM 2.0 */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* */
/* (c) Copyright IBM Corporation 2018 - 2020 */
/* */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or without */
/* modification, are permitted provided that the following conditions are */
/* met: */
/* */
/* Redistributions of source code must retain the above copyright notice, */
/* this list of conditions and the following disclaimer. */
/* */
/* Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in the */
/* documentation and/or other materials provided with the distribution. */
/* */
/* Neither the names of the IBM Corporation nor the names of its */
/* contributors may be used to endorse or promote products derived from */
/* this software without specific prior written permission. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/********************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#ifdef TPM_POSIX
#include <netinet/in.h>
#endif
#ifdef TPM_WINDOWS
#include <winsock2.h>
#endif
#include "tssauth.h"
#include "tssauth20.h"
#include <ibmtss/tss.h>
#include "tssproperties.h"
#include <ibmtss/tsstransmit.h>
#include <ibmtss/tssutils.h>
#include <ibmtss/tssresponsecode.h>
#include <ibmtss/tssmarshal.h>
#include <ibmtss/Unmarshal_fp.h>
#include "tssccattributes.h"
#ifndef TPM_TSS_NOCRYPTO
#include <ibmtss/tsscrypto.h>
#include <ibmtss/tsscryptoh.h>
#endif
#include <ibmtss/tssprintcmd.h>
#include "tss20.h"
/* Files:
h01xxxxxx.bin - NV index name
h02xxxxxx.bin - hmac session context
h03xxxxxx.bin - policy session context
h80xxxxxx.bin - transient object name
cxxxx...xxxx.bin - context blob name
*/
/* NOTE Synchronize with
TSS_HmacSession_InitContext
TSS_HmacSession_Unmarshal
TSS_HmacSession_Marshal
*/
struct TSS_HMAC_CONTEXT {
TPMI_SH_AUTH_SESSION sessionHandle; /* the session handle */
TPMI_ALG_HASH authHashAlg; /* hash algorithm to use for the session */
#ifndef TPM_TSS_NOCRYPTO
uint32_t sizeInBytes; /* hash algorithm mapped to size */
#endif /* TPM_TSS_NOCRYPTO */
TPMT_SYM_DEF symmetric; /* the algorithm and key size for parameter
encryption */
TPMI_DH_ENTITY bind; /* bind handle */
TPM2B_NAME bindName; /* Name corresponding to the the bind
handle */
TPM2B_AUTH bindAuthValue; /* password corresponding to the bind
handle */
#ifndef TPM_TSS_NOCRYPTO
TPM2B_NONCE nonceTPM; /* from TPM in response */
TPM2B_NONCE nonceCaller; /* from caller in command */
TPM2B_DIGEST sessionKey; /* from KDFa at session creation */
#endif /* TPM_TSS_NOCRYPTO */
TPM_SE sessionType; /* HMAC (0), policy (1), or trial policy */
uint8_t isPasswordNeeded; /* flag set by policy password */
uint8_t isAuthValueNeeded; /* flag set by policy authvalue */
/* Items below this line are for the lifetime of one command. They are not saved and loaded. */
TPM2B_KEY hmacKey; /* HMAC key calculated for each command */
#ifndef TPM_TSS_NOCRYPTO
TPM2B_KEY sessionValue; /* KDFa secret for parameter encryption */
#endif /* TPM_TSS_NOCRYPTO */
} TSS_HMAC_CONTEXT;
/* functions for command pre- and post- processing */
typedef TPM_RC (*TSS_PreProcessFunction_t)(TSS_CONTEXT *tssContext,
COMMAND_PARAMETERS *in,
EXTRA_PARAMETERS *extra);
typedef TPM_RC (*TSS_ChangeAuthFunction_t)(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
COMMAND_PARAMETERS *in);
typedef TPM_RC (*TSS_PostProcessFunction_t)(TSS_CONTEXT *tssContext,
COMMAND_PARAMETERS *in,
RESPONSE_PARAMETERS *out,
EXTRA_PARAMETERS *extra);
static TPM_RC TSS_PR_StartAuthSession(TSS_CONTEXT *tssContext,
StartAuthSession_In *in,
StartAuthSession_Extra *extra);
static TPM_RC TSS_PR_NV_DefineSpace(TSS_CONTEXT *tssContext,
NV_DefineSpace_In *in,
void *extra);
static TPM_RC TSS_CA_HierarchyChangeAuth(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
HierarchyChangeAuth_In *in);
static TPM_RC TSS_CA_NV_UndefineSpaceSpecial(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
NV_UndefineSpaceSpecial_In *in);
static TPM_RC TSS_CA_NV_ChangeAuth(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
NV_ChangeAuth_In *in);
static TPM_RC TSS_PO_StartAuthSession(TSS_CONTEXT *tssContext,
StartAuthSession_In *in,
StartAuthSession_Out *out,
StartAuthSession_Extra *extra);
static TPM_RC TSS_PO_ContextSave(TSS_CONTEXT *tssContext,
ContextSave_In *in,
ContextSave_Out *out,
void *extra);
static TPM_RC TSS_PO_ContextLoad(TSS_CONTEXT *tssContext,
ContextLoad_In *in,
ContextLoad_Out *out,
void *extra);
static TPM_RC TSS_PO_FlushContext(TSS_CONTEXT *tssContext,
FlushContext_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_EvictControl(TSS_CONTEXT *tssContext,
EvictControl_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_Load(TSS_CONTEXT *tssContext,
Load_In *in,
Load_Out *out,
void *extra);
static TPM_RC TSS_PO_LoadExternal(TSS_CONTEXT *tssContext,
LoadExternal_In *in,
LoadExternal_Out *out,
void *extra);
static TPM_RC TSS_PO_ReadPublic(TSS_CONTEXT *tssContext,
ReadPublic_In *in,
ReadPublic_Out *out,
void *extra);
static TPM_RC TSS_PO_CreateLoaded(TSS_CONTEXT *tssContext,
CreateLoaded_In *in,
CreateLoaded_Out *out,
void *extra);
static TPM_RC TSS_PO_HMAC_Start(TSS_CONTEXT *tssContext,
HMAC_Start_In *in,
HMAC_Start_Out *out,
void *extra);
static TPM_RC TSS_PO_HashSequenceStart(TSS_CONTEXT *tssContext,
HashSequenceStart_In *in,
HashSequenceStart_Out *out,
void *extra);
static TPM_RC TSS_PO_SequenceComplete(TSS_CONTEXT *tssContext,
SequenceComplete_In *in,
SequenceComplete_Out *out,
void *extra);
static TPM_RC TSS_PO_EventSequenceComplete(TSS_CONTEXT *tssContext,
EventSequenceComplete_In *in,
EventSequenceComplete_Out *out,
void *extra);
static TPM_RC TSS_PO_PolicyAuthValue(TSS_CONTEXT *tssContext,
PolicyAuthValue_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_PolicyPassword(TSS_CONTEXT *tssContext,
PolicyPassword_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_CreatePrimary(TSS_CONTEXT *tssContext,
CreatePrimary_In *in,
CreatePrimary_Out *out,
void *extra);
static TPM_RC TSS_PO_NV_DefineSpace(TSS_CONTEXT *tssContext,
NV_DefineSpace_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_NV_ReadPublic(TSS_CONTEXT *tssContext,
NV_ReadPublic_In *in,
NV_ReadPublic_Out *out,
void *extra);
static TPM_RC TSS_PO_NV_UndefineSpace(TSS_CONTEXT *tssContext,
NV_UndefineSpace_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_NV_UndefineSpaceSpecial(TSS_CONTEXT *tssContext,
NV_UndefineSpaceSpecial_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_NV_Write(TSS_CONTEXT *tssContext,
NV_Write_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_NV_WriteLock(TSS_CONTEXT *tssContext,
NV_WriteLock_In *in,
void *out,
void *extra);
static TPM_RC TSS_PO_NV_ReadLock(TSS_CONTEXT *tssContext,
NV_ReadLock_In *in,
void *out,
void *extra);
typedef struct TSS_TABLE {
TPM_CC commandCode;
TSS_PreProcessFunction_t preProcessFunction;
TSS_ChangeAuthFunction_t changeAuthFunction;
TSS_PostProcessFunction_t postProcessFunction;
} TSS_TABLE;
/* This table indexes from the command to pre- and post- processing functions. A missing entry is
not an error, and indicates a command with no functions. */
static const TSS_TABLE tssTable [] = {
{TPM_CC_Startup, NULL, NULL, NULL},
{TPM_CC_Shutdown, NULL, NULL, NULL},
{TPM_CC_SelfTest, NULL, NULL, NULL},
{TPM_CC_IncrementalSelfTest, NULL, NULL, NULL},
{TPM_CC_GetTestResult, NULL, NULL, NULL},
{TPM_CC_StartAuthSession, (TSS_PreProcessFunction_t)TSS_PR_StartAuthSession, NULL, (TSS_PostProcessFunction_t)TSS_PO_StartAuthSession},
{TPM_CC_PolicyRestart, NULL, NULL, NULL},
{TPM_CC_Create, NULL, NULL, NULL},
{TPM_CC_Load, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_Load},
{TPM_CC_LoadExternal, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_LoadExternal},
{TPM_CC_ReadPublic, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_ReadPublic},
{TPM_CC_ActivateCredential, NULL, NULL, NULL},
{TPM_CC_MakeCredential, NULL, NULL, NULL},
{TPM_CC_Unseal, NULL, NULL, NULL},
{TPM_CC_ObjectChangeAuth, NULL, NULL, NULL},
{TPM_CC_CreateLoaded, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_CreateLoaded},
{TPM_CC_Duplicate, NULL, NULL, NULL},
{TPM_CC_Rewrap, NULL, NULL, NULL},
{TPM_CC_Import, NULL, NULL, NULL},
{TPM_CC_RSA_Encrypt, NULL, NULL, NULL},
{TPM_CC_RSA_Decrypt, NULL, NULL, NULL},
{TPM_CC_ECDH_KeyGen, NULL, NULL, NULL},
{TPM_CC_ECDH_ZGen, NULL, NULL, NULL},
{TPM_CC_ECC_Parameters, NULL, NULL, NULL},
{TPM_CC_ZGen_2Phase, NULL, NULL, NULL},
{TPM_CC_EncryptDecrypt, NULL, NULL, NULL},
{TPM_CC_EncryptDecrypt2, NULL, NULL, NULL},
{TPM_CC_Hash, NULL, NULL, NULL},
{TPM_CC_HMAC, NULL, NULL, NULL},
{TPM_CC_GetRandom, NULL, NULL, NULL},
{TPM_CC_StirRandom, NULL, NULL, NULL},
{TPM_CC_HMAC_Start, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_HMAC_Start},
{TPM_CC_HashSequenceStart, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_HashSequenceStart},
{TPM_CC_SequenceUpdate, NULL, NULL, NULL},
{TPM_CC_SequenceComplete, NULL,NULL, (TSS_PostProcessFunction_t)TSS_PO_SequenceComplete},
{TPM_CC_EventSequenceComplete, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_EventSequenceComplete},
{TPM_CC_Certify, NULL, NULL, NULL},
{TPM_CC_CertifyX509, NULL, NULL, NULL},
{TPM_CC_CertifyCreation, NULL, NULL, NULL},
{TPM_CC_Quote, NULL, NULL, NULL},
{TPM_CC_GetSessionAuditDigest, NULL, NULL, NULL},
{TPM_CC_GetCommandAuditDigest, NULL, NULL, NULL},
{TPM_CC_GetTime, NULL, NULL, NULL},
{TPM_CC_Commit, NULL, NULL, NULL},
{TPM_CC_EC_Ephemeral, NULL, NULL, NULL},
{TPM_CC_VerifySignature, NULL, NULL, NULL},
{TPM_CC_Sign, NULL, NULL, NULL},
{TPM_CC_SetCommandCodeAuditStatus, NULL, NULL, NULL},
{TPM_CC_PCR_Extend, NULL, NULL, NULL},
{TPM_CC_PCR_Event, NULL, NULL, NULL},
{TPM_CC_PCR_Read, NULL, NULL, NULL},
{TPM_CC_PCR_Allocate, NULL, NULL, NULL},
{TPM_CC_PCR_SetAuthPolicy, NULL, NULL, NULL},
{TPM_CC_PCR_SetAuthValue, NULL, NULL, NULL},
{TPM_CC_PCR_Reset, NULL, NULL, NULL},
{TPM_CC_PolicySigned, NULL, NULL, NULL},
{TPM_CC_PolicySecret, NULL, NULL, NULL},
{TPM_CC_PolicyTicket, NULL, NULL, NULL},
{TPM_CC_PolicyOR, NULL, NULL, NULL},
{TPM_CC_PolicyPCR, NULL, NULL, NULL},
{TPM_CC_PolicyLocality, NULL, NULL, NULL},
{TPM_CC_PolicyNV, NULL, NULL, NULL},
{TPM_CC_PolicyAuthorizeNV, NULL, NULL, NULL},
{TPM_CC_PolicyCounterTimer, NULL, NULL, NULL},
{TPM_CC_PolicyCommandCode, NULL, NULL, NULL},
{TPM_CC_PolicyPhysicalPresence, NULL, NULL, NULL},
{TPM_CC_PolicyCpHash, NULL, NULL, NULL},
{TPM_CC_PolicyNameHash, NULL, NULL, NULL},
{TPM_CC_PolicyDuplicationSelect, NULL, NULL, NULL},
{TPM_CC_PolicyAuthorize, NULL, NULL, NULL},
{TPM_CC_PolicyAuthValue, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_PolicyAuthValue},
{TPM_CC_PolicyPassword, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_PolicyPassword},
{TPM_CC_PolicyGetDigest, NULL, NULL, NULL},
{TPM_CC_PolicyNvWritten, NULL, NULL, NULL},
{TPM_CC_PolicyTemplate, NULL, NULL, NULL},
{TPM_CC_CreatePrimary, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_CreatePrimary},
{TPM_CC_HierarchyControl, NULL, NULL, NULL},
{TPM_CC_SetPrimaryPolicy, NULL, NULL, NULL},
{TPM_CC_ChangePPS, NULL, NULL, NULL},
{TPM_CC_ChangeEPS, NULL, NULL, NULL},
{TPM_CC_Clear, NULL, NULL, NULL},
{TPM_CC_ClearControl, NULL, NULL, NULL},
{TPM_CC_HierarchyChangeAuth, NULL, (TSS_ChangeAuthFunction_t)TSS_CA_HierarchyChangeAuth, NULL},
{TPM_CC_DictionaryAttackLockReset, NULL, NULL, NULL},
{TPM_CC_DictionaryAttackParameters, NULL, NULL, NULL},
{TPM_CC_PP_Commands, NULL, NULL, NULL},
{TPM_CC_SetAlgorithmSet, NULL, NULL, NULL},
{TPM_CC_ContextSave, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_ContextSave},
{TPM_CC_ContextLoad, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_ContextLoad},
{TPM_CC_FlushContext, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_FlushContext},
{TPM_CC_EvictControl, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_EvictControl},
{TPM_CC_ReadClock, NULL, NULL, NULL},
{TPM_CC_ClockSet, NULL, NULL, NULL},
{TPM_CC_ClockRateAdjust, NULL, NULL, NULL},
{TPM_CC_GetCapability, NULL, NULL, NULL},
{TPM_CC_TestParms, NULL, NULL, NULL},
{TPM_CC_NV_DefineSpace, (TSS_PreProcessFunction_t)TSS_PR_NV_DefineSpace, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_DefineSpace},
{TPM_CC_NV_UndefineSpace, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_UndefineSpace},
{TPM_CC_NV_UndefineSpaceSpecial, NULL, (TSS_ChangeAuthFunction_t)TSS_CA_NV_UndefineSpaceSpecial, (TSS_PostProcessFunction_t)TSS_PO_NV_UndefineSpaceSpecial},
{TPM_CC_NV_ReadPublic, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_ReadPublic},
{TPM_CC_NV_Write, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_Write},
{TPM_CC_NV_Increment, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_Write},
{TPM_CC_NV_Extend, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_Write},
{TPM_CC_NV_SetBits, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_Write},
{TPM_CC_NV_WriteLock, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_WriteLock},
{TPM_CC_NV_GlobalWriteLock, NULL, NULL, NULL},
{TPM_CC_NV_Read, NULL, NULL, NULL},
{TPM_CC_NV_ReadLock, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_ReadLock},
{TPM_CC_NV_ChangeAuth, NULL, (TSS_ChangeAuthFunction_t)TSS_CA_NV_ChangeAuth, NULL},
{TPM_CC_NV_Certify, NULL, NULL, NULL}
};
#ifndef TPM_TSS_NO_PRINT
typedef void (*TSS_InPrintFunction_t)(COMMAND_PARAMETERS *in, unsigned int indent);
typedef struct TSS_PRINT_TABLE {
TPM_CC commandCode;
TSS_InPrintFunction_t inPrintFunction;
} TSS_PRINT_TABLE;
/* This table indexes from the command to print functions. A missing entry is
not an error, and indicates a command with no function. */
static const TSS_PRINT_TABLE tssPrintTable [] = {
{TPM_CC_Startup, (TSS_InPrintFunction_t)Startup_In_Print},
{TPM_CC_Shutdown, (TSS_InPrintFunction_t)Shutdown_In_Print},
{TPM_CC_SelfTest, (TSS_InPrintFunction_t)SelfTest_In_Print},
{TPM_CC_IncrementalSelfTest, (TSS_InPrintFunction_t)IncrementalSelfTest_In_Print},
{TPM_CC_GetTestResult, NULL},
{TPM_CC_StartAuthSession, (TSS_InPrintFunction_t)StartAuthSession_In_Print},
{TPM_CC_PolicyRestart, (TSS_InPrintFunction_t)PolicyRestart_In_Print},
{TPM_CC_Create,(TSS_InPrintFunction_t)Create_In_Print},
{TPM_CC_Load, (TSS_InPrintFunction_t)Load_In_Print},
{TPM_CC_LoadExternal, (TSS_InPrintFunction_t)LoadExternal_In_Print},
{TPM_CC_ReadPublic, (TSS_InPrintFunction_t)ReadPublic_In_Print},
{TPM_CC_ActivateCredential, (TSS_InPrintFunction_t)ActivateCredential_In_Print},
{TPM_CC_MakeCredential, (TSS_InPrintFunction_t)MakeCredential_In_Print},
{TPM_CC_Unseal, (TSS_InPrintFunction_t)Unseal_In_Print},
{TPM_CC_ObjectChangeAuth, (TSS_InPrintFunction_t)ObjectChangeAuth_In_Print},
{TPM_CC_CreateLoaded, (TSS_InPrintFunction_t)CreateLoaded_In_Print},
{TPM_CC_Duplicate, (TSS_InPrintFunction_t)Duplicate_In_Print},
{TPM_CC_Rewrap, (TSS_InPrintFunction_t)Rewrap_In_Print},
{TPM_CC_Import, (TSS_InPrintFunction_t)Import_In_Print},
{TPM_CC_RSA_Encrypt, (TSS_InPrintFunction_t)RSA_Encrypt_In_Print},
{TPM_CC_RSA_Decrypt, (TSS_InPrintFunction_t)RSA_Decrypt_In_Print},
{TPM_CC_ECDH_KeyGen, (TSS_InPrintFunction_t)ECDH_KeyGen_In_Print},
{TPM_CC_ECDH_ZGen, (TSS_InPrintFunction_t)ECDH_ZGen_In_Print},
{TPM_CC_ECC_Parameters, (TSS_InPrintFunction_t)ECC_Parameters_In_Print},
{TPM_CC_ZGen_2Phase, (TSS_InPrintFunction_t)ZGen_2Phase_In_Print},
{TPM_CC_EncryptDecrypt, (TSS_InPrintFunction_t)EncryptDecrypt_In_Print},
{TPM_CC_EncryptDecrypt2, (TSS_InPrintFunction_t)EncryptDecrypt2_In_Print},
{TPM_CC_Hash, (TSS_InPrintFunction_t)Hash_In_Print},
{TPM_CC_HMAC, (TSS_InPrintFunction_t)HMAC_In_Print},
{TPM_CC_GetRandom, (TSS_InPrintFunction_t)GetRandom_In_Print},
{TPM_CC_StirRandom, (TSS_InPrintFunction_t)StirRandom_In_Print},
{TPM_CC_HMAC_Start, (TSS_InPrintFunction_t)HMAC_Start_In_Print},
{TPM_CC_HashSequenceStart, (TSS_InPrintFunction_t)HashSequenceStart_In_Print},
{TPM_CC_SequenceUpdate, (TSS_InPrintFunction_t)SequenceUpdate_In_Print},
{TPM_CC_SequenceComplete, (TSS_InPrintFunction_t)SequenceComplete_In_Print},
{TPM_CC_EventSequenceComplete, (TSS_InPrintFunction_t)EventSequenceComplete_In_Print},
{TPM_CC_Certify, (TSS_InPrintFunction_t)Certify_In_Print},
{TPM_CC_CertifyX509, (TSS_InPrintFunction_t)CertifyX509_In_Print},
{TPM_CC_CertifyCreation, (TSS_InPrintFunction_t)CertifyCreation_In_Print},
{TPM_CC_Quote, (TSS_InPrintFunction_t)Quote_In_Print},
{TPM_CC_GetSessionAuditDigest, (TSS_InPrintFunction_t)GetSessionAuditDigest_In_Print},
{TPM_CC_GetCommandAuditDigest, (TSS_InPrintFunction_t)GetCommandAuditDigest_In_Print},
{TPM_CC_GetTime, (TSS_InPrintFunction_t)GetTime_In_Print},
{TPM_CC_Commit, (TSS_InPrintFunction_t)Commit_In_Print},
{TPM_CC_EC_Ephemeral, (TSS_InPrintFunction_t)EC_Ephemeral_In_Print},
{TPM_CC_VerifySignature, (TSS_InPrintFunction_t)VerifySignature_In_Print},
{TPM_CC_Sign, (TSS_InPrintFunction_t)Sign_In_Print},
{TPM_CC_SetCommandCodeAuditStatus, (TSS_InPrintFunction_t)SetCommandCodeAuditStatus_In_Print},
{TPM_CC_PCR_Extend, (TSS_InPrintFunction_t)PCR_Extend_In_Print},
{TPM_CC_PCR_Event, (TSS_InPrintFunction_t)PCR_Event_In_Print},
{TPM_CC_PCR_Read, (TSS_InPrintFunction_t)PCR_Read_In_Print},
{TPM_CC_PCR_Allocate, (TSS_InPrintFunction_t)PCR_Allocate_In_Print},
{TPM_CC_PCR_SetAuthPolicy, (TSS_InPrintFunction_t)PCR_SetAuthPolicy_In_Print},
{TPM_CC_PCR_SetAuthValue, (TSS_InPrintFunction_t)PCR_SetAuthValue_In_Print},
{TPM_CC_PCR_Reset, (TSS_InPrintFunction_t)PCR_Reset_In_Print},
{TPM_CC_PolicySigned, (TSS_InPrintFunction_t)PolicySigned_In_Print},
{TPM_CC_PolicySecret, (TSS_InPrintFunction_t)PolicySecret_In_Print},
{TPM_CC_PolicyTicket, (TSS_InPrintFunction_t)PolicyTicket_In_Print},
{TPM_CC_PolicyOR, (TSS_InPrintFunction_t)PolicyOR_In_Print},
{TPM_CC_PolicyPCR, (TSS_InPrintFunction_t)PolicyPCR_In_Print},
{TPM_CC_PolicyLocality, (TSS_InPrintFunction_t)PolicyLocality_In_Print},
{TPM_CC_PolicyNV, (TSS_InPrintFunction_t)PolicyNV_In_Print},
{TPM_CC_PolicyAuthorizeNV, (TSS_InPrintFunction_t)PolicyAuthorizeNV_In_Print},
{TPM_CC_PolicyCounterTimer, (TSS_InPrintFunction_t)PolicyCounterTimer_In_Print},
{TPM_CC_PolicyCommandCode, (TSS_InPrintFunction_t)PolicyCommandCode_In_Print},
{TPM_CC_PolicyPhysicalPresence, (TSS_InPrintFunction_t)PolicyPhysicalPresence_In_Print},
{TPM_CC_PolicyCpHash, (TSS_InPrintFunction_t)PolicyCpHash_In_Print},
{TPM_CC_PolicyNameHash, (TSS_InPrintFunction_t)PolicyNameHash_In_Print},
{TPM_CC_PolicyDuplicationSelect, (TSS_InPrintFunction_t)PolicyDuplicationSelect_In_Print},
{TPM_CC_PolicyAuthorize, (TSS_InPrintFunction_t)PolicyAuthorize_In_Print},
{TPM_CC_PolicyAuthValue, (TSS_InPrintFunction_t)PolicyAuthValue_In_Print},
{TPM_CC_PolicyPassword, (TSS_InPrintFunction_t)PolicyPassword_In_Print},
{TPM_CC_PolicyGetDigest, (TSS_InPrintFunction_t)PolicyGetDigest_In_Print},
{TPM_CC_PolicyNvWritten, (TSS_InPrintFunction_t)PolicyNvWritten_In_Print},
{TPM_CC_PolicyTemplate, (TSS_InPrintFunction_t)PolicyTemplate_In_Print},
{TPM_CC_CreatePrimary, (TSS_InPrintFunction_t)CreatePrimary_In_Print},
{TPM_CC_HierarchyControl, (TSS_InPrintFunction_t)HierarchyControl_In_Print},
{TPM_CC_SetPrimaryPolicy, (TSS_InPrintFunction_t)SetPrimaryPolicy_In_Print},
{TPM_CC_ChangePPS, (TSS_InPrintFunction_t)ChangePPS_In_Print},
{TPM_CC_ChangeEPS, (TSS_InPrintFunction_t)ChangeEPS_In_Print},
{TPM_CC_Clear, (TSS_InPrintFunction_t)Clear_In_Print},
{TPM_CC_ClearControl, (TSS_InPrintFunction_t)ClearControl_In_Print},
{TPM_CC_HierarchyChangeAuth, (TSS_InPrintFunction_t)HierarchyChangeAuth_In_Print},
{TPM_CC_DictionaryAttackLockReset, (TSS_InPrintFunction_t)DictionaryAttackLockReset_In_Print},
{TPM_CC_DictionaryAttackParameters, (TSS_InPrintFunction_t)DictionaryAttackParameters_In_Print},
{TPM_CC_PP_Commands, (TSS_InPrintFunction_t)PP_Commands_In_Print},
{TPM_CC_SetAlgorithmSet, (TSS_InPrintFunction_t)SetAlgorithmSet_In_Print},
{TPM_CC_ContextSave, (TSS_InPrintFunction_t)ContextSave_In_Print},
{TPM_CC_ContextLoad, (TSS_InPrintFunction_t)ContextLoad_In_Print},
{TPM_CC_FlushContext, (TSS_InPrintFunction_t)FlushContext_In_Print},
{TPM_CC_EvictControl, (TSS_InPrintFunction_t)EvictControl_In_Print},
{TPM_CC_ReadClock, (TSS_InPrintFunction_t)NULL},
{TPM_CC_ClockSet, (TSS_InPrintFunction_t)ClockSet_In_Print},
{TPM_CC_ClockRateAdjust, (TSS_InPrintFunction_t)ClockRateAdjust_In_Print},
{TPM_CC_GetCapability, (TSS_InPrintFunction_t)GetCapability_In_Print},
{TPM_CC_TestParms, (TSS_InPrintFunction_t)TestParms_In_Print},
{TPM_CC_NV_DefineSpace, (TSS_InPrintFunction_t)NV_DefineSpace_In_Print},
{TPM_CC_NV_UndefineSpace, (TSS_InPrintFunction_t)NV_UndefineSpace_In_Print},
{TPM_CC_NV_UndefineSpaceSpecial, (TSS_InPrintFunction_t)NV_UndefineSpaceSpecial_In_Print},
{TPM_CC_NV_ReadPublic, (TSS_InPrintFunction_t)NV_ReadPublic_In_Print},
{TPM_CC_NV_Write, (TSS_InPrintFunction_t)NV_Write_In_Print},
{TPM_CC_NV_Increment, (TSS_InPrintFunction_t)NV_Increment_In_Print},
{TPM_CC_NV_Extend, (TSS_InPrintFunction_t)NV_Extend_In_Print},
{TPM_CC_NV_SetBits, (TSS_InPrintFunction_t)NV_SetBits_In_Print},
{TPM_CC_NV_WriteLock, (TSS_InPrintFunction_t)NV_WriteLock_In_Print},
{TPM_CC_NV_GlobalWriteLock, (TSS_InPrintFunction_t)NV_GlobalWriteLock_In_Print},
{TPM_CC_NV_Read, (TSS_InPrintFunction_t)NV_Read_In_Print},
{TPM_CC_NV_ReadLock, (TSS_InPrintFunction_t)NV_ReadLock_In_Print},
{TPM_CC_NV_ChangeAuth, (TSS_InPrintFunction_t)NV_ChangeAuth_In_Print},
{TPM_CC_NV_Certify, (TSS_InPrintFunction_t)NV_Certify_In_Print}
};
#endif /* TPM_TSS_NO_PRINT */
/* local prototypes */
static TPM_RC TSS_Execute_valist(TSS_CONTEXT *tssContext,
COMMAND_PARAMETERS *in,
va_list ap);
static TPM_RC TSS_PwapSession_Set(TPMS_AUTH_COMMAND *authCommand,
const char *password);
static TPM_RC TSS_PwapSession_Verify(TPMS_AUTH_RESPONSE *authResponse);
static TPM_RC TSS_HmacSession_GetContext(struct TSS_HMAC_CONTEXT **session);
static void TSS_HmacSession_InitContext(struct TSS_HMAC_CONTEXT *session);
static void TSS_HmacSession_FreeContext(struct TSS_HMAC_CONTEXT *session);
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_HmacSession_SetSessionKey(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
TPM2B_DIGEST *salt,
TPMI_DH_ENTITY bind,
TPM2B_AUTH *bindAuthValue);
static TPM_RC TSS_HmacSession_SetNonceCaller(struct TSS_HMAC_CONTEXT *session,
TPMS_AUTH_COMMAND *authC);
static TPM_RC TSS_HmacSession_SetHmacKey(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
const char *password);
#endif /* TPM_TSS_NOCRYPTO */
static TPM_RC TSS_HmacSession_SetHMAC(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session[],
TPMS_AUTH_COMMAND *authCommand[],
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[],
const char *password[],
TPM2B_NAME *name0,
TPM2B_NAME *name1,
TPM2B_NAME *name2);
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_HmacSession_Verify(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session,
TPMS_AUTH_RESPONSE *authResponse);
#endif /* TPM_TSS_NOCRYPTO */
static TPM_RC TSS_HmacSession_Continue(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
TPMS_AUTH_RESPONSE *authR);
static TPM_RC TSS_HmacSession_SaveSession(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session);
static TPM_RC TSS_HmacSession_LoadSession(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
TPMI_SH_AUTH_SESSION sessionHandle);
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_HmacSession_SaveData(TSS_CONTEXT *tssContext,
TPMI_SH_AUTH_SESSION sessionHandle,
uint32_t outLength,
uint8_t *outBuffer);
static TPM_RC TSS_HmacSession_LoadData(TSS_CONTEXT *tssContext,
uint32_t *inLength, uint8_t **inData,
TPMI_SH_AUTH_SESSION sessionHandle);
static TPM_RC TSS_HmacSession_DeleteData(TSS_CONTEXT *tssContext,
TPMI_SH_AUTH_SESSION sessionHandle);
static TPM_RC TSS_HmacSession_GetSlotForHandle(TSS_CONTEXT *tssContext,
size_t *slotIndex,
TPMI_SH_AUTH_SESSION sessionHandle);
#endif
static TPM_RC TSS_HmacSession_Marshal(struct TSS_HMAC_CONTEXT *source,
uint16_t *written, uint8_t **buffer, uint32_t *size);
static TPM_RC TSS_HmacSession_Unmarshal(struct TSS_HMAC_CONTEXT *target,
uint8_t **buffer, uint32_t *size);
static TPM_RC TSS_Name_GetAllNames(TSS_CONTEXT *tssContext,
TPM2B_NAME **names);
static TPM_RC TSS_Name_GetName(TSS_CONTEXT *tssContext,
TPM2B_NAME *name,
TPM_HANDLE handle);
static TPM_RC TSS_Name_Store(TSS_CONTEXT *tssContext,
TPM2B_NAME *name,
TPM_HANDLE handle,
const char *string);
static TPM_RC TSS_Name_Load(TSS_CONTEXT *tssContext,
TPM2B_NAME *name,
TPM_HANDLE handle,
const char *string);
static TPM_RC TSS_Name_Copy(TSS_CONTEXT *tssContext,
TPM_HANDLE outHandle,
const char *outString,
TPM_HANDLE inHandle,
const char *inString);
static TPM_RC TSS_Public_Store(TSS_CONTEXT *tssContext,
TPM2B_PUBLIC *public,
TPM_HANDLE handle,
const char *string);
static TPM_RC TSS_Public_Load(TSS_CONTEXT *tssContext,
TPM2B_PUBLIC *public,
TPM_HANDLE handle,
const char *string);
static TPM_RC TSS_Public_Copy(TSS_CONTEXT *tssContext,
TPM_HANDLE outHandle,
const char *outString,
TPM_HANDLE inHandle,
const char *inString);
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_ObjectPublic_GetSlotForHandle(TSS_CONTEXT *tssContext,
size_t *slotIndex,
TPM_HANDLE handle);
static TPM_RC TSS_ObjectPublic_DeleteData(TSS_CONTEXT *tssContext, TPM_HANDLE handle);
#endif
static TPM_RC TSS_DeleteHandle(TSS_CONTEXT *tssContext,
TPM_HANDLE handle);
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_ObjectPublic_GetName(TPM2B_NAME *name,
TPMT_PUBLIC *tpmtPublic);
static TPM_RC TSS_NVPublic_Store(TSS_CONTEXT *tssContext,
TPMS_NV_PUBLIC *nvPublic,
TPMI_RH_NV_INDEX handle);
static TPM_RC TSS_NVPublic_Load(TSS_CONTEXT *tssContext,
TPMS_NV_PUBLIC *nvPublic,
TPMI_RH_NV_INDEX handle);
#endif
static TPM_RC TSS_NVPublic_Delete(TSS_CONTEXT *tssContext,
TPMI_RH_NV_INDEX nvIndex);
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_NvPublic_GetSlotForHandle(TSS_CONTEXT *tssContext,
size_t *slotIndex,
TPMI_RH_NV_INDEX nvIndex);
#endif
static TPM_RC TSS_Command_Decrypt(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session[],
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[]);
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_Command_DecryptXor(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session);
static TPM_RC TSS_Command_DecryptAes(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session);
#endif /* TPM_TSS_NOCRYPTO */
static TPM_RC TSS_Response_Encrypt(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session[],
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[]);
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_Response_EncryptXor(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session);
static TPM_RC TSS_Response_EncryptAes(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session);
static TPM_RC TSS_Command_ChangeAuthProcessor(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
COMMAND_PARAMETERS *in);
#endif /* TPM_TSS_NOCRYPTO */
static TPM_RC TSS_Command_PreProcessor(TSS_CONTEXT *tssContext,
TPM_CC commandCode,
COMMAND_PARAMETERS *in,
EXTRA_PARAMETERS *extra);
static TPM_RC TSS_Response_PostProcessor(TSS_CONTEXT *tssContext,
COMMAND_PARAMETERS *in,
RESPONSE_PARAMETERS *out,
EXTRA_PARAMETERS *extra);
static TPM_RC TSS_Sessions_GetDecryptSession(unsigned int *isDecrypt,
unsigned int *decryptSession,
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[]);
static TPM_RC TSS_Sessions_GetEncryptSession(unsigned int *isEncrypt,
unsigned int *encryptSession,
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[]);
#ifndef TPM_TSS_NOFILE
static TPM_RC TSS_HashToString(char *str, uint8_t *digest);
#endif
#ifndef TPM_TSS_NOCRYPTO
#ifndef TPM_TSS_NORSA
static TPM_RC TSS_RSA_Salt(TPM2B_DIGEST *salt,
TPM2B_ENCRYPTED_SECRET *encryptedSalt,
TPMT_PUBLIC *publicArea);
#endif /* TPM_TSS_NORSA */
#endif /* TPM_TSS_NOCRYPTO */
extern int tssVerbose;
extern int tssVverbose;
extern int tssFirstCall;
TPM_RC TSS_Execute20(TSS_CONTEXT *tssContext,
RESPONSE_PARAMETERS *out,
COMMAND_PARAMETERS *in,
EXTRA_PARAMETERS *extra,
TPM_CC commandCode,
va_list ap)
{
TPM_RC rc = 0;
/* create a TSS authorization context */
if (rc == 0) {
TSS_InitAuthContext(tssContext->tssAuthContext);
}
/* handle any command specific command pre-processing */
if (rc == 0) {
rc = TSS_Command_PreProcessor(tssContext,
commandCode,
in,
extra);
}
/* marshal input parameters */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute20: Command %08x marshal\n", commandCode);
rc = TSS_Marshal(tssContext->tssAuthContext,
in,
commandCode);
}
/* execute the command */
if (rc == 0) {
rc = TSS_Execute_valist(tssContext, in, ap);
}
/* unmarshal the response parameters */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute20: Command %08x unmarshal\n", commandCode);
rc = TSS_Unmarshal(tssContext->tssAuthContext, out);
}
/* handle any command specific response post-processing */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute20: Command %08x post processor\n", commandCode);
rc = TSS_Response_PostProcessor(tssContext,
in,
out,
extra);
}
return rc;
}
/* TSS_Execute_valist() transmits the marshaled command and receives the marshaled response.
varargs are TPMI_SH_AUTH_SESSION sessionHandle, const char *password, unsigned int
sessionAttributes
Terminates with sessionHandle TPM_RH_NULL
Processes up to MAX_SESSION_NUM sessions. It handles HMAC generation and command and response
parameter encryption. It loads each session context, rolls nonces, and saves or deletes the
session context.
*/
static TPM_RC TSS_Execute_valist(TSS_CONTEXT *tssContext,
COMMAND_PARAMETERS *in,
va_list ap)
{
TPM_RC rc = 0;
int done;
int haveNames = FALSE; /* names are common to all HMAC sessions */
size_t i = 0;
/* the vararg parameters */
TPMI_SH_AUTH_SESSION sessionHandle[MAX_SESSION_NUM];
const char *password[MAX_SESSION_NUM];
unsigned int sessionAttributes[MAX_SESSION_NUM];
/* structures filled in */
TPMS_AUTH_COMMAND *authCommand[MAX_SESSION_NUM];
TPMS_AUTH_RESPONSE *authResponse[MAX_SESSION_NUM];
/* pointer to the above structures as used */
TPMS_AUTH_COMMAND *authC[MAX_SESSION_NUM];
TPMS_AUTH_RESPONSE *authR[MAX_SESSION_NUM];
/* TSS sessions */
struct TSS_HMAC_CONTEXT *session[MAX_SESSION_NUM];
TPM2B_NAME *names[MAX_SESSION_NUM];
for (i = 0 ; i < MAX_SESSION_NUM ; i++) {
authCommand[i] = NULL; /* for safe free */
authResponse[i] = NULL; /* for safe free */
names[i] = NULL; /* for safe free */
authC[i] = NULL; /* array of TPMS_AUTH_COMMAND structures, NULL for
TSS_SetCmdAuths */
authR[i] = NULL; /* array of TPMS_AUTH_RESPONSE structures, NULL for
TSS_GetRspAuths */
session[i] = NULL; /* for free, used for HMAC and encrypt/decrypt sessions */
/* the varargs list inputs */
sessionHandle[i] = TPM_RH_NULL;
password[i] = NULL;
sessionAttributes[i] = 0;
}
/* Step 1: initialization */
if (tssVverbose) printf("TSS_Execute_valist: Step 1: initialization\n");
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) ; i++) {
if (rc == 0) {
rc = TSS_Malloc((unsigned char **)&authCommand[i], /* freed @1 */
sizeof(TPMS_AUTH_COMMAND));
}
if (rc == 0) {
rc = TSS_Malloc((unsigned char **)&authResponse[i], /* freed @2 */
sizeof(TPMS_AUTH_RESPONSE));
}
if (rc == 0) {
rc = TSS_Malloc((unsigned char **)&names[i], /* freed @3 */
sizeof(TPM2B_NAME));
}
if (rc == 0) {
names[i]->b.size = 0; /* to ignore unused names in cpHash calculation */
}
}
/* Step 2: gather the command authorizations
Process PWAP immediately
For HMAC, get the session context
*/
done = FALSE;
for (i = 0 ; (rc == 0) && !done && (i < MAX_SESSION_NUM) ; i++) {
sessionHandle[i] = va_arg(ap, TPMI_SH_AUTH_SESSION); /* first vararg is the session
handle */
password[i]= va_arg(ap, const char *); /* second vararg is the password */
sessionAttributes[i] = va_arg(ap, unsigned int); /* third argument is
sessionAttributes */
sessionAttributes[i] &= 0xff; /* is uint8_t */
if (sessionHandle[i] != TPM_RH_NULL) { /* varargs termination value */
if (tssVverbose) printf("TSS_Execute_valist: Step 2: authorization %u\n",
(unsigned int)i);
if (tssVverbose) printf("TSS_Execute_valist: session %u handle %08x\n",
(unsigned int)i, sessionHandle[i]);
/* make used, non-NULL for command and response varargs */
authC[i] = authCommand[i];
authR[i] = authResponse[i];
/* if password session, populate authC with password, etc. immediately */
if (sessionHandle[i] == TPM_RS_PW) {
rc = TSS_PwapSession_Set(authC[i], password[i]);
}
/* if HMAC or encrypt/decrypt session */
else {
/* initialize a TSS HMAC session */
if (rc == 0) {
rc = TSS_HmacSession_GetContext(&session[i]);
}
/* load the session created by startauthsession */
if (rc == 0) {
rc = TSS_HmacSession_LoadSession(tssContext, session[i], sessionHandle[i]);
}
/* if there is at least one HMAC session, get the names corresponding to the
handles */
if ((session[i]->sessionType == TPM_SE_HMAC) || /* HMAC session. OR */
((session[i]->sessionType == TPM_SE_POLICY) && /* Policy session AND */
#ifndef TPM_TSS_NOCRYPTO
((session[i]->isAuthValueNeeded) || /* PolicyAuthValue ran, OR */
(session[i]->sessionKey.b.size != 0))) /* Already session key (bind or salt) */
#else
(session[i]->isAuthValueNeeded)) /* PolicyAuthValue ran, OR */
#endif /* TPM_TSS_NOCRYPTO */
) {
if ((rc == 0) && !haveNames) {
rc = TSS_Name_GetAllNames(tssContext, names);
haveNames = TRUE; /* get only once, minor optimization */
}
}
}
}
else {
done = TRUE;
}
}
/* Step 3: Roll nonceCaller, save in the session context for the response */
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
if (sessionHandle[i] != TPM_RS_PW) { /* no nonce for password sessions */
if (tssVverbose)
printf("TSS_Execute_valist: Step 3: nonceCaller %08x\n", sessionHandle[i]);
#ifndef TPM_TSS_NOCRYPTO
rc = TSS_HmacSession_SetNonceCaller(session[i], authC[i]);
#else
authC[i]->nonce.b.size = 16;
memset(&authC[i]->nonce.b.buffer, 0, 16);
#endif /* TPM_TSS_NOCRYPTO */
}
}
#ifndef TPM_TSS_NOCRYPTO
/* Step 4: Calculate the HMAC key */
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
if (sessionHandle[i] != TPM_RS_PW) { /* no HMAC key for password sessions */
if (tssVverbose) printf("TSS_Execute_valist: Step 4: Session %u HMAC key for %08x\n",
(unsigned int)i, sessionHandle[i]);
rc = TSS_HmacSession_SetHmacKey(tssContext, session[i], i, password[i]);
}
}
#endif /* TPM_TSS_NOCRYPTO */
/* Step 5: command parameter encryption */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute_valist: Step 5: command encrypt\n");
rc = TSS_Command_Decrypt(tssContext->tssAuthContext,
session,
sessionHandle,
sessionAttributes);
}
/* Step 6: for each HMAC session, calculate cpHash, calculate the HMAC, and set it in
TPMS_AUTH_COMMAND */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute_valist: Step 6 calculate HMACs\n");
rc = TSS_HmacSession_SetHMAC(tssContext->tssAuthContext, /* TSS auth context */
session, /* TSS session contexts */
authC, /* output: command authorizations */
sessionHandle, /* list of session handles for the command */
sessionAttributes, /* attributes for this command */
password, /* for plaintext password sessions */
names[0], /* Name */
names[1], /* Name */
names[2]); /* Name */
}
/* Step 7: set the command authorizations in the TSS command stream */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute_valist: Step 7 set command authorizations\n");
rc = TSS_SetCmdAuths(tssContext->tssAuthContext,
authC[0],
authC[1],
authC[2],
NULL);
}
/* Step 8: process the command. Normally returns the TPM response code. */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute_valist: Step 8: process the command\n");
rc = TSS_AuthExecute(tssContext);
}
/* Step 9: get the response authorizations from the TSS response stream */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute_valist: Step 9 get response authorizations\n");
rc = TSS_GetRspAuths(tssContext->tssAuthContext,
authR[0],
authR[1],
authR[2],
NULL);
}
/* Step 10: process the response authorizations, validate the HMAC */
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
if (tssVverbose)
printf("TSS_Execute_valist: Step 10: process response authorization %08x\n",
sessionHandle[i]);
if (sessionHandle[i] == TPM_RS_PW) {
rc = TSS_PwapSession_Verify(authR[i]);
}
/* HMAC session */
else {
#ifndef TPM_TSS_NOCRYPTO
/* save nonceTPM in the session context */
if (rc == 0) {
rc = TSS_TPM2B_Copy(&session[i]->nonceTPM.b, &authR[i]->nonce.b, sizeof(TPMU_HA));
}
#endif /* TPM_TSS_NOCRYPTO */
/* the HMAC key is already part of the TSS session context. For policy sessions with
policy password, the response hmac is empty. */
if ((session[i]->sessionType == TPM_SE_HMAC) ||
((session[i]->sessionType == TPM_SE_POLICY) && (session[i]->isAuthValueNeeded))) {
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
rc = TSS_Command_ChangeAuthProcessor(tssContext, session[i], i, in);
}
if (rc == 0) {
rc = TSS_HmacSession_Verify(tssContext->tssAuthContext, /* authorization
context */
session[i], /* TSS session context */
authR[i]); /* input: response authorization */
}
#else
in = in;
if (tssVerbose)
printf("TSS_Execute_valist: "
"Error, HMAC verify with no crypto not implemented\n");
rc = TSS_RC_NOT_IMPLEMENTED;
#endif /* TPM_TSS_NOCRYPTO */
}
}
}
/* Step 11: process the audit flag */
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
if ((sessionHandle[i] != TPM_RS_PW) &&
(session[i]->bind != TPM_RH_NULL) &&
(authR[i]->sessionAttributes.val & TPMA_SESSION_AUDIT)) {
if (tssVverbose) printf("TSS_Execute_valist: Step 11: process bind audit flag %08x\n",
sessionHandle[i]);
/* if bind audit session, bind value is lost and further use requires authValue */
session[i]->bind = TPM_RH_NULL;
}
}
/* Step 12: process the response continue flag */
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
if (sessionHandle[i] != TPM_RS_PW) {
if (tssVverbose) printf("TSS_Execute_valist: Step 12: process continue flag %08x\n",
sessionHandle[i]);
rc = TSS_HmacSession_Continue(tssContext, session[i], authR[i]);
}
}
/* Step 13: response parameter decryption */
if (rc == 0) {
if (tssVverbose) printf("TSS_Execute_valist: Step 13: response decryption\n");
rc = TSS_Response_Encrypt(tssContext->tssAuthContext,
session,
sessionHandle,
sessionAttributes);
}
/* cleanup */
for (i = 0 ; i < MAX_SESSION_NUM ; i++) {
TSS_HmacSession_FreeContext(session[i]);
free(authCommand[i]); /* @1 */
free(authResponse[i]); /* @2 */
free(names[i]); /* @3 */
}
return rc;
}
/*
PWAP - Password Session
*/
/* TSS_PwapSession_Set() sets all members of the TPMS_AUTH_COMMAND structure for a PWAP session.
*/
static TPM_RC TSS_PwapSession_Set(TPMS_AUTH_COMMAND *authCommand,
const char *password)
{
TPM_RC rc = 0;
if (rc == 0) {
authCommand->sessionHandle = TPM_RS_PW;
authCommand->nonce.t.size = 0;
authCommand->sessionAttributes.val = 0;
}
if (password != NULL) {
rc = TSS_TPM2B_StringCopy(&authCommand->hmac.b,
password, sizeof(authCommand->hmac.t.buffer));
}
else {
authCommand->hmac.t.size = 0;
}
return rc;
}
/* TSS_PwapSession_Verify() verifies the PWAP session response. */
static TPM_RC TSS_PwapSession_Verify(TPMS_AUTH_RESPONSE *authResponse)
{
TPM_RC rc = 0;
if (rc == 0) {
if (authResponse->nonce.t.size != 0) {
if (tssVerbose) printf("TSS_PwapSession_Verify: nonce size %u not zero\n",
authResponse->nonce.t.size);
rc = TSS_RC_BAD_PWAP_NONCE;
}
}
if (rc == 0) {
if (authResponse->sessionAttributes.val != TPMA_SESSION_CONTINUESESSION) {
if (tssVerbose) printf("TSS_PwapSession_Verify: continue %02x not set\n",
authResponse->sessionAttributes.val);
rc = TSS_RC_BAD_PWAP_ATTRIBUTES;
}
}
if (rc == 0) {
if (authResponse->hmac.t.size != 0) {
if (tssVerbose) printf("TSS_PwapSession_Verify: HMAC size %u not zero\n",
authResponse->hmac.t.size);
rc = TSS_RC_BAD_PWAP_HMAC;
}
}
return rc;
}
/*
HMAC Session
*/
static TPM_RC TSS_HmacSession_GetContext(struct TSS_HMAC_CONTEXT **session)
{
TPM_RC rc = 0;
if (rc == 0) {
rc = TSS_Malloc((uint8_t **)session, sizeof(TSS_HMAC_CONTEXT));
}
if (rc == 0) {
TSS_HmacSession_InitContext(*session);
}
return rc;
}
static void TSS_HmacSession_InitContext(struct TSS_HMAC_CONTEXT *session)
{
session->sessionHandle = TPM_RH_NULL;
session->authHashAlg = TPM_ALG_NULL;
#ifndef TPM_TSS_NOCRYPTO
session->sizeInBytes = 0;
#endif
session->symmetric.algorithm = TPM_ALG_NULL;
session->bind = TPM_RH_NULL;
session->bindName.b.size = 0;
session->bindAuthValue.t.size = 0;
#ifndef TPM_TSS_NOCRYPTO
memset(session->nonceTPM.t.buffer, 0, sizeof(TPMU_HA));
session->nonceTPM.b.size = 0;
memset(session->nonceCaller.t.buffer, 0, sizeof(TPMU_HA));
session->nonceCaller.b.size = 0;
memset(session->sessionKey.t.buffer, 0, sizeof(TPMU_HA));
session->sessionKey.b.size = 0;
#endif
session->sessionType = 0;
session->isPasswordNeeded = FALSE;
session->isAuthValueNeeded = FALSE;
memset(session->hmacKey.t.buffer, 0, sizeof(TPMU_HA) + sizeof(TPMU_HA));
session->hmacKey.b.size = 0;
#ifndef TPM_TSS_NOCRYPTO
memset(session->sessionValue.t.buffer, 0, sizeof(TPMU_HA) + sizeof(TPMU_HA));
session->sessionValue.b.size = 0;
#endif
}
void TSS_HmacSession_FreeContext(struct TSS_HMAC_CONTEXT *session)
{
if (session != NULL) {
TSS_HmacSession_InitContext(session);
free(session);
}
return;
}
/* TSS_HmacSession_SetSessionKey() is called by the StartAuthSession post processor to calculate and
store the session key
19.6.8 sessionKey Creation
*/
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_HmacSession_SetSessionKey(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
TPM2B_DIGEST *salt,
TPMI_DH_ENTITY bind,
TPM2B_AUTH *bindAuthValue)
{
TPM_RC rc = 0;
TPM2B_KEY key; /* HMAC key for the KDFa */
if (rc == 0) {
/* save the bind handle, non-null indicates a bound session */
session->bind = bind;
/* if bind, save the bind Name in the session context. The handle might change, but the
name will not */
if ((rc == 0) && (bind != TPM_RH_NULL)) {
rc = TSS_Name_GetName(tssContext, &session->bindName, bind);
}
}
if (rc == 0) {
if ((bind != TPM_RH_NULL) ||
(salt->b.size != 0)) {
/* session key is bindAuthValue || salt */
/* copy bindAuthValue. This is set during the post processor to either the supplied
bind password or Empty */
if (rc == 0) {
rc = TSS_TPM2B_Copy(&key.b, &bindAuthValue->b, sizeof(TPMU_HA) + sizeof(TPMT_HA));
}
/* copy salt. This is set during the postprocessor to either the salt from the
preprocessor or empty. */
if (rc == 0) {
rc = TSS_TPM2B_Append(&key.b, &salt->b, sizeof(TPMU_HA) + sizeof(TPMT_HA));
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_HmacSession_SetSessionKey: KDFa HMAC key",
key.b.buffer, key.b.size);
}
/* KDFa for the session key */
if (rc == 0) {
rc = TSS_KDFA(session->sessionKey.b.buffer,
session->authHashAlg,
&key.b,
"ATH",
&session->nonceTPM.b,
&session->nonceCaller.b,
session->sizeInBytes * 8);
}
if (rc == 0) {
session->sessionKey.b.size = session->sizeInBytes;
if (tssVverbose)
TSS_PrintAll("TSS_HmacSession_SetSessionKey: Session key",
session->sessionKey.b.buffer, session->sessionKey.b.size);
}
}
else {
session->sessionKey.b.size = 0;
}
}
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
/* TSS_HmacSession_SaveSession() saves a session in two cases:
The initial session from startauthsession
The updated session a TPM response
*/
static TPM_RC TSS_HmacSession_SaveSession(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session)
{
TPM_RC rc = 0;
uint8_t *buffer = NULL; /* marshaled TSS_HMAC_CONTEXT */
uint16_t written = 0;
#ifndef TPM_TSS_NOFILE
char sessionFilename[TPM_DATA_DIR_PATH_LENGTH];
uint8_t *outBuffer = NULL;
uint32_t outLength;
#endif
if (tssVverbose) printf("TSS_HmacSession_SaveSession: handle %08x\n", session->sessionHandle);
if (rc == 0) {
rc = TSS_Structure_Marshal(&buffer, /* freed @1 */
&written,
session,
(MarshalFunction_t)TSS_HmacSession_Marshal);
}
#ifndef TPM_TSS_NOFILE
if (rc == 0) {
#ifndef TPM_TSS_NOCRYPTO
/* if the flag is set, encrypt the session state before store */
if (tssContext->tssEncryptSessions) {
rc = TSS_AES_Encrypt(tssContext->tssSessionEncKey,
&outBuffer, /* output, freed @2 */
&outLength, /* output */
buffer, /* input */
written); /* input */
}
/* else store the session state in plaintext */
else {
#endif /* TPM_TSS_NOCRYPTO */
outBuffer = buffer;
outLength = written;
#ifndef TPM_TSS_NOCRYPTO
}
#endif /* TPM_TSS_NOCRYPTO */
}
/* save the session in a hard coded file name hxxxxxxxx.bin where xxxxxxxx is the session
handle */
if (rc == 0) {
sprintf(sessionFilename, "%s/h%08x.bin",
tssContext->tssDataDirectory, session->sessionHandle);
}
if (rc == 0) {
rc = TSS_File_WriteBinaryFile(outBuffer,
outLength,
sessionFilename);
}
if (tssContext->tssEncryptSessions) {
free(outBuffer); /* @2 */
}
#else /* no file support, save to context */
if (rc == 0) {
rc = TSS_HmacSession_SaveData(tssContext,
session->sessionHandle,
written, buffer);
}
#endif
free(buffer); /* @1 */
return rc;
}
/* TSS_HmacSession_LoadSession() loads an existing HMAC session context saved by:
startauthsession
an update after a TPM response
*/
static TPM_RC TSS_HmacSession_LoadSession(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
TPMI_SH_AUTH_SESSION sessionHandle)
{
TPM_RC rc = 0;
uint8_t *buffer = NULL;
uint8_t *buffer1 = NULL;
#ifndef TPM_TSS_NOFILE
size_t length = 0;
char sessionFilename[TPM_DATA_DIR_PATH_LENGTH];
#endif
unsigned char *inData = NULL; /* output */
uint32_t inLength; /* output */
if (tssVverbose) printf("TSS_HmacSession_LoadSession: handle %08x\n", sessionHandle);
#ifndef TPM_TSS_NOFILE
/* load the session from a hard coded file name hxxxxxxxx.bin where xxxxxxxx is the session
handle */
if (rc == 0) {
sprintf(sessionFilename, "%s/h%08x.bin", tssContext->tssDataDirectory, sessionHandle);
rc = TSS_File_ReadBinaryFile(&buffer, /* freed @1 */
&length,
sessionFilename);
}
if (rc == 0) {
#ifndef TPM_TSS_NOCRYPTO
/* if the flag is set, decrypt the session state before unmarshal */
if (tssContext->tssEncryptSessions) {
rc = TSS_AES_Decrypt(tssContext->tssSessionDecKey,
&inData, /* output, freed @2 */
&inLength, /* output */
buffer, /* input */
length); /* input */
}
/* else the session was loaded in plaintext */
else {
#endif /* TPM_TSS_NOCRYPTO */
inData = buffer;
inLength = length;
#ifndef TPM_TSS_NOCRYPTO
}
#endif /* TPM_TSS_NOCRYPTO */
}
#else /* no file support, load from context */
if (rc == 0) {
rc = TSS_HmacSession_LoadData(tssContext,
&inLength, &inData,
sessionHandle);
}
#endif
if (rc == 0) {
uint32_t ilength = inLength;
buffer1 = inData;
rc = TSS_HmacSession_Unmarshal(session, &buffer1, &ilength);
}
#ifndef TPM_TSS_NOFILE
if (tssContext->tssEncryptSessions) {
free(inData); /* @2 */
}
#endif
free(buffer); /* @1 */
return rc;
}
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_HmacSession_SaveData(TSS_CONTEXT *tssContext,
TPMI_SH_AUTH_SESSION sessionHandle,
uint32_t outLength,
uint8_t *outBuffer)
{
TPM_RC rc = 0;
size_t slotIndex;
/* if this handle is already used, overwrite the slot */
if (rc == 0) {
rc = TSS_HmacSession_GetSlotForHandle(tssContext, &slotIndex, sessionHandle);
if (rc != 0) {
rc = TSS_HmacSession_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
if (rc == 0) {
tssContext->sessions[slotIndex].sessionHandle = sessionHandle;
}
else {
if (tssVerbose)
printf("TSS_HmacSession_SaveData: Error, no slot available for handle %08x\n",
sessionHandle);
}
}
}
/* reallocate memory and adjust the size */
if (rc == 0) {
rc = TSS_Realloc(&tssContext->sessions[slotIndex].sessionData, outLength);
}
if (rc == 0) {
tssContext->sessions[slotIndex].sessionDataLength = outLength;
memcpy(tssContext->sessions[slotIndex].sessionData, outBuffer, outLength);
}
return rc;
}
static TPM_RC TSS_HmacSession_LoadData(TSS_CONTEXT *tssContext,
uint32_t *inLength, uint8_t **inData,
TPMI_SH_AUTH_SESSION sessionHandle)
{
TPM_RC rc = 0;
size_t slotIndex;
if (rc == 0) {
rc = TSS_HmacSession_GetSlotForHandle(tssContext, &slotIndex, sessionHandle);
if (rc != 0) {
if (tssVerbose)
printf("TSS_HmacSession_LoadData: Error, no slot found for handle %08x\n",
sessionHandle);
}
}
if (rc == 0) {
*inLength = tssContext->sessions[slotIndex].sessionDataLength;
*inData = tssContext->sessions[slotIndex].sessionData;
}
return rc;
}
static TPM_RC TSS_HmacSession_DeleteData(TSS_CONTEXT *tssContext,
TPMI_SH_AUTH_SESSION sessionHandle)
{
TPM_RC rc = 0;
size_t slotIndex;
if (rc == 0) {
rc = TSS_HmacSession_GetSlotForHandle(tssContext, &slotIndex, sessionHandle);
if (rc != 0) {
if (tssVerbose)
printf("TSS_HmacSession_DeleteData: Error, no slot found for handle %08x\n",
sessionHandle);
}
}
if (rc == 0) {
tssContext->sessions[slotIndex].sessionHandle = TPM_RH_NULL;
/* erase any secrets */
memset(tssContext->sessions[slotIndex].sessionData, 0,
tssContext->sessions[slotIndex].sessionDataLength);
free(tssContext->sessions[slotIndex].sessionData);
tssContext->sessions[slotIndex].sessionData = NULL;
tssContext->sessions[slotIndex].sessionDataLength = 0;
}
return rc;
}
/* TSS_HmacSession_GetSlotForHandle() finds the session slot corresponding to the session handle.
Returns non-zero if no slot is found.
*/
static TPM_RC TSS_HmacSession_GetSlotForHandle(TSS_CONTEXT *tssContext,
size_t *slotIndex,
TPMI_SH_AUTH_SESSION sessionHandle)
{
size_t i;
/* search all slots for handle */
for (i = 0 ; i < (sizeof(tssContext->sessions) / sizeof(TSS_SESSIONS)) ; i++) {
if (tssContext->sessions[i].sessionHandle == sessionHandle) {
*slotIndex = i;
return 0;
}
}
return TSS_RC_NO_SESSION_SLOT;
}
#endif
static TPM_RC TSS_HmacSession_Marshal(struct TSS_HMAC_CONTEXT *source,
uint16_t *written,
uint8_t **buffer,
uint32_t *size)
{
TPM_RC rc = 0;
if (rc == 0) {
rc = TSS_TPMI_SH_AUTH_SESSION_Marshalu(&source->sessionHandle, written, buffer, size);
}
if (rc == 0) {
rc = TSS_TPMI_ALG_HASH_Marshalu(&source->authHashAlg, written, buffer, size);
}
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
rc = TSS_UINT32_Marshalu(&source->sizeInBytes, written, buffer, size);
}
#endif
if (rc == 0) {
rc = TSS_TPMT_SYM_DEF_Marshalu(&source->symmetric, written, buffer, size);
}
if (rc == 0) {
rc = TSS_TPMI_DH_ENTITY_Marshalu(&source->bind, written, buffer, size);
}
if (rc == 0) {
rc = TSS_TPM2B_NAME_Marshalu(&source->bindName, written, buffer, size);
}
#ifdef TPM_WINDOWS
/* FIXME Why does a VS release build need a printf here? */
if (tssVverbose) printf("");
#endif
if (rc == 0) {
rc = TSS_TPM2B_AUTH_Marshalu(&source->bindAuthValue, written, buffer, size);
}
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
rc = TSS_TPM2B_NONCE_Marshalu(&source->nonceTPM, written, buffer, size);
}
if (rc == 0) {
rc = TSS_TPM2B_NONCE_Marshalu(&source->nonceCaller, written, buffer, size);
}
if (rc == 0) {
rc = TSS_TPM2B_DIGEST_Marshalu(&source->sessionKey, written, buffer, size);
}
#endif
if (rc == 0) {
rc = TSS_TPM_SE_Marshalu(&source->sessionType, written, buffer, size);
}
if (rc == 0) {
rc = TSS_UINT8_Marshalu(&source->isPasswordNeeded, written, buffer, size);
}
if (rc == 0) {
rc = TSS_UINT8_Marshalu(&source->isAuthValueNeeded, written, buffer, size);
}
return rc;
}
static TPM_RC TSS_HmacSession_Unmarshal(struct TSS_HMAC_CONTEXT *target,
uint8_t **buffer, uint32_t *size)
{
TPM_RC rc = 0;
if (rc == 0) {
rc = TSS_TPMI_SH_AUTH_SESSION_Unmarshalu(&target->sessionHandle, buffer, size, NO);
}
if (rc == 0) {
rc = TSS_TPMI_ALG_HASH_Unmarshalu(&target->authHashAlg, buffer, size, NO);
}
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
rc = TSS_UINT32_Unmarshalu(&target->sizeInBytes, buffer, size);
}
#endif
if (rc == 0) {
rc = TSS_TPMT_SYM_DEF_Unmarshalu(&target->symmetric, buffer, size, YES);
}
if (rc == 0) {
rc = TSS_TPMI_DH_ENTITY_Unmarshalu(&target->bind, buffer, size, YES);
}
if (rc == 0) {
rc = TSS_TPM2B_NAME_Unmarshalu(&target->bindName, buffer, size);
}
if (rc == 0) {
rc = TSS_TPM2B_AUTH_Unmarshalu(&target->bindAuthValue, buffer, size);
}
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
rc = TSS_TPM2B_NONCE_Unmarshalu(&target->nonceTPM, buffer, size);
}
if (rc == 0) {
rc = TSS_TPM2B_NONCE_Unmarshalu(&target->nonceCaller, buffer, size);
}
if (rc == 0) {
rc = TSS_TPM2B_DIGEST_Unmarshalu(&target->sessionKey, buffer, size);
}
#endif
if (rc == 0) {
rc = TSS_TPM_SE_Unmarshalu(&target->sessionType, buffer, size);
}
if (rc == 0) {
rc = TSS_UINT8_Unmarshalu(&target->isPasswordNeeded, buffer, size);
}
if (rc == 0) {
rc = TSS_UINT8_Unmarshalu(&target->isAuthValueNeeded, buffer, size);
}
return rc;
}
/*
Name handling
*/
/* TSS_Name_GetAllNames() files in the names array based on the handles marshaled into the TSS
context command stream. */
static TPM_RC TSS_Name_GetAllNames(TSS_CONTEXT *tssContext,
TPM2B_NAME **names)
{
TPM_RC rc = 0;
size_t i;
size_t commandHandleCount; /* number of handles in the command stream */
TPM_HANDLE commandHandle;
/* get the number of handles in the command stream */
if (rc == 0) {
rc = TSS_GetCommandHandleCount(tssContext->tssAuthContext, &commandHandleCount);
if (tssVverbose) printf("TSS_Name_GetAllNames: commandHandleCount %u\n",
(unsigned int)commandHandleCount);
}
for (i = 0 ; (rc == 0) && (i < commandHandleCount) ; i++) {
/* get a handle from the command stream */
if (rc == 0) {
rc = TSS_GetCommandHandle(tssContext->tssAuthContext,
&commandHandle,
i);
}
/* get the Name corresponding to the handle */
if (rc == 0) {
if (tssVverbose) printf("TSS_Name_GetAllNames: commandHandle %u %08x\n",
(unsigned int)i, commandHandle);
rc = TSS_Name_GetName(tssContext, names[i], commandHandle);
}
}
return rc;
}
/* TSS_Name_GetName() gets the Name associated with the handle */
static TPM_RC TSS_Name_GetName(TSS_CONTEXT *tssContext,
TPM2B_NAME *name,
TPM_HANDLE handle)
{
TPM_RC rc = 0;
TPM_HT handleType;
if (tssVverbose) printf("TSS_Name_GetName: Handle %08x\n", handle);
handleType = (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
/* Table 3 - Equations for Computing Entity Names */
switch (handleType) {
/* for these, the Name is simply the handle value */
case TPM_HT_PCR:
case TPM_HT_HMAC_SESSION:
case TPM_HT_POLICY_SESSION:
case TPM_HT_PERMANENT:
rc = TSS_TPM2B_CreateUint32(&name->b, handle, sizeof(name->t.name));
break;
/* for NV, the Names was calculated at NV read public */
case TPM_HT_NV_INDEX:
/* for objects, the Name was returned at creation or load */
case TPM_HT_TRANSIENT:
case TPM_HT_PERSISTENT:
rc = TSS_Name_Load(tssContext, name, handle, NULL);
break;
default:
if (tssVerbose) printf("TSS_Name_GetName: not implemented for handle %08x\n", handle);
rc = TSS_RC_NAME_NOT_IMPLEMENTED;
break;
}
if (rc == 0) {
if (tssVverbose)
TSS_PrintAll("TSS_Name_GetName: ",
name->t.name, name->t.size);
}
return rc;
}
/* TSS_Name_Store() stores the 'name' parameter in a file.
If handle is not 0, the handle is used as the file name.
If 'string' is not NULL, the string is used as the file name.
*/
#ifndef TPM_TSS_NOFILE
static TPM_RC TSS_Name_Store(TSS_CONTEXT *tssContext,
TPM2B_NAME *name,
TPM_HANDLE handle,
const char *string)
{
TPM_RC rc = 0;
char nameFilename[TPM_DATA_DIR_PATH_LENGTH];
if (rc == 0) {
if (string == NULL) {
if (handle != 0) {
sprintf(nameFilename, "%s/h%08x.bin", tssContext->tssDataDirectory, handle);
}
else {
if (tssVerbose) printf("TSS_Name_Store: handle and string are both null");
rc = TSS_RC_NAME_FILENAME;
}
}
else {
if (handle == 0) {
sprintf(nameFilename, "%s/h%s.bin", tssContext->tssDataDirectory, string);
}
else {
if (tssVerbose) printf("TSS_Name_Store: handle and string are both not null");
rc = TSS_RC_NAME_FILENAME;
}
}
}
if (rc == 0) {
if (tssVverbose) printf("TSS_Name_Store: File %s\n", nameFilename);
rc = TSS_File_WriteBinaryFile(name->b.buffer, name->b.size, nameFilename);
}
return rc;
}
#endif
/* TSS_Name_Load() loads the 'name' from a file.
If handle is not 0, the handle is used as the file name.
If 'string' is not NULL, the string is used as the file name.
*/
#ifndef TPM_TSS_NOFILE
static TPM_RC TSS_Name_Load(TSS_CONTEXT *tssContext,
TPM2B_NAME *name,
TPM_HANDLE handle,
const char *string)
{
TPM_RC rc = 0;
char nameFilename[TPM_DATA_DIR_PATH_LENGTH];
if (rc == 0) {
if (string == NULL) {
if (handle != 0) {
sprintf(nameFilename, "%s/h%08x.bin", tssContext->tssDataDirectory, handle);
}
else {
if (tssVerbose) printf("TSS_Name_Load: handle and string are both null\n");
rc = TSS_RC_NAME_FILENAME;
}
}
else {
if (handle == 0) {
sprintf(nameFilename, "%s/h%s.bin", tssContext->tssDataDirectory, string);
}
else {
if (tssVerbose) printf("TSS_Name_Load: handle and string are both not null\n");
rc = TSS_RC_NAME_FILENAME;
}
}
}
if (rc == 0) {
if (tssVverbose) printf("TSS_Name_Load: File %s\n", nameFilename);
rc = TSS_File_Read2B(&name->b,
sizeof(name->t.name),
nameFilename);
}
return rc;
}
#endif
/* TSS_Name_Store() stores the 'name' parameter the TSS context.
*/
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_Name_Store(TSS_CONTEXT *tssContext,
TPM2B_NAME *name,
TPM_HANDLE handle,
const char *string)
{
TPM_RC rc = 0;
TPM_HT handleType;
size_t slotIndex;
if (tssVverbose) printf("TSS_Name_Store: Handle %08x\n", handle);
handleType = (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
switch (handleType) {
case TPM_HT_NV_INDEX:
/* for NV, the Name was returned at creation */
rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
if (rc != 0) {
rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
if (rc == 0) {
tssContext->nvPublic[slotIndex].nvIndex = handle;
}
else {
if (tssVerbose)
printf("TSS_Name_Store: Error, no slot available for handle %08x\n", handle);
}
}
if (rc == 0) {
tssContext->nvPublic[slotIndex].name = *name;
}
break;
case TPM_HT_TRANSIENT:
case TPM_HT_PERSISTENT:
if (rc == 0) {
if (string == NULL) {
if (handle != 0) {
/* if this handle is already used, overwrite the slot */
rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
if (rc != 0) {
rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
if (rc == 0) {
tssContext->objectPublic[slotIndex].objectHandle = handle;
}
else {
if (tssVerbose)
printf("TSS_Name_Store: "
"Error, no slot available for handle %08x\n",
handle);
}
}
}
else {
if (tssVerbose) printf("TSS_Name_Store: handle and string are both null");
rc = TSS_RC_NAME_FILENAME;
}
}
else {
if (handle == 0) {
if (tssVerbose) printf("TSS_Name_Store: string unimplemented");
rc = TSS_RC_NAME_FILENAME;
}
else {
if (tssVerbose) printf("TSS_Name_Store: handle and string are both not null");
rc = TSS_RC_NAME_FILENAME;
}
}
}
if (rc == 0) {
tssContext->objectPublic[slotIndex].name = *name;
}
break;
default:
if (tssVerbose) printf("TSS_Name_Store: handle type %02x unimplemented", handleType);
rc = TSS_RC_NAME_FILENAME;
}
return rc;
}
#endif
/* TSS_Name_Load() loads the 'name' from the TSS context.
*/
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_Name_Load(TSS_CONTEXT *tssContext,
TPM2B_NAME *name,
TPM_HANDLE handle,
const char *string)
{
TPM_RC rc = 0;
TPM_HT handleType;
size_t slotIndex;
string = string;
if (tssVverbose) printf("TSS_Name_Load: Handle %08x\n", handle);
handleType = (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
switch (handleType) {
case TPM_HT_NV_INDEX:
rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
if (rc != 0) {
if (tssVerbose)
printf("TSS_Name_Load: Error, no slot found for handle %08x\n", handle);
}
if (rc == 0) {
*name = tssContext->nvPublic[slotIndex].name;
}
break;
case TPM_HT_TRANSIENT:
case TPM_HT_PERSISTENT:
rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
if (rc != 0) {
if (tssVerbose)
printf("TSS_Name_Load: Error, no slot found for handle %08x\n", handle);
}
if (rc == 0) {
*name = tssContext->objectPublic[slotIndex].name;
}
break;
default:
if (tssVerbose) printf("TSS_Name_Load: handle type %02x unimplemented", handleType);
rc = TSS_RC_NAME_FILENAME;
}
return rc;
}
#endif
/* TSS_Name_Copy() copies the name from either inHandle or inString to either outHandle or
outString */
static TPM_RC TSS_Name_Copy(TSS_CONTEXT *tssContext,
TPM_HANDLE outHandle,
const char *outString,
TPM_HANDLE inHandle,
const char *inString)
{
TPM_RC rc = 0;
TPM2B_NAME name;
if (rc == 0) {
rc = TSS_Name_Load(tssContext, &name, inHandle, inString);
}
if (rc == 0) {
rc = TSS_Name_Store(tssContext, &name, outHandle, outString);
}
return rc;
}
/* TSS_Public_Store() stores the 'public' parameter in a file.
If handle is not 0, the handle is used as the file name.
If 'string' is not NULL, the string is used as the file name.
*/
#ifndef TPM_TSS_NOFILE
static TPM_RC TSS_Public_Store(TSS_CONTEXT *tssContext,
TPM2B_PUBLIC *public,
TPM_HANDLE handle,
const char *string)
{
TPM_RC rc = 0;
char publicFilename[TPM_DATA_DIR_PATH_LENGTH];
if (rc == 0) {
if (string == NULL) {
if (handle != 0) { /* store by handle */
sprintf(publicFilename, "%s/hp%08x.bin", tssContext->tssDataDirectory, handle);
}
else {
if (tssVerbose) printf("TSS_Public_Store: handle and string are both null");
rc = TSS_RC_NAME_FILENAME;
}
}
else {
if (handle == 0) { /* store by string */
sprintf(publicFilename, "%s/hp%s.bin", tssContext->tssDataDirectory, string);
}
else {
if (tssVerbose) printf("TSS_Public_Store: handle and string are both not null");
rc = TSS_RC_NAME_FILENAME;
}
}
}
if (rc == 0) {
if (tssVverbose) printf("TSS_Public_Store: File %s\n", publicFilename);
rc = TSS_File_WriteStructure(public,
(MarshalFunction_t)TSS_TPM2B_PUBLIC_Marshalu,
publicFilename);
}
return rc;
}
#endif
/* TSS_Public_Load() loads the 'public' parameter from a file.
If handle is not 0, the handle is used as the file name.
If 'string' is not NULL, the string is used as the file name.
*/
#ifndef TPM_TSS_NOFILE
static TPM_RC TSS_Public_Load(TSS_CONTEXT *tssContext,
TPM2B_PUBLIC *public,
TPM_HANDLE handle,
const char *string)
{
TPM_RC rc = 0;
char publicFilename[TPM_DATA_DIR_PATH_LENGTH];
if (rc == 0) {
if (string == NULL) {
if (handle != 0) {
sprintf(publicFilename, "%s/hp%08x.bin", tssContext->tssDataDirectory, handle);
}
else {
if (tssVerbose) printf("TSS_Public_Load: handle and string are both null\n");
rc = TSS_RC_NAME_FILENAME;
}
}
else {
if (handle == 0) {
sprintf(publicFilename, "%s/hp%s.bin", tssContext->tssDataDirectory, string);
}
else {
if (tssVerbose) printf("TSS_Public_Load: handle and string are both not null\n");
rc = TSS_RC_NAME_FILENAME;
}
}
}
if (rc == 0) {
if (tssVverbose) printf("TSS_Public_Load: File %s\n", publicFilename);
rc = TSS_File_ReadStructureFlag(public,
(UnmarshalFunctionFlag_t)TSS_TPM2B_PUBLIC_Unmarshalu,
TRUE, /* NULL permitted */
publicFilename);
}
return rc;
}
#endif /* TPM_TSS_NOFILE */
/* TSS_Public_Copy() copies the TPM2B_PUBLIC from either inHandle or inString to either outHandle or
outString */
static TPM_RC TSS_Public_Copy(TSS_CONTEXT *tssContext,
TPM_HANDLE outHandle,
const char *outString,
TPM_HANDLE inHandle,
const char *inString)
{
TPM_RC rc = 0;
TPM2B_PUBLIC public;
if (rc == 0) {
rc = TSS_Public_Load(tssContext, &public, inHandle, inString);
}
if (rc == 0) {
rc = TSS_Public_Store(tssContext, &public, outHandle, outString);
}
return rc;
}
/* TSS_Public_Store() stores the 'public' parameter in the TSS context.
*/
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_Public_Store(TSS_CONTEXT *tssContext,
TPM2B_PUBLIC *public,
TPM_HANDLE handle,
const char *string)
{
TPM_RC rc = 0;
size_t slotIndex;
if (rc == 0) {
if (string == NULL) {
if (handle != 0) {
/* if this handle is already used, overwrite the slot */
rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
if (rc != 0) {
rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
if (rc == 0) {
tssContext->objectPublic[slotIndex].objectHandle = handle;
}
else {
if (tssVerbose)
printf("TSS_Public_Store: Error, no slot available for handle %08x\n",
handle);
}
}
}
else {
if (tssVerbose) printf("TSS_Public_Store: handle and string are both null");
rc = TSS_RC_NAME_FILENAME;
}
}
else {
if (handle == 0) {
if (tssVerbose) printf("TSS_Public_Store: string not implemented yet");
rc = TSS_RC_NAME_FILENAME;
}
else {
if (tssVerbose) printf("TSS_Public_Store: handle and string are both not null");
rc = TSS_RC_NAME_FILENAME;
}
}
}
if (rc == 0) {
tssContext->objectPublic[slotIndex].objectPublic = *public;
}
return rc;
}
#endif
/* TSS_Public_Load() loaded the object public from the TSS context.
*/
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_Public_Load(TSS_CONTEXT *tssContext,
TPM2B_PUBLIC *public,
TPM_HANDLE handle,
const char *string)
{
TPM_RC rc = 0;
size_t slotIndex;
if (rc == 0) {
if (string == NULL) {
if (handle != 0) {
rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
if (rc != 0) {
if (tssVerbose)
printf("TSS_Public_Load: Error, no slot found for handle %08x\n",
handle);
}
}
else {
if (tssVerbose) printf("TSS_Public_Load: handle and string are both null\n");
rc = TSS_RC_NAME_FILENAME;
}
}
else {
if (handle == 0) {
if (tssVerbose) printf("TSS_Public_Load: string not implemented yet");
rc = TSS_RC_NAME_FILENAME;
}
else {
if (tssVerbose) printf("TSS_Public_Load: handle and string are both not null\n");
rc = TSS_RC_NAME_FILENAME;
}
}
}
if (rc == 0) {
*public = tssContext->objectPublic[slotIndex].objectPublic;
}
return rc;
}
#endif /* TPM_TSS_NOFILE */
#ifdef TPM_TSS_NOFILE
/* TSS_ObjectPublic_GetSlotForHandle() finds the object public slot corresponding to the handle.
Returns non-zero if no slot is found.
*/
static TPM_RC TSS_ObjectPublic_GetSlotForHandle(TSS_CONTEXT *tssContext,
size_t *slotIndex,
TPM_HANDLE handle)
{
size_t i;
/* search all slots for handle */
for (i = 0 ; i < (sizeof(tssContext->sessions) / sizeof(TSS_SESSIONS)) ; i++) {
if (tssContext->objectPublic[i].objectHandle == handle) {
*slotIndex = i;
return 0;
}
}
return TSS_RC_NO_OBJECTPUBLIC_SLOT;
}
#endif
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_ObjectPublic_DeleteData(TSS_CONTEXT *tssContext, TPM_HANDLE handle)
{
TPM_RC rc = 0;
size_t slotIndex;
if (rc == 0) {
rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
if (rc != 0) {
if (tssVerbose)
printf("TSS_ObjectPublic_DeleteData: Error, no slot found for handle %08x\n",
handle);
}
}
if (rc == 0) {
tssContext->objectPublic[slotIndex].objectHandle = TPM_RH_NULL;
}
return rc;
}
#endif
/* TSS_DeleteHandle() removes retained state stored by the TSS for a handle
*/
static TPM_RC TSS_DeleteHandle(TSS_CONTEXT *tssContext,
TPM_HANDLE handle)
{
TPM_RC rc = 0;
TPM_HT handleType;
#ifndef TPM_TSS_NOFILE
char filename[TPM_DATA_DIR_PATH_LENGTH];
#endif
handleType = (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
#ifndef TPM_TSS_NOFILE
/* delete the Name */
if (rc == 0) {
sprintf(filename, "%s/h%08x.bin", tssContext->tssDataDirectory, handle);
if (tssVverbose) printf("TSS_DeleteHandle: delete Name file %s\n", filename);
rc = TSS_File_DeleteFile(filename);
}
/* delete the public if it exists */
if (rc == 0) {
if ((handleType == TPM_HT_TRANSIENT) ||
(handleType == TPM_HT_PERSISTENT)) {
sprintf(filename, "%s/hp%08x.bin", tssContext->tssDataDirectory, handle);
if (tssVverbose) printf("TSS_DeleteHandle: delete public file %s\n", filename);
TSS_File_DeleteFile(filename);
}
}
#else
/* sessions persist in the context and can be deleted */
if (rc == 0) {
switch (handleType) {
case TPM_HT_NV_INDEX:
rc = TSS_RC_NOT_IMPLEMENTED;
break;
case TPM_HT_HMAC_SESSION:
case TPM_HT_POLICY_SESSION:
if (tssVverbose) printf("TSS_DeleteHandle: delete session state %08x\n", handle);
rc = TSS_HmacSession_DeleteData(tssContext, handle);
break;
case TPM_HT_TRANSIENT:
case TPM_HT_PERSISTENT:
rc = TSS_ObjectPublic_DeleteData(tssContext, handle);
break;
}
}
#endif
return rc;
}
#ifndef TPM_TSS_NOCRYPTO
/* TSS_ObjectPublic_GetName() calculates the Name from the TPMT_PUBLIC. The Name provides security,
because the Name returned from the TPM2_ReadPublic cannot be trusted.
*/
static TPM_RC TSS_ObjectPublic_GetName(TPM2B_NAME *name,
TPMT_PUBLIC *tpmtPublic)
{
TPM_RC rc = 0;
uint16_t written = 0;
TPMT_HA digest;
uint32_t sizeInBytes = 0;
uint8_t *buffer = NULL;
if (rc == 0) {
rc = TSS_Malloc(&buffer, MAX_RESPONSE_SIZE); /* freed @1 */
}
/* marshal the TPMT_PUBLIC */
if (rc == 0) {
uint32_t size = MAX_RESPONSE_SIZE;
uint8_t *buffer1 = buffer;
rc = TSS_TPMT_PUBLIC_Marshalu(tpmtPublic, &written, &buffer1, &size);
}
/* hash the public area */
if (rc == 0) {
sizeInBytes = TSS_GetDigestSize(tpmtPublic->nameAlg);
digest.hashAlg = tpmtPublic->nameAlg; /* Name digest algorithm */
/* generate the TPMT_HA */
rc = TSS_Hash_Generate(&digest,
written, buffer,
0, NULL);
}
if (rc == 0) {
TPMI_ALG_HASH nameAlgNbo;
/* copy the digest */
memcpy(name->t.name + sizeof(TPMI_ALG_HASH), (uint8_t *)&digest.digest, sizeInBytes);
/* copy the hash algorithm */
nameAlgNbo = htons(tpmtPublic->nameAlg);
memcpy(name->t.name, (uint8_t *)&nameAlgNbo, sizeof(TPMI_ALG_HASH));
/* set the size */
name->t.size = sizeInBytes + sizeof(TPMI_ALG_HASH);
}
free(buffer); /* @1 */
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
/* TSS_NVPublic_Store() stores the NV public data in a file.
*/
#ifndef TPM_TSS_NOFILE
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_NVPublic_Store(TSS_CONTEXT *tssContext,
TPMS_NV_PUBLIC *nvPublic,
TPMI_RH_NV_INDEX nvIndex)
{
TPM_RC rc = 0;
char nvpFilename[TPM_DATA_DIR_PATH_LENGTH];
if (rc == 0) {
sprintf(nvpFilename, "%s/nvp%08x.bin", tssContext->tssDataDirectory, nvIndex);
rc = TSS_File_WriteStructure(nvPublic,
(MarshalFunction_t)TSS_TPMS_NV_PUBLIC_Marshalu,
nvpFilename);
}
return rc;
}
#endif
#endif
/* TSS_NVPublic_Load() loads the NV public from a file.
*/
#ifndef TPM_TSS_NOFILE
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_NVPublic_Load(TSS_CONTEXT *tssContext,
TPMS_NV_PUBLIC *nvPublic,
TPMI_RH_NV_INDEX nvIndex)
{
TPM_RC rc = 0;
char nvpFilename[TPM_DATA_DIR_PATH_LENGTH];
if (rc == 0) {
sprintf(nvpFilename, "%s/nvp%08x.bin", tssContext->tssDataDirectory, nvIndex);
rc = TSS_File_ReadStructure(nvPublic,
(UnmarshalFunction_t)TSS_TPMS_NV_PUBLIC_Unmarshalu,
nvpFilename);
}
return rc;
}
#endif
#endif
#ifndef TPM_TSS_NOFILE
static TPM_RC TSS_NVPublic_Delete(TSS_CONTEXT *tssContext,
TPMI_RH_NV_INDEX nvIndex)
{
TPM_RC rc = 0;
char nvpFilename[TPM_DATA_DIR_PATH_LENGTH];
if (rc == 0) {
sprintf(nvpFilename, "%s/nvp%08x.bin", tssContext->tssDataDirectory, nvIndex);
rc = TSS_File_DeleteFile(nvpFilename);
}
return rc;
}
#endif
#ifdef TPM_TSS_NOFILE
#ifndef TPM_TSS_NOCRYPTO
/* TSS_NVPublic_Store() stores the NV public data in a file.
*/
static TPM_RC TSS_NVPublic_Store(TSS_CONTEXT *tssContext,
TPMS_NV_PUBLIC *nvPublic,
TPMI_RH_NV_INDEX nvIndex)
{
TPM_RC rc = 0;
size_t slotIndex;
if (rc == 0) {
rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, nvIndex);
if (rc != 0) {
rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
if (rc == 0) {
tssContext->nvPublic[slotIndex].nvIndex = nvIndex;
}
else {
if (tssVerbose)
printf("TSS_NVPublic_Store: Error, no slot available for handle %08x\n",
nvIndex);
}
}
}
if (rc == 0) {
tssContext->nvPublic[slotIndex].nvPublic = *nvPublic;
}
return rc;
}
#endif
#endif
#ifdef TPM_TSS_NOFILE
#ifndef TPM_TSS_NOCRYPTO
/* TSS_NVPublic_Load() loads the NV public from a file.
*/
static TPM_RC TSS_NVPublic_Load(TSS_CONTEXT *tssContext,
TPMS_NV_PUBLIC *nvPublic,
TPMI_RH_NV_INDEX nvIndex)
{
TPM_RC rc = 0;
size_t slotIndex;
if (rc == 0) {
rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, nvIndex);
if (rc != 0) {
if (tssVerbose)
printf("TSS_NVPublic_Load: Error, no slot found for handle %08x\n",
nvIndex);
}
}
if (rc == 0) {
*nvPublic = tssContext->nvPublic[slotIndex].nvPublic;
}
return rc;
}
#endif
#endif
#ifdef TPM_TSS_NOFILE
static TPM_RC TSS_NVPublic_Delete(TSS_CONTEXT *tssContext,
TPMI_RH_NV_INDEX nvIndex)
{
TPM_RC rc = 0;
size_t slotIndex;
if (rc == 0) {
rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, nvIndex);
if (rc != 0) {
if (tssVerbose)
printf("TSS_NVPublic_Delete: Error, no slot found for handle %08x\n",
nvIndex);
}
}
if (rc == 0) {
tssContext->nvPublic[slotIndex].nvIndex = TPM_RH_NULL;
}
return rc;
}
#endif
#ifdef TPM_TSS_NOFILE
/* TSS_NvPublic_GetSlotForHandle() finds the object public slot corresponding to the handle.
Returns non-zero if no slot is found.
*/
static TPM_RC TSS_NvPublic_GetSlotForHandle(TSS_CONTEXT *tssContext,
size_t *slotIndex,
TPMI_RH_NV_INDEX nvIndex)
{
size_t i;
/* search all slots for handle */
for (i = 0 ; i < (sizeof(tssContext->nvPublic) / sizeof(TSS_NVPUBLIC)) ; i++) {
if (tssContext->nvPublic[i].nvIndex == nvIndex) {
*slotIndex = i;
return 0;
}
}
return TSS_RC_NO_NVPUBLIC_SLOT;
}
#endif
/* TSS_NVPublic_GetName() calculates the Name from the TPMS_NV_PUBLIC. The Name provides security,
because the Name returned from the TPM2_NV_ReadPublic cannot be trusted.
*/
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_NVPublic_GetName(TPM2B_NAME *name,
TPMS_NV_PUBLIC *nvPublic)
{
TPM_RC rc = 0;
uint16_t written = 0;
TPMT_HA digest;
uint32_t sizeInBytes = 0;
uint8_t *buffer = NULL;
if (rc == 0) {
rc = TSS_Malloc(&buffer, MAX_RESPONSE_SIZE); /* freed @1 */
}
/* marshal the TPMS_NV_PUBLIC */
if (rc == 0) {
uint32_t size = MAX_RESPONSE_SIZE;
uint8_t *buffer1 = buffer;
rc = TSS_TPMS_NV_PUBLIC_Marshalu(nvPublic, &written, &buffer1, &size);
}
/* hash the public area */
if (rc == 0) {
sizeInBytes = TSS_GetDigestSize(nvPublic->nameAlg);
digest.hashAlg = nvPublic->nameAlg; /* Name digest algorithm */
/* generate the TPMT_HA */
rc = TSS_Hash_Generate(&digest,
written, buffer,
0, NULL);
}
if (rc == 0) {
TPMI_ALG_HASH nameAlgNbo;
/* copy the digest */
memcpy(name->t.name + sizeof(TPMI_ALG_HASH), (uint8_t *)&digest.digest, sizeInBytes);
/* copy the hash algorithm */
nameAlgNbo = htons(nvPublic->nameAlg);
memcpy(name->t.name, (uint8_t *)&nameAlgNbo, sizeof(TPMI_ALG_HASH));
/* set the size */
name->t.size = sizeInBytes + sizeof(TPMI_ALG_HASH);
}
free(buffer); /* @1 */
return rc;
}
#endif
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_HmacSession_SetNonceCaller(struct TSS_HMAC_CONTEXT *session,
TPMS_AUTH_COMMAND *authC)
{
TPM_RC rc = 0;
/* generate a new nonceCaller */
if (rc == 0) {
session->nonceCaller.b.size = session->sizeInBytes;
rc = TSS_RandBytes(session->nonceCaller.t.buffer, session->sizeInBytes);
}
/* nonceCaller for the command */
if (rc == 0) {
rc = TSS_TPM2B_Copy(&authC->nonce.b, &session->nonceCaller.b, sizeof(TPMU_HA));
}
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
#ifndef TPM_TSS_NOCRYPTO
/* TSS_HmacSession_SetHmacKey() calculates the session HMAC key.
handleNumber is index into the session area. The first sessions, the authorization sessions,
have a corresponding handle in the command handle.
*/
static TPM_RC TSS_HmacSession_SetHmacKey(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber, /* index into the handle area */
const char *password)
{
TPM_RC rc = 0;
TPM_HANDLE commandHandle; /* from handle area, for bound session */
TPM2B_NAME name;
TPM2B_AUTH authValue;
int bindMatch = FALSE;
int done = FALSE; /* done with authorization sessions */
/*
authHMAC = HMAC sessionAlg ((sessionKey || authValue),
(pHash || nonceNewer || nonceOlder
{ || nonceTPMdecrypt } { || nonceTPMencrypt }
|| sessionAttributes))
*/
/* HMAC key is sessionKey || authValue */
/* copy the session key to HMAC key */
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_HmacSession_SetHmacKey: sessionKey",
session->sessionKey.b.buffer, session->sessionKey.b.size);
rc = TSS_TPM2B_Copy(&session->hmacKey.b,
&session->sessionKey.b, sizeof(TPMU_HA) + sizeof(TPMT_HA));
}
/* copy the session key to sessionValue */
if (rc == 0) {
rc = TSS_TPM2B_Copy(&session->sessionValue.b,
&session->sessionKey.b, sizeof(TPMU_HA) + sizeof(TPMT_HA));
}
if (rc == 0) {
if (tssVverbose)
TSS_PrintAll("TSS_HmacSession_SetHmacKey: preliminary sessionValue",
session->sessionValue.b.buffer, session->sessionValue.b.size);
}
/* This value is an EmptyAuth if the HMAC is being computed to authorize an action on the
object to which the session is bound.
*/
/* The first sessions are authorization sessions. They can have a bind entity. All others can
be encrypt or decrypt sessions, but the authValue is not included in the session key.
*/
if (rc == 0) {
AUTH_ROLE authRole = TSS_GetAuthRole(tssContext->tssAuthContext, handleNumber);
if (authRole == AUTH_NONE) {
if (tssVverbose) printf("TSS_HmacSession_SetHmacKey: Done, not auth session\n");
done = TRUE; /* not an authorization session, could be audit or
encrypt/decrypt */
}
}
/* If not an authorization session, there is no authValue to append to the HMAC key or encrypt
sessionValue, regardless of the binding. Below is for auth sessions. */
if (!done) {
/* First, if there was a bind handle, check if the name matches. Else bindMatch remains
FALSE. */
if (session->bind != TPM_RH_NULL) {
/* get the handle for this session */
if (tssVverbose)
printf("TSS_HmacSession_SetHmacKey: Processing bind handle %08x\n", session->bind);
if (rc == 0) {
rc = TSS_GetCommandHandle(tssContext->tssAuthContext,
&commandHandle,
handleNumber);
}
/* get the Name corresponding to the handle */
if (rc == 0) {
if (tssVverbose)
printf("TSS_HmacSession_SetHmacKey: commandHandle %08x bindHandle %08x\n",
commandHandle, session->bind);
rc = TSS_Name_GetName(tssContext, &name, commandHandle);
}
/* compare the authorized object name to the bind object name */
if (rc == 0) {
bindMatch = TSS_TPM2B_Compare(&name.b, &session->bindName.b);
if (tssVverbose) printf("TSS_HmacSession_SetHmacKey: bind match %u\n", bindMatch);
}
}
/* Second, append password to session key for HMAC key if required */
/* When performing an HMAC for authorization, the HMAC key is normally the concatenation of
the entity's authValue to the sessions sessionKey (created at
TPM2_StartAuthSession(). However, if the authorization is for the entity to
which the session is bound, the authValue is not included in the HMAC key. When
a policy requires that an HMAC be computed, it is always concatenated.
*/
if ((rc == 0) &&
/* append if HMAC session and not bind match */
(((session->sessionType == TPM_SE_HMAC) && !bindMatch) ||
/* append if policy and policy authvalue */
((session->sessionType == TPM_SE_POLICY) && session->isAuthValueNeeded)) &&
(password != NULL) /* if password is NULL, nothing to append. */
) {
if (tssVverbose)
printf("TSS_HmacSession_SetHmacKey: Appending authValue to HMAC key\n");
/* convert the password to an authvalue */
if (rc == 0) {
rc = TSS_TPM2B_StringCopy(&authValue.b, password, sizeof(authValue.t.buffer));
}
/* append the authvalue to the session key to create the hmac key */
if (rc == 0) {
rc = TSS_TPM2B_Append(&session->hmacKey.b, &authValue.b,
sizeof(TPMU_HA) + sizeof(TPMT_HA));
}
}
/* Third, append password to session key for sessionValue
If a session is also being used for authorization, sessionValue (see 21.2 and 21.3) is
sessionKey || authValue. The binding of the session is ignored. If the session is not
being used for authorization, sessionValue is sessionKey.
*/
/* NOTE This step occurs even if there is a bind match. That is, the password is effectively
appended twice. */
if (rc == 0) {
/* if not bind, sessionValue is sessionKey || authValue (same as HMAC key) */
if (!bindMatch) {
if (tssVverbose)
printf("TSS_HmacSession_SetHmacKey: "
"No bind, appending authValue to sessionValue\n");
/* convert the password to an authvalue */
if (rc == 0) {
rc = TSS_TPM2B_StringCopy(&authValue.b, password, sizeof(authValue.t.buffer));
}
if (rc == 0) {
rc = TSS_TPM2B_Append(&session->sessionValue.b, &authValue.b,
sizeof(TPMU_HA) + sizeof(TPMT_HA));
}
}
/* if bind, sessionValue is sessionKey || bindAuthValue */
else {
if (tssVverbose)
printf("TSS_HmacSession_SetHmacKey: "
"Bind, appending bind authValue to sessionValue\n");
if (rc == 0) {
rc = TSS_TPM2B_Append(&session->sessionValue.b, &session->bindAuthValue.b,
sizeof(TPMU_HA) + sizeof(TPMT_HA));
}
}
if (rc == 0) {
if (tssVverbose)
TSS_PrintAll("TSS_HmacSession_SetHmacKey: bindAuthValue",
session->bindAuthValue.b.buffer, session->bindAuthValue.b.size);
}
}
}
if (rc == 0) {
if (tssVverbose)
TSS_PrintAll("TSS_HmacSession_SetHmacKey: hmacKey",
session->hmacKey.b.buffer, session->hmacKey.b.size);
if (tssVverbose)
TSS_PrintAll("TSS_HmacSession_SetHmacKey: sessionValue",
session->sessionValue.b.buffer, session->sessionValue.b.size);
}
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
/* TSS_HmacSession_SetHMAC() is used for a command. It sets all the values in one
TPMS_AUTH_COMMAND, ready for marshaling into the command packet.
- gets cpBuffer
- generates cpHash
- generates the HMAC
- copies the result into authCommand
Unused names must have size 0.
The HMAC key is already in the session structure.
*/
static TPM_RC TSS_HmacSession_SetHMAC(TSS_AUTH_CONTEXT *tssAuthContext, /* authorization context */
struct TSS_HMAC_CONTEXT *session[],
TPMS_AUTH_COMMAND *authCommand[], /* output: command
authorization */
TPMI_SH_AUTH_SESSION sessionHandle[], /* session handles in
command */
unsigned int sessionAttributes[], /* attributes for this
command */
const char *password[],
TPM2B_NAME *name0, /* up to 3 names */
TPM2B_NAME *name1, /* unused names have length 0 */
TPM2B_NAME *name2)
{
TPM_RC rc = 0;
unsigned int i = 0;
#ifndef TPM_TSS_NOCRYPTO
TPMT_HA cpHash;
TPMT_HA hmac;
TPM2B_NONCE nonceTPMDecrypt;
TPM2B_NONCE nonceTPMEncrypt;
cpHash.hashAlg = TPM_ALG_NULL; /* for cpHash calculation optimization */
#endif /* TPM_TSS_NOCRYPTO */
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
uint8_t sessionAttr8;
if (tssVverbose) printf("TSS_HmacSession_SetHMAC: Step 6 session %08x\n", sessionHandle[i]);
/* password sessions were serviced in step 2. */
if (sessionHandle[i] == TPM_RS_PW) {
continue;
}
if (tssVverbose) printf("TSS_HmacSession_SetHMAC: sessionType %02x\n",
session[i]->sessionType);
if (tssVverbose) printf("TSS_HmacSession_SetHMAC: isPasswordNeeded %02x\n",
session[i]->isPasswordNeeded);
if (tssVverbose) printf("TSS_HmacSession_SetHMAC: isAuthValueNeeded %02x\n",
session[i]->isAuthValueNeeded);
/* sessionHandle */
authCommand[i]->sessionHandle = session[i]->sessionHandle;
/* attributes come from command */
sessionAttr8 = (uint8_t)sessionAttributes[i];
authCommand[i]->sessionAttributes.val = sessionAttr8;
/* policy session with policy password handled below, no hmac. isPasswordNeeded is never
true for an HMAC session, so don't need to test session type here. */
if (!(session[i]->isPasswordNeeded)) {
/* HMAC session */
if ((session[i]->sessionType == TPM_SE_HMAC) ||
/* policy session with TPM2_PolicyAuthValue */
((session[i]->sessionType == TPM_SE_POLICY) && (session[i]->isAuthValueNeeded)) ||
/* salted session */
(session[i]->hmacKey.t.size != 0)
) {
/* needs HMAC */
#ifndef TPM_TSS_NOCRYPTO
if (tssVverbose) printf("TSS_HmacSession_SetHMAC: calculate HMAC\n");
/* calculate cpHash. Performance optimization: If there is more than one session,
and the hash algorithm is the same, use the previously calculated version. */
if ((rc == 0) && (cpHash.hashAlg != session[i]->authHashAlg)) {
uint32_t cpBufferSize;
uint8_t *cpBuffer;
TPM_CC commandCode;
TPM_CC commandCodeNbo;
rc = TSS_GetCpBuffer(tssAuthContext,
&cpBufferSize,
&cpBuffer);
if (tssVverbose) TSS_PrintAll("TSS_HmacSession_SetHMAC: cpBuffer",
cpBuffer, cpBufferSize);
cpHash.hashAlg = session[i]->authHashAlg;
/* cpHash = hash(commandCode [ || authName1 */
/* [ || authName2 */
/* [ || authName3 ]]] */
/* [ || parameters]) */
/* A cpHash can contain just a commandCode only if the lone session is */
/* an audit session. */
commandCode = TSS_GetCommandCode(tssAuthContext);
commandCodeNbo = htonl(commandCode);
rc = TSS_Hash_Generate(&cpHash, /* largest size of a digest */
sizeof(TPM_CC), &commandCodeNbo,
name0->b.size, &name0->b.buffer,
name1->b.size, &name1->b.buffer,
name2->b.size, &name2->b.buffer,
cpBufferSize, cpBuffer,
0, NULL);
}
if (i == 0) {
unsigned int isDecrypt = 0; /* count number of sessions with decrypt
set */
unsigned int decryptSession = 0; /* which one is decrypt */
unsigned int isEncrypt = 0; /* count number of sessions with decrypt
set */
unsigned int encryptSession = 0; /* which one is decrypt */
nonceTPMDecrypt.t.size = 0;
nonceTPMEncrypt.t.size = 0;
/* if a different session is being used for parameter decryption, then the
nonceTPM for that session is included in the HMAC of the first authorization
session */
if (rc == 0) {
rc = TSS_Sessions_GetDecryptSession(&isDecrypt,
&decryptSession,
sessionHandle,
sessionAttributes);
}
if ((rc == 0) && isDecrypt && (decryptSession != 0)) {
rc = TSS_TPM2B_Copy(&nonceTPMDecrypt.b,
&session[decryptSession]->nonceTPM.b, sizeof(TPMU_HA));
}
/* if a different session is being used for parameter encryption, then the
nonceTPM for that session is included in the HMAC of the first authorization
session */
if (rc == 0) {
rc = TSS_Sessions_GetEncryptSession(&isEncrypt,
&encryptSession,
sessionHandle,
sessionAttributes);
}
/* Don't include the same nonce twice */
if ((rc == 0) && isEncrypt && (encryptSession != 0)) {
if (!isDecrypt || (encryptSession != decryptSession)) {
rc = TSS_TPM2B_Copy(&nonceTPMEncrypt.b,
&session[encryptSession]->nonceTPM.b,
sizeof(TPMU_HA));
}
}
}
/* for other than the first session, those nonces are not used */
else {
nonceTPMDecrypt.t.size = 0;
nonceTPMEncrypt.t.size = 0;
}
/* */
if (rc == 0) {
hmac.hashAlg = session[i]->authHashAlg;
rc = TSS_HMAC_Generate(&hmac, /* output hmac */
&session[i]->hmacKey, /* input key */
session[i]->sizeInBytes, (uint8_t *)&cpHash.digest,
/* new is nonceCaller */
session[i]->nonceCaller.b.size,
&session[i]->nonceCaller.b.buffer,
/* old is previous nonceTPM */
session[i]->nonceTPM.b.size,
&session[i]->nonceTPM.b.buffer,
/* nonceTPMDecrypt */
nonceTPMDecrypt.b.size, nonceTPMDecrypt.b.buffer,
/* nonceTPMEncrypt */
nonceTPMEncrypt.b.size, nonceTPMEncrypt.b.buffer,
/* 1 byte, no endian conversion */
sizeof(uint8_t), &sessionAttr8,
0, NULL);
if (tssVverbose) {
TSS_PrintAll("TSS_HmacSession_SetHMAC: HMAC key",
session[i]->hmacKey.t.buffer, session[i]->hmacKey.t.size);
TSS_PrintAll("TSS_HmacSession_SetHMAC: cpHash",
(uint8_t *)&cpHash.digest, session[i]->sizeInBytes);
TSS_PrintAll("TSS_HmacSession_Set: nonceCaller",
session[i]->nonceCaller.b.buffer,
session[i]->nonceCaller.b.size);
TSS_PrintAll("TSS_HmacSession_SetHMAC: nonceTPM",
session[i]->nonceTPM.b.buffer, session[i]->nonceTPM.b.size);
TSS_PrintAll("TSS_HmacSession_SetHMAC: nonceTPMDecrypt",
nonceTPMDecrypt.b.buffer, nonceTPMDecrypt.b.size);
TSS_PrintAll("TSS_HmacSession_SetHMAC: nonceTPMEncrypt",
nonceTPMEncrypt.b.buffer, nonceTPMEncrypt.b.size);
TSS_PrintAll("TSS_HmacSession_SetHMAC: sessionAttributes",
&sessionAttr8, sizeof(uint8_t));
TSS_PrintAll("TSS_HmacSession_SetHMAC: HMAC",
(uint8_t *)&hmac.digest, session[i]->sizeInBytes);
}
}
/* copy HMAC into authCommand TPM2B_AUTH hmac */
if (rc == 0) {
rc = TSS_TPM2B_Create(&authCommand[i]->hmac.b,
(uint8_t *)&hmac.digest,
session[i]->sizeInBytes,
sizeof(authCommand[i]->hmac.t.buffer));
}
#else
tssAuthContext = tssAuthContext;
name0 = name0;
name1 = name1;
name2 = name2;
if (tssVerbose)
printf("TSS_HmacSession_SetHMAC: Error, with no crypto not implemented\n");
rc = TSS_RC_NOT_IMPLEMENTED;
#endif /* TPM_TSS_NOCRYPTO */
}
/* not HMAC, not policy requiring password or hmac */
else {
authCommand[i]->hmac.b.size = 0;
}
}
/* For a policy session that contains TPM2_PolicyPassword(), the password takes precedence
and must be present in hmac. */
else { /* isPasswordNeeded true */
if (tssVverbose) printf("TSS_HmacSession_SetHMAC: use password\n");
/* nonce has already been set */
rc = TSS_TPM2B_StringCopy(&authCommand[i]->hmac.b,
password[i], sizeof(authCommand[i]->hmac.t.buffer));
}
}
return rc;
}
#ifndef TPM_TSS_NOCRYPTO
/* TSS_HmacSession_Verify() is used for a response. It uses the values in TPMS_AUTH_RESPONSE to
validate the response HMAC
*/
static TPM_RC TSS_HmacSession_Verify(TSS_AUTH_CONTEXT *tssAuthContext, /* authorization context */
struct TSS_HMAC_CONTEXT *session, /* TSS session context */
TPMS_AUTH_RESPONSE *authResponse) /* input: response authorization */
{
TPM_RC rc = 0;
uint32_t rpBufferSize;
uint8_t *rpBuffer;
TPMT_HA rpHash;
TPMT_HA actualHmac;
/* get the rpBuffer */
if (rc == 0) {
rc = TSS_GetRpBuffer(tssAuthContext, &rpBufferSize, &rpBuffer);
if (tssVverbose) TSS_PrintAll("TSS_HmacSession_Verify: rpBuffer",
rpBuffer, rpBufferSize);
}
/* calculate rpHash */
if (rc == 0) {
TPM_CC commandCode;
TPM_CC commandCodeNbo;
rpHash.hashAlg = session->authHashAlg;
commandCode = TSS_GetCommandCode(tssAuthContext);
commandCodeNbo = htonl(commandCode);
/* rpHash = HsessionAlg (responseCode || commandCode {|| parameters }) */
rc = TSS_Hash_Generate(&rpHash, /* largest size of a digest */
sizeof(TPM_RC), &rc, /* RC is always 0, no need to endian
convert */
sizeof(TPM_CC), &commandCodeNbo,
rpBufferSize, rpBuffer,
0, NULL);
}
/* construct the actual HMAC as TPMT_HA */
if (rc == 0) {
actualHmac.hashAlg = session->authHashAlg;
if (authResponse->hmac.t.size != session->sizeInBytes) {
if (tssVerbose)
printf("TSS_HmacSession_Verify: HMAC size %u inconsistent with algorithm %u\n",
authResponse->hmac.t.size, session->sizeInBytes);
rc = TSS_RC_HMAC_SIZE;
}
}
if (rc == 0) {
memcpy((uint8_t *)&actualHmac.digest, &authResponse->hmac.t.buffer,
authResponse->hmac.t.size);
}
/* verify the HMAC */
if (rc == 0) {
if (tssVverbose) {
TSS_PrintAll("TSS_HmacSession_Verify: HMAC key",
session->hmacKey.t.buffer, session->hmacKey.t.size);
TSS_PrintAll("TSS_HmacSession_Verify: rpHash",
(uint8_t *)&rpHash.digest, session->sizeInBytes);
TSS_PrintAll("TSS_HmacSession_Verify: nonceTPM",
session->nonceTPM.b.buffer, session->nonceTPM.b.size);
TSS_PrintAll("TSS_HmacSession_Verify: nonceCaller",
session->nonceCaller.b.buffer, session->nonceCaller.b.size);
TSS_PrintAll("TSS_HmacSession_Verify: sessionAttributes",
&authResponse->sessionAttributes.val, sizeof(uint8_t));
TSS_PrintAll("TSS_HmacSession_Verify: response HMAC",
(uint8_t *)&authResponse->hmac.t.buffer, session->sizeInBytes);
}
rc = TSS_HMAC_Verify(&actualHmac, /* input response hmac */
&session->hmacKey, /* input HMAC key */
session->sizeInBytes,
/* rpHash */
session->sizeInBytes, (uint8_t *)&rpHash.digest,
/* new is nonceTPM */
session->nonceTPM.b.size, &session->nonceTPM.b.buffer,
/* old is nonceCaller */
session->nonceCaller.b.size, &session->nonceCaller.b.buffer,
/* 1 byte, no endian conversion */
sizeof(uint8_t), &authResponse->sessionAttributes.val,
0, NULL);
}
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
/* TSS_HmacSession_Continue() handles the response continueSession flag. It either saves the
updated session or deletes the session state. */
static TPM_RC TSS_HmacSession_Continue(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
TPMS_AUTH_RESPONSE *authR)
{
TPM_RC rc = 0;
if (rc == 0) {
/* if continue set */
if (authR->sessionAttributes.val & TPMA_SESSION_CONTINUESESSION) {
/* clear the policy flags in preparation for the next use */
session->isPasswordNeeded = FALSE;
session->isAuthValueNeeded = FALSE;
/* save the session */
rc = TSS_HmacSession_SaveSession(tssContext, session);
}
else { /* continue clear */
/* delete the session state */
rc = TSS_DeleteHandle(tssContext, session->sessionHandle);
}
}
return rc;
}
/* TSS_Sessions_GetDecryptSession() searches for a command decrypt session. If found, returns
isDecrypt TRUE, and the session number in decryptSession.
*/
static TPM_RC TSS_Sessions_GetDecryptSession(unsigned int *isDecrypt,
unsigned int *decryptSession,
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[])
{
TPM_RC rc = 0;
unsigned int i = 0;
/* count the number of command decrypt sessions */
*isDecrypt = 0; /* number of sessions with decrypt set */
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) &&
(sessionHandle[i] != TPM_RH_NULL) &&
(sessionHandle[i] != TPM_RS_PW) ;
i++) {
if (sessionAttributes[i] & TPMA_SESSION_DECRYPT) {
(*isDecrypt)++; /* count number of decrypt sessions */
*decryptSession = i; /* record which one it was */
}
}
/* how many decrypt sessions were found */
if (rc == 0) {
if (tssVverbose) printf("TSS_Sessions_GetDecryptSession: Found %u decrypt sessions at %u\n",
*isDecrypt, *decryptSession);
if (*isDecrypt > 1) {
if (tssVerbose)
printf("TSS_Sessions_GetDecryptSession: Error, found %u decrypt sessions\n",
*isDecrypt);
rc = TSS_RC_DECRYPT_SESSIONS;
}
}
return rc;
}
/* TSS_Sessions_GetEncryptSession() searches for a response encrypt session. If found, returns
isEncrypt TRUE, and the session number in encryptSession.
*/
static TPM_RC TSS_Sessions_GetEncryptSession(unsigned int *isEncrypt,
unsigned int *encryptSession,
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[])
{
TPM_RC rc = 0;
unsigned int i = 0;
/* count the number of command encrypt sessions */
*isEncrypt = 0; /* number of sessions with encrypt set */
for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) &&
(sessionHandle[i] != TPM_RH_NULL) &&
(sessionHandle[i] != TPM_RS_PW) ;
i++) {
if (sessionAttributes[i] & TPMA_SESSION_ENCRYPT) {
(*isEncrypt)++; /* count number of encrypt sessions */
*encryptSession = i; /* record which one it was */
}
}
/* how many encrypt sessions were found */
if (rc == 0) {
if (tssVverbose) printf("TSS_Sessions_GetEncryptSession: Found %u encrypt sessions at %u\n",
*isEncrypt, *encryptSession);
if (*isEncrypt > 1) {
if (tssVerbose)
printf("TSS_Sessions_GetEncryptSession: Error, found %u encrypt sessions\n",
*isEncrypt);
rc = TSS_RC_ENCRYPT_SESSIONS;
}
}
return rc;
}
/* TSS_Command_Decrypt() determines whether any sessions are command decrypt sessions. If so, it
encrypts the first command parameter.
It does common error checking, then calls algorithm specific functions.
*/
static TPM_RC TSS_Command_Decrypt(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session[],
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[])
{
TPM_RC rc = 0;
unsigned int isDecrypt = 0; /* count number of sessions with decrypt set */
unsigned int decryptSession = 0; /* which session is decrypt */
/* determine if there is a decrypt session */
if (rc == 0) {
rc = TSS_Sessions_GetDecryptSession(&isDecrypt,
&decryptSession,
sessionHandle,
sessionAttributes);
}
#ifndef TPM_TSS_NOCRYPTO
{
COMMAND_INDEX tpmCommandIndex; /* index into TPM table */
TPM_CC commandCode;
int decryptSize; /* size of TPM2B size, 2 if there is a TPM2B, 0 if
not */
uint32_t paramSize; /* size of the parameter to encrypt */
uint8_t *decryptParamBuffer;
/* can the command parameter be encrypted */
if ((rc == 0) && isDecrypt) {
/* get the commandCode, stored in TSS during marshal */
commandCode = TSS_GetCommandCode(tssAuthContext);
/* get the index into the TPM command attributes table */
tpmCommandIndex = CommandCodeToCommandIndex(commandCode);
/* can this be a decrypt command (this is size of TPM2B size, not size of parameter) */
decryptSize = getDecryptSize(tpmCommandIndex);
if (decryptSize != 2) { /* only handle TPM2B */
printf("TSS_Command_Decrypt: Error, command cannot be encrypted\n");
rc = TSS_RC_NO_DECRYPT_PARAMETER;
}
}
/* get the TPM2B parameter to encrypt */
if ((rc == 0) && isDecrypt) {
rc = TSS_GetCommandDecryptParam(tssAuthContext, &paramSize, &decryptParamBuffer);
}
/* if the size of the parameter to encrypt is zero, nothing to encrypt */
if ((rc == 0) && isDecrypt) {
if (paramSize == 0) {
isDecrypt = FALSE; /* none, done with this function */
}
}
/* error checking complete, do the encryption */
if ((rc == 0) && isDecrypt) {
switch (session[decryptSession]->symmetric.algorithm) {
case TPM_ALG_XOR:
rc = TSS_Command_DecryptXor(tssAuthContext, session[decryptSession]);
break;
case TPM_ALG_AES:
rc = TSS_Command_DecryptAes(tssAuthContext, session[decryptSession]);
break;
default:
if (tssVerbose) printf("TSS_Command_Decrypt: Error, algorithm %04x not implemented\n",
session[decryptSession]->symmetric.algorithm);
rc = TSS_RC_BAD_DECRYPT_ALGORITHM;
break;
}
}
}
#else
tssAuthContext = tssAuthContext;
session = session;
if ((rc == 0) && isDecrypt) {
if (tssVerbose)
printf("TSS_Command_Decrypt: Error, with no crypto not implemented\n");
rc = TSS_RC_NOT_IMPLEMENTED;
}
#endif
return rc;
}
#ifndef TPM_TSS_NOCRYPTO
/* NOTE: if AES also works, do in place encryption */
static TPM_RC TSS_Command_DecryptXor(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session)
{
TPM_RC rc = 0;
unsigned int i;
uint32_t paramSize;
uint8_t *decryptParamBuffer;
uint8_t *mask = NULL;
uint8_t *encryptParamBuffer = NULL;
/* get the TPM2B parameter to encrypt */
if (rc == 0) {
rc = TSS_GetCommandDecryptParam(tssAuthContext, &paramSize, &decryptParamBuffer);
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: decrypt in",
decryptParamBuffer, paramSize);
}
if (rc == 0) {
rc = TSS_Malloc(&mask, paramSize);
}
if (rc == 0) {
rc = TSS_Malloc(&encryptParamBuffer, paramSize);
}
/* generate the XOR pad */
/* 21.2 XOR Parameter Obfuscation
XOR(parameter, hashAlg, sessionValue, nonceNewer, nonceOlder)
parameter a variable sized buffer containing the parameter to be obfuscated
hashAlg the hash algorithm associated with the session
sessionValue the session-specific HMAC key
nonceNewer for commands, this will be nonceCaller and for responses it will be nonceTPM
nonceOlder for commands, this will be nonceTPM and for responses it will be nonceCaller
11.4.6.3 XOR Obfuscation
XOR(data, hashAlg, key, contextU, contextV)
mask = KDFa (hashAlg, key, "XOR", contextU, contextV, data.size * 8)
*/
/* KDFa for the XOR mask */
if (rc == 0) {
if (tssVverbose) printf("TSS_Command_DecryptXor: hashAlg %04x\n", session->authHashAlg);
if (tssVverbose) printf("TSS_Command_DecryptXor: sizeInBits %04x\n", paramSize * 8);
if (tssVverbose)
TSS_PrintAll("TSS_Command_DecryptXor: sessionKey",
session->sessionKey.b.buffer, session->sessionKey.b.size);
if (tssVverbose)
TSS_PrintAll("TSS_Command_DecryptXor: sessionValue",
session->sessionValue.b.buffer, session->sessionValue.b.size);
rc = TSS_KDFA(mask,
session->authHashAlg,
&session->sessionValue.b,
"XOR",
&session->nonceCaller.b,
&session->nonceTPM.b,
paramSize * 8);
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: mask",
mask, paramSize);
}
/* XOR */
for (i = 0 ; (rc == 0) && (i < paramSize ) ; i++) {
encryptParamBuffer[i] = decryptParamBuffer[i] ^ mask[i];
}
if (rc == 0) {
rc = TSS_SetCommandDecryptParam(tssAuthContext, paramSize, encryptParamBuffer);
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: encrypt out",
encryptParamBuffer, paramSize);
}
free(mask);
free(encryptParamBuffer);
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
#ifndef TPM_TSS_NOCRYPTO
/* NOTE: if AES also works, do in place encryption */
static TPM_RC TSS_Command_DecryptAes(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session)
{
TPM_RC rc = 0;
uint32_t paramSize;
uint8_t *decryptParamBuffer;
uint8_t *encryptParamBuffer = NULL;
TPM2B_IV iv;
uint32_t kdfaBits;
uint16_t keySizeinBytes;
uint8_t symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; /* AES key + IV */
/* get the TPM2B parameter to encrypt */
if (rc == 0) {
rc = TSS_GetCommandDecryptParam(tssAuthContext, &paramSize, &decryptParamBuffer);
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptAes: decrypt in",
decryptParamBuffer, paramSize);
}
if (rc == 0) {
rc = TSS_Malloc(&encryptParamBuffer, paramSize); /* free @1 */
}
/* generate the encryption key and IV */
/* 21.3 CFB Mode Parameter Encryption
KDFa (hashAlg, sessionValue, "CFB", nonceNewer, nonceOlder, bits) (34)
hashAlg the hash algorithm associated with the session
sessionValue the session-specific HMAC key
"CFB" label to differentiate use of KDFa() (see 4.2)
nonceNewer nonceCaller for a command and nonceTPM for a response
nonceOlder nonceTPM for a command and nonceCaller for a response
bits the number of bits required for the symmetric key plus an IV
*/
if (rc == 0) {
iv.t.size = TSS_Sym_GetBlockSize(session->symmetric.algorithm,
session->symmetric.keyBits.aes);
/* generate random values for both the AES key and the IV */
kdfaBits = session->symmetric.keyBits.aes + (iv.t.size * 8);
if (tssVverbose) printf("TSS_Command_DecryptAes: hashAlg %04x\n",
session->authHashAlg);
if (tssVverbose) printf("TSS_Command_DecryptAes: AES key bits %u\n",
session->symmetric.keyBits.aes);
if (tssVverbose) printf("TSS_Command_DecryptAes: kdfaBits %04x\n",
kdfaBits);
if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptAes: session key",
session->sessionKey.b.buffer, session->sessionKey.b.size);
rc = TSS_KDFA(&symParmString[0],
session->authHashAlg,
&session->sessionValue.b,
"CFB",
&session->nonceCaller.b,
&session->nonceTPM.b,
kdfaBits);
}
/* copy the latter part of the kdf output to the IV */
if (rc == 0) {
keySizeinBytes = session->symmetric.keyBits.aes / 8;
memcpy(iv.t.buffer, &symParmString[keySizeinBytes], iv.t.size);
if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptAes: IV",
iv.t.buffer, iv.t.size);
}
/* AES CFB encrypt the command */
if (rc == 0) {
TPM_RC crc;
crc = TSS_AES_EncryptCFB(encryptParamBuffer, /* output */
session->symmetric.keyBits.aes, /* 128 */
symParmString, /* key */
iv.t.buffer, /* IV */
paramSize, /* length */
(uint8_t *)decryptParamBuffer); /* input */
if (crc != 0) {
if (tssVerbose) printf("TSS_Command_DecryptAes: AES encrypt failed\n");
rc = TSS_RC_AES_ENCRYPT_FAILURE;
}
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptAes: encrypt out",
encryptParamBuffer, paramSize);
}
if (rc == 0) {
rc = TSS_SetCommandDecryptParam(tssAuthContext, paramSize, encryptParamBuffer);
}
free(encryptParamBuffer); /* @1 */
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
static TPM_RC TSS_Response_Encrypt(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session[],
TPMI_SH_AUTH_SESSION sessionHandle[],
unsigned int sessionAttributes[])
{
TPM_RC rc = 0;
unsigned int isEncrypt = 0; /* count number of sessions with decrypt set */
unsigned int encryptSession = 0; /* which one is decrypt */
/* determine if there is an encrypt session */
if (rc == 0) {
rc = TSS_Sessions_GetEncryptSession(&isEncrypt,
&encryptSession,
sessionHandle,
sessionAttributes);
}
#ifndef TPM_TSS_NOCRYPTO
{
COMMAND_INDEX tpmCommandIndex; /* index into TPM table */
TPM_CC commandCode;
int encryptSize; /* size of TPM2B size, 2 if there is a TPM2B, 0 if
not */
uint32_t paramSize; /* size of the parameter to decrypt */
uint8_t *encryptParamBuffer;
/* can the response parameter be decrypted */
if ((rc == 0) && isEncrypt) {
/* get the commandCode, stored in TSS during marshal */
commandCode = TSS_GetCommandCode(tssAuthContext);
/* get the index into the TPM command attributes table */
tpmCommandIndex = CommandCodeToCommandIndex(commandCode);
/* can this be a decrypt command */
encryptSize = getEncryptSize(tpmCommandIndex);
if (encryptSize == 0) {
if (tssVerbose) printf("TSS_Response_Encrypt: "
"Error, response cannot be encrypted\n");
rc = TSS_RC_NO_ENCRYPT_PARAMETER;
}
}
/* get the TPM2B parameter to decrypt */
if ((rc == 0) && isEncrypt) {
rc = TSS_GetResponseEncryptParam(tssAuthContext, &paramSize, &encryptParamBuffer);
}
/* if the size of the parameter to decrypt is zero, nothing to decrypt */
if ((rc == 0) && isEncrypt) {
if (paramSize == 0) {
isEncrypt = FALSE; /* none, done with this function */
}
}
/* error checking complete, do the decryption */
if ((rc == 0) && isEncrypt) {
switch (session[encryptSession]->symmetric.algorithm) {
case TPM_ALG_XOR:
rc = TSS_Response_EncryptXor(tssAuthContext, session[encryptSession]);
break;
case TPM_ALG_AES:
rc = TSS_Response_EncryptAes(tssAuthContext, session[encryptSession]);
break;
default:
if (tssVerbose) printf("TSS_Response_Encrypt: "
"Error, algorithm %04x not implemented\n",
session[encryptSession]->symmetric.algorithm);
rc = TSS_RC_BAD_ENCRYPT_ALGORITHM;
break;
}
}
}
#else
tssAuthContext = tssAuthContext;
session = session;
if ((rc == 0) && isEncrypt) {
if (tssVerbose)
printf("TSS_Response_Encrypt: Error, with no crypto not implemented\n");
rc = TSS_RC_NOT_IMPLEMENTED;
}
#endif
return rc;
}
#ifndef TPM_TSS_NOCRYPTO
/* NOTE: if CFB also works, do in place decryption */
static TPM_RC TSS_Response_EncryptXor(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session)
{
TPM_RC rc = 0;
unsigned int i;
uint32_t paramSize;
uint8_t *encryptParamBuffer;
uint8_t *mask = NULL;
uint8_t *decryptParamBuffer = NULL;
/* get the TPM2B parameter to decrypt */
if (rc == 0) {
rc = TSS_GetResponseEncryptParam(tssAuthContext,
&paramSize, &encryptParamBuffer);
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptXor: encrypt in",
encryptParamBuffer, paramSize);
}
if (rc == 0) {
rc = TSS_Malloc(&mask, paramSize); /* freed @1 */
}
if (rc == 0) {
rc = TSS_Malloc(&decryptParamBuffer, paramSize); /* freed @2 */
}
/* generate the XOR pad */
/* 21.2 XOR Parameter Obfuscation
XOR(parameter, hashAlg, sessionValue, nonceNewer, nonceOlder)
parameter a variable sized buffer containing the parameter to be obfuscated
hashAlg the hash algorithm associated with the session
sessionValue the session-specific HMAC key
nonceNewer for commands, this will be nonceCaller and for responses it will be nonceTPM
nonceOlder for commands, this will be nonceTPM and for responses it will be nonceCaller
11.4.6.3 XOR Obfuscation
XOR(data, hashAlg, key, contextU, contextV)
mask = KDFa (hashAlg, key, "XOR", contextU, contextV, data.size * 8)
*/
/* KDFa for the XOR mask */
if (rc == 0) {
if (tssVverbose) printf("TSS_Response_EncryptXor: hashAlg %04x\n", session->authHashAlg);
if (tssVverbose) printf("TSS_Response_EncryptXor: sizeInBits %04x\n", paramSize * 8);
if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptXor: session key",
session->sessionKey.b.buffer, session->sessionKey.b.size);
rc = TSS_KDFA(mask,
session->authHashAlg,
&session->sessionValue.b,
"XOR",
&session->nonceTPM.b,
&session->nonceCaller.b,
paramSize * 8);
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptXor: mask",
mask, paramSize);
}
/* XOR */
for (i = 0 ; (rc == 0) && (i < paramSize ) ; i++) {
decryptParamBuffer[i] = encryptParamBuffer[i] ^ mask[i];
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptXor: decrypt out",
decryptParamBuffer, paramSize);
}
if (rc == 0) {
rc = TSS_SetResponseDecryptParam(tssAuthContext,
paramSize, decryptParamBuffer);
}
free(mask); /* @1 */
free(decryptParamBuffer); /* @2 */
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
#ifndef TPM_TSS_NOCRYPTO
/* NOTE: if CFB also works, do in place decryption */
static TPM_RC TSS_Response_EncryptAes(TSS_AUTH_CONTEXT *tssAuthContext,
struct TSS_HMAC_CONTEXT *session)
{
TPM_RC rc = 0;
uint32_t paramSize;
uint8_t *encryptParamBuffer;
uint8_t *decryptParamBuffer = NULL;
TPM2B_IV iv;
uint32_t kdfaBits;
uint16_t keySizeinBytes;
uint8_t symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; /* AES key + IV */
/* get the TPM2B parameter to decrypt */
if (rc == 0) {
rc = TSS_GetResponseEncryptParam(tssAuthContext,
&paramSize, &encryptParamBuffer);
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptAes: encrypt in",
encryptParamBuffer, paramSize);
}
if (rc == 0) {
rc = TSS_Malloc(&decryptParamBuffer, paramSize); /* freed @1 */
}
/* generate the encryption key and IV */
/* 21.3 CFB Mode Parameter Encryption
KDFa (hashAlg, sessionValue, "CFB", nonceNewer, nonceOlder, bits) (34)
*/
if (rc == 0) {
iv.t.size = TSS_Sym_GetBlockSize(session->symmetric.algorithm,
session->symmetric.keyBits.aes);
/* generate random values for both the AES key and the IV */
kdfaBits = session->symmetric.keyBits.aes + (iv.t.size * 8);
if (tssVverbose) printf("TSS_Response_EncryptAes: hashAlg %04x\n",
session->authHashAlg);
if (tssVverbose) printf("TSS_Response_EncryptAes: AES key bits %u\n",
session->symmetric.keyBits.aes);
if (tssVverbose) printf("TSS_Response_EncryptAes: kdfaBits %04x\n",
kdfaBits);
if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptAes: session key",
session->sessionKey.b.buffer, session->sessionKey.b.size);
rc = TSS_KDFA(&symParmString[0],
session->authHashAlg,
&session->sessionValue.b,
"CFB",
&session->nonceTPM.b,
&session->nonceCaller.b,
kdfaBits);
}
/* copy the latter part of the kdf output to the IV */
if (rc == 0) {
keySizeinBytes = session->symmetric.keyBits.aes / 8;
memcpy(iv.t.buffer, &symParmString[keySizeinBytes], iv.t.size);
if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptAes: IV",
iv.t.buffer, iv.t.size);
}
/* AES CFB decrypt the response */
if (rc == 0) {
TPM_RC crc;
crc = TSS_AES_DecryptCFB(decryptParamBuffer, /* output */
session->symmetric.keyBits.aes, /* 128 */
symParmString, /* key */
iv.t.buffer, /* IV */
paramSize, /* length */
(uint8_t *)encryptParamBuffer); /* input */
if (crc != 0) {
if (tssVerbose) printf("TSS_Response_EncryptAes: AES decrypt failed\n");
rc = TSS_RC_AES_DECRYPT_FAILURE;
}
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptAes: decrypt out",
decryptParamBuffer, paramSize);
}
if (rc == 0) {
rc = TSS_SetResponseDecryptParam(tssAuthContext,
paramSize, decryptParamBuffer);
}
free(decryptParamBuffer); /* @1 */
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
/*
Command Change Authorization Processor
*/
#ifndef TPM_TSS_NOCRYPTO
static TPM_RC TSS_Command_ChangeAuthProcessor(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
COMMAND_PARAMETERS *in)
{
TPM_RC rc = 0;
size_t index;
int found;
TSS_ChangeAuthFunction_t changeAuthFunction = NULL;
TPM_CC commandCode = TSS_GetCommandCode(tssContext->tssAuthContext);
/* search the table for a change authorization processing function */
if (rc == 0) {
found = FALSE;
for (index = 0 ; (index < (sizeof(tssTable) / sizeof(TSS_TABLE))) && !found ; index++) {
if (tssTable[index].commandCode == commandCode) {
found = TRUE;
break; /* don't increment index if found */
}
}
}
/* found false means there is no change authorization function. This permits the table to be
smaller if desired. */
if ((rc == 0) && found) {
changeAuthFunction = tssTable[index].changeAuthFunction;
/* there could also be an entry that is currently NULL, nothing to do */
if (changeAuthFunction == NULL) {
found = FALSE;
}
}
/* call the processing function */
if ((rc == 0) && found) {
rc = changeAuthFunction(tssContext, session, handleNumber, in);
}
return rc;
}
#endif /* TPM_TSS_NOCRYPTO */
static TPM_RC TSS_CA_HierarchyChangeAuth(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
HierarchyChangeAuth_In *in)
{
TPM_RC rc = 0;
char *password = NULL;
if (tssVverbose) printf("TSS_CA_HierarchyChangeAuth\n");
if (in->newAuth.t.size == 0) {
password = NULL;
}
else {
if (rc == 0) {
rc = TSS_Malloc((uint8_t **)&password, /* freed @1 */
in->newAuth.t.size + 1);
}
if (rc == 0) {
/* copy the password */
memcpy(password, in->newAuth.t.buffer, in->newAuth.t.size);
password[in->newAuth.t.size] = '\0'; /* nul terminate string */
}
}
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
rc = TSS_HmacSession_SetHmacKey(tssContext,
session,
handleNumber,
password);
}
#else
tssContext = tssContext;
session = session;
handleNumber = handleNumber;
#endif /* TPM_TSS_NOCRYPTO */
free(password); /* @1 */
return rc;
}
static TPM_RC TSS_CA_NV_ChangeAuth(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
NV_ChangeAuth_In *in)
{
TPM_RC rc = 0;
char *password = NULL;
if (tssVverbose) printf("TSS_CA_NV_ChangeAuth\n");
if (in->newAuth.t.size == 0) {
password = NULL;
}
else {
if (rc == 0) {
rc = TSS_Malloc((uint8_t **)&password, /* freed @1 */
in->newAuth.t.size + 1);
}
if (rc == 0) {
/* copy the password */
memcpy(password, in->newAuth.t.buffer, in->newAuth.t.size);
password[in->newAuth.t.size] = '\0'; /* nul terminate string */
}
}
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
rc = TSS_HmacSession_SetHmacKey(tssContext,
session,
handleNumber,
password);
}
#else
tssContext = tssContext;
session = session;
handleNumber = handleNumber;
#endif /* TPM_TSS_NOCRYPTO */
free(password); /* @1 */
return rc;
}
static TPM_RC TSS_CA_NV_UndefineSpaceSpecial(TSS_CONTEXT *tssContext,
struct TSS_HMAC_CONTEXT *session,
size_t handleNumber,
NV_UndefineSpaceSpecial_In *in)
{
TPM_RC rc = 0;
in = in;
if (tssVverbose) printf("TSS_CA_NV_UndefineSpaceSpecial\n");
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
/* the nvIndex authorization, the zeroth authorization, has special handling */
if (handleNumber == 0) {
/* the Empty Buffer is used as the authValue when generating the response HMAC */
rc = TSS_HmacSession_SetHmacKey(tssContext,
session,
handleNumber,
NULL); /* password */
}
}
#else
tssContext = tssContext;
session = session;
handleNumber = handleNumber;
#endif /* TPM_TSS_NOCRYPTO */
return rc;
}
/*
Command Pre-Processor
*/
static TPM_RC TSS_Command_PreProcessor(TSS_CONTEXT *tssContext,
TPM_CC commandCode,
COMMAND_PARAMETERS *in,
EXTRA_PARAMETERS *extra)
{
TPM_RC rc = 0;
size_t index;
int found;
TSS_PreProcessFunction_t preProcessFunction = NULL;
/* search the table for a pre-processing function */
if (rc == 0) {
found = FALSE;
for (index = 0 ; (index < (sizeof(tssTable) / sizeof(TSS_TABLE))) && !found ; index++) {
if (tssTable[index].commandCode == commandCode) {
found = TRUE;
break; /* don't increment index if found */
}
}
}
/* found false means there is no pre-processing function. This permits the table to be smaller
if desired. */
if ((rc == 0) && found) {
preProcessFunction = tssTable[index].preProcessFunction;
/* call the pre processing function if there is one */
if (preProcessFunction != NULL) {
rc = preProcessFunction(tssContext, in, extra);
}
}
#ifndef TPM_TSS_NO_PRINT
if ((rc == 0) && tssVverbose) {
found = FALSE;
for (index = 0 ;
(index < (sizeof(tssPrintTable) / sizeof(TSS_PRINT_TABLE))) && !found ;
index++) {
if (tssPrintTable[index].commandCode == commandCode) {
found = TRUE;
break; /* don't increment index if found */
}
}
}
/* found false means there is no print function. This permits the table to be smaller
if desired. */
if ((rc == 0) && tssVverbose && found) {
TSS_InPrintFunction_t inPrintFunction = tssPrintTable[index].inPrintFunction;
/* call the pre processing function if there is one */
if (inPrintFunction != NULL) {
printf("TSS_Command_PreProcessor: Input parameters\n");
inPrintFunction(in, 8); /* hard code indent 8 */
}
}
#endif /* TPM_TSS_NO_PRINT */
return rc;
}
/*
Command specific pre processing functions
*/
/* TSS_PR_StartAuthSession handles StartAuthSession pre processing.
If the salt key in->tpmKey is not NULL and an RSA key, the preprocessor supplies the encrypted
salt. It passes the unencrypted salt to the post processor for session key processing.
An input salt (encrypted or unencrypted) is ignored.
Returns an error if the key is not an RSA key.
*/
static TPM_RC TSS_PR_StartAuthSession(TSS_CONTEXT *tssContext,
StartAuthSession_In *in,
StartAuthSession_Extra *extra)
{
TPM_RC rc = 0;
if (tssVverbose) printf("TSS_PR_StartAuthSession\n");
/* if (tssVverbose) StartAuthSession_In_Print(in, 8); */
#ifndef TPM_TSS_NOCRYPTO
/* generate nonceCaller */
if (rc == 0) {
/* the size is determined by the session hash algorithm */
in->nonceCaller.t.size = TSS_GetDigestSize(in->authHash);
if (in->nonceCaller.t.size == 0) {
if (tssVerbose) printf("TSS_PR_StartAuthSession: hash algorithm %04x not implemented\n",
in->authHash);
rc = TSS_RC_BAD_HASH_ALGORITHM;
}
}
if (rc == 0) {
rc = TSS_RandBytes((unsigned char *)&in->nonceCaller.t.buffer, in->nonceCaller.t.size);
}
#else
in->nonceCaller.t.size = 16;
memset(&in->nonceCaller.t.buffer, 0, 16);
#endif /* TPM_TSS_NOCRYPTO */
/* initialize to handle unsalted session */
in->encryptedSalt.t.size = 0;
if (extra != NULL) { /* extra NULL is handled at the port processor */
extra->salt.t.size = 0;
}
/* if the caller requests a salted session */
if (in->tpmKey != TPM_RH_NULL) {
#ifndef TPM_TSS_NOCRYPTO
TPM2B_PUBLIC bPublic;
if (rc == 0) {
if (extra == NULL) {
if (tssVerbose)
printf("TSS_PR_StartAuthSession: salt session requires extra parameter\n");
rc = TSS_RC_NULL_PARAMETER;
}
}
/* get the tpmKey public key */
if (rc == 0) {
rc = TSS_Public_Load(tssContext, &bPublic, in->tpmKey, NULL);
}
/* generate the salt and encrypted salt based on the asymmetric key type */
if (rc == 0) {
switch (bPublic.publicArea.type) {
#ifndef TPM_TSS_NOECC
case TPM_ALG_ECC:
rc = TSS_ECC_Salt(&extra->salt,
&in->encryptedSalt,
&bPublic.publicArea);
break;
#endif /* TPM_TSS_NOECC */
#ifndef TPM_TSS_NORSA
case TPM_ALG_RSA:
rc = TSS_RSA_Salt(&extra->salt,
&in->encryptedSalt,
&bPublic.publicArea);
break;
#endif /* TPM_TSS_NORSA */
default:
if (tssVerbose)
printf("TSS_PR_StartAuthSession: public key type %04x not supported\n",
bPublic.publicArea.type);
rc = TSS_RC_BAD_SALT_KEY;
}
}
#else
tssContext = tssContext;
rc = TSS_RC_NOT_IMPLEMENTED;
#endif /* TPM_TSS_NOCRYPTO */
}
return rc;
}
#ifndef TPM_TSS_NOCRYPTO
#ifndef TPM_TSS_NORSA
/* TSS_RSA_Salt() returns both the plaintext and excrypted salt, based on the salt key bPublic. */
static TPM_RC TSS_RSA_Salt(TPM2B_DIGEST *salt,
TPM2B_ENCRYPTED_SECRET *encryptedSalt,
TPMT_PUBLIC *publicArea)
{
TPM_RC rc = 0;
if (rc == 0) {
{
/* error conditions when true */
int b1 = publicArea->type != TPM_ALG_RSA;
int b2 = publicArea->objectAttributes.val & TPMA_OBJECT_SIGN;
int b3 = !(publicArea->objectAttributes.val & TPMA_OBJECT_DECRYPT);
int b4 = (publicArea->parameters.rsaDetail.exponent != 0) &&
/* some HW TPMs return 010001 for the RSA EK with the default IWG template */
(publicArea->parameters.rsaDetail.exponent != RSA_DEFAULT_PUBLIC_EXPONENT);
/* TSS support checks */
if (b1 || b2 || b3 || b4) {
if (tssVerbose)
printf("TSS_RSA_Salt: public key attributes not supported\n");
rc = TSS_RC_BAD_SALT_KEY;
}
}
}
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_RSA_Salt: public key",
publicArea->unique.rsa.t.buffer,
publicArea->unique.rsa.t.size);
}
/* generate a salt */
if (rc == 0) {
/* The size of the secret value is limited to the size of the digest produced by the
nameAlg of the object that is associated with the public key used for OAEP
encryption. */
salt->t.size = TSS_GetDigestSize(publicArea->nameAlg);
if (tssVverbose) printf("TSS_RSA_Salt: "
"Hash algorithm %04x Salt size %u\n",
publicArea->nameAlg, salt->t.size);
/* place the salt in extra so that it can be retrieved by post processor */
rc = TSS_RandBytes((uint8_t *)&salt->t.buffer, salt->t.size);
}
/* In TPM2_StartAuthSession(), when tpmKey is an RSA key, the secret value (salt) is
encrypted using OAEP as described in B.4. The string "SECRET" (see 4.5) is used as
the L value and the nameAlg of the encrypting key is used for the hash algorithm. The
data value in OAEP-encrypted blob (salt) is used to compute sessionKey. */
if (rc == 0) {
if (tssVverbose) TSS_PrintAll("TSS_RSA_Salt: salt",
(uint8_t *)&salt->t.buffer,
salt->t.size);
}
/* encrypt the salt */
if (rc == 0) {
/* public exponent */
unsigned char earr[3] = {0x01, 0x00, 0x01};
/* encrypt the salt with the tpmKey public key */
rc = TSS_RSAPublicEncrypt((uint8_t *)&encryptedSalt->t.secret, /* encrypted data */
publicArea->unique.rsa.t.size, /* size of encrypted data buffer */
(uint8_t *)&salt->t.buffer, /* decrypted data */
salt->t.size,
publicArea->unique.rsa.t.buffer, /* public modulus */
publicArea->unique.rsa.t.size,
earr, /* public exponent */
sizeof(earr),
(unsigned char *)"SECRET", /* encoding parameter */
sizeof("SECRET"),
publicArea->nameAlg);
}
if (rc == 0) {
encryptedSalt->t.size = publicArea->unique.rsa.t.size;
if (tssVverbose) TSS_PrintAll("TSS_RSA_Salt: RSA encrypted salt",
encryptedSalt->t.secret,
encryptedSalt->t.size);
}
return rc;
}
#endif /* TPM_TSS_NORSA */
#endif /* TPM_TSS_NOCRYPTO */
static TPM_RC TSS_PR_NV_DefineSpace(TSS_CONTEXT *tssContext,
NV_DefineSpace_In *in,
void *extra)
{
TPM_RC rc = 0;
tssContext = tssContext;
extra = extra;
if (tssVverbose) printf("TSS_PR_NV_DefineSpace\n");
/* Test that TPMA_NVA_POLICY_DELETE is only set when a policy is also set. Otherwise, the index
cannot ever be deleted, even with Platform Authorization. If the application really wants to
do this, set the policy to one that cannot be satisfied, e.g., all 0xff's. */
if (rc == 0) {
if (in->publicInfo.nvPublic.attributes.val & TPMA_NVA_POLICY_DELETE) {
if (in->publicInfo.nvPublic.authPolicy.b.size == 0) {
if (tssVverbose) printf("TSS_PR_NV_DefineSpace POLICY_DELETE requires a policy\n");
rc = TSS_RC_IN_PARAMETER;
}
}
}
return rc;
}
/*
Response Post Processor
*/
/* TSS_Response_PostProcessor() handles any response specific post processing
*/
static TPM_RC TSS_Response_PostProcessor(TSS_CONTEXT *tssContext,
COMMAND_PARAMETERS *in,
RESPONSE_PARAMETERS *out,
EXTRA_PARAMETERS *extra)
{
TPM_RC rc = 0;
size_t index;
int found;
TSS_PostProcessFunction_t postProcessFunction = NULL;
/* search the table for a post processing function */
if (rc == 0) {
TPM_CC commandCode = TSS_GetCommandCode(tssContext->tssAuthContext);
found = FALSE;
for (index = 0 ; (index < (sizeof(tssTable) / sizeof(TSS_TABLE))) && !found ; index++) {
if (tssTable[index].commandCode == commandCode) {
found = TRUE;
break; /* don't increment index if found */
}
}
}
/* found false means there is no post processing function. This permits the table to be smaller
if desired. */
if ((rc == 0) && found) {
postProcessFunction = tssTable[index].postProcessFunction;
/* there could also be an entry that it currently NULL, nothing to do */
if (postProcessFunction == NULL) {
found = FALSE;
}
}
/* call the function */
if ((rc == 0) && found) {
rc = postProcessFunction(tssContext, in, out, extra);
}
return rc;
}
/*
Command specific post processing functions
*/
/* TSS_PO_StartAuthSession handles StartAuthSession post processing. It:
creates a TSS HMAC session
saves the session handle, hash algorithm, and symmetric algorithm, nonceCaller and nonceTPM
It calculates the session key and saves it
Finally, it marshals the session and stores it
*/
static TPM_RC TSS_PO_StartAuthSession(TSS_CONTEXT *tssContext,
StartAuthSession_In *in,
StartAuthSession_Out *out,
StartAuthSession_Extra *extra)
{
TPM_RC rc = 0;
struct TSS_HMAC_CONTEXT *session = NULL;
TPM2B_DIGEST salt;
if (tssVverbose) printf("TSS_PO_StartAuthSession\n");
/* allocate a TSS_HMAC_CONTEXT session context */
if (rc == 0) {
rc = TSS_HmacSession_GetContext(&session);
}
if (rc == 0) {
session->sessionHandle = out->sessionHandle;
session->authHashAlg = in->authHash;
#ifndef TPM_TSS_NOCRYPTO
session->sizeInBytes = TSS_GetDigestSize(session->authHashAlg);
#endif
session->symmetric = in->symmetric;
session->sessionType = in->sessionType;
}
/* if not a bind session or if no bind password was supplied */
if (rc == 0) {
if ((extra == NULL) || (in->bind == TPM_RH_NULL) || (extra->bindPassword == NULL)) {
session->bindAuthValue.b.size = 0;
}
else {
rc = TSS_TPM2B_StringCopy(&session->bindAuthValue.b,
extra->bindPassword, sizeof(session->bindAuthValue.t.buffer));
}
}
if (rc == 0) {
/* if the caller did not supply extra, the salt must be empty */
if (extra == NULL) {
salt.b.size = 0;
}
/* if the caller supplied extra, the preprocessor sets salt to empty (unsalted) or the
plaintext salt value */
else {
rc = TSS_TPM2B_Copy(&salt.b, &extra->salt.b, sizeof(TPMT_HA));
}
}
#ifndef TPM_TSS_NOCRYPTO
if (rc == 0) {
rc = TSS_TPM2B_Copy(&session->nonceTPM.b, &out->nonceTPM.b, sizeof(TPMT_HA));
}
if (rc == 0) {
rc = TSS_TPM2B_Copy(&session->nonceCaller.b, &in->nonceCaller.b, sizeof(TPMT_HA));
}
if (rc == 0) {
rc = TSS_HmacSession_SetSessionKey(tssContext, session,
&salt,
in->bind, &session->bindAuthValue);
}
#endif /* TPM_TSS_NOCRYPTO */
if (rc == 0) {
rc = TSS_HmacSession_SaveSession(tssContext, session);
}
TSS_HmacSession_FreeContext(session);
return rc;
}
/* TSS_PO_ContextSave() saves the name of an object in a filename that is a hash of the contextBlob.
This permits the name to be found during ContextLoad.
*/
static TPM_RC TSS_PO_ContextSave(TSS_CONTEXT *tssContext,
ContextSave_In *in,
ContextSave_Out *out,
void *extra)
{
TPM_RC rc = 0;
#ifndef TPM_TSS_NOFILE
TPMT_HA cpHash; /* largest size of a digest */
char string[65]; /* sha256 hash * 2 + 1 */
TPM_HT handleType;
int done = FALSE;
#endif
in = in;
extra = extra;
#ifndef TPM_TSS_NOFILE
if (tssVverbose) printf("TSS_PO_ContextSave: handle %08x\n", in->saveHandle);
/* only for objects and sequence objects, not sessions */
if (rc == 0) {
handleType = (TPM_HT) ((in->saveHandle & HR_RANGE_MASK) >> HR_SHIFT);
if (handleType != TPM_HT_TRANSIENT) {
done = TRUE;
}
}
if ((rc == 0) && !done) {
cpHash.hashAlg = TPM_ALG_SHA256; /* arbitrary choice */
rc = TSS_Hash_Generate(&cpHash,
out->context.contextBlob.b.size, out->context.contextBlob.b.buffer,
0, NULL);
}
/* convert a hash of the context blob to a string */
if ((rc == 0) && !done) {
rc = TSS_HashToString(string, cpHash.digest.sha256);
}
if ((rc == 0) && !done) {
rc = TSS_Name_Copy(tssContext,
0, string, /* to context */
in->saveHandle, NULL); /* from handle */
}
/* get the public key of the object being context saved */
/* save the public key under the context */
if ((rc == 0) && !done) {
rc = TSS_Public_Copy(tssContext,
0,
string,
in->saveHandle,
NULL);
}
#else
tssContext = tssContext;
out = out;
#endif
return rc;
}
static TPM_RC TSS_PO_ContextLoad(TSS_CONTEXT *tssContext,
ContextLoad_In *in,
ContextLoad_Out *out,
void *extra)
{
TPM_RC rc = 0;
#ifndef TPM_TSS_NOFILE
TPMT_HA cpHash; /* largest size of a digest */
char string[65]; /* sha256 hash * 2 + 1 */
TPM_HT handleType;
int done = FALSE;
#endif
out = out;
extra = extra;
#ifndef TPM_TSS_NOFILE
if (tssVverbose) printf("TSS_PO_ContextLoad: handle %08x\n", out->loadedHandle);
/* only for objects and sequence objects, not sessions */
if (rc == 0) {
handleType = (TPM_HT) ((out->loadedHandle & HR_RANGE_MASK) >> HR_SHIFT);
if (handleType != TPM_HT_TRANSIENT) {
done = TRUE;
}
}
if ((rc == 0) && !done) {
cpHash.hashAlg = TPM_ALG_SHA256; /* arbitrary choice */
rc = TSS_Hash_Generate(&cpHash,
in->context.contextBlob.b.size, in->context.contextBlob.b.buffer,
0, NULL);
}
/* convert a hash of the context blob to a string */
if ((rc == 0) && !done) {
rc = TSS_HashToString(string, cpHash.digest.sha256);
}
/* get the Name of the object being context loaded */
/* write the name with the loaded context's handle */
if ((rc == 0) && !done) {
rc = TSS_Name_Copy(tssContext,
out->loadedHandle, NULL, /* to handle */
0, string); /* from context */
}
/* get the public key of the object being context loaded */
/* write the public key with the loaded context's handle */
if ((rc == 0) && !done) {
rc = TSS_Public_Copy(tssContext,
out->loadedHandle,
NULL,
0,
string);
}
#else
tssContext = tssContext;
in = in;
#endif
return rc;
}
/* TSS_HashToString() converts a SHA-256 binary hash (really any 32-byte value) to a string
string must be 65 bytes: 32*2 + 1
NOTE: Hard coded to SHA256
*/
#ifndef TPM_TSS_NOFILE
static TPM_RC TSS_HashToString(char *str, uint8_t *digest)
{
size_t i;
for (i = 0 ; i < SHA256_DIGEST_SIZE ; i++) {
sprintf(str +(i*2), "%02x", digest[i]);
}
if (tssVverbose) printf("TSS_HashToString: %s\n", str);
return 0;
}
#endif
/* TSS_PO_FlushContext() removes persistent state associated with the handle */
static TPM_RC TSS_PO_FlushContext(TSS_CONTEXT *tssContext,
FlushContext_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
out = out;
extra = extra;
if (tssVverbose) printf("TSS_PO_FlushContext: flushHandle %08x\n", in->flushHandle);
if (rc == 0) {
rc = TSS_DeleteHandle(tssContext, in->flushHandle);
}
return rc;
}
/* TSS_PO_EvictControl() removes persistent state associated with the handle */
static TPM_RC TSS_PO_EvictControl(TSS_CONTEXT *tssContext,
EvictControl_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
out = out;
extra = extra;
if (tssVverbose) printf("TSS_PO_EvictControl: object %08x persistent %08x\n",
in->objectHandle, in->persistentHandle);
/* if it successfully made a persistent copy */
if (in->objectHandle != in->persistentHandle) {
/* TPM2B_PUBLIC bPublic; */
if (rc == 0) {
rc = TSS_Name_Copy(tssContext,
in->persistentHandle, NULL, /* to persistent handle */
in->objectHandle, NULL); /* from transient handle */
}
/* get the transient object public key */
/* copy it to the persistent object public key */
if (rc == 0) {
rc = TSS_Public_Copy(tssContext,
in->persistentHandle,
NULL,
in->objectHandle,
NULL);
}
}
/* if it successfully evicted the persistent object */
else {
if (rc == 0) {
rc = TSS_DeleteHandle(tssContext, in->persistentHandle);
}
}
return rc;
}
/* TSS_PO_Load() saves the Name returned for the loaded object. It saves the TPM2B_PUBLIC */
static TPM_RC TSS_PO_Load(TSS_CONTEXT *tssContext,
Load_In *in,
Load_Out *out,
void *extra)
{
TPM_RC rc = 0;
in = in;
extra = extra;
if (tssVverbose) printf("TSS_PO_Load: handle %08x\n", out->objectHandle);
/* use handle as file name */
if (rc == 0) {
rc = TSS_Name_Store(tssContext, &out->name, out->objectHandle, NULL);
}
if (rc == 0) {
rc = TSS_Public_Store(tssContext, &in->inPublic, out->objectHandle, NULL);
}
return rc;
}
/* TSS_PO_LoadExternal() saves the Name returned for the loaded object */
static TPM_RC TSS_PO_LoadExternal(TSS_CONTEXT *tssContext,
LoadExternal_In *in,
LoadExternal_Out *out,
void *extra)
{
TPM_RC rc = 0;
in = in;
extra = extra;
if (tssVverbose) printf("TSS_PO_LoadExternal: handle %08x\n", out->objectHandle);
/* use handle as file name */
if (rc == 0) {
rc = TSS_Name_Store(tssContext, &out->name, out->objectHandle, NULL);
}
if (rc == 0) {
rc = TSS_Public_Store(tssContext, &in->inPublic, out->objectHandle, NULL);
}
return rc;
}
/* TSS_PO_ReadPublic() saves the Name returned for the loaded object */
static TPM_RC TSS_PO_ReadPublic(TSS_CONTEXT *tssContext,
ReadPublic_In *in,
ReadPublic_Out *out,
void *extra)
{
TPM_RC rc = 0;
in = in;
extra = extra;
if (tssVverbose) printf("TSS_PO_ReadPublic: handle %08x\n", in->objectHandle);
/* if the TSS is compiled without crypto support, it cannot recalculate the Name from the public
area. It has to trust the response from the TPM. This should be OK since a 'no crypto' TSS
is used when there is a tructed path to the TPM. */
#ifndef TPM_TSS_NOCRYPTO
/* validate the Name against the public area */
/* Name = nameAlg || HnameAlg (handle->publicArea)
where
nameAlg algorithm used to compute Name
HnameAlg hash using the nameAlg parameter in the object associated with handle
publicArea contents of the TPMT_PUBLIC associated with handle
*/
{
TPM2B_NAME name;
if (rc == 0) {
rc = TSS_ObjectPublic_GetName(&name, &out->outPublic.publicArea);
}
if (rc == 0) {
if (name.t.size != out->name.t.size) {
if (tssVerbose)
printf("TSS_PO_ReadPublic: TPMT_PUBLIC does not match TPM2B_NAME\n");
rc = TSS_RC_MALFORMED_PUBLIC;
}
else {
int irc;
irc = memcmp(name.t.name, out->name.t.name, out->name.t.size);
if (irc != 0) {
if (tssVerbose)
printf("TSS_PO_ReadPublic: TPMT_PUBLIC does not match TPM2B_NAME\n");
rc = TSS_RC_MALFORMED_PUBLIC;
}
}
}
}
#endif
/* use handle as file name */
if (rc == 0) {
rc = TSS_Name_Store(tssContext, &out->name, in->objectHandle, NULL);
}
if (rc == 0) {
rc = TSS_Public_Store(tssContext, &out->outPublic, in->objectHandle, NULL);
}
return rc;
}
/* TSS_PO_Load() saves the Name returned for the loaded object. It saves the TPM2B_PUBLIC */
static TPM_RC TSS_PO_CreateLoaded(TSS_CONTEXT *tssContext,
CreateLoaded_In *in,
CreateLoaded_Out *out,
void *extra)
{
TPM_RC rc = 0;
in = in;
extra = extra;
if (tssVverbose) printf("TSS_PO_CreateLoaded: handle %08x\n", out->objectHandle);
/* use handle as file name */
if (rc == 0) {
rc = TSS_Name_Store(tssContext, &out->name, out->objectHandle, NULL);
}
if (rc == 0) {
rc = TSS_Public_Store(tssContext, &out->outPublic, out->objectHandle, NULL);
}
return rc;
}
/* TSS_PO_HashSequenceStart() saves the Name returned for the started sequence object */
static TPM_RC TSS_PO_HashSequenceStart(TSS_CONTEXT *tssContext,
HashSequenceStart_In *in,
HashSequenceStart_Out *out,
void *extra)
{
TPM_RC rc = 0;
TPM2B_NAME name;
in = in;
extra = extra;
if (tssVverbose) printf("TSS_PO_HashSequenceStart\n");
/* Part 1 Table 3 The Name of a sequence object is an Empty Buffer */
if (rc == 0) {
name.b.size = 0;
/* use handle as file name */
rc = TSS_Name_Store(tssContext, &name, out->sequenceHandle, NULL);
}
return rc;
}
/* TSS_PO_HMAC_Start() saves the Name returned for the started sequence object */
static TPM_RC TSS_PO_HMAC_Start(TSS_CONTEXT *tssContext,
HMAC_Start_In *in,
HMAC_Start_Out *out,
void *extra)
{
TPM_RC rc = 0;
TPM2B_NAME name;
in = in;
extra = extra;
if (tssVverbose) printf("TSS_PO_HMAC_Start\n");
/* Part 1 Table 3 The Name of a sequence object is an Empty Buffer */
if (rc == 0) {
name.b.size = 0;
/* use handle as file name */
rc = TSS_Name_Store(tssContext, &name, out->sequenceHandle, NULL);
}
return rc;
}
static TPM_RC TSS_PO_SequenceComplete(TSS_CONTEXT *tssContext,
SequenceComplete_In *in,
SequenceComplete_Out *out,
void *extra)
{
TPM_RC rc = 0;
out = out;
extra = extra;
if (tssVverbose) printf("TSS_PO_SequenceComplete: sequenceHandle %08x\n", in->sequenceHandle);
if (rc == 0) {
rc = TSS_DeleteHandle(tssContext, in->sequenceHandle);
}
return rc;
}
static TPM_RC TSS_PO_EventSequenceComplete(TSS_CONTEXT *tssContext,
EventSequenceComplete_In *in,
EventSequenceComplete_Out *out,
void *extra)
{
TPM_RC rc = 0;
out = out;
extra = extra;
if (tssVverbose)
printf("TSS_PO_EventSequenceComplete: sequenceHandle %08x\n", in->sequenceHandle);
if (rc == 0) {
rc = TSS_DeleteHandle(tssContext, in->sequenceHandle);
}
return rc;
}
static TPM_RC TSS_PO_PolicyAuthValue(TSS_CONTEXT *tssContext,
PolicyAuthValue_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
struct TSS_HMAC_CONTEXT *session = NULL;
out = out;
extra = extra;
if (tssVverbose) printf("TSS_PO_PolicyAuthValue\n");
if (rc == 0) {
rc = TSS_Malloc((unsigned char **)&session, sizeof(TSS_HMAC_CONTEXT)); /* freed @1 */
}
if (rc == 0) {
rc = TSS_HmacSession_LoadSession(tssContext, session, in->policySession);
}
if (rc == 0) {
session->isPasswordNeeded = FALSE;
session->isAuthValueNeeded = TRUE;
rc = TSS_HmacSession_SaveSession(tssContext, session);
}
free(session); /* @1 */
return rc;
}
static TPM_RC TSS_PO_PolicyPassword(TSS_CONTEXT *tssContext,
PolicyPassword_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
struct TSS_HMAC_CONTEXT *session = NULL;
out = out;
extra = extra;
if (tssVverbose) printf("TSS_PO_PolicyPassword\n");
if (rc == 0) {
rc = TSS_Malloc((unsigned char **)&session, sizeof(TSS_HMAC_CONTEXT)); /* freed @1 */
}
if (rc == 0) {
rc = TSS_HmacSession_LoadSession(tssContext, session, in->policySession);
}
if (rc == 0) {
session->isPasswordNeeded = TRUE;
session->isAuthValueNeeded = FALSE;
rc = TSS_HmacSession_SaveSession(tssContext, session);
}
free(session); /* @1 */
return rc;
}
static TPM_RC TSS_PO_CreatePrimary(TSS_CONTEXT *tssContext,
CreatePrimary_In *in,
CreatePrimary_Out *out,
void *extra)
{
TPM_RC rc = 0;
in = in;
extra = extra;
if (tssVverbose) printf("TSS_PO_CreatePrimary: handle %08x\n", out->objectHandle);
/* use handle as file name */
if (rc == 0) {
rc = TSS_Name_Store(tssContext, &out->name, out->objectHandle, NULL);
}
if (rc == 0) {
rc = TSS_Public_Store(tssContext, &out->outPublic, out->objectHandle, NULL);
}
return rc;
}
static TPM_RC TSS_PO_NV_DefineSpace(TSS_CONTEXT *tssContext,
NV_DefineSpace_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
if (tssVverbose) printf("TSS_PO_NV_DefineSpace\n");
#ifndef TPM_TSS_NOCRYPTO
{
TPM2B_NAME name;
/* calculate the Name from the input public area */
/* Name = nameAlg || HnameAlg (handle->nvPublicArea)
where
nameAlg algorithm used to compute Name
HnameAlg hash using the nameAlg parameter in the NV Index location associated with handle
nvPublicArea contents of the TPMS_NV_PUBLIC associated with handle
*/
/* calculate the Name from the input TPMS_NV_PUBLIC */
if (rc == 0) {
rc = TSS_NVPublic_GetName(&name, &in->publicInfo.nvPublic);
}
/* use handle as file name */
if (rc == 0) {
rc = TSS_Name_Store(tssContext, &name, in->publicInfo.nvPublic.nvIndex, NULL);
}
if (rc == 0) {
rc = TSS_NVPublic_Store(tssContext, &in->publicInfo.nvPublic,
in->publicInfo.nvPublic.nvIndex);
}
}
#else
tssContext = tssContext;
in = in;
#endif
out = out;
extra = extra;
return rc;
}
static TPM_RC TSS_PO_NV_ReadPublic(TSS_CONTEXT *tssContext,
NV_ReadPublic_In *in,
NV_ReadPublic_Out *out,
void *extra)
{
TPM_RC rc = 0;
if (tssVverbose) printf("TSS_PO_NV_ReadPublic\n");
/* validate the Name against the public area */
/* Name = nameAlg || HnameAlg (handle->nvPublicArea)
where
nameAlg algorithm used to compute Name
HnameAlg hash using the nameAlg parameter in the NV Index location associated with handle
nvPublicArea contents of the TPMS_NV_PUBLIC associated with handle
*/
#ifndef TPM_TSS_NOCRYPTO
{
TPM2B_NAME name;
/* calculate the Name from the TPMS_NV_PUBLIC */
if (rc == 0) {
rc = TSS_NVPublic_GetName(&name, &out->nvPublic.nvPublic);
}
if (rc == 0) {
if (name.t.size != out->nvName.t.size) {
if (tssVerbose)
printf("TSS_PO_NV_ReadPublic: TPMT_NV_PUBLIC does not match TPM2B_NAME\n");
rc = TSS_RC_MALFORMED_NV_PUBLIC;
}
else {
int irc;
irc = memcmp(name.t.name, out->nvName.t.name, out->nvName.t.size);
if (irc != 0) {
if (tssVerbose)
printf("TSS_PO_NV_ReadPublic: TPMT_NV_PUBLIC does not match TPM2B_NAME\n");
rc = TSS_RC_MALFORMED_NV_PUBLIC;
}
}
}
/* use handle as file name */
if (rc == 0) {
rc = TSS_Name_Store(tssContext, &out->nvName, in->nvIndex, NULL);
}
if (rc == 0) {
rc = TSS_NVPublic_Store(tssContext, &out->nvPublic.nvPublic, in->nvIndex);
}
}
#else
tssContext = tssContext;
in = in;
out = out;
#endif
extra = extra;
return rc;
}
static TPM_RC TSS_PO_NV_UndefineSpace(TSS_CONTEXT *tssContext,
NV_UndefineSpace_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
out = out;
extra = extra;
if (tssVverbose) printf("TSS_PO_NV_UndefineSpace\n");
#ifndef TPM_TSS_NOCRYPTO
/* Don't check return code. */
TSS_DeleteHandle(tssContext, in->nvIndex);
TSS_NVPublic_Delete(tssContext, in->nvIndex);
#else
tssContext = tssContext;
in = in;
#endif
return rc;
}
static TPM_RC TSS_PO_NV_UndefineSpaceSpecial(TSS_CONTEXT *tssContext,
NV_UndefineSpaceSpecial_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
out = out;
extra = extra;
if (tssVverbose) printf("TSS_PO_NV_UndefineSpaceSpecial\n");
/* Don't check return code. The name will only exist if NV_ReadPublic has been issued */
TSS_DeleteHandle(tssContext, in->nvIndex);
TSS_NVPublic_Delete(tssContext, in->nvIndex);
return rc;
}
/* TSS_PO_NV_Write() handles the Name and NVPublic update for the 4 NV write commands: write,
increment, extend, and setbits */
static TPM_RC TSS_PO_NV_Write(TSS_CONTEXT *tssContext,
NV_Write_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
if (tssVverbose) printf("TSS_PO_NV_Write, Increment, Extend, SetBits:\n");
#ifndef TPM_TSS_NOCRYPTO
{
TPMS_NV_PUBLIC nvPublic;
TPM2B_NAME name; /* new name */
if (rc == 0) {
rc = TSS_NVPublic_Load(tssContext, &nvPublic, in->nvIndex);
}
/* if the previous store had written clear */
if (!(nvPublic.attributes.val & TPMA_NVA_WRITTEN)) {
if (rc == 0) {
/* set the written bit */
nvPublic.attributes.val |= TPMA_NVA_WRITTEN;
/* save the TPMS_NV_PUBLIC */
rc = TSS_NVPublic_Store(tssContext, &nvPublic, in->nvIndex);
}
/* calculate the name */
if (rc == 0) {
rc = TSS_NVPublic_GetName(&name, &nvPublic);
}
/* save the name */
if (rc == 0) {
/* use handle as file name */
rc = TSS_Name_Store(tssContext, &name, in->nvIndex, NULL);
}
/* if there is a failure. delete the name and NVPublic */
if (rc != 0) {
TSS_DeleteHandle(tssContext, in->nvIndex);
TSS_NVPublic_Delete(tssContext, in->nvIndex);
}
}
}
#else
tssContext = tssContext;
in = in;
#endif
out = out;
extra = extra;
return rc;
}
/* TSS_PO_NV_WriteLock() handles the Name and NVPublic update for the write lock command */
static TPM_RC TSS_PO_NV_WriteLock(TSS_CONTEXT *tssContext,
NV_WriteLock_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
if (tssVverbose) printf("TSS_PO_NV_WriteLock:\n");
#ifndef TPM_TSS_NOCRYPTO
{
TPMS_NV_PUBLIC nvPublic;
TPM2B_NAME name; /* new name */
if (rc == 0) {
rc = TSS_NVPublic_Load(tssContext, &nvPublic, in->nvIndex);
}
/* if the previous store had write lock clear */
if (!(nvPublic.attributes.val & TPMA_NVA_WRITELOCKED)) {
if (rc == 0) {
/* set the write lock bit */
nvPublic.attributes.val |= TPMA_NVA_WRITELOCKED;
/* save the TPMS_NV_PUBLIC */
rc = TSS_NVPublic_Store(tssContext, &nvPublic, in->nvIndex);
}
/* calculate the name */
if (rc == 0) {
rc = TSS_NVPublic_GetName(&name, &nvPublic);
}
/* save the name */
if (rc == 0) {
/* use handle as file name */
rc = TSS_Name_Store(tssContext, &name, in->nvIndex, NULL);
}
/* if there is a failure. delete the name and NVPublic */
if (rc != 0) {
TSS_DeleteHandle(tssContext, in->nvIndex);
TSS_NVPublic_Delete(tssContext, in->nvIndex);
}
}
}
#else
tssContext = tssContext;
in = in;
#endif
out = out;
extra = extra;
return rc;
}
/* TSS_PO_NV_WriteLock() handles the Name and NVPublic update for the read lock command */
static TPM_RC TSS_PO_NV_ReadLock(TSS_CONTEXT *tssContext,
NV_ReadLock_In *in,
void *out,
void *extra)
{
TPM_RC rc = 0;
if (tssVverbose) printf("TSS_PO_NV_ReadLock:");
#ifndef TPM_TSS_NOCRYPTO
{
TPMS_NV_PUBLIC nvPublic;
TPM2B_NAME name; /* new name */
if (rc == 0) {
rc = TSS_NVPublic_Load(tssContext, &nvPublic, in->nvIndex);
}
/* if the previous store had read lock clear */
if (!(nvPublic.attributes.val & TPMA_NVA_READLOCKED)) {
if (rc == 0) {
/* set the read lock bit */
nvPublic.attributes.val |= TPMA_NVA_READLOCKED;
/* save the TPMS_NV_PUBLIC */
rc = TSS_NVPublic_Store(tssContext, &nvPublic, in->nvIndex);
}
/* calculate the name */
if (rc == 0) {
rc = TSS_NVPublic_GetName(&name, &nvPublic);
}
/* save the name */
if (rc == 0) {
/* use handle as file name */
rc = TSS_Name_Store(tssContext, &name, in->nvIndex, NULL);
}
/* if there is a failure. delete the name and NVPublic */
if (rc != 0) {
TSS_DeleteHandle(tssContext, in->nvIndex);
TSS_NVPublic_Delete(tssContext, in->nvIndex);
}
}
}
#else
tssContext = tssContext;
in = in;
#endif
out = out;
extra = extra;
return rc;
}