blob: 27f03445ef38730d06cb921a6326ec4804beeacc [file] [log] [blame]
/* Software-based Trusted Platform Module (TPM) Emulator
* Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
*
* This module is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This module is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* $Id: tpm_startup.c 367 2010-02-13 15:52:18Z mast $
*/
#include "tpm_emulator.h"
#include "tpm_commands.h"
#include "tpm_data.h"
#include "tpm_handles.h"
/*
* Admin Startup and State ([TPM_Part3], Section 3)
* This section describes the commands that start a TPM.
*/
void TPM_Init(TPM_STARTUP_TYPE startupType)
{
info("TPM_Init()");
/* startup the TPM */
tpmData.stany.flags.postInitialise = TRUE;
TPM_SelfTestFull();
TPM_Startup(startupType);
}
#define SET_TO_ZERO(a) memset(a, 0x00, sizeof(*a))
#define SET_TO_0xFF(a) memset(a, 0xff, sizeof(*a))
#define SET_TO_RAND(a) tpm_get_random_bytes(a, sizeof(*a))
TPM_RESULT TPM_Startup(TPM_STARTUP_TYPE startupType)
{
int i;
info("TPM_Startup(%d)", startupType);
if (tpmData.stany.flags.postInitialise == FALSE) return TPM_INVALID_POSTINIT;
/* reset STANY_FLAGS */
SET_TO_ZERO(&tpmData.stany.flags);
tpmData.stany.flags.tag = TPM_TAG_STANY_FLAGS;
/* set data and flags according to the given startup type */
if (startupType == TPM_ST_CLEAR) {
/* reset STANY_DATA (invalidates ALL sessions) */
SET_TO_ZERO(&tpmData.stany.data);
tpmData.stany.data.tag = TPM_TAG_STANY_DATA;
/* init session-context nonce */
SET_TO_RAND(&tpmData.stany.data.contextNonceSession);
/* reset PCR values */
for (i = 0; i < TPM_NUM_PCR; i++) {
if (tpmData.permanent.data.pcrAttrib[i].pcrReset)
SET_TO_0xFF(&tpmData.permanent.data.pcrValue[i].digest);
else
SET_TO_ZERO(&tpmData.permanent.data.pcrValue[i].digest);
}
/* reset STCLEAR_FLAGS */
SET_TO_ZERO(&tpmData.stclear.flags);
tpmData.stclear.flags.tag = TPM_TAG_STCLEAR_FLAGS;
tpmData.stclear.flags.deactivated = tpmData.permanent.flags.deactivated;
/* reset STCLEAR_DATA */
SET_TO_ZERO(&tpmData.stclear.data);
tpmData.stclear.data.tag = TPM_TAG_STCLEAR_DATA;
/* flush volatiles and PCR dependent keys */
for (i = 0; i < TPM_MAX_KEYS; i++) {
if (tpmData.permanent.data.keys[i].payload
&& ((tpmData.permanent.data.keys[i].keyFlags & TPM_KEY_FLAG_VOLATILE)
|| tpmData.permanent.data.keys[i].parentPCRStatus))
TPM_FlushSpecific(INDEX_TO_KEY_HANDLE(i), TPM_RT_KEY);
}
/* init key-context nonce */
SET_TO_RAND(&tpmData.stclear.data.contextNonceKey);
/* invalidate counter handle */
tpmData.stclear.data.countID = TPM_INVALID_HANDLE;
/* reset NV read and write flags */
for (i = 0; i < TPM_MAX_NVS; i++) {
tpmData.permanent.data.nvStorage[i].pubInfo.bReadSTClear = FALSE;
tpmData.permanent.data.nvStorage[i].pubInfo.bWriteSTClear = FALSE;
}
} else if (startupType == TPM_ST_STATE) {
if (!tpmData.permanent.flags.dataRestored) {
error("restoring permanent data failed");
tpmData.permanent.data.testResult = "tpm_restore_permanent_data() failed";
tpmData.permanent.flags.selfTestSucceeded = FALSE;
return TPM_FAIL;
}
} else if (startupType == TPM_ST_DEACTIVATED) {
tpmData.stclear.flags.deactivated = TRUE;
/* invalidate any saved state */
tpm_erase_permanent_data();
} else {
return TPM_BAD_PARAMETER;
}
tpmData.stany.flags.postInitialise = FALSE;
tpmData.stany.flags.TOSPresent = FALSE;
return TPM_SUCCESS;
}
TPM_RESULT TPM_SaveState()
{
info("TPM_SaveState()");
if (tpmData.permanent.flags.selfTestSucceeded && !tpmData.stclear.flags.deactivated) {
return (tpm_store_permanent_data()) ? TPM_FAIL : TPM_SUCCESS;
} else {
debug("TPM is deactivated or in fail-stop mode, thus the permanent data is not stored");
return TPM_SUCCESS;
}
}