aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tss12.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tss12.c')
-rw-r--r--roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tss12.c1423
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;
+}