summaryrefslogtreecommitdiffstats
path: root/src/tpm12/tpm_permanent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tpm12/tpm_permanent.c')
-rw-r--r--src/tpm12/tpm_permanent.c1333
1 files changed, 1333 insertions, 0 deletions
diff --git a/src/tpm12/tpm_permanent.c b/src/tpm12/tpm_permanent.c
new file mode 100644
index 0000000..b9a6209
--- /dev/null
+++ b/src/tpm12/tpm_permanent.c
@@ -0,0 +1,1333 @@
+/********************************************************************************/
+/* */
+/* Permanent Flag and Data Handler */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: tpm_permanent.c 4623 2011-09-28 15:15:09Z kgoldman $ */
+/* */
+/* (c) Copyright IBM Corporation 2006, 2010. */
+/* */
+/* 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tpm_audit.h"
+#include "tpm_counter.h"
+#include "tpm_crypto.h"
+#include "tpm_cryptoh.h"
+#include "tpm_debug.h"
+#include "tpm_delegate.h"
+#include "tpm_digest.h"
+#include "tpm_error.h"
+#include "tpm_global.h"
+#include "tpm_key.h"
+#include "tpm_nonce.h"
+#include "tpm_nvfile.h"
+#include "tpm_nvfilename.h"
+#include "tpm_nvram.h"
+#include "tpm_pcr.h"
+#include "tpm_secret.h"
+#include "tpm_storage.h"
+#include "tpm_structures.h"
+#include "tpm_types.h"
+#include "tpm_svnrevision.h"
+
+
+#include "tpm_permanent.h"
+
+/*
+ TPM_PERMANENT_FLAGS
+*/
+
+void TPM_PermanentFlags_Init(TPM_PERMANENT_FLAGS *tpm_permanent_flags)
+{
+ printf(" TPM_PermanentFlags_Init:\n");
+#ifndef TPM_ENABLE_ACTIVATE
+ tpm_permanent_flags->disable = TRUE;
+#else /* for servers, not TCG standard */
+ tpm_permanent_flags->disable = FALSE;
+#endif
+ tpm_permanent_flags->ownership = TRUE;
+#ifndef TPM_ENABLE_ACTIVATE
+ tpm_permanent_flags->deactivated = TRUE;
+#else /* for servers, not TCG standard */
+ tpm_permanent_flags->deactivated = FALSE;
+#endif
+ tpm_permanent_flags->readPubek = TRUE;
+ tpm_permanent_flags->disableOwnerClear = FALSE;
+ tpm_permanent_flags->allowMaintenance = TRUE;
+ tpm_permanent_flags->physicalPresenceLifetimeLock = FALSE;
+ tpm_permanent_flags->physicalPresenceHWEnable = FALSE;
+#ifndef TPM_PP_CMD_ENABLE /* TCG standard */
+ tpm_permanent_flags->physicalPresenceCMDEnable = FALSE;
+#else /* 'ship' TRUE */
+ tpm_permanent_flags->physicalPresenceCMDEnable = TRUE;
+#endif
+ /* tpm_permanent_flags->CEKPUsed = ; This flag has no default value */
+ tpm_permanent_flags->TPMpost = FALSE;
+ tpm_permanent_flags->TPMpostLock = FALSE;
+ tpm_permanent_flags->FIPS = FALSE; /* if TRUE, could not test no-auth commands */
+ tpm_permanent_flags->tpmOperator = FALSE;
+ tpm_permanent_flags->enableRevokeEK = TRUE;
+ tpm_permanent_flags->nvLocked = FALSE;
+ tpm_permanent_flags->readSRKPub = FALSE;
+ tpm_permanent_flags->tpmEstablished = FALSE;
+ tpm_permanent_flags->maintenanceDone = FALSE;
+#if (TPM_REVISION >= 103) /* added for rev 103 */
+ tpm_permanent_flags->disableFullDALogicInfo = FALSE;
+#endif
+}
+
+/* TPM_PermanentFlags_Load()
+
+ deserializes the structure from a 'stream'
+ 'stream_size' is checked for sufficient data
+ returns 0 or error codes
+
+ It is used when deserializing the structure from storage in NVRAM.
+*/
+
+TPM_RESULT TPM_PermanentFlags_Load(TPM_PERMANENT_FLAGS *tpm_permanent_flags,
+ unsigned char **stream,
+ uint32_t *stream_size)
+{
+ TPM_RESULT rc = 0;
+ uint32_t tpm_bitmap;
+ TPM_TAG permanentFlagsVersion;
+
+ printf(" TPM_PermanentFlags_Load:\n");
+ /* load the TPM_PERMANENT_FLAGS version tag from the stream */
+ if (rc == 0) {
+ rc = TPM_Load16(&permanentFlagsVersion, stream, stream_size);
+ }
+ /* load the TPM_PERMANENT_FLAGS from the stream */
+ if (rc == 0) {
+ rc = TPM_Load32(&tpm_bitmap, stream, stream_size);
+ }
+ /* load the TPM_PERMANENT_FLAGS from the bitmap */
+ if (rc == 0) {
+ rc = TPM_PermanentFlags_LoadBitmap(tpm_permanent_flags, permanentFlagsVersion, tpm_bitmap);
+ }
+ return rc;
+}
+
+/* TPM_PermanentFlags_Store() serializes the TPM_PERMANENT_FLAGS structure as a bitmap.
+
+ It is used when serializing the structure for storage in NVRAM.
+*/
+
+TPM_RESULT TPM_PermanentFlags_Store(TPM_STORE_BUFFER *sbuffer,
+ const TPM_PERMANENT_FLAGS *tpm_permanent_flags)
+
+{
+ TPM_RESULT rc = 0;
+ uint32_t tpm_bitmap;
+
+ printf(" TPM_PermanentFlags_Store:\n");
+ /* store the TPM_PERMANENT_FLAGS structure in a bit map */
+ if (rc == 0) {
+ rc = TPM_PermanentFlags_StoreBitmap(&tpm_bitmap, tpm_permanent_flags);
+ }
+ /* append a TPM_PERMANENT_FLAGS version tag */
+#if (TPM_REVISION >= 103)
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_PF103);
+ }
+#else
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_PF94);
+ }
+#endif
+ /* append the bitmap to the stream */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append32(sbuffer, tpm_bitmap);
+ }
+ return rc;
+}
+
+/* TPM_PermanentFlags_StoreBytes() serializes the TPM_PERMANENT_FLAGS structure as bytes
+
+ */
+
+TPM_RESULT TPM_PermanentFlags_StoreBytes(TPM_STORE_BUFFER *sbuffer,
+ const TPM_PERMANENT_FLAGS *tpm_permanent_flags)
+{
+ TPM_RESULT rc = 0;
+
+ printf(" TPM_PermanentFlags_StoreBytes:\n");
+ /* store tag */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_PERMANENT_FLAGS);
+ }
+ /* store disable */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->disable), sizeof(BYTE));
+ }
+ /* store ownership */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->ownership), sizeof(BYTE));
+ }
+ /* store deactivated */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->deactivated), sizeof(BYTE));
+ }
+ /* store readPubek */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->readPubek), sizeof(BYTE));
+ }
+ /* store disableOwnerClear */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->disableOwnerClear), sizeof(BYTE));
+ }
+ /* store allowMaintenance */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->allowMaintenance), sizeof(BYTE));
+ }
+ /* store physicalPresenceLifetimeLock */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceLifetimeLock),
+ sizeof(BYTE));
+ }
+ /* store physicalPresenceHWEnable */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceHWEnable),
+ sizeof(BYTE));
+ }
+ /* store physicalPresenceCMDEnable */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceCMDEnable),
+ sizeof(BYTE));
+ }
+ /* store CEKPUsed */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->CEKPUsed), sizeof(BYTE));
+ }
+ /* store TPMpost */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->TPMpost), sizeof(BYTE));
+ }
+ /* store TPMpostLock */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->TPMpostLock), sizeof(BYTE));
+ }
+ /* store FIPS */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->FIPS), sizeof(BYTE));
+ }
+ /* store operator */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->tpmOperator), sizeof(BYTE));
+ }
+ /* store enableRevokeEK */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->enableRevokeEK), sizeof(BYTE));
+ }
+ /* store nvLocked */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->nvLocked), sizeof(BYTE));
+ }
+ /* store readSRKPub */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->readSRKPub), sizeof(BYTE));
+ }
+ /* store tpmEstablished */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->tpmEstablished), sizeof(BYTE));
+ }
+ /* store maintenanceDone */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->maintenanceDone), sizeof(BYTE));
+ }
+#if (TPM_REVISION >= 103) /* added for rev 103 */
+ /* store disableFullDALogicInfo */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer,
+ &(tpm_permanent_flags->disableFullDALogicInfo), sizeof(BYTE));
+ }
+#endif
+ return rc;
+}
+
+/* TPM_PermanentFlags_LoadBitmap() loads the TPM_PERMANENT_FLAGS structure from the bit map
+
+ permanentFlagsVersion indicates the version being loaded from NVRAM
+*/
+
+TPM_RESULT TPM_PermanentFlags_LoadBitmap(TPM_PERMANENT_FLAGS *tpm_permanent_flags,
+ TPM_TAG permanentFlagsVersion,
+ uint32_t tpm_bitmap)
+{
+ TPM_RESULT rc = 0;
+ uint32_t pos = 0; /* position in bitmap */
+
+ if (rc == 0) {
+ switch (permanentFlagsVersion) {
+ case TPM_TAG_NVSTATE_PF94:
+ break;
+ case TPM_TAG_NVSTATE_PF103:
+ /* if the TPM_REVISION supports the permanentFlagsVersion, break with no error. If it
+ doesn't, omit the break and fall through to the unsupported case. */
+#if (TPM_REVISION >= 103)
+ break;
+#endif
+ default:
+ /* no forward compatibility */
+ printf("TPM_PermanentFlags_LoadBitmap: Error (fatal) unsupported version tag %04x\n",
+ permanentFlagsVersion);
+ rc = TPM_FAIL;
+ break;
+ }
+ }
+ printf(" TPM_PermanentFlags_LoadBitmap:\n");
+ /* load disable */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disable), tpm_bitmap, &pos);
+ }
+ /* load ownership */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->ownership), tpm_bitmap, &pos);
+ }
+ /* load deactivated */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->deactivated), tpm_bitmap, &pos);
+ }
+ /* load readPubek */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->readPubek), tpm_bitmap, &pos);
+ }
+ /* load disableOwnerClear */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disableOwnerClear), tpm_bitmap, &pos);
+ }
+ /* load allowMaintenance */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->allowMaintenance), tpm_bitmap, &pos);
+ }
+ /* load physicalPresenceLifetimeLock */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceLifetimeLock),
+ tpm_bitmap, &pos);
+ }
+ /* load physicalPresenceHWEnable */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceHWEnable), tpm_bitmap, &pos);
+ }
+ /* load physicalPresenceCMDEnable */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceCMDEnable), tpm_bitmap, &pos);
+ }
+ /* load CEKPUsed */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->CEKPUsed), tpm_bitmap, &pos);
+ }
+ /* load TPMpost */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->TPMpost), tpm_bitmap, &pos);
+ }
+ /* load TPMpostLock */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->TPMpostLock), tpm_bitmap, &pos);
+ }
+ /* load FIPS */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->FIPS), tpm_bitmap, &pos);
+ }
+ /* load operator */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->tpmOperator), tpm_bitmap, &pos);
+ }
+ /* load enableRevokeEK */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->enableRevokeEK), tpm_bitmap, &pos);
+ }
+ /* load nvLocked */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->nvLocked), tpm_bitmap, &pos);
+ }
+ /* load readSRKPub */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->readSRKPub), tpm_bitmap, &pos);
+ }
+ /* load tpmEstablished */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->tpmEstablished), tpm_bitmap, &pos);
+ }
+ /* load maintenanceDone */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->maintenanceDone), tpm_bitmap, &pos);
+ }
+#if (TPM_REVISION >= 103) /* added for rev 103 */
+ if (rc == 0) {
+ switch (permanentFlagsVersion) {
+ case TPM_TAG_NVSTATE_PF94:
+ /* 94 to 103, set extra flags to default value */
+ tpm_permanent_flags->disableFullDALogicInfo = FALSE;
+ break;
+ case TPM_TAG_NVSTATE_PF103:
+ /* 103 to 103, process normally */
+ /* load disableFullDALogicInfo */
+ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disableFullDALogicInfo), tpm_bitmap, &pos);
+ break;
+ }
+ }
+#endif
+ return rc;
+}
+
+/* TPM_PermanentFlags_StoreBitmap() stores the TPM_PERMANENT_FLAGS structure in a bit map
+
+ It is used when serializing the structure for storage in NVRAM and as the return to
+ TPM_GetCapability.
+*/
+
+TPM_RESULT TPM_PermanentFlags_StoreBitmap(uint32_t *tpm_bitmap,
+ const TPM_PERMANENT_FLAGS *tpm_permanent_flags)
+{
+ TPM_RESULT rc = 0;
+ uint32_t pos = 0; /* position in bitmap */
+
+ printf(" TPM_PermanentFlags_StoreBitmap:\n");
+ *tpm_bitmap = 0; /* set unused bits to 0 */
+ /* store disable */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disable, &pos);
+ }
+ /* store ownership */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->ownership, &pos);
+ }
+ /* store deactivated */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->deactivated, &pos);
+ }
+ /* store readPubek */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->readPubek, &pos);
+ }
+ /* store disableOwnerClear */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disableOwnerClear, &pos);
+ }
+ /* store allowMaintenance */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->allowMaintenance, &pos);
+ }
+ /* store physicalPresenceLifetimeLock */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceLifetimeLock, &pos);
+ }
+ /* store physicalPresenceHWEnable */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceHWEnable, &pos);
+ }
+ /* store physicalPresenceCMDEnable */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceCMDEnable, &pos);
+ }
+ /* store CEKPUsed */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->CEKPUsed, &pos);
+ }
+ /* store TPMpost */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->TPMpost, &pos);
+ }
+ /* store TPMpostLock */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->TPMpostLock, &pos);
+ }
+ /* store FIPS */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->FIPS, &pos);
+ }
+ /* store operator */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->tpmOperator, &pos);
+ }
+ /* store enableRevokeEK */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->enableRevokeEK, &pos);
+ }
+ /* store nvLocked */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->nvLocked, &pos);
+ }
+ /* store readSRKPub */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->readSRKPub, &pos);
+ }
+ /* store tpmEstablished */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->tpmEstablished, &pos);
+ }
+ /* store maintenanceDone */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->maintenanceDone, &pos);
+ }
+#if (TPM_REVISION >= 103) /* added for rev 103 */
+ /* store disableFullDALogicInfo */
+ if (rc == 0) {
+ rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disableFullDALogicInfo, &pos);
+ }
+#endif
+ return rc;
+}
+
+/*
+ TPM_PERMANENT_DATA
+*/
+
+/* TPM_PermanentData_Init()
+
+ sets members to default values
+ sets all pointers to NULL and sizes to 0
+
+ This function generates a new contextKey, delegateKey, daaBlobKey.
+*/
+
+
+TPM_RESULT TPM_PermanentData_Init(TPM_PERMANENT_DATA *tpm_permanent_data,
+ TPM_BOOL instanceData)
+{
+ TPM_RESULT rc = 0;
+
+ printf(" TPM_PermanentData_Init:\n");
+ if (rc == 0) {
+ tpm_permanent_data->revMajor = ((tpm_svn_revision >> 8) & 0xff);
+ tpm_permanent_data->revMinor = ((tpm_svn_revision ) & 0xff);
+ printf(" TPM_PermanentData_Init: revMajor %02x revMinor %02x\n",
+ tpm_permanent_data->revMajor, tpm_permanent_data->revMinor);
+ /* zero all secrets */
+ TPM_PermanentData_Zero(tpm_permanent_data, instanceData);
+
+#ifndef TPM_NOMAINTENANCE
+ TPM_Pubkey_Init(&(tpm_permanent_data->manuMaintPub));
+#endif
+ TPM_Key_Init(&(tpm_permanent_data->endorsementKey));
+ TPM_Key_Init(&(tpm_permanent_data->srk));
+ tpm_permanent_data->contextKey = NULL;
+ rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->contextKey));
+ }
+ if (rc == 0) {
+ tpm_permanent_data->delegateKey = NULL;
+ rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->delegateKey));
+ }
+ if (rc == 0) {
+ TPM_CounterValue_Init(&(tpm_permanent_data->auditMonotonicCounter));
+ TPM_Counters_Init(tpm_permanent_data->monotonicCounter);
+ TPM_PCRAttributes_Init(tpm_permanent_data->pcrAttrib);
+ rc = TPM_OrdinalAuditStatus_Init(tpm_permanent_data);
+ }
+ if (rc == 0) {
+ TPM_FamilyTable_Init(&(tpm_permanent_data->familyTable));
+ TPM_DelegateTable_Init(&(tpm_permanent_data->delegateTable));
+ tpm_permanent_data->lastFamilyID = 0;
+ tpm_permanent_data->noOwnerNVWrite = 0;
+ tpm_permanent_data->restrictDelegate = 0;
+ /* tpmDAASeed done by TPM_PermanentData_Zero() */
+ /* daaProof done by TPM_PermanentData_Zero() */
+ rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->daaBlobKey));
+ }
+ if (rc == 0) {
+ tpm_permanent_data->ownerInstalled = FALSE;
+ /* tscOrdinalAuditStatus initialized by TPM_OrdinalAuditStatus_Init() */
+ /* instanceOrdinalAuditStatus initialized by TPM_OrdinalAuditStatus_Init() */
+ tpm_permanent_data->allowLoadMaintPub = TRUE;
+ if (instanceData) {
+ }
+ }
+ return rc;
+}
+
+/* TPM_PermanentData_Load()
+
+ deserializes the structure from a 'stream'
+ 'stream_size' is checked for sufficient data
+ returns 0 or error codes
+*/
+
+TPM_RESULT TPM_PermanentData_Load(TPM_PERMANENT_DATA *tpm_permanent_data,
+ unsigned char **stream,
+ uint32_t *stream_size,
+ TPM_BOOL instanceData)
+{
+ TPM_RESULT rc = 0;
+ size_t i;
+ TPM_BOOL tpm_bool;
+
+
+ printf(" TPM_PermanentData_Load:\n");
+ /* check tag */
+ if (rc == 0) {
+ rc = TPM_CheckTag(TPM_TAG_PERMANENT_DATA, stream, stream_size);
+ }
+ /* load revMajor */
+ /* load revMinor */
+ /* not stored, loaded from hard coded value */
+ if (rc == 0) {
+ tpm_permanent_data->revMajor = (tpm_svn_revision >> 8) & 0xff;
+ tpm_permanent_data->revMinor = tpm_svn_revision & 0xff;
+ }
+ /* load tpmProof */
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Loading tpmProof\n");
+ rc = TPM_Secret_Load(tpm_permanent_data->tpmProof, stream, stream_size);
+ }
+ /* load EKReset */
+ if (rc == 0) {
+ rc = TPM_Nonce_Load(tpm_permanent_data->EKReset, stream, stream_size);
+ }
+ /* load ownerAuth */
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Loading ownerAuth \n");
+ rc = TPM_Secret_Load(tpm_permanent_data->ownerAuth, stream, stream_size);
+ }
+ /* load operatorAuth */
+ if (rc == 0) {
+ rc = TPM_Secret_Load(tpm_permanent_data->operatorAuth, stream, stream_size);
+ }
+ /* load authDIR */
+ if (rc == 0) {
+ rc = TPM_Digest_Load(tpm_permanent_data->authDIR, stream, stream_size);
+ }
+ /* load manuMaintPub present marker */
+ if (rc == 0) {
+ rc = TPM_Load8(&tpm_bool, stream, stream_size);
+ }
+#ifndef TPM_NOMAINTENANCE
+ /* check that manuMaintPub is present */
+ if (rc == 0) {
+ if (!tpm_bool) {
+ printf(" TPM_PermanentData_Load: Error (fatal) missing manuMaintPub\n");
+ rc = TPM_FAIL;
+ }
+ }
+ /* load manuMaintPub */
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Load manuMaintPub\n");
+ rc = TPM_Pubkey_Load(&(tpm_permanent_data->manuMaintPub), stream, stream_size);
+ }
+#else
+ /* check that manuMaintPub is absent */
+ if (tpm_bool) {
+ printf(" TPM_PermanentData_Load: Error (fatal) contains manuMaintPub\n");
+ rc = TPM_FAIL;
+ }
+#endif
+ /* load endorsementKey */
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Load endorsement key\n");
+ rc = TPM_Key_LoadClear(&(tpm_permanent_data->endorsementKey), TRUE, stream, stream_size);
+ }
+ /* load srk */
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Load SRK\n");
+ rc = TPM_Key_LoadClear(&(tpm_permanent_data->srk), FALSE, stream, stream_size);
+ }
+ /* load contextKey */
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Load contextKey\n");
+ rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->contextKey, stream, stream_size);
+ }
+ /* load delegateKey */
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Load delegateKey\n");
+ rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->delegateKey, stream, stream_size);
+ }
+ /* load auditMonotonicCounter */
+ if (rc == 0) {
+ rc = TPM_CounterValue_Load(&(tpm_permanent_data->auditMonotonicCounter),
+ stream, stream_size);
+ }
+ /* load monotonicCounter's */
+ if (rc == 0) {
+ rc = TPM_Counters_Load(tpm_permanent_data->monotonicCounter, stream, stream_size);
+ }
+ /* load pcrAttrib's, since they are constants, no need to load from NV space */
+ if (rc == 0) {
+ TPM_PCRAttributes_Init(tpm_permanent_data->pcrAttrib);
+ }
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Load ordinalAuditStatus\n");
+ }
+ /* load ordinalAuditStatus's */
+ for (i = 0 ; (rc == 0) && (i < (TPM_ORDINALS_MAX/CHAR_BIT)) ; i++) {
+ rc = TPM_Load8(&(tpm_permanent_data->ordinalAuditStatus[i]), stream, stream_size);
+ }
+ /* load familyTable */
+ if (rc == 0) {
+ rc = TPM_FamilyTable_Load(&(tpm_permanent_data->familyTable), stream, stream_size);
+ }
+ /* load delegateTable */
+ if (rc == 0) {
+ rc = TPM_DelegateTable_Load(&(tpm_permanent_data->delegateTable), stream, stream_size);
+ }
+ /* load lastFamilyID */
+ if (rc == 0) {
+ rc = TPM_Load32(&(tpm_permanent_data->lastFamilyID), stream, stream_size);
+ }
+ /* load noOwnerNVWrite */
+ if (rc == 0) {
+ rc = TPM_Load32(&(tpm_permanent_data->noOwnerNVWrite), stream, stream_size);
+ }
+ /* load restrictDelegate */
+ if (rc == 0) {
+ rc = TPM_Load32(&(tpm_permanent_data->restrictDelegate), stream, stream_size);
+ }
+ /* load tpmDAASeed */
+ if (rc == 0) {
+ rc = TPM_Nonce_Load(tpm_permanent_data->tpmDAASeed, stream, stream_size);
+ }
+ /* load ownerInstalled */
+ if (rc == 0) {
+ rc = TPM_LoadBool(&(tpm_permanent_data->ownerInstalled), stream, stream_size);
+ }
+ /* load tscOrdinalAuditStatus */
+ if (rc == 0) {
+ rc = TPM_Load8(&(tpm_permanent_data->tscOrdinalAuditStatus), stream, stream_size);
+ }
+ /* load allowLoadMaintPub */
+ if (rc == 0) {
+ rc = TPM_LoadBool(&(tpm_permanent_data->allowLoadMaintPub), stream, stream_size);
+ }
+ /* load daaProof */
+ if (rc == 0) {
+ rc = TPM_Nonce_Load(tpm_permanent_data->daaProof, stream, stream_size);
+ }
+ /* load daaBlobKey */
+ if (rc == 0) {
+ printf(" TPM_PermanentData_Load: Loading DAA Blob key\n");
+ rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->daaBlobKey, stream, stream_size);
+ }
+ instanceData = instanceData; /* to quiet the compiler */
+ return rc;
+}
+
+/* TPM_PermanentData_Store() serializes the TPM_PERMANENT_DATA structure
+
+ */
+
+TPM_RESULT TPM_PermanentData_Store(TPM_STORE_BUFFER *sbuffer,
+ TPM_PERMANENT_DATA *tpm_permanent_data,
+ TPM_BOOL instanceData)
+{
+ TPM_RESULT rc = 0;
+ size_t i;
+
+ printf(" TPM_PermanentData_Store:\n");
+ /* store tag */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_PERMANENT_DATA);
+ }
+ /* store revMajor */
+ /* store revMinor */
+ /* not stored, loaded from hard coded value */
+ /* store tpmProof */
+ if (rc == 0) {
+ rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->tpmProof);
+ }
+ /* store EKReset */
+ if (rc == 0) {
+ rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->EKReset);
+ }
+ /* store ownerAuth */
+ if (rc == 0) {
+ rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->ownerAuth);
+ }
+ /* store operatorAuth */
+ if (rc == 0) {
+ rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->operatorAuth);
+ }
+ /* store authDIR */
+ if (rc == 0) {
+ rc = TPM_Digest_Store(sbuffer, tpm_permanent_data->authDIR);
+ }
+#ifndef TPM_NOMAINTENANCE
+ /* mark that manuMaintPub is present */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append8(sbuffer, TRUE);
+ }
+ /* store manuMaintPub */
+ if (rc == 0) {
+ rc = TPM_Pubkey_Store(sbuffer, &(tpm_permanent_data->manuMaintPub));
+ }
+#else
+ /* mark that manuMaintPub is absent */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, FALSE);
+ }
+#endif
+ /* store endorsementKey */
+ if (rc == 0) {
+ rc = TPM_Key_StoreClear(sbuffer, TRUE, &(tpm_permanent_data->endorsementKey));
+ }
+ /* store srk */
+ if (rc == 0) {
+ rc = TPM_Key_StoreClear(sbuffer, FALSE, &(tpm_permanent_data->srk));
+ }
+ /* store contextKey */
+ if (rc == 0) {
+ rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->contextKey);
+ }
+ /* store delegateKey */
+ if (rc == 0) {
+ rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->delegateKey);
+ }
+ /* store auditMonotonicCounter */
+ if (rc == 0) {
+ rc = TPM_CounterValue_Store(sbuffer, &(tpm_permanent_data->auditMonotonicCounter));
+ }
+ /* store monotonicCounter */
+ if (rc == 0) {
+ rc = TPM_Counters_Store(sbuffer, tpm_permanent_data->monotonicCounter);
+ }
+ /* store pcrAttrib, since they are constants, no need to store to NV space */
+ /* store ordinalAuditStatus */
+ for (i = 0 ; (rc == 0) && (i < (TPM_ORDINALS_MAX/CHAR_BIT)) ; i++) {
+ rc = TPM_Sbuffer_Append(sbuffer,
+ &(tpm_permanent_data->ordinalAuditStatus[i]), sizeof(BYTE));
+ }
+ /* store familyTable */
+ if (rc == 0) {
+ rc = TPM_FamilyTable_Store(sbuffer,
+ &(tpm_permanent_data->familyTable),
+ FALSE); /* don't store the tag, to save NV space */
+ }
+ /* store delegateTable */
+ if (rc == 0) {
+ rc = TPM_DelegateTable_Store(sbuffer, &(tpm_permanent_data->delegateTable));
+ }
+ /* store lastFamilyID */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->lastFamilyID);
+ }
+ /* store noOwnerNVWrite */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->noOwnerNVWrite);
+ }
+ /* store restrictDelegate */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->restrictDelegate);
+ }
+ /* store tpmDAASeed */
+ if (rc == 0) {
+ rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->tpmDAASeed);
+ }
+ /* store ownerInstalled */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->ownerInstalled), sizeof(BYTE));
+ }
+ /* store tscOrdinalAuditStatus */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->tscOrdinalAuditStatus),
+ sizeof(BYTE));
+ }
+ /* store allowLoadMaintPub */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->allowLoadMaintPub), sizeof(BYTE));
+ }
+ /* store daaProof */
+ if (rc == 0) {
+ rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->daaProof);
+ }
+ /* store daaBlobKey */
+ if (rc == 0) {
+ rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->daaBlobKey);
+ }
+ instanceData = instanceData; /* to quiet the compiler */
+ return rc;
+}
+
+/* TPM_PermanentData_Delete()
+
+ No-OP if the parameter is NULL, else:
+ frees memory allocated for the object
+ sets pointers to NULL
+ calls TPM_PermanentData_Zero to zero secrets that are not Delete'd
+ The object itself is not freed
+*/
+
+void TPM_PermanentData_Delete(TPM_PERMANENT_DATA *tpm_permanent_data,
+ TPM_BOOL instanceData)
+{
+ printf(" TPM_PermanentData_Delete:\n");
+ if (tpm_permanent_data != NULL) {
+#ifndef TPM_NOMAINTENANCE
+ TPM_Pubkey_Delete(&(tpm_permanent_data->manuMaintPub));
+#endif
+ TPM_Key_Delete(&(tpm_permanent_data->endorsementKey));
+ TPM_Key_Delete(&(tpm_permanent_data->srk));
+ TPM_SymmetricKeyData_Free(&(tpm_permanent_data->contextKey));
+ TPM_SymmetricKeyData_Free(&(tpm_permanent_data->delegateKey));
+ TPM_FamilyTable_Delete(&(tpm_permanent_data->familyTable));
+ TPM_DelegateTable_Delete(&(tpm_permanent_data->delegateTable));
+ TPM_SymmetricKeyData_Free(&(tpm_permanent_data->daaBlobKey));
+ /* zero all secrets */
+ TPM_PermanentData_Zero(tpm_permanent_data, instanceData);
+ }
+ return;
+}
+
+/* TPM_PermanentData_Zero() zeros all secrets not already zeroed and freed by
+ TPM_PermanentData_Delete()
+
+ It is called by TPM_PermanentData_Delete() and TPM_PermanentData_Init(). It does a subset of
+ TPM_PermanentData_Init() that will never fail.
+*/
+
+void TPM_PermanentData_Zero(TPM_PERMANENT_DATA *tpm_permanent_data,
+ TPM_BOOL instanceData)
+{
+ printf(" TPM_PermanentData_Zero:\n");
+ instanceData = instanceData;
+ if (tpm_permanent_data != NULL) {
+ TPM_Secret_Init(tpm_permanent_data->tpmProof);
+ TPM_Nonce_Init(tpm_permanent_data->EKReset);
+ TPM_Secret_Init(tpm_permanent_data->ownerAuth);
+ TPM_Secret_Init(tpm_permanent_data->operatorAuth);
+ TPM_Digest_Init(tpm_permanent_data->authDIR);
+ /* endorsementKey handled by TPM_Key_Delete() */
+ /* srk handled by TPM_Key_Delete() */
+ /* contextKey handled by TPM_SymmetricKeyData_Free() */
+ /* delegateKey handled by TPM_SymmetricKeyData_Free() */
+ TPM_Nonce_Init(tpm_permanent_data->tpmDAASeed);
+ TPM_Nonce_Init(tpm_permanent_data->daaProof);
+ /* daaBlobKey handled by TPM_SymmetricKeyData_Free() */
+ }
+ return;
+}
+
+/* TPM_PermanentData_InitDaa() generates new values for the 3 DAA elements: tpmDAASeed, daaProof,
+ and daaBlobKey.
+
+ This is common code, use when creating the EK, revoke trust, and the set capability
+ used by the owner to invalidate DAA blobs.
+*/
+
+TPM_RESULT TPM_PermanentData_InitDaa(TPM_PERMANENT_DATA *tpm_permanent_data)
+{
+ TPM_RESULT rc = 0;
+
+ printf(" TPM_PermanentData_InitDaa:\n");
+ /* generate tpmDAASeed */
+ if (rc == 0) {
+ rc = TPM_Nonce_Generate(tpm_permanent_data->tpmDAASeed);
+ }
+ /* generate daaProof*/
+ if (rc == 0) {
+ rc = TPM_Nonce_Generate(tpm_permanent_data->daaProof);
+ }
+ /* generate daaBlobKey */
+ if (rc == 0) {
+ rc = TPM_SymmetricKeyData_GenerateKey(tpm_permanent_data->daaBlobKey);
+ }
+ return rc;
+}
+
+/*
+ PermanentAll is TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys, and NV defined space.
+*/
+
+/* TPM_PermanentAll_Load() deserializes all TPM NV data from a stream created by
+ TPM_PermanentAll_Store().
+
+ The two functions must be kept in sync.
+
+ Data includes TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, Owner Evict keys, and NV defined space.
+*/
+
+TPM_RESULT TPM_PermanentAll_Load(tpm_state_t *tpm_state,
+ unsigned char **stream,
+ uint32_t *stream_size)
+{
+ TPM_RESULT rc = 0;
+ unsigned char *stream_start = *stream; /* copy for integrity check */
+ uint32_t stream_size_start = *stream_size;
+
+ printf(" TPM_PermanentAll_Load:\n");
+ /* check format tag */
+ /* In the future, if multiple formats are supported, this check will be replaced by a 'switch'
+ on the tag */
+ if (rc == 0) {
+ rc = TPM_CheckTag(TPM_TAG_NVSTATE_V1, stream, stream_size);
+ }
+ /* TPM_PERMANENT_DATA deserialize from stream */
+ if (rc == 0) {
+ rc = TPM_PermanentData_Load(&(tpm_state->tpm_permanent_data),
+ stream, stream_size, TRUE);
+ }
+ /* TPM_PERMANENT_FLAGS deserialize from stream */
+ if (rc == 0) {
+ rc = TPM_PermanentFlags_Load(&(tpm_state->tpm_permanent_flags),
+ stream, stream_size);
+ }
+ /* owner evict keys deserialize from stream */
+ if (rc == 0) {
+ rc = TPM_KeyHandleEntries_OwnerEvictLoad(tpm_state->tpm_key_handle_entries,
+ stream, stream_size);
+ }
+ /* NV defined space deserialize from stream */
+ if (rc == 0) {
+ rc = TPM_NVIndexEntries_Load(&(tpm_state->tpm_nv_index_entries),
+ stream, stream_size);
+ }
+ /* sanity check the stream size */
+ if (rc == 0) {
+ if (*stream_size != TPM_DIGEST_SIZE) {
+ printf("TPM_PermanentAll_Load: Error (fatal) stream size %u not %u\n",
+ *stream_size, TPM_DIGEST_SIZE);
+ rc = TPM_FAIL;
+ }
+ }
+ /* check the integrity digest */
+ if (rc == 0) {
+ printf(" TPM_PermanentAll_Load: Checking integrity digest\n");
+ rc = TPM_SHA1_Check(*stream, /* currently points to integrity digest */
+ stream_size_start - TPM_DIGEST_SIZE, stream_start,
+ 0, NULL);
+ }
+ /* remove the integrity digest from the stream */
+ if (rc == 0) {
+ *stream_size -= TPM_DIGEST_SIZE;
+ }
+ return rc;
+}
+
+/* TPM_PermanentAll_Store() serializes all TPM NV data into a stream that can be restored through
+ TPM_PermanentAll_Load().
+
+ The two functions must be kept in sync.
+
+ Data includes TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, Owner Evict keys, and NV defined space.
+
+ The TPM_STORE_BUFFER, buffer and length are returned for convenience.
+
+ This has two uses:
+
+ - It is called before the actual NV store to serialize the data
+ - It is called by TPM_NV_DefineSpace to determine if there is enough NV space for the new index
+*/
+
+TPM_RESULT TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer, /* freed by caller */
+ const unsigned char **buffer,
+ uint32_t *length,
+ tpm_state_t *tpm_state)
+{
+ TPM_RESULT rc = 0;
+ TPM_DIGEST tpm_digest;
+
+ printf(" TPM_PermanentAll_Store:\n");
+ /* overall format tag */
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_V1);
+ }
+ /* serialize TPM_PERMANENT_DATA */
+ if (rc == 0) {
+ rc = TPM_PermanentData_Store(sbuffer,
+ &(tpm_state->tpm_permanent_data), TRUE);
+ }
+ /* serialize TPM_PERMANENT_FLAGS */
+ if (rc == 0) {
+ rc = TPM_PermanentFlags_Store(sbuffer,
+ &(tpm_state->tpm_permanent_flags));
+ }
+ /* serialize owner evict keys */
+ if (rc == 0) {
+ rc = TPM_KeyHandleEntries_OwnerEvictStore(sbuffer,
+ tpm_state->tpm_key_handle_entries);
+ }
+ /* serialize NV defined space */
+ if (rc == 0) {
+ rc = TPM_NVIndexEntries_Store(sbuffer,
+ &(tpm_state->tpm_nv_index_entries));
+ }
+ if (rc == 0) {
+ /* get the current serialized buffer and its length */
+ TPM_Sbuffer_Get(sbuffer, buffer, length);
+ /* generate the integrity digest */
+ rc = TPM_SHA1(tpm_digest,
+ *length, *buffer,
+ 0, NULL);
+ }
+ /* append the integrity digest to the stream */
+ if (rc == 0) {
+ printf(" TPM_PermanentAll_Store: Appending integrity digest\n");
+ rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE);
+ }
+ /* get the final serialized buffer and its length */
+ if (rc == 0) {
+ TPM_Sbuffer_Get(sbuffer, buffer, length);
+ }
+ return rc;
+}
+
+/* TPM_PermanentAll_NVLoad()
+
+ Deserialize the TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys, and NV defined
+ space from a stream read from the NV file TPM_PERMANENT_ALL_NAME.
+
+ Returns:
+
+ 0 success
+ TPM_RETRY if file does not exist (first time)
+ TPM_FAIL on failure to load (fatal), since they should never occur
+*/
+
+TPM_RESULT TPM_PermanentAll_NVLoad(tpm_state_t *tpm_state)
+{
+ TPM_RESULT rc = 0;
+ unsigned char *stream = NULL;
+ unsigned char *stream_start = NULL;
+ uint32_t stream_size;
+
+ printf(" TPM_PermanentAll_NVLoad:\n");
+ if (rc == 0) {
+ /* try loading from NVRAM */
+ /* Returns TPM_RETRY on non-existent file */
+ rc = TPM_NVRAM_LoadData(&stream, /* freed @1 */
+ &stream_size,
+ tpm_state->tpm_number,
+ TPM_PERMANENT_ALL_NAME);
+ }
+ /* deserialize from stream */
+ if (rc == 0) {
+ stream_start = stream; /* save starting point for free() */
+ rc = TPM_PermanentAll_Load(tpm_state, &stream, &stream_size);
+ if (rc != 0) {
+ printf("TPM_PermanentAll_NVLoad: Error (fatal) loading deserializing NV state\n");
+ rc = TPM_FAIL;
+ }
+ }
+ free(stream_start); /* @1 */
+ return rc;
+}
+
+/* TPM_PermanentAll_NVStore() serializes all NV data and stores it in the NV file
+ TPM_PERMANENT_ALL_NAME
+
+ If the writeAllNV flag is FALSE, the function is a no-op, and returns the input 'rcIn'.
+
+ If writeAllNV is TRUE and rcIn is not TPM_SUCCESS, this indicates that the ordinal
+ modified the in-memory TPM_PERMANENT_DATA and/or TPM_PERMANENT_FLAGS structures (perhaps only
+ partially) and then detected an error. Since the command is failing, roll back the structure by
+ reading the NV file. If the read then fails, this is a fatal error.
+
+ Similarly, if writeAllNV is TRUE and the actual NV write fails, this is a fatal error.
+*/
+
+TPM_RESULT TPM_PermanentAll_NVStore(tpm_state_t *tpm_state,
+ TPM_BOOL writeAllNV,
+ TPM_RESULT rcIn)
+{
+ TPM_RESULT rc = 0;
+ TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */
+ const unsigned char *buffer;
+ uint32_t length;
+ TPM_NV_DATA_ST *tpm_nv_data_st = NULL; /* array of saved NV index volatile flags */
+
+ printf(" TPM_PermanentAll_NVStore: write flag %u\n", writeAllNV);
+ TPM_Sbuffer_Init(&sbuffer); /* freed @1 */
+ if (writeAllNV) {
+ if (rcIn == TPM_SUCCESS) {
+ /* serialize state to be written to NV */
+ if (rc == 0) {
+ rc = TPM_PermanentAll_Store(&sbuffer,
+ &buffer, &length,
+ tpm_state);
+ }
+ /* validate the length of the stream against the maximum provided NV space */
+ if (rc == 0) {
+ printf(" TPM_PermanentAll_NVStore: Require %u bytes\n", length);
+ if (length > TPM_MAX_NV_SPACE) {
+ printf("TPM_PermanentAll_NVStore: Error, No space, need %u max %u\n",
+ length, TPM_MAX_NV_SPACE);
+ rc = TPM_NOSPACE;
+ }
+ }
+ /* store the buffer in NVRAM */
+ if (rc == 0) {
+ rc = TPM_NVRAM_StoreData(buffer,
+ length,
+ tpm_state->tpm_number,
+ TPM_PERMANENT_ALL_NAME);
+ }
+ if (rc != 0) {
+ printf("TPM_PermanentAll_NVStore: Error (fatal), "
+ "NV structure in-memory caches are in invalid state\n");
+ rc = TPM_FAIL;
+ }
+ }
+ else {
+ /* An in-memory structure was altered, but the ordinal had a subsequent error. Since
+ the structure is in an invalid state, roll back to the previous value by reading the
+ NV file. */
+ printf(" TPM_PermanentAll_NVStore: Ordinal error, "
+ "rolling back NV structure cache\n");
+ /* Save a copy of the NV defined space volatile state. It is not stored in NV, so it
+ will be destroyed during the rollback. */
+ /* get a copy of the NV volatile flags, to be used during a rollback */
+ if (rc == 0) {
+ rc = TPM_NVIndexEntries_GetVolatile(&tpm_nv_data_st, /* freed @2 */
+ &(tpm_state->tpm_nv_index_entries));
+ }
+ /* Returns TPM_RETRY on non-existent file */
+ if (rc == 0) {
+ printf(" TPM_PermanentAllNVStore: Deleting TPM_PERMANENT_DATA structure\n");
+ TPM_PermanentData_Delete(&(tpm_state->tpm_permanent_data), TRUE);
+ printf(" TPM_PermanentAllNVStore: Deleting owner evict keys\n");
+ TPM_KeyHandleEntries_OwnerEvictDelete(tpm_state->tpm_key_handle_entries);
+ printf(" TPM_PermanentAllNVStore: Deleting NV defined space \n");
+ TPM_NVIndexEntries_Delete(&(tpm_state->tpm_nv_index_entries));
+ printf(" TPM_PermanentAllNVStore: "
+ "Rereading TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys\n");
+ /* re-allocate TPM_PERMANENT_DATA data structures */
+ rc = TPM_PermanentData_Init(&(tpm_state->tpm_permanent_data), TRUE);
+ }
+ if (rc == 0) {
+ rc = TPM_PermanentAll_NVLoad(tpm_state);
+ }
+ if (rc == 0) {
+ rc = TPM_NVIndexEntries_SetVolatile(tpm_nv_data_st,
+ &(tpm_state->tpm_nv_index_entries));
+ }
+ /* after a successful rollback, return the ordinal's original error code */
+ if (rc == 0) {
+ rc = rcIn;
+ }
+ /* a failure during rollback is fatal */
+ else {
+ printf("TPM_PermanentAll_NVStore: Error (fatal), "
+ "Permanent Data, Flags, or owner evict keys structure is invalid\n");
+ rc = TPM_FAIL;
+ }
+
+ }
+ }
+ /* no write required, no-op */
+ else {
+ rc = rcIn;
+ }
+ TPM_Sbuffer_Delete(&sbuffer); /* @1 */
+ free(tpm_nv_data_st); /* @2 */
+ return rc;
+}
+
+/* TPM_PermanentAll_NVDelete() deletes ann NV data in the NV file TPM_PERMANENT_ALL_NAME.
+
+ If mustExist is TRUE, returns an error if the file does not exist.
+
+ It does not delete the in-memory copy.
+*/
+
+TPM_RESULT TPM_PermanentAll_NVDelete(uint32_t tpm_number,
+ TPM_BOOL mustExist)
+{
+ TPM_RESULT rc = 0;
+
+ printf(" TPM_PermanentAll_NVDelete:\n");
+ /* remove the NVRAM file */
+ if (rc == 0) {
+ rc = TPM_NVRAM_DeleteName(tpm_number,
+ TPM_PERMANENT_ALL_NAME,
+ mustExist);
+ }
+ return rc;
+}
+
+/* TPM_PermanentAll_IsSpace() determines if there is enough NV space for the serialized NV state.
+
+ It does this by serializing the entire state and comparing the length to the configured maximum.
+*/
+
+TPM_RESULT TPM_PermanentAll_IsSpace(tpm_state_t *tpm_state)
+{
+ TPM_RESULT rc = 0;
+ TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */
+ const unsigned char *buffer;
+ uint32_t length;
+
+ printf("TPM_PermanentAll_IsSpace :\n");
+ TPM_Sbuffer_Init(&sbuffer); /* freed @1 */
+ if (rc == 0) {
+ rc = TPM_PermanentAll_Store(&sbuffer,
+ &buffer, &length,
+ tpm_state);
+ }
+ if (rc == 0) {
+ printf(" TPM_PermanentAll_IsSpace: Require %u bytes\n", length);
+ if (length > TPM_MAX_NV_SPACE) {
+ printf("TPM_PermanentAll_IsSpace: No space, need %u max %u\n",
+ length, TPM_MAX_NV_SPACE);
+ rc = TPM_NOSPACE;
+ }
+ }
+ TPM_Sbuffer_Delete(&sbuffer); /* @1 */
+ return rc;
+}
+
+/* TPM_PermanentAll_GetSpace() returns the NV free space.
+
+ It does this by serializing the entire state and comparing the length to the configured maximum.
+*/
+
+TPM_RESULT TPM_PermanentAll_GetSpace(uint32_t *bytes_free,
+ tpm_state_t *tpm_state)
+{
+ TPM_RESULT rc = 0;
+ TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */
+ const unsigned char *buffer;
+ uint32_t length;
+
+ printf(" TPM_NVRAM_IsSpace:\n");
+ TPM_Sbuffer_Init(&sbuffer); /* freed @1 */
+ if (rc == 0) {
+ rc = TPM_PermanentAll_Store(&sbuffer,
+ &buffer, &length,
+ tpm_state);
+ }
+ if (rc == 0) {
+ printf(" TPM_PermanentAll_GetSpace: Used %u max %u bytes\n", length, TPM_MAX_NV_SPACE);
+ if (length > TPM_MAX_NV_SPACE) {
+ /* This should never occur */
+ printf("TPM_PermanentAll_GetSpace: Error (fatal) Used more than maximum\n");
+ rc = TPM_FAIL;
+ }
+ }
+ if (rc == 0) {
+ *bytes_free = TPM_MAX_NV_SPACE - length;
+ printf(" TPM_PermanentAll_GetSpace: Free space %u\n", *bytes_free);
+ }
+ TPM_Sbuffer_Delete(&sbuffer); /* @1 */
+ return rc;
+}
+