blob: 623193362c2f79bfb46da9745e5ff0331c92f37f [file] [log] [blame]
/********************************************************************************/
/* */
/* 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;
}