diff options
Diffstat (limited to 'roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tss12.c')
-rw-r--r-- | roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tss12.c | 1423 |
1 files changed, 1423 insertions, 0 deletions
diff --git a/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tss12.c b/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tss12.c new file mode 100644 index 000000000..623193362 --- /dev/null +++ b/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tss12.c @@ -0,0 +1,1423 @@ +/********************************************************************************/ +/* */ +/* TSS Primary API for TPM 1.2 */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2018 - 2019. */ +/* */ +/* 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 <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 <ibmtss/tsscrypto.h> +#include <ibmtss/tsscryptoh.h> +#include <ibmtss/tssprintcmd.h> +#include <ibmtss/tpmconstants12.h> +#include "tss12.h" +#include "tssauth12.h" + +/* Files: + + hxxxxxxxx.bin - session context +*/ + +/* NOTE Synchronize with + + TSS_HmacSession12_InitContext + TSS_HmacSession12_Unmarshal + TSS_HmacSession12_Marshal +*/ + +typedef struct TSS_HMAC12_CONTEXT { + TPM_AUTHHANDLE authHandle; /* the authorization session handle */ + TPM_NONCE nonceEven; /* from the TPM in response */ + TPM_NONCE nonceEvenOSAP; /* from the TPM for OSAP in response */ + TPMT_HA sharedSecret; /* from KDF at OSAP session creation */ + /* uint16 */ + /* LSB is type of entityValue */ + /* MSB is ADIP encryption scheme */ + TPM_ENTITY_TYPE entityType; /* The type of entity in use */ + UINT32 entityValue; /* The selection value based on entityType, + e.g. a keyHandle #, TPM_RH_NULL for OIAP + session */ + /* Items below this line are for the lifetime of one command. They are not saved and loaded. */ + TPM_NONCE nonceOdd; /* from the TSS in command */ + TPM_NONCE nonceOddOSAP; /* from the TSS for OSAP in command */ + /* for TPM 1.2, OIAP SHA-1 of password, OSAP sharedSecret */ + TPMT_HA hmacKey; +} TSS_HMAC12_CONTEXT; + + +/* functions for command pre- and post- processing */ + +typedef TPM_RC (*TSS_PreProcessFunction_t)(TSS_CONTEXT *tssContext, + COMMAND_PARAMETERS *in, + EXTRA12_PARAMETERS *extra); +typedef TPM_RC (*TSS_ChangeAuthFunction_t)(TSS_CONTEXT *tssContext, + TSS_HMAC12_CONTEXT *session, + size_t handleNumber, + COMMAND_PARAMETERS *in); +typedef TPM_RC (*TSS_PostProcessFunction_t)(TSS_CONTEXT *tssContext, + COMMAND_PARAMETERS *in, + RESPONSE_PARAMETERS *out, + EXTRA12_PARAMETERS *extra); + +static TPM_RC TSS_PR_CreateWrapKey(TSS_CONTEXT *tssContext, + CreateWrapKey_In *in, + void *extra); +static TPM_RC TSS_PR_MakeIdentity(TSS_CONTEXT *tssContext, + MakeIdentity_In *in, + void *extra); +static TPM_RC TSS_PR_NV_DefineSpace(TSS_CONTEXT *tssContext, + NV_DefineSpace_In *in, + void *extra); +#if 0 +static TPM_RC TSS_PR_Seal(TSS_CONTEXT *tssContext, + Seal_in *In, + void *extra); +static TPM_RC TSS_PR_Sealx(TSS_CONTEXT *tssContext, + Sealx_in *In, + void *extra); + +#endif +static TPM_RC TSS_PO_FlushSpecific(TSS_CONTEXT *tssContext, + FlushSpecific_In *in, + void *out, + void *extra); +static TPM_RC TSS_PR_OSAP(TSS_CONTEXT *tssContext, + OSAP_In *in, + OSAP_Extra *extra); +static TPM_RC TSS_PO_OIAP(TSS_CONTEXT *tssContext, + void *in, + OIAP_Out *out, + void *extra); +static TPM_RC TSS_PO_OSAP(TSS_CONTEXT *tssContext, + OSAP_In *in, + OSAP_Out *out, + OSAP_Extra *extra); + +typedef struct TSS_TABLE { + TPM_CC commandCode; + TSS_PreProcessFunction_t preProcessFunction; + TSS_ChangeAuthFunction_t changeAuthFunction; + TSS_PostProcessFunction_t postProcessFunction; +} TSS_TABLE; + +/* FIXME offsets + changeauth +16, createownerdel, createkeydel -45 + createwrapkey +14, +34 + cmkcreatekey, changeauthowner +14 + changeauth 16 +*/ + +/* session handles numbers + #0 of 1 seal, sealx, createwrapkey, cmk_create, changeauthowner, del_ckd, del_cod, nv_define, createctr + #1 of 2 changeauth +*/ + + +static const TSS_TABLE tssTable [] = { + + {TPM_ORD_Init, NULL, NULL, NULL}, + {TPM_ORD_ActivateIdentity, NULL, NULL, NULL}, + {TPM_ORD_ContinueSelfTest, NULL, NULL, NULL}, + {TPM_ORD_CreateWrapKey, (TSS_PreProcessFunction_t)TSS_PR_CreateWrapKey, NULL, NULL}, + {TPM_ORD_CreateEndorsementKeyPair, NULL, NULL, NULL}, + {TPM_ORD_Extend, NULL, NULL, NULL}, + {TPM_ORD_FlushSpecific, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_FlushSpecific}, + {TPM_ORD_GetCapability, NULL, NULL, NULL}, + {TPM_ORD_MakeIdentity, (TSS_PreProcessFunction_t)TSS_PR_MakeIdentity, NULL, NULL}, + {TPM_ORD_OIAP, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_OIAP}, + {TPM_ORD_OSAP, (TSS_PreProcessFunction_t)TSS_PR_OSAP, NULL, (TSS_PostProcessFunction_t)TSS_PO_OSAP}, + {TPM_ORD_OwnerReadInternalPub, NULL, NULL, NULL}, + {TPM_ORD_NV_DefineSpace, (TSS_PreProcessFunction_t)TSS_PR_NV_DefineSpace, NULL, NULL}, + {TPM_ORD_NV_ReadValue, NULL, NULL, NULL}, + {TPM_ORD_NV_ReadValueAuth, NULL, NULL, NULL}, + {TPM_ORD_NV_WriteValue, NULL, NULL, NULL}, + {TPM_ORD_NV_WriteValueAuth, NULL, NULL, NULL}, + {TPM_ORD_PcrRead, NULL, NULL, NULL}, + {TPM_ORD_PCR_Reset, NULL, NULL, NULL}, +#if 0 + {TPM_ORD_Seal, (TSS_PreProcessFunction_t)TSS_PR_Seal, NULL, NULL}, + {TPM_ORD_Sealx, (TSS_PreProcessFunction_t)TSS_PR_Sealx, NULL, NULL}, +#endif + {TPM_ORD_Startup, NULL, NULL, NULL}, +}; + +/* local prototypes */ + + +static TPM_RC TSS_Execute12_valist(TSS_CONTEXT *tssContext, + COMMAND_PARAMETERS *in, + va_list ap); + +static TPM_RC TSS_Command_PreProcessor(TSS_CONTEXT *tssContext, + TPM_CC commandCode, + COMMAND_PARAMETERS *in, + EXTRA12_PARAMETERS *extra); +static TPM_RC TSS_Response_PostProcessor(TSS_CONTEXT *tssContext, + COMMAND_PARAMETERS *in, + RESPONSE_PARAMETERS *out, + EXTRA12_PARAMETERS *extra); + +static TPM_RC TSS_HmacSession12_GetContext(TSS_HMAC12_CONTEXT **session); +static void TSS_HmacSession12_InitContext(TSS_HMAC12_CONTEXT *session); +static void TSS_HmacSession12_FreeContext(TSS_HMAC12_CONTEXT *session); +static TPM_RC TSS_HmacSession12_SaveSession(TSS_CONTEXT *tssContext, + TSS_HMAC12_CONTEXT *session); +static TPM_RC TSS_HmacSession12_LoadSession(TSS_CONTEXT *tssContext, + TSS_HMAC12_CONTEXT *session, + TPM_AUTHHANDLE authHandle); +static TPM_RC TSS_HmacSession12_Marshal(TSS_HMAC12_CONTEXT *source, + uint16_t *written, + uint8_t **buffer, + uint32_t *size); +static TPM_RC TSS_HmacSession12_DeleteSession(TSS_CONTEXT *tssContext, + TPM_AUTHHANDLE handle); +static TPM_RC TSS_HmacSession12_Unmarshal(TSS_HMAC12_CONTEXT *target, + uint8_t **buffer, uint32_t *size); +static TPM_RC TSS_HmacSession12_SetHMAC(TSS_AUTH_CONTEXT *tssAuthContext, + size_t numSessions, + TSS_HMAC12_CONTEXT *session[], + TPMS_AUTH12_COMMAND *authCommand[], + TPM_AUTHHANDLE sessionHandle[], + unsigned int sessionAttributes[]); +static TPM_RC TSS_HmacSession12_Verify(TSS_AUTH_CONTEXT *tssAuthContext, + size_t numSessions, + TSS_HMAC12_CONTEXT *session[], + TPMS_AUTH12_RESPONSE *authResponse[]); +static TPM_RC TSS_HmacSession12_Continue(TSS_CONTEXT *tssContext, + TSS_HMAC12_CONTEXT *session, + TPMS_AUTH12_RESPONSE *authR); +static TPM_RC TSS_Command_Decrypt(TSS_AUTH_CONTEXT *tssAuthContext, + struct TSS_HMAC12_CONTEXT *session[], + TPM_AUTHHANDLE sessionHandle[]); +static TPM_RC TSS_Command_DecryptXor(TSS_AUTH_CONTEXT *tssAuthContext, + TSS_HMAC12_CONTEXT *session, + uint8_t *encAuth, + int parameterNumber); + +extern int tssVerbose; +extern int tssVverbose; + +/* TSS_Execute12() performs the complete command / response process. + + It sends the command specified by commandCode and the parameters 'in', returning the response + parameters 'out'. + + ... varargs are + + TPM_AUTHHANDLE authHandle, + const char *password, + unsigned int sessionAttributes + + Terminates with TPM_RH_NULL, NULL, 0 + + Processes up to MAX_SESSION_NUM sessions. +*/ + +TPM_RC TSS_Execute12(TSS_CONTEXT *tssContext, + RESPONSE_PARAMETERS *out, + COMMAND_PARAMETERS *in, + EXTRA12_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_Execute12: Command %08x marshal\n", commandCode); + rc = TSS_Marshal12(tssContext->tssAuthContext, + in, + commandCode); + } + /* execute the command */ + if (rc == 0) { + rc = TSS_Execute12_valist(tssContext, in, ap); + } + /* unmarshal the response parameters */ + if (rc == 0) { + if (tssVverbose) printf("TSS_Execute12: Command %08x unmarshal\n", commandCode); + rc = TSS_Unmarshal12(tssContext->tssAuthContext, out); + } + /* handle any command specific response post-processing */ + if (rc == 0) { + if (tssVverbose) printf("TSS_Execute12: Command %08x post processor\n", commandCode); + rc = TSS_Response_PostProcessor(tssContext, + in, + out, + extra); + } + return rc; +} + +/* TSS_Execute12_valist() transmits the marshaled command and receives the marshaled response. + + varargs are TPM_AUTHHANDLE 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_Execute12_valist(TSS_CONTEXT *tssContext, + COMMAND_PARAMETERS *in, + va_list ap) +{ + TPM_RC rc = 0; + size_t i = 0; + size_t numSessions = 0; + + /* the vararg parameters */ + TPM_AUTHHANDLE sessionHandle[MAX_SESSION_NUM]; + const char *password[MAX_SESSION_NUM]; + unsigned int sessionAttributes[MAX_SESSION_NUM]; + + /* structures filled in */ + TPMS_AUTH12_COMMAND authCommand[MAX_SESSION_NUM]; + TPMS_AUTH12_RESPONSE authResponse[MAX_SESSION_NUM]; + + /* pointer to the above structures as used */ + TPMS_AUTH12_COMMAND *authC[MAX_SESSION_NUM]; + TPMS_AUTH12_RESPONSE *authR[MAX_SESSION_NUM]; + + /* TSS sessions */ + TSS_HMAC12_CONTEXT *session[MAX_SESSION_NUM]; + + in = in; + ap = ap; + + /* Step 1: initialization */ + if (tssVverbose) printf("TSS_Execute12_valist: Step 1: initialization\n"); + for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) ; i++) { + authC[i] = NULL; /* array of TPMS_AUTH12_COMMAND structures, NULL for + TSS_SetCmdAuths */ + authR[i] = NULL; /* array of TPMS_AUTH12_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 2: gather the command authorizations */ + for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) ; i++) { + sessionHandle[i] = va_arg(ap, TPM_AUTHHANDLE); /* 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_Execute12_valist: Step 2: authorization %u\n", + (unsigned int)i); + if (tssVverbose) printf("TSS_Execute12_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]; + + /* initialize a TSS HMAC session */ + if (rc == 0) { + rc = TSS_HmacSession12_GetContext(&session[i]); + } + /* load the session created by either OIAP or OSAP */ + if (rc == 0) { + rc = TSS_HmacSession12_LoadSession(tssContext, session[i], sessionHandle[i]); + } + if (rc == 0) { + if (session[i]->entityValue == TPM_RH_NULL) { /* if OIAP, use password */ + if (password[i] != NULL) { /* if a password was specified, hash it */ + /* hash the password, algorithm set to SHA-1 at initialization */ + rc = TSS_Hash_Generate(&session[i]->hmacKey, + strlen(password[i]), (unsigned char *)password[i], + 0, NULL); + } + /* TPM 1.2 convention seems to use all zeros as a well known auth */ + else { + memset((uint8_t *)&session[i]->hmacKey.digest, 0, SHA1_DIGEST_SIZE); + } + } + else { /* use shared secret from OSAP setup */ + memcpy((uint8_t *)&session[i]->hmacKey.digest, + (uint8_t *)&session[i]->sharedSecret.digest, SHA1_DIGEST_SIZE); + } + } + } + else { + numSessions = i; /* record the number of auth sessions */ + break; + } + } + /* Step 3: Roll nonceOdd, save in the session context for the response */ + for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) { + if (tssVverbose) + printf("TSS_Execute12_valist: Step 3: nonceOdd for session %08x\n", sessionHandle[i]); + if (rc == 0) { + rc = TSS_RandBytes(session[i]->nonceOdd, SHA1_DIGEST_SIZE); + memcpy(authC[i]->nonce, session[i]->nonceOdd, SHA1_DIGEST_SIZE); + } + } + /* Step 4: Calculate the HMAC key */ + /* not needed for TPM 1.2, HMAC key is either hash of password or OSAP shared secret, calculated + in previous step */ + /* Step 5: TPM_ENCAUTH encryption */ + if ((rc == 0) && (numSessions > 0)) { + if (tssVverbose) printf("TSS_Execute12_valist: Step 5: command ADIP encrypt\n"); + rc = TSS_Command_Decrypt(tssContext->tssAuthContext, + session, + sessionHandle); + } + /* Step 6: for each HMAC session, calculate cpHash, calculate the HMAC, and set it in + TPMS_AUTH12_COMMAND */ + if (rc == 0) { + if (tssVverbose) printf("TSS_Execute12_valist: Step 6: calculate HMACs\n"); + rc = TSS_HmacSession12_SetHMAC(tssContext->tssAuthContext, /* TSS auth context */ + numSessions, + session, /* TSS session contexts */ + authC, /* output: command authorizations */ + sessionHandle, /* list of session handles for the command */ + sessionAttributes /* attributes for this command */ + ); + } + /* Step 7: set the command authorizations in the TSS command stream */ + if (rc == 0) { + if (tssVverbose) printf("TSS_Execute12_valist: Step 7: set command authorizations\n"); + rc = TSS_SetCmdAuths12(tssContext->tssAuthContext, + numSessions, + authC); + } + /* Step 8: process the command. Normally returns the TPM response code. */ + if (rc == 0) { + if (tssVverbose) printf("TSS_Execute12_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_Execute12_valist: Step 9: get response authorizations\n"); + rc = TSS_GetRspAuths12(tssContext->tssAuthContext, + numSessions, + authR); + } + /* Step 10: process the response authorizations, validate the HMAC */ + if (rc == 0) { + if (tssVverbose) printf("TSS_Execute12_valist: Step 10: verify HMAC\n"); +#if 0 + for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) { + rc = TSS_Command_ChangeAuthProcessor(tssContext, session[i], i, in); + } +#endif + if (rc == 0) { + rc = TSS_HmacSession12_Verify(tssContext->tssAuthContext, /* authorization + context */ + numSessions, + session, /* TSS session context */ + authR); /* input: response authorization */ + } + } + /* Step 12: process the response continue flag */ + for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) { + if (tssVverbose) printf("TSS_Execute12_valist: Step 12: process continue flag %08x\n", + sessionHandle[i]); + rc = TSS_HmacSession12_Continue(tssContext, session[i], authR[i]); + } + /* cleanup */ + for (i = 0 ; i < MAX_SESSION_NUM ; i++) { + TSS_HmacSession12_FreeContext(session[i]); + } + return rc; +} + +/* + HMAC Session +*/ + +/* TSS_HmacSession12_GetContext() allocates and initializes a TSS_HMAC12_CONTEXT structure */ + +static TPM_RC TSS_HmacSession12_GetContext(TSS_HMAC12_CONTEXT **session) +{ + TPM_RC rc = 0; + + if (rc == 0) { + rc = TSS_Malloc((uint8_t **)session, sizeof(TSS_HMAC12_CONTEXT)); + } + if (rc == 0) { + TSS_HmacSession12_InitContext(*session); + } + return rc; +} + +/* TSS_HmacSession12_InitContext() initializes a TSS_HMAC12_CONTEXT structure */ + +static void TSS_HmacSession12_InitContext(TSS_HMAC12_CONTEXT *session) +{ + session->authHandle = TPM_RH_NULL; + memset(session->nonceEven, 0, SHA1_DIGEST_SIZE); + memset(session->nonceEvenOSAP, 0, SHA1_DIGEST_SIZE); + memset(&session->sharedSecret.digest, 0, SHA1_DIGEST_SIZE); + memset(session->nonceOdd, 0, SHA1_DIGEST_SIZE); + memset(session->nonceOddOSAP, 0, SHA1_DIGEST_SIZE); + session->hmacKey.hashAlg = TPM_ALG_SHA1; + memset((uint8_t *)&session->hmacKey.digest, 0, SHA1_DIGEST_SIZE); + return; +} + +/* TSS_HmacSession12_FreeContext() initializes (to erase secrets) and frees a TSS_HMAC12_CONTEXT + structure */ + +static void TSS_HmacSession12_FreeContext(TSS_HMAC12_CONTEXT *session) +{ + if (session != NULL) { + TSS_HmacSession12_InitContext(session); + free(session); + } + return; +} + +/* TSS_HmacSession12_SaveSession() marshals, optionally encrypts, and saves a TSS_HMAC12_CONTEXT + structure */ + +static TPM_RC TSS_HmacSession12_SaveSession(TSS_CONTEXT *tssContext, + TSS_HMAC12_CONTEXT *session) +{ + TPM_RC rc = 0; + uint8_t *buffer = NULL; /* marshaled TSS_HMAC12_CONTEXT */ + uint16_t written = 0; + char sessionFilename[TPM_DATA_DIR_PATH_LENGTH]; + uint8_t *outBuffer = NULL; + uint32_t outLength; + + if (tssVverbose) printf("TSS_HmacSession12_SaveSession: handle %08x\n", session->authHandle); + if (rc == 0) { + rc = TSS_Structure_Marshal(&buffer, /* freed @1 */ + &written, + session, + (MarshalFunction_t)TSS_HmacSession12_Marshal); + } + if (rc == 0) { + /* 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 { + outBuffer = buffer; + outLength = written; + } + } + /* 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->authHandle); + } + if (rc == 0) { + rc = TSS_File_WriteBinaryFile(outBuffer, + outLength, + sessionFilename); + } + if (tssContext->tssEncryptSessions) { + free(outBuffer); /* @2 */ + } + free(buffer); /* @1 */ + return rc; +} + +/* TSS_HmacSession12_LoadSession() loads and decrypts an HMAC existing session saved by: + + OIAP and OSAP + an update after a TPM response +*/ + +static TPM_RC TSS_HmacSession12_LoadSession(TSS_CONTEXT *tssContext, + TSS_HMAC12_CONTEXT *session, + TPM_AUTHHANDLE authHandle) +{ + TPM_RC rc = 0; + uint8_t *buffer = NULL; + uint8_t *buffer1 = NULL; + size_t length = 0; + char sessionFilename[TPM_DATA_DIR_PATH_LENGTH]; + unsigned char *inData = NULL; /* output */ + uint32_t inLength; /* output */ + + if (tssVverbose) printf("TSS_HmacSession12_LoadSession: handle %08x\n", authHandle); + /* 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, authHandle); + rc = TSS_File_ReadBinaryFile(&buffer, /* freed @1 */ + &length, + sessionFilename); + } + if (rc == 0) { + /* 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 { + inData = buffer; + inLength = length; + } + } + if (rc == 0) { + uint32_t ilength = inLength; + buffer1 = inData; + rc = TSS_HmacSession12_Unmarshal(session, &buffer1, &ilength); + } + if (tssContext->tssEncryptSessions) { + free(inData); /* @2 */ + } + free(buffer); /* @1 */ + return rc; +} + +/* TSS_HmacSession12_DeleteSession() deletes the file corresponding to the HMAC session */ + +static TPM_RC TSS_HmacSession12_DeleteSession(TSS_CONTEXT *tssContext, + TPM_AUTHHANDLE handle) +{ + TPM_RC rc = 0; + char filename[TPM_DATA_DIR_PATH_LENGTH]; + + /* delete the Name */ + if (rc == 0) { + sprintf(filename, "%s/h%08x.bin", tssContext->tssDataDirectory, handle); + if (tssVverbose) printf("TSS_HmacSession12_DeleteSession: delete session file %s\n", filename); + rc = TSS_File_DeleteFile(filename); + } + return rc; +} + +/* TSS_HmacSession12_Marshal() serializes a TSS_HMAC12_CONTEXT + */ + +static TPM_RC TSS_HmacSession12_Marshal(TSS_HMAC12_CONTEXT *source, + uint16_t *written, + uint8_t **buffer, + uint32_t *size) +{ + TPM_RC rc = 0; + + if (rc == 0) { + rc = TSS_UINT32_Marshalu(&source->authHandle, written, buffer, size); + } + if (rc == 0) { + rc = TSS_Array_Marshalu(source->nonceEven, SHA1_DIGEST_SIZE, written, buffer, size); + } + if (rc == 0) { + rc = TSS_Array_Marshalu(source->nonceEvenOSAP, SHA1_DIGEST_SIZE, written, buffer, size); + } + if (rc == 0) { + rc = TSS_Array_Marshalu((uint8_t *)&source->sharedSecret.digest, SHA1_DIGEST_SIZE, written, buffer, size); + } + if (rc == 0) { + rc = TSS_UINT16_Marshalu(&source->entityType, written, buffer, size); + } + if (rc == 0) { + rc = TSS_UINT32_Marshalu(&source->entityValue, written, buffer, size); + } + return rc; +} + +/* TSS_HmacSession12_Unmarshal() deserializes a TSS_HMAC12_CONTEXT */ + +static TPM_RC TSS_HmacSession12_Unmarshal(TSS_HMAC12_CONTEXT *target, + uint8_t **buffer, uint32_t *size) +{ + TPM_RC rc = 0; + + if (rc == 0) { + rc = TSS_UINT32_Unmarshalu(&target->authHandle, buffer, size); + } + if (rc == 0) { + rc = TSS_Array_Unmarshalu(target->nonceEven, SHA1_DIGEST_SIZE, buffer, size); + } + if (rc == 0) { + rc = TSS_Array_Unmarshalu(target->nonceEvenOSAP, SHA1_DIGEST_SIZE, buffer, size); + } + if (rc == 0) { + rc = TSS_Array_Unmarshalu((uint8_t *)&target->sharedSecret.digest, SHA1_DIGEST_SIZE, buffer, size); + } + if (rc == 0) { + rc = TSS_UINT16_Unmarshalu(&target->entityType, buffer, size); + } + if (rc == 0) { + rc = TSS_UINT32_Unmarshalu(&target->entityValue, buffer, size); + } + return rc; +} + +/* TSS_HmacSession12_SetHMAC() is used for a command. It sets all the values in one + TPMS_AUTH12_COMMAND, ready for marshaling into the command packet. + + - gets cpBuffer + - generates cpHash + - generates the HMAC + - copies the result into authCommand + + The HMAC key is already in the session structure. +*/ + +static TPM_RC TSS_HmacSession12_SetHMAC(TSS_AUTH_CONTEXT *tssAuthContext, /* authorization context */ + size_t numSessions, + TSS_HMAC12_CONTEXT *session[], + + TPMS_AUTH12_COMMAND *authCommand[], /* output: command + authorization */ + TPM_AUTHHANDLE sessionHandle[], /* session handles in + command */ + unsigned int sessionAttributes[]) /* attributes for this + command */ +{ + TPM_RC rc = 0; + unsigned int i = 0; + TPMT_HA cpHash; + TPMT_HA hmac; + + /* Step 6: calculate cpHash. For TPM 1.2, it is the same for all sessions. Name is not used */ + if ((rc == 0) && (numSessions > 0)) { + uint32_t cpBufferSize; + uint8_t *cpBuffer; + TPM_CC commandCode = TSS_GetCommandCode(tssAuthContext); + TPM_CC commandCodeNbo = htonl(commandCode); + + rc = TSS_GetCpBuffer(tssAuthContext, &cpBufferSize, &cpBuffer); + if (tssVverbose) TSS_PrintAll("TSS_HmacSession12_SetHMAC: cpBuffer", + cpBuffer, cpBufferSize); + /* Create cpHash - digest of inputs above the double line. */ + cpHash.hashAlg = TPM_ALG_SHA1; + rc = TSS_Hash_Generate(&cpHash, + sizeof(TPM_CC), &commandCodeNbo, /* 1S */ + cpBufferSize, cpBuffer, /* 2S - ... */ + 0, NULL); + if (rc == 0) { + if (tssVverbose) TSS_PrintAll("TSS_HmacSession12_SetHMAC: cpHash", + (uint8_t *)&cpHash.digest, + SHA1_DIGEST_SIZE); + } + } + for (i = 0 ; (rc == 0) && (i < numSessions) ; i++) { + uint8_t sessionAttr8; + TPM2B_KEY hmacKey; + + if (tssVverbose) printf("TSS_HmacSession12_SetHMAC: Step 6 session %08x\n", + sessionHandle[i]); + /* sessionHandle */ + authCommand[i]->sessionHandle = session[i]->authHandle; + /* attributes come from command */ + sessionAttr8 = (uint8_t)sessionAttributes[i]; + authCommand[i]->sessionAttributes.val = sessionAttr8; + + if (tssVverbose) printf("TSS_HmacSession12_SetHMAC: calculate HMAC\n"); + /* auth HMAC = HMAC(cpHash | nonceEven, nonceOdd, attributes */ + + /* convert the TPMT_HA hmacKey to a TPM2B_KEY hmac key */ + if (rc == 0) { + rc = TSS_TPM2B_Create(&hmacKey.b, + (uint8_t *)&session[i]->hmacKey.digest, SHA1_DIGEST_SIZE, + sizeof(hmacKey.t.buffer)); + } + if (rc == 0) { + hmac.hashAlg = TPM_ALG_SHA1; + rc = TSS_HMAC_Generate(&hmac, /* output hmac */ + &hmacKey, /* input key */ + SHA1_DIGEST_SIZE, (uint8_t *)&cpHash.digest, + SHA1_DIGEST_SIZE, session[i]->nonceEven, + SHA1_DIGEST_SIZE, session[i]->nonceOdd, + sizeof(uint8_t), &sessionAttr8, + 0, NULL); + } + if (rc == 0) { + if (tssVverbose) { + TSS_PrintAll("TSS_HmacSession12_SetHMAC: HMAC key", + (uint8_t *)&session[i]->hmacKey.digest, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_HmacSession12_SetHMAC: cpHash", + (uint8_t *)&cpHash.digest, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_HmacSession12_Set: nonceEven", + session[i]->nonceEven, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_HmacSession12_SetHMAC: nonceOdd", + session[i]->nonceOdd, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_HmacSession12_SetHMAC: sessionAttributes", + &sessionAttr8, sizeof(uint8_t)); + TSS_PrintAll("TSS_HmacSession12_SetHMAC: HMAC", + (uint8_t *)&hmac.digest, SHA1_DIGEST_SIZE); + } + } + /* copy HMAC into authCommand TPM2B_AUTH hmac */ + if (rc == 0) { + memcpy(authCommand[i]->hmac, (uint8_t *)&hmac.digest, SHA1_DIGEST_SIZE); + } + } + return rc; +} + +/* TSS_HmacSession12_Verify() is used for a response. It uses the values in TPMS_AUTH12_RESPONSE to + validate the response HMAC */ + +static TPM_RC TSS_HmacSession12_Verify(TSS_AUTH_CONTEXT *tssAuthContext, /* authorization + context */ + size_t numSessions, + TSS_HMAC12_CONTEXT *session[], /* TSS session + context */ + TPMS_AUTH12_RESPONSE *authResponse[]) /* input: response + authorization */ +{ + TPM_RC rc = 0; + unsigned int i = 0; + TPMT_HA rpHash; + TPMT_HA actualHmac; + + /* Step 10: calculate rpHash. For TPM 1.2, it is the same for all sessions. Name is not used */ + if ((rc == 0) && (numSessions > 0)) { + uint32_t rpBufferSize; + uint8_t *rpBuffer; + TPM_CC commandCode = TSS_GetCommandCode(tssAuthContext); + TPM_CC commandCodeNbo = htonl(commandCode); + + rc = TSS_GetRpBuffer12(tssAuthContext, &rpBufferSize, &rpBuffer, numSessions); + if (tssVverbose) TSS_PrintAll("TSS_HmacSession12_Verify: rpBuffer", + rpBuffer, rpBufferSize); + /* Create rpHash - digest of inputs above the double line. */ + rpHash.hashAlg = TPM_ALG_SHA1; + rc = TSS_Hash_Generate(&rpHash, + sizeof(TPM_RC), &rc, /* 1S */ + sizeof(TPM_CC), &commandCodeNbo, /* 2S */ + rpBufferSize, rpBuffer, /* 3S - ... */ + 0, NULL); + if (rc == 0) { + if (tssVverbose) TSS_PrintAll("TSS_HmacSession12_Verify: rpHash", + (uint8_t *)&rpHash.digest, + SHA1_DIGEST_SIZE); + } + } + for (i = 0 ; (rc == 0) && (i < numSessions) ; i++) { + uint8_t sessionAttr8; + TPM2B_KEY hmacKey; + if (tssVverbose) printf("TSS_HmacSession12_Verify: Step 10 session %u handle %08x\n", + i, session[i]->authHandle); + /* attributes come from response */ + sessionAttr8 = (uint8_t)authResponse[i]->sessionAttributes.val; + /* save nonceEven in the session context */ + if (rc == 0) { + memcpy(session[i]->nonceEven, authResponse[i]->nonce, SHA1_DIGEST_SIZE); + } + if (rc == 0) { + memcpy((uint8_t *)&actualHmac.digest, &authResponse[i]->hmac, + SHA1_DIGEST_SIZE); + } + /* convert the TPMT_HA hmacKey to a TPM2B_KEY hmac key */ + if (rc == 0) { + rc = TSS_TPM2B_Create(&hmacKey.b, + (uint8_t *)&session[i]->hmacKey.digest, SHA1_DIGEST_SIZE, + sizeof(hmacKey.t.buffer)); + } + /* verify the HMAC */ + if (rc == 0) { + if (tssVverbose) { + TSS_PrintAll("TSS_HmacSession12_Verify: HMAC key", + (uint8_t *)&session[i]->hmacKey.digest, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_HmacSession12_Verify: rpHash", + (uint8_t *)&rpHash.digest, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_HmacSession12_Verify: nonceEven", + session[i]->nonceEven, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_HmacSession12_Verify: nonceOdd", + session[i]->nonceOdd, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_HmacSession12_Verify: sessionAttributes", + &sessionAttr8, sizeof(uint8_t)); + TSS_PrintAll("TSS_HmacSession12_Verify: response HMAC", + (uint8_t *)&authResponse[i]->hmac, SHA1_DIGEST_SIZE); + } + actualHmac.hashAlg = TPM_ALG_SHA1; + rc = TSS_HMAC_Verify(&actualHmac, /* input response hmac */ + &hmacKey, /* input HMAC key */ + SHA1_DIGEST_SIZE, + /* rpHash */ + SHA1_DIGEST_SIZE, (uint8_t *)&rpHash.digest, + /* new is nonceEven */ + SHA1_DIGEST_SIZE, session[i]->nonceEven, + /* old is nonceOdd */ + SHA1_DIGEST_SIZE, session[i]->nonceOdd, + /* 1 byte, no endian conversion */ + sizeof(uint8_t), &authResponse[i]->sessionAttributes.val, + 0, NULL); + if (rc == 0) { + if (tssVverbose) printf("TSS_HmacSession12_Verify: session %u verified\n", i); + } + else { + if (tssVerbose) TSS_PrintAll("TSS_HmacSession12_Verify: HMAC verify failed, actual", + (uint8_t *)&actualHmac.digest, SHA1_DIGEST_SIZE); + } + } + } + return rc; +} + +/* TSS_HmacSession12_Continue() handles the response continueSession flag. It either saves the + updated session or deletes the session state. */ + +static TPM_RC TSS_HmacSession12_Continue(TSS_CONTEXT *tssContext, + TSS_HMAC12_CONTEXT *session, + TPMS_AUTH12_RESPONSE *authR) +{ + TPM_RC rc = 0; + + if (rc == 0) { + /* if continue set */ + if (authR->sessionAttributes.val & TPMA_SESSION_CONTINUESESSION) { + /* save the session */ + rc = TSS_HmacSession12_SaveSession(tssContext, session); + } + else { /* continue clear */ + /* delete the session state */ + rc = TSS_HmacSession12_DeleteSession(tssContext, session->authHandle); + } + } + return rc; +} + +/* TSS_Command_Decrypt() does the command ADIP encryption (the TPM does the decrypt). + + It does common error checking, then calls algorithm specific functions. Currently, only XOR is + implemented. + +*/ + +static TPM_RC TSS_Command_Decrypt(TSS_AUTH_CONTEXT *tssAuthContext, + TSS_HMAC12_CONTEXT *session[], + TPM_AUTHHANDLE sessionHandle[]) +{ + TPM_RC rc = 0; + uint16_t sessionNumber; + uint8_t *encAuth0; + uint8_t *encAuth1; + TSS_HMAC12_CONTEXT *decryptSession; + int done = FALSE; + int isXor; /* true for XOR, false for AES */ + + /* which session is the OSAP session used for the encryption */ + if (rc == 0) { + rc = TSS_GetSessionNumber(tssAuthContext, + &sessionNumber); + } + if (rc == 0) { + if (sessionNumber == 0xffff) { + done = TRUE; + } + } + /* get the session used for the encryption */ + if ((rc == 0) && !done) { + decryptSession = session[sessionNumber]; + isXor = (session[sessionNumber]->entityType & 0xff00) == (TPM_ET_XOR << 8); + if (!isXor) { + if (tssVerbose) printf("TSS_Command_Decrypt: bad entityType %04x for session %08x\n", + session[sessionNumber]->entityType, + sessionHandle[sessionNumber]); + rc = TSS_RC_BAD_DECRYPT_ALGORITHM; + } + else { + if (tssVverbose) printf("TSS_Command_Decrypt: using session %08x\n", + sessionHandle[sessionNumber]); + } + + } + /* get pointers to the parameters to be encrypted */ + if ((rc == 0) && !done) { + rc = TSS_GetEncAuths(tssAuthContext, + &encAuth0, + &encAuth1); + } + if ((rc == 0) && !done) { + if (tssVverbose) printf("TSS_Command_Decrypt: TPM_ENC_AUTH's at %p, %p\n", + encAuth0, encAuth1); + } + if ((rc == 0) && !done && (encAuth0 != NULL)) { + rc = TSS_Command_DecryptXor(tssAuthContext, decryptSession, encAuth0, 0); + } + if ((rc == 0) && !done && (encAuth1 != NULL)) { + rc = TSS_Command_DecryptXor(tssAuthContext, decryptSession, encAuth1, 1); + } + return rc; +} + +/* + pad = sha1(shared secret || lastnonceeven) + enc = xor (auth, pad) +*/ + +static TPM_RC TSS_Command_DecryptXor(TSS_AUTH_CONTEXT *tssAuthContext, + TSS_HMAC12_CONTEXT *session, + uint8_t *encAuth, + int parameterNumber) +{ + TPM_RC rc = 0; + TPMT_HA padHash; + unsigned int i; + + tssAuthContext = tssAuthContext; + /* generate the pad */ + if (rc == 0) { + padHash.hashAlg = TPM_ALG_SHA1; + if (parameterNumber == 0) { + rc = TSS_Hash_Generate(&padHash, + SHA1_DIGEST_SIZE, (uint8_t *)&session->sharedSecret.digest, + SHA1_DIGEST_SIZE, session->nonceEven, + 0, NULL); + } + else { + rc = TSS_Hash_Generate(&padHash, + SHA1_DIGEST_SIZE, (uint8_t *)&session->sharedSecret.digest, + SHA1_DIGEST_SIZE, session->nonceOdd, + 0, NULL); + } + } + if (rc == 0) { + if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: pad", + (uint8_t *)&padHash.digest, + SHA1_DIGEST_SIZE); + if (tssVverbose) printf("TSS_Command_DecryptXor: parameter %u\n", + parameterNumber); + if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: plaintext", + encAuth, SHA1_DIGEST_SIZE); + } + /* do the XOR */ + if (rc == 0) { + for (i = 0 ; i < SHA1_DIGEST_SIZE ; i++) { + *(encAuth + i) = *(encAuth + i) ^ padHash.digest.sha1[i]; + } + } + if (rc == 0) { + if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: ciphertext", + encAuth, SHA1_DIGEST_SIZE); + } + return rc; +} + +/* + Command Pre-Processor +*/ + +static TPM_RC TSS_Command_PreProcessor(TSS_CONTEXT *tssContext, + TPM_CC commandCode, + COMMAND_PARAMETERS *in, + EXTRA12_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; + /* there could also be an entry that is currently NULL, nothing to do */ + if (preProcessFunction == NULL) { + found = FALSE; + } + } + /* call the pre processing function */ + if ((rc == 0) && found) { + rc = preProcessFunction(tssContext, in, extra); + } + return rc; +} + +/* + Command specific pre processing functions +*/ + +static TPM_RC TSS_PR_CreateWrapKey(TSS_CONTEXT *tssContext, + CreateWrapKey_In *in, + void *extra) +{ + TPM_RC rc = 0; + in = in; + extra = extra; + if (tssVverbose) printf("TSS_PR_CreateWrapKey\n"); + /* TPM_ENCAUTH is predictable distance from start */ + if (rc == 0) { + rc = TSS_SetEncAuthOffset0(tssContext->tssAuthContext, + sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT) + + sizeof(TPM_KEY_HANDLE)); + } + if (rc == 0) { + rc = TSS_SetEncAuthOffset1(tssContext->tssAuthContext, + sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT) + + sizeof(TPM_KEY_HANDLE) + + SHA1_DIGEST_SIZE); + } + if (rc == 0) { + rc = TSS_SetSessionNumber(tssContext->tssAuthContext, 0); + } + if (rc == 0) { + if (tssVverbose) printf("TSS_PR_CreateWrapKey: ADIP offset at %lu and %lu\n", + (unsigned long)(sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT) + + sizeof(TPM_KEY_HANDLE)), + (unsigned long)(sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT) + + sizeof(TPM_KEY_HANDLE) + + SHA1_DIGEST_SIZE)); + } + return rc; +} + +static TPM_RC TSS_PR_MakeIdentity(TSS_CONTEXT *tssContext, + MakeIdentity_In *in, + void *extra) +{ + TPM_RC rc = 0; + in = in; + extra = extra; + if (tssVverbose) printf("TSS_PR_MakeIdentity\n"); + /* TPM_ENCAUTH is predictable distance from start */ + if (rc == 0) { + rc = TSS_SetEncAuthOffset0(tssContext->tssAuthContext, + sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT)); + } + if (rc == 0) { + rc = TSS_SetSessionNumber(tssContext->tssAuthContext, 1); + } + if (rc == 0) { + if (tssVverbose) printf("TSS_PR_MakeIdentity: ADIP offset at %lu\n", + (unsigned long)(sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT))); + } + return rc; +} + +static TPM_RC TSS_PR_NV_DefineSpace(TSS_CONTEXT *tssContext, + NV_DefineSpace_In *in, + void *extra) +{ + TPM_RC rc = 0; + in = in; + extra = extra; + if (tssVverbose) printf("TSS_PR_NV_DefineSpace\n"); + /* TPM_ENCAUTH is predictable distance from end */ + if (rc == 0) { + rc = TSS_SetEncAuthOffset0(tssContext->tssAuthContext, + -SHA1_DIGEST_SIZE); /* encauth */ + + } + if (rc == 0) { + rc = TSS_SetSessionNumber(tssContext->tssAuthContext, 0); + } + if (rc == 0) { + if (tssVverbose) printf("TSS_PR_NV_DefineSpace: ADIP offset at %d\n", + -SHA1_DIGEST_SIZE); + } + return rc; +} + +static TPM_RC TSS_PR_OSAP(TSS_CONTEXT *tssContext, + OSAP_In *in, + OSAP_Extra *extra) +{ + TPM_RC rc = 0; + tssContext = tssContext; + extra = extra; + + if (tssVverbose) printf("TSS_PR_OSAP\n"); + /* generate nonceOddOSAP */ + if (rc == 0) { + rc = TSS_RandBytes((unsigned char *)in->nonceOddOSAP, SHA1_DIGEST_SIZE); + } + return rc; +} + +#if 0 +static TPM_RC TSS_PR_Seal(TSS_CONTEXT *tssContext, + Seal_in *In, + void *extra) +{ + TPM_RC rc = 0; + in = in; + extra = extra; + if (tssVverbose) printf("TSS_PR_Seal\n"); + /* TPM_ENCAUTH is predictable distance from start */ + if (rc == 0) { + rc = TSS_SetEncAuthOffset0(tssContext->tssAuthContext, + sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT) + + sizeof(TPM_KEY_HANDLE)); + } + if (rc == 0) { + rc = TSS_SetSessionNumber(tssContext->tssAuthContext, 0); + } + if (rc == 0) { + if (tssVverbose) printf("TSS_PR_Seal: ADIP offset at %u\n", + sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT) + + sizeof(TPM_KEY_HANDLE)); + } + return rc; +} + +static TPM_RC TSS_PR_Sealx(TSS_CONTEXT *tssContext, + Sealx_in *In, + void *extra) +{ + TPM_RC rc = 0; + in = in; + extra = extra; + if (tssVverbose) printf("TSS_PR_Sealx\n"); + /* TPM_ENCAUTH is predictable distance from start */ + if (rc == 0) { + rc = TSS_SetEncAuthOffset0(tssContext->tssAuthContext, + sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT) + + sizeof(TPM_KEY_HANDLE)); + rc = TSS_SetSessionNumber(tssContext->tssAuthContext, 0); + } + if (rc == 0) { + if (tssVverbose) printf("TSS_PR_Seal: ADIP offset at %u\n", + sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_RESULT) + + sizeof(TPM_KEY_HANDLE)); + } + return rc; +} + +#endif + +/* + 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, + EXTRA12_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 +*/ + +static TPM_RC TSS_PO_FlushSpecific(TSS_CONTEXT *tssContext, + FlushSpecific_In *in, + void *out, + void *extra) +{ + TPM_RC rc = 0; + out = out; + extra = extra; + if (tssVverbose) printf("TSS_PO_FlushSpecific: handle %08x\n", in->handle); + if ((rc == 0) && (in->resourceType == TPM_RT_AUTH)) { + rc = TSS_HmacSession12_DeleteSession(tssContext, in->handle); + } + return rc; +} + +static TPM_RC TSS_PO_OIAP(TSS_CONTEXT *tssContext, + void *in, + OIAP_Out *out, + void *extra) +{ + TPM_RC rc = 0; + TSS_HMAC12_CONTEXT *session = NULL; + + in = in; + extra = extra; + /* allocate a TSS_HMAC_CONTEXT session context */ + if (rc == 0) { + rc = TSS_HmacSession12_GetContext(&session); + } + if (rc == 0) { + /* store OIAP ordinal outputs */ + session->authHandle = out->authHandle; + session->entityValue = TPM_RH_NULL; /* distinguish OIAP form OSAP */ + memcpy(session->nonceEven, out->nonceEven, SHA1_DIGEST_SIZE); + } + /* persist the session */ + if (rc == 0) { + rc = TSS_HmacSession12_SaveSession(tssContext, session); + } + TSS_HmacSession12_FreeContext(session); + return rc; +} + +static TPM_RC TSS_PO_OSAP(TSS_CONTEXT *tssContext, + OSAP_In *in, + OSAP_Out *out, + OSAP_Extra *extra) +{ + TPM_RC rc = 0; + TSS_HMAC12_CONTEXT *session = NULL; + TPM2B_KEY hmacKey; + TPMT_HA usageAuth; /* digest of the OSAP password */ + + /* allocate a TSS_HMAC_CONTEXT session context */ + if (rc == 0) { + rc = TSS_HmacSession12_GetContext(&session); + } + if (rc == 0) { + session->entityType = in->entityType; + session->entityValue = in->entityValue; /* mark OSAP session */ + memcpy(session->nonceOddOSAP, in->nonceOddOSAP, SHA1_DIGEST_SIZE); + /* store OSAP ordinal outputs */ + session->authHandle = out->authHandle; + memcpy(session->nonceEven, out->nonceEven, SHA1_DIGEST_SIZE); + memcpy(session->nonceEvenOSAP, out->nonceEvenOSAP, SHA1_DIGEST_SIZE); + } + /* SHA1 hash the usageAuth */ + if (rc == 0) { + if (extra->usagePassword != NULL) { /* if a password was specified, hash it */ + usageAuth.hashAlg = TPM_ALG_SHA1; + rc = TSS_Hash_Generate(&usageAuth, + strlen(extra->usagePassword), + (unsigned char *)extra->usagePassword, + 0, NULL); + } + /* TPM 1.2 convention seems to use all zeros as a well known auth */ + else { + memset((uint8_t *)&usageAuth.digest, 0, SHA1_DIGEST_SIZE); + } + } + /* convert the TPMT_HA hash to a TPM2B_KEY hmac key */ + if (rc == 0) { + rc = TSS_TPM2B_Create(&hmacKey.b, (uint8_t *)&usageAuth.digest, SHA1_DIGEST_SIZE, + sizeof(hmacKey.t.buffer)); + } + /* calculate the sharedSecret */ + if (rc == 0) { + session->sharedSecret.hashAlg = TPM_ALG_SHA1; + rc = TSS_HMAC_Generate(&session->sharedSecret, /* output hmac */ + &hmacKey, /* input key */ + SHA1_DIGEST_SIZE, session->nonceEvenOSAP, + SHA1_DIGEST_SIZE, in->nonceOddOSAP, + 0, NULL); + } + if ((rc == 0) && tssVverbose) { + printf("TSS_PO_OSAP: out->authHandle %08x\n",out->authHandle); + printf("TSS_PO_OSAP: in->entityType %08x\n", in->entityType); + printf("TSS_PO_OSAP: in->entityValue %08x\n", in->entityValue); + TSS_PrintAll("TSS_PO_OSAP: session->nonceEven", + session->nonceEven, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_PO_OSAP: session->nonceEvenOSAP", + session->nonceEvenOSAP, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_PO_OSAP: session->nonceOddOSAP", + session->nonceOddOSAP, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_PO_OSAP: usageAuth", + (uint8_t *)&usageAuth.digest, SHA1_DIGEST_SIZE); + TSS_PrintAll("TSS_PO_OSAP: sharedSecret", + (uint8_t *)&session->sharedSecret.digest, SHA1_DIGEST_SIZE); + } + /* persist the session */ + if (rc == 0) { + rc = TSS_HmacSession12_SaveSession(tssContext, session); + } + TSS_HmacSession12_FreeContext(session); + return rc; +} |