mirror of https://github.com/wolfSSL/wolfTPM.git
Fix parameter encryption for NVRAM commands
* Make sure hmac buffer space is reserved * Add name computation for NV handles, modify TPM2_GetName * Make TPM2_GetName handle multiple TPM Handle types * Add wolfTPM2_SetNameHandle for passing handle name to parameter encryption * Compute fresh NV Index Name during NVWrite with updated nvPublic information * Compute fresh NV Index Name during NVRead, the same way NVWrite needs it The NV_WRITTEN flag is being set, when there are consequtive reads, which forces the hash to update. In order for this to take place, we need to read the current(fresh) nvPublic information using TPM2_NV_ReadPublic. * Add wolfTPM2_UnsetAuth to clear past authorization sessions when not needed A way to clear auth sessions that are no longer needed was missing. For example, after a TPM2_NVRead which uses two auth session slots, there was no way for the user to clear the second slot afterwards. The only possibility before was to overwrite with invalid values. This way a TPM2_NVUndefineSpace would fail right after TPM2_NVRead, just because there was an auth session not prevously cleared. This can be handled either by the user manually or the user can use wolfTPM2 wrappers that handle it now automatically using wolfTPM2_UnsetAuth. Signed-off-by: Dimitar Tomov <dimi@wolfssl.com>pull/145/head
parent
df0107605e
commit
87e29005bf
97
src/tpm2.c
97
src/tpm2.c
|
@ -108,7 +108,8 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet,
|
|||
int rc = TPM_RC_SUCCESS;
|
||||
UINT32 authSz;
|
||||
BYTE *param, *encParam = NULL;
|
||||
int paramSz, encParamSz = 0, authPos, i;
|
||||
int paramSz, encParamSz = 0;
|
||||
int i, authPos, handlePos;
|
||||
|
||||
/* Skip the header and handles area */
|
||||
packet->pos = TPM2_HEADER_SIZE + (info->inHandleCnt * sizeof(TPM_HANDLE));
|
||||
|
@ -187,9 +188,16 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet,
|
|||
}
|
||||
|
||||
#ifndef WOLFTPM2_NO_WOLFCRYPT
|
||||
rc = TPM2_GetName(ctx, info->inHandleCnt, 0, &name1);
|
||||
rc |= TPM2_GetName(ctx, info->inHandleCnt, 1, &name2);
|
||||
rc |= TPM2_GetName(ctx, info->inHandleCnt, 2, &name3);
|
||||
UINT32 handleValue;
|
||||
|
||||
handlePos = packet->pos;
|
||||
packet->pos = TPM2_HEADER_SIZE; /* Handles are right after header */
|
||||
TPM2_Packet_ParseU32(packet, &handleValue);
|
||||
packet->pos = handlePos;
|
||||
|
||||
rc = TPM2_GetName(ctx, handleValue, info->inHandleCnt, 0, &name1);
|
||||
rc |= TPM2_GetName(ctx, handleValue, info->inHandleCnt, 1, &name2);
|
||||
rc |= TPM2_GetName(ctx, handleValue, info->inHandleCnt, 2, &name3);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("Error getting names for cpHash!\n");
|
||||
|
@ -5269,7 +5277,7 @@ int TPM2_GetNonce(byte* nonceBuf, int nonceSz)
|
|||
}
|
||||
|
||||
/* Get name for object/handle */
|
||||
int TPM2_GetName(TPM2_CTX* ctx, int handleCnt, int idx, TPM2B_NAME* name)
|
||||
int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2B_NAME* name)
|
||||
{
|
||||
TPM2_AUTH_SESSION* session;
|
||||
|
||||
|
@ -5279,10 +5287,28 @@ int TPM2_GetName(TPM2_CTX* ctx, int handleCnt, int idx, TPM2B_NAME* name)
|
|||
return TPM_RC_SUCCESS;
|
||||
|
||||
session = &ctx->session[idx];
|
||||
|
||||
#if 0
|
||||
if (session->name.size > 0) {
|
||||
name->size = session->name.size;
|
||||
XMEMCPY(name->name, session->name.name, name->size);
|
||||
}
|
||||
(void)handleValue;
|
||||
#else
|
||||
if ((handleValue >= TRANSIENT_FIRST) ||
|
||||
(handleValue >= NV_INDEX_FIRST && handleValue <= NV_INDEX_LAST)) {
|
||||
if (session->name.size > 0) {
|
||||
name->size = session->name.size;
|
||||
XMEMCPY(name->name, session->name.name, name->size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
handleValue = TPM2_Packet_SwapU32(handleValue);
|
||||
name->size = sizeof(handleValue);
|
||||
XMEMCPY(name->name, (byte*)&handleValue, name->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||
printf("Name %d: %d\n", idx, name->size);
|
||||
TPM2_PrintBin(name->name, name->size);
|
||||
|
@ -5649,6 +5675,67 @@ UINT16 TPM2_GetVendorID(void)
|
|||
return vid;
|
||||
}
|
||||
|
||||
/* Stores nameAlg + the digest of nvPublic in buffer, total size in size */
|
||||
int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size)
|
||||
{
|
||||
int rc;
|
||||
#ifndef WOLFTPM2_NO_WOLFCRYPT
|
||||
int hashSize, nameAlgValue, nameAlgSize;
|
||||
wc_HashAlg hash;
|
||||
enum wc_HashType hashType;
|
||||
byte appending[sizeof(TPMS_NV_PUBLIC)];
|
||||
TPM2B_DIGEST digest;
|
||||
TPM2_Packet packet;
|
||||
|
||||
/* Prepare temporary buffer */
|
||||
packet.buf = appending;
|
||||
packet.pos = 0;
|
||||
packet.size = sizeof(appending);
|
||||
|
||||
/* nvPublic must be in Marshaled state for hashing */
|
||||
TPM2_Packet_AppendU32(&packet, nvPublic->nvIndex);
|
||||
TPM2_Packet_AppendU16(&packet, nvPublic->nameAlg);
|
||||
TPM2_Packet_AppendU32(&packet, nvPublic->attributes);
|
||||
TPM2_Packet_AppendU16(&packet, nvPublic->authPolicy.size);
|
||||
TPM2_Packet_AppendBytes(&packet, nvPublic->authPolicy.buffer,
|
||||
nvPublic->authPolicy.size);
|
||||
TPM2_Packet_AppendU16(&packet, nvPublic->dataSize);
|
||||
|
||||
/* Hashing nvPublic */
|
||||
rc = TPM2_GetHashType(nvPublic->nameAlg);
|
||||
hashType = (enum wc_HashType)rc;
|
||||
rc = wc_HashGetDigestSize(hashType);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
hashSize = rc;
|
||||
|
||||
rc = wc_HashInit(&hash, hashType);
|
||||
if(rc == 0) {
|
||||
rc = wc_HashUpdate(&hash, hashType, packet.buf, packet.pos);
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
rc = wc_HashFinal(&hash, hashType, digest.buffer);
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
nameAlgValue = TPM2_Packet_SwapU16(nvPublic->nameAlg);
|
||||
nameAlgSize = sizeof(nvPublic->nameAlg);
|
||||
XMEMCPY(buffer, (byte*)&nameAlgValue, nameAlgSize);
|
||||
XMEMCPY(&buffer[2], digest.buffer, hashSize);
|
||||
/* account for nameAlg concatenation */
|
||||
*size = hashSize + nameAlgSize;
|
||||
}
|
||||
|
||||
wc_HashFree(&hash, hashType);
|
||||
|
||||
return TPM_RC_SUCCESS;
|
||||
#else
|
||||
return TPM_RC_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
#define LINE_LEN 16
|
||||
void TPM2_PrintBin(const byte* buffer, word32 length)
|
||||
|
|
|
@ -320,7 +320,9 @@ void TPM2_Packet_AppendAuthCmd(TPM2_Packet* packet, TPMS_AUTH_COMMAND* authCmd)
|
|||
if (packet == NULL || authCmd == NULL)
|
||||
return;
|
||||
|
||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||
TPM2_PrintAuth(authCmd);
|
||||
#endif
|
||||
|
||||
/* make sure continueSession is set for TPM_RS_PW */
|
||||
if (authCmd->sessionHandle == TPM_RS_PW &&
|
||||
|
|
106
src/tpm2_wrap.c
106
src/tpm2_wrap.c
|
@ -26,6 +26,11 @@
|
|||
|
||||
/* For some struct to buffer conversions */
|
||||
#include <wolftpm/tpm2_packet.h>
|
||||
#ifndef WOLFTPM2_NO_WOLFCRYPT
|
||||
/* Required in wolfTPM2_CreateAuth() for name computation of NV handles */
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Local Functions */
|
||||
static int wolfTPM2_GetCapabilities_NoDev(WOLFTPM2_CAPS* cap);
|
||||
|
@ -369,6 +374,20 @@ int wolfTPM2_GetCapabilities(WOLFTPM2_DEV* dev, WOLFTPM2_CAPS* cap)
|
|||
return wolfTPM2_GetCapabilities_NoDev(cap);
|
||||
}
|
||||
|
||||
int wolfTPM2_UnsetAuth(WOLFTPM2_DEV* dev, int index)
|
||||
{
|
||||
TPM2_AUTH_SESSION* session;
|
||||
|
||||
if (dev == NULL || index >= MAX_SESSION_NUM) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
session = &dev->session[index];
|
||||
XMEMSET(session, 0, sizeof(TPM2_AUTH_SESSION));
|
||||
|
||||
return TPM2_SetSessionAuth(dev->session);
|
||||
}
|
||||
|
||||
int wolfTPM2_SetAuth(WOLFTPM2_DEV* dev, int index,
|
||||
TPM_HANDLE sessionHandle, const TPM2B_AUTH* auth,
|
||||
TPMA_SESSION sessionAttributes, const TPM2B_NAME* name)
|
||||
|
@ -415,6 +434,24 @@ int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index,
|
|||
return wolfTPM2_SetAuth(dev, index, TPM_RS_PW, auth, 0, name);
|
||||
}
|
||||
|
||||
int wolfTPM2_SetNameHandle(WOLFTPM2_DEV* dev, int index,
|
||||
const WOLFTPM2_HANDLE* handle)
|
||||
{
|
||||
const TPM2B_NAME* name = NULL;
|
||||
TPM2_AUTH_SESSION* session;
|
||||
|
||||
if (dev == NULL || handle == NULL || index >= MAX_SESSION_NUM) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
name = &handle->name;
|
||||
session = &dev->session[index];
|
||||
|
||||
session->name.size = name->size;
|
||||
XMEMCPY(session->name.name, name->name, session->name.size);
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
|
||||
int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index,
|
||||
const WOLFTPM2_SESSION* tpmSession, TPMA_SESSION sessionAttributes)
|
||||
{
|
||||
|
@ -446,6 +483,15 @@ int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index,
|
|||
session->nonceTPM.size = tpmSession->nonceTPM.size;
|
||||
XMEMCPY(session->nonceTPM.buffer, tpmSession->nonceTPM.buffer,
|
||||
session->nonceTPM.size);
|
||||
|
||||
/* Parameter Encryption session will have an hmac added later.
|
||||
* Reserve space, the same way it was done for nonceCaller above.
|
||||
*/
|
||||
if (session->sessionHandle != TPM_RS_PW &&
|
||||
((session->sessionAttributes & TPMA_SESSION_encrypt) ||
|
||||
(session->sessionAttributes & TPMA_SESSION_decrypt))) {
|
||||
session->auth.size = TPM2_GetHashDigestSize(session->authHash);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -2524,6 +2570,7 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent,
|
|||
{
|
||||
int rc;
|
||||
NV_DefineSpace_In in;
|
||||
TPM2B_NAME name;
|
||||
|
||||
if (dev == NULL || nv == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
@ -2533,6 +2580,7 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent,
|
|||
wolfTPM2_SetAuthHandle(dev, 0, parent);
|
||||
}
|
||||
|
||||
XMEMSET(&name, 0, sizeof(name));
|
||||
XMEMSET(&in, 0, sizeof(in));
|
||||
in.authHandle = parent->hndl;
|
||||
if (auth && authSz > 0) {
|
||||
|
@ -2560,9 +2608,15 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* Compute NV Index name in case of parameter encryption */
|
||||
rc = TPM2_HashNvPublic(&in.publicInfo.nvPublic, name.name, &name.size);
|
||||
|
||||
/* return new NV handle */
|
||||
XMEMSET(nv, 0, sizeof(*nv));
|
||||
nv->handle.hndl = (TPM_HANDLE)nvIndex;
|
||||
nv->handle.auth = in.auth;
|
||||
nv->handle.name.size = name.size;
|
||||
XMEMCPY(&nv->handle.name.name, name.name, nv->handle.name.size);
|
||||
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM2_NV_DefineSpace: Auth 0x%x, Idx 0x%x, Attribs 0x%d, Size %d\n",
|
||||
|
@ -2596,6 +2650,8 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv,
|
|||
int rc = TPM_RC_SUCCESS;
|
||||
word32 pos = 0, towrite;
|
||||
NV_Write_In in;
|
||||
NV_ReadPublic_In inPublic;
|
||||
NV_ReadPublic_Out outPublic;
|
||||
|
||||
if (dev == NULL || nv == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
@ -2605,6 +2661,27 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv,
|
|||
wolfTPM2_SetAuthHandle(dev, 0, &nv->handle);
|
||||
}
|
||||
|
||||
XMEMSET((byte*)&inPublic, 0, sizeof(inPublic));
|
||||
XMEMSET((byte*)&outPublic, 0, sizeof(outPublic));
|
||||
/* Read the NV Index publicArea to have up to date NV Index Name */
|
||||
inPublic.nvIndex = nv->handle.hndl;
|
||||
rc = TPM2_NV_ReadPublic(&inPublic, &outPublic);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("Failed to read fresh NvPublic\n");
|
||||
#endif
|
||||
return TPM_RC_FAILURE;
|
||||
}
|
||||
|
||||
/* Compute NV Index name in case of parameter encryption */
|
||||
rc = TPM2_HashNvPublic(&outPublic.nvPublic.nvPublic,
|
||||
(byte*)&nv->handle.name.name,
|
||||
&nv->handle.name.size);
|
||||
|
||||
/* Necessary, because NVWrite has two handles, second is NV Index */
|
||||
wolfTPM2_SetNameHandle(dev, 0, &nv->handle);
|
||||
wolfTPM2_SetNameHandle(dev, 1, &nv->handle);
|
||||
|
||||
while (dataSz > 0) {
|
||||
towrite = dataSz;
|
||||
if (towrite > MAX_NV_BUFFER_SIZE)
|
||||
|
@ -2629,7 +2706,8 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv,
|
|||
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM2_NV_Write: Auth 0x%x, Idx 0x%x, Offset %d, Size %d\n",
|
||||
(word32)in.authHandle, (word32)in.nvIndex, in.offset, in.data.size);
|
||||
(word32)in.authHandle, (word32)in.nvIndex,
|
||||
in.offset, in.data.size);
|
||||
#endif
|
||||
|
||||
pos += towrite;
|
||||
|
@ -2656,6 +2734,8 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv,
|
|||
word32 pos = 0, toread, dataSz;
|
||||
NV_Read_In in;
|
||||
NV_Read_Out out;
|
||||
NV_ReadPublic_In inPublic;
|
||||
NV_ReadPublic_Out outPublic;
|
||||
|
||||
if (dev == NULL || nv == NULL || pDataSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
@ -2665,6 +2745,27 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv,
|
|||
wolfTPM2_SetAuthHandle(dev, 0, &nv->handle);
|
||||
}
|
||||
|
||||
XMEMSET((byte*)&inPublic, 0, sizeof(inPublic));
|
||||
XMEMSET((byte*)&outPublic, 0, sizeof(outPublic));
|
||||
/* Read the NV Index publicArea to have up to date NV Index Name */
|
||||
inPublic.nvIndex = nv->handle.hndl;
|
||||
rc = TPM2_NV_ReadPublic(&inPublic, &outPublic);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("Failed to read fresh NvPublic\n");
|
||||
#endif
|
||||
return TPM_RC_FAILURE;
|
||||
}
|
||||
|
||||
/* Compute NV Index name in case of parameter encryption */
|
||||
rc = TPM2_HashNvPublic(&outPublic.nvPublic.nvPublic,
|
||||
(byte*)&nv->handle.name.name,
|
||||
&nv->handle.name.size);
|
||||
|
||||
/* Necessary, because NVWrite has two handles, second is NV Index */
|
||||
wolfTPM2_SetNameHandle(dev, 0, &nv->handle);
|
||||
wolfTPM2_SetNameHandle(dev, 1, &nv->handle);
|
||||
|
||||
dataSz = *pDataSz;
|
||||
|
||||
while (dataSz > 0) {
|
||||
|
@ -2773,6 +2874,9 @@ int wolfTPM2_NVDeleteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent,
|
|||
/* set session auth for key */
|
||||
if (dev->ctx.session) {
|
||||
wolfTPM2_SetAuthHandle(dev, 0, parent);
|
||||
/* Make sure no other auth sessions exist */
|
||||
wolfTPM2_UnsetAuth(dev, 1);
|
||||
wolfTPM2_UnsetAuth(dev, 2);
|
||||
}
|
||||
|
||||
XMEMSET(&in, 0, sizeof(in));
|
||||
|
|
|
@ -2800,7 +2800,8 @@ WOLFTPM_API int TPM2_GetTpmCurve(int curveID);
|
|||
WOLFTPM_API int TPM2_GetWolfCurve(int curve_id);
|
||||
|
||||
WOLFTPM_API int TPM2_ParseAttest(const TPM2B_ATTEST* in, TPMS_ATTEST* out);
|
||||
WOLFTPM_LOCAL int TPM2_GetName(TPM2_CTX* ctx, int handleCnt, int idx, TPM2B_NAME* name);
|
||||
WOLFTPM_LOCAL int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2B_NAME* name);
|
||||
WOLFTPM_API int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size);
|
||||
|
||||
#ifdef WOLFTPM2_USE_WOLF_RNG
|
||||
WOLFTPM_API int TPM2_GetWolfRng(WC_RNG** rng);
|
||||
|
|
|
@ -131,6 +131,7 @@ WOLFTPM_API int wolfTPM2_GetTpmDevId(WOLFTPM2_DEV* dev);
|
|||
WOLFTPM_API int wolfTPM2_SelfTest(WOLFTPM2_DEV* dev);
|
||||
WOLFTPM_API int wolfTPM2_GetCapabilities(WOLFTPM2_DEV* dev, WOLFTPM2_CAPS* caps);
|
||||
|
||||
WOLFTPM_API int wolfTPM2_UnsetAuth(WOLFTPM2_DEV* dev, int index);
|
||||
WOLFTPM_API int wolfTPM2_SetAuth(WOLFTPM2_DEV* dev, int index,
|
||||
TPM_HANDLE sessionHandle, const TPM2B_AUTH* auth, TPMA_SESSION sessionAttributes,
|
||||
const TPM2B_NAME* name);
|
||||
|
@ -138,6 +139,7 @@ WOLFTPM_API int wolfTPM2_SetAuthPassword(WOLFTPM2_DEV* dev, int index, const TPM
|
|||
WOLFTPM_API int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle);
|
||||
WOLFTPM_API int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index,
|
||||
const WOLFTPM2_SESSION* tpmSession, TPMA_SESSION sessionAttributes);
|
||||
WOLFTPM_API int wolfTPM2_SetNameHandle(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle);
|
||||
|
||||
WOLFTPM_API int wolfTPM2_StartSession(WOLFTPM2_DEV* dev,
|
||||
WOLFTPM2_SESSION* session, WOLFTPM2_KEY* tpmKey,
|
||||
|
|
Loading…
Reference in New Issue