summaryrefslogtreecommitdiffstats
path: root/src/tpm12/tpm_admin.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 21:41:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 21:41:43 +0000
commit92cccad89d1c12b39165d5f0ed7ccd2d44965a1a (patch)
treef59a2764cd8c50959050a428bd8fc935138df750 /src/tpm12/tpm_admin.c
parentInitial commit. (diff)
downloadlibtpms-92cccad89d1c12b39165d5f0ed7ccd2d44965a1a.tar.xz
libtpms-92cccad89d1c12b39165d5f0ed7ccd2d44965a1a.zip
Adding upstream version 0.9.2.upstream/0.9.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tpm12/tpm_admin.c')
-rw-r--r--src/tpm12/tpm_admin.c2010
1 files changed, 2010 insertions, 0 deletions
diff --git a/src/tpm12/tpm_admin.c b/src/tpm12/tpm_admin.c
new file mode 100644
index 0000000..28d33bb
--- /dev/null
+++ b/src/tpm12/tpm_admin.c
@@ -0,0 +1,2010 @@
+/********************************************************************************/
+/* */
+/* TPM Admin Test and Opt-in */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: tpm_admin.c 4505 2011-03-20 17:43:27Z 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 "tpm_auth.h"
+#include "tpm_cryptoh.h"
+#include "tpm_digest.h"
+#include "tpm_debug.h"
+#include "tpm_error.h"
+#include "tpm_key.h"
+#include "tpm_nonce.h"
+#include "tpm_permanent.h"
+#include "tpm_process.h"
+#include "tpm_secret.h"
+#include "tpm_ticks.h"
+#include "tpm_time.h"
+
+#include "tpm_admin.h"
+
+/* The Software TPM Self Test works as follows:
+
+ TPM_LimitedSelfTestCommon(void) - self tests which affect all TPM's
+ TPM_LimitedSelfTestTPM(tpm_state) - self test per virtual TPM
+
+ TPM_ContinueSelfTestCmd(tpm_state) - currently does nothing
+ on failure, sets tpm_state->testState to failure for the virtual TPM
+
+ TPM_SelfTestFullCmd(tpm_state) calls
+ TPM_LimitedSelfTestTPM()
+ TPM_ContinueSelfTestCmd(tpm_state)
+ on failure, sets tpm_state->testState to failure for the virtual TPM
+
+ TPM_MainInit(void) calls
+ TPM_LimitedSelfTestCommon(void)
+ TPM_LimitedSelfTestTPM(tpm_state)
+
+ TPM_Process_ContinueSelfTest(tpm_state) calls either (depending on FIPS mode)
+ TPM_SelfTestFullCmd(tpm_state)
+ TPM_ContinueSelfTestCmd(tpm_state)
+
+ TPM_Process_SelfTestFull(tpm_state) calls
+ TPM_SelfTestFullCmd(tpm_state)
+
+ The Software TPM assumes that the coprocessor has run self tests before the application code even
+ begins. So this code doesn't do any real testing of the underlying hardware. This simplifies
+ the state machine, since TPM_Process_ContinueSelfTest doesn't require a separate thread.
+*/
+
+/* TPM_LimitedSelfTestCommon() provides the assurance that a selected subset of TPM commands will
+ perform properly. The limited nature of the self-test allows the TPM to be functional in as short
+ of time as possible. all the TPM tests.
+
+ The caller is responsible for setting the shutdown state on error.
+*/
+
+TPM_RESULT TPM_LimitedSelfTestCommon(void)
+{
+ TPM_RESULT rc = 0;
+ uint32_t tv_sec;
+ uint32_t tv_usec;
+
+ printf(" TPM_LimitedSelfTestCommon:\n");
+#if 0
+ if (rc == 0) {
+ rc = TPM_Sbuffer_Test();
+ }
+#endif
+ if (rc == 0) {
+ rc = TPM_Uint64_Test();
+ }
+ if (rc == 0) {
+ rc = TPM_CryptoTest();
+ }
+ /* test time of day clock */
+ if (rc == 0) {
+ rc = TPM_GetTimeOfDay(&tv_sec, &tv_usec);
+ }
+ if (rc != 0) {
+ rc = TPM_FAILEDSELFTEST;
+ }
+ return rc;
+}
+
+TPM_RESULT TPM_LimitedSelfTestTPM(tpm_state_t *tpm_state)
+{
+ TPM_RESULT rc = 0;
+ TPM_NONCE clrData;
+ TPM_SIZED_BUFFER encData;
+ TPM_NONCE decData;
+ uint32_t decLength;
+
+
+ printf(" TPM_LimitedSelfTestTPM:\n");
+ TPM_SizedBuffer_Init(&encData); /* freed @1 */
+
+ /* 8. The TPM MUST check the following: */
+ /* a. RNG functionality */
+ /* NOTE Tested by coprocessor boot */
+ /* b. Reading and extending the integrity registers. The self-test for the integrity registers
+ will leave the integrity registers in a known state. */
+ /* NOTE Since there is nothing special about the PCR's, the common TPM_CryptoTest() is
+ sufficient */
+ /* c. Testing the EK integrity, if it exists */
+ /* i. This requirement specifies that the TPM will verify that the endorsement key pair can
+ encrypt and decrypt a known value. This tests the RSA engine. If the EK has not yet been
+ generated the TPM action is manufacturer specific. */
+ if ((rc == 0) &&
+ (tpm_state->tpm_permanent_data.endorsementKey.keyUsage != TPM_KEY_UNINITIALIZED)) {
+ /* check the key integrity */
+ if (rc == 0) {
+ rc = TPM_Key_CheckPubDataDigest(&(tpm_state->tpm_permanent_data.endorsementKey));
+ }
+ /* encrypt */
+ if (rc == 0) {
+ TPM_Nonce_Generate(clrData);
+ rc = TPM_RSAPublicEncrypt_Key(&encData, /* output */
+ clrData, /* input */
+ TPM_NONCE_SIZE, /* input */
+ &(tpm_state->tpm_permanent_data.endorsementKey));
+ }
+ /* decrypt */
+ if (rc == 0) {
+ rc = TPM_RSAPrivateDecryptH(decData, /* decrypted data */
+ &decLength, /* length of data put into decrypt_data */
+ TPM_NONCE_SIZE, /* size of decrypt_data buffer */
+ encData.buffer,
+ encData.size,
+ &(tpm_state->tpm_permanent_data.endorsementKey));
+ }
+ /* verify */
+ if (rc == 0) {
+ if (decLength != TPM_NONCE_SIZE) {
+ printf("TPM_LimitedSelfTestTPM: Error, decrypt length %u should be %u\n",
+ decLength, TPM_NONCE_SIZE);
+ rc = TPM_FAILEDSELFTEST;
+ }
+ }
+ if (rc == 0) {
+ rc = TPM_Nonce_Compare(clrData, decData);
+ }
+ }
+ /* d. The integrity of the protected capabilities of the TPM */
+ /* i. This means that the TPM must ensure that its "microcode" has not changed, and not that a
+ test must be run on each function. */
+ /* e. Any tamper-resistance markers */
+ /* i. The tests on the tamper-resistance or tamper-evident markers are under programmable
+ control. */
+ /* There is no requirement to check tamper-evident tape or the status of epoxy surrounding the
+ case. */
+ /* NOTE: Done by coprocessor POST */
+ /* 9. The TPM SHOULD check the following: */
+ /* a. The hash functionality */
+ /* i. This check will hash a known value and compare it to an expected result. There is no
+ requirement to accept external data to perform the check. */
+ /* ii. The TPM MAY support a test using external data. */
+ /* NOTE: Done by TPM_CryptoTest() */
+ /* b. Any symmetric algorithms */
+ /* i. This check will use known data with a random key to encrypt and decrypt the data */
+ /* NOTE: Done by TPM_CryptoTest() */
+ /* c. Any additional asymmetric algorithms */
+ /* i. This check will use known data to encrypt and decrypt. */
+ /* NOTE: So far only RSA is supported */
+ /* d. The key-wrapping mechanism */
+ /* i. The TPM should wrap and unwrap a key. The TPM MUST NOT use the endorsement key pair for
+ this test. */
+ /* NOTE: There is nothing special about serializing a TPM_STORE_ASYMKEY */
+ /* e. Any other internal mechanisms */
+ TPM_SizedBuffer_Delete(&encData); /* @1 */
+ if (rc != 0) {
+ rc = TPM_FAILEDSELFTEST;
+ }
+ /* set the TPM test state */
+ if ((rc == 0) && (tpm_state->testState != TPM_TEST_STATE_FAILURE)) {
+ printf(" TPM_LimitedSelfTestTPM: Set testState to %u \n", TPM_TEST_STATE_LIMITED);
+ tpm_state->testState = TPM_TEST_STATE_LIMITED;
+ }
+ else {
+ printf(" TPM_LimitedSelfTestTPM: Set testState to %u \n", TPM_TEST_STATE_FAILURE);
+ tpm_state->testState = TPM_TEST_STATE_FAILURE;
+ }
+ return rc;
+}
+
+/* TPM_ContinueSelfTestCmd() runs the continue self test actions
+
+*/
+
+TPM_RESULT TPM_ContinueSelfTestCmd(tpm_state_t *tpm_state)
+{
+ TPM_RESULT rc = 0;
+
+ /* NOTE all done by limited self test */
+ printf(" TPM_ContinueSelfTestCmd:\n");
+ if (rc != 0) {
+ rc = TPM_FAILEDSELFTEST;
+ }
+ /* set the TPM test state */
+ if (rc == 0) {
+ printf(" TPM_ContinueSelfTestCmd: Set testState to %u \n", TPM_TEST_STATE_FULL);
+ tpm_state->testState = TPM_TEST_STATE_FULL;
+ }
+ else {
+ printf(" TPM_ContinueSelfTestCmd: Set testState to %u \n", TPM_TEST_STATE_FAILURE);
+ tpm_state->testState = TPM_TEST_STATE_FAILURE;
+ }
+ return rc;
+}
+
+/* TPM_SelfTestFullCmd is a request to have the TPM perform another complete self-test. This test
+ will take some time but provides an accurate assessment of the TPM's ability to perform all
+ operations.
+
+ Runs the actions of self test full.
+*/
+
+TPM_RESULT TPM_SelfTestFullCmd(tpm_state_t *tpm_state)
+{
+ TPM_RESULT rc = 0;
+
+ printf(" TPM_SelfTestFullCmd\n");
+ if (rc == 0) {
+ rc = TPM_LimitedSelfTestTPM(tpm_state);
+ }
+ if (rc == 0) {
+ rc = TPM_ContinueSelfTestCmd(tpm_state);
+ }
+ return rc;
+}
+
+/* 4.1 TPM_SelfTestFull rev 88
+
+ SelfTestFull tests all of the TPM capabilities.
+
+ Unlike TPM_ContinueSelfTest, which may optionally return immediately and then perform the tests,
+ TPM_SelfTestFull always performs the tests and then returns success or failure.
+*/
+
+TPM_RESULT TPM_Process_SelfTestFull(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_SelfTestFull: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_NO_LOCKOUT));
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag0(tag);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_SelfTestFull: Error, command has %u extra bytes\n", paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /*
+ Processing
+ */
+ /* 1. TPM_SelfTestFull SHALL cause a TPM to perform self-test of each TPM internal function. */
+ /* a. If the self-test succeeds, return TPM_SUCCESS. */
+ /* b. If the self-test fails, return TPM_FAILEDSELFTEST. */
+ /* 2. Failure of any test results in overall failure, and the TPM goes into failure mode. */
+ /* 3. If the TPM has not executed the action of TPM_ContinueSelfTest, the TPM */
+ /* a. MAY perform the full self-test. */
+ /* b. MAY return TPM_NEEDS_SELFTEST. */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_SelfTestFullCmd(tpm_state);
+ }
+ /*
+ response
+ */
+ if (rcf == 0) {
+ printf("TPM_Process_SelfTestFull: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ return rcf;
+}
+
+/* 4.2 TPM_ContinueSelfTest rev 88
+
+ TPM_Process_ContinueSelfTest informs the TPM that it may complete the self test of all TPM
+ functions.
+
+ The TPM may return success immediately and then perform the self-test, or it may perform the
+ self-test and then return success or failure.
+
+ 1. Prior to executing the actions of TPM_ContinueSelfTest, if the TPM receives a command C1 that
+ uses an untested TPM function, the TPM MUST take one of these actions:
+
+ a. The TPM MAY return TPM_NEEDS_SELFTEST
+
+ i. This indicates that the TPM has not tested the internal resources required to execute C1.
+
+ ii. The TPM does not execute C1.
+
+ iii. The caller MUST issue TPM_ContinueSelfTest before re-issuing the command C1.
+
+ (1) If the TPM permits TPM_SelfTestFull prior to completing the actions of TPM_ContinueSelfTest,
+ the caller MAY issue TPM_SelfTestFull rather than TPM_ContinueSelfTest.
+
+ b. The TPM MAY return TPM_DOING_SELFTEST
+
+ i. This indicates that the TPM is doing the actions of TPM_ContinueSelfTest implicitly, as if the
+ TPM_ContinueSelfTest command had been issued.
+
+ ii. The TPM does not execute C1.
+
+ iii. The caller MUST wait for the actions of TPM_ContinueSelfTest to complete before reissuing
+ the command C1.
+
+ c. The TPM MAY return TPM_SUCCESS or an error code associated with C1.
+
+ i. This indicates that the TPM has completed the actions of TPM_ContinueSelfTest and has
+ completed the command C1.
+
+ ii. The error code MAY be TPM_FAILEDSELFTEST.
+*/
+
+TPM_RESULT TPM_Process_ContinueSelfTest(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_ContinueSelfTest: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_NO_LOCKOUT));
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag0(tag);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_ContinueSelfTest: Error, command has %u extra bytes\n", paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /*
+ Processing
+ */
+ if (returnCode == TPM_SUCCESS) {
+ /* 1. If TPM_PERMANENT_FLAGS -> FIPS is TRUE or TPM_PERMANENT_FLAGS -> TPMpost is TRUE */
+ if ((tpm_state->tpm_permanent_flags.FIPS) ||
+ (tpm_state->tpm_permanent_flags.TPMpost)) {
+ /* a. The TPM MUST run ALL self-tests */
+ returnCode = TPM_SelfTestFullCmd(tpm_state);
+ }
+ /* 2. Else */
+ else {
+ /* a. The TPM MUST complete all self-tests that are outstanding */
+ /* i. Instead of completing all outstanding self-tests the TPM MAY run all self-tests */
+ returnCode = TPM_ContinueSelfTestCmd(tpm_state);
+ }
+ }
+ /* 3. The TPM either
+ a. MAY immediately return TPM_SUCCESS
+ i. When TPM_ContinueSelfTest finishes execution, it MUST NOT respond to the caller with a
+ return code.
+ b. MAY complete the self-test and then return TPM_SUCCESS or TPM_FAILEDSELFTEST.
+ NOTE Option 3.b. implemented
+ */
+ /*
+ response
+ */
+ if (rcf == 0) {
+ printf("TPM_Process_ContinueSelfTest: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ return rcf;
+}
+
+/* 4.3 TPM_GetTestResult rev 96
+
+ TPM_GetTestResult provides manufacturer specific information regarding the results of the self
+ test. This command will work when the TPM is in self test failure mode. The reason for allowing
+ this command to operate in the failure mode is to allow TPM manufacturers to obtain diagnostic
+ information.
+*/
+
+TPM_RESULT TPM_Process_GetTestResult(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+ TPM_SIZED_BUFFER outData; /* The outData this is manufacturer specific */
+
+ printf("TPM_Process_GetTestResult: Ordinal Entry\n");
+ TPM_SizedBuffer_Init(&outData); /* freed @1 */
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ /* This command will work when the TPM is in self test failure or limited operation mode. */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_NO_LOCKOUT);
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag0(tag);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_GetTestResult: Error, command has %u extra bytes\n", paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /*
+ Processing
+ */
+ /* 1. The TPM SHALL respond to this command with a manufacturer specific block of information
+ that describes the result of the latest self test. */
+ /* 2. The information MUST NOT contain any data that uniquely identifies an individual TPM. */
+ /* allocate some reasonable area */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_SizedBuffer_Allocate(&outData, 128);
+ }
+ /* for now, just return the state of shutdown as a printable string */
+ if (returnCode == TPM_SUCCESS) {
+ size_t len = outData.size;
+ /* cast because TPM_SIZED_BUFFER is typically unsigned (binary) but snprintf expects char */
+ outData.size = snprintf((char *)(outData.buffer), len,
+ "Shutdown %08x\n", tpm_state->testState);
+ if (outData.size >= len) {
+ printf("TPM_Process_GetTestResult: Error (fatal), buffer too small\n");
+ returnCode = TPM_FAIL;
+ }
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_GetTestResult: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* return outData */
+ returnCode = TPM_SizedBuffer_Store(response, &outData);
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ /*
+ cleanup
+ */
+ TPM_SizedBuffer_Delete(&outData); /* @1 */
+ return rcf;
+}
+
+/* 5.1 TPM_SetOwnerInstall rev 100
+
+ When enabled but without an owner this command sets the PERMANENT flag that allows or disallows
+ the ability to insert an owner.
+ */
+
+TPM_RESULT TPM_Process_SetOwnerInstall(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* input parameters */
+ TPM_BOOL state; /* State to which ownership flag is to be set. */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */
+ TPM_BOOL physicalPresence;
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_SetOwnerInstall: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* get state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_LoadBool(&state, &command, &paramSize);
+ }
+ /* save the ending point of inParam's for authorization */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag0(tag);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_SetOwnerInstall: Error, command has %u extra bytes\n", paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /*
+ Processing
+ */
+ if (returnCode == TPM_SUCCESS) {
+ /* 1. If the TPM has a current owner, this command immediately returns with TPM_SUCCESS. */
+ if (tpm_state->tpm_permanent_data.ownerInstalled) {
+ printf("TPM_Process_SetOwnerInstall: Already current owner\n");
+ }
+ /* If the TPM does not have a current owner */
+ else {
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_SetOwnerInstall: No current owner\n");
+ /* 2. The TPM validates the assertion of physical presence. The TPM then sets the
+ value of TPM_PERMANENT_FLAGS -> ownership to the value in state.
+ */
+ returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (!physicalPresence) {
+ printf("TPM_Process_SetOwnerInstall: Error, physicalPresence is FALSE\n");
+ returnCode = TPM_BAD_PRESENCE;
+ }
+ }
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_SetOwnerInstall: Setting ownership to %02x\n", state);
+ TPM_SetCapability_Flag(&writeAllNV, /* altered */
+ &(tpm_state->tpm_permanent_flags.ownership), /* flag */
+ state); /* value */
+ /* Store the permanent flags back to NVRAM */
+ returnCode = TPM_PermanentAll_NVStore(tpm_state,
+ writeAllNV,
+ returnCode);
+ }
+ }
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_SetOwnerInstall: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ return rcf;
+}
+
+/* 5.2 TPM_OwnerSetDisable rev 107
+
+ The TPM owner sets the PERMANENT disable flag to TRUE or FALSE.
+*/
+
+TPM_RESULT TPM_Process_OwnerSetDisable(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* input parameters */
+ TPM_BOOL disableState; /* Value for disable state */
+ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */
+ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
+ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the
+ authorization handle */
+ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner
+ authorization. HMAC key: ownerAuth. */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+ TPM_BOOL authHandleValid = FALSE;
+ TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */
+ TPM_SECRET *hmacKey;
+ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_OwnerSetDisable: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* get disableState parameter */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_LoadBool(&disableState, &command, &paramSize);
+ }
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_OWNER |
+ TPM_CHECK_NO_LOCKOUT));
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag1(tag);
+ }
+ /* get the 'below the line' authorization parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_AuthParams_Get(&authHandle,
+ &authHandleValid,
+ nonceOdd,
+ &continueAuthSession,
+ ownerAuth,
+ &command, &paramSize);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_OwnerSetDisable: Error, command has %u extra bytes\n", paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /* do not terminate sessions if the command did not parse correctly */
+ if (returnCode != TPM_SUCCESS) {
+ authHandleValid = FALSE;
+ }
+ /*
+ Processing
+ */
+ /* 1. The TPM SHALL authenticate the command as coming from the TPM Owner. If unsuccessful, the
+ TPM SHALL return TPM_AUTHFAIL. */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_AuthSessions_GetData(&auth_session_data,
+ &hmacKey,
+ tpm_state,
+ authHandle,
+ TPM_PID_NONE,
+ TPM_ET_OWNER,
+ ordinal,
+ NULL,
+ &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */
+ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */
+ }
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_Authdata_Check(tpm_state,
+ *hmacKey, /* owner HMAC key */
+ inParamDigest,
+ auth_session_data, /* authorization session */
+ nonceOdd, /* Nonce generated by system
+ associated with authHandle */
+ continueAuthSession,
+ ownerAuth); /* Authorization digest for input */
+ }
+ /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS -> disable flag to the value in the
+ disableState parameter. */
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_OwnerSetDisable: Setting disable to %u\n", disableState);
+ TPM_SetCapability_Flag(&writeAllNV, /* altered */
+ &(tpm_state->tpm_permanent_flags.disable), /* flag */
+ disableState); /* value */
+ /* Store the permanent flags back to NVRAM */
+ returnCode = TPM_PermanentAll_NVStore(tpm_state,
+ writeAllNV,
+ returnCode);
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_OwnerSetDisable: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* calculate and set the below the line parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_AuthParams_Set(response,
+ *hmacKey, /* owner HMAC key */
+ auth_session_data,
+ outParamDigest,
+ nonceOdd,
+ continueAuthSession);
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ /* if there was an error, terminate the session. */
+ if (((rcf != 0) ||
+ ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
+ !continueAuthSession) &&
+ authHandleValid) {
+ TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
+ }
+ return rcf;
+}
+
+/* 5.3 TPM_PhysicalEnable rev 87
+
+ Sets the PERMANENT disable flag to FALSE using physical presence as authorization.
+*/
+
+TPM_RESULT TPM_Process_PhysicalEnable(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */
+ TPM_BOOL physicalPresence;
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_PhysicalEnable: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_NO_LOCKOUT));
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag0(tag);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_PhysicalEnable: Error, command has %u extra bytes\n", paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /*
+ Processing
+ */
+ /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (!physicalPresence) {
+ printf("TPM_Process_PhysicalEnable: Error, physicalPresence is FALSE\n");
+ returnCode = TPM_BAD_PRESENCE;
+ }
+ }
+ /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.disable value to FALSE. */
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_PhysicalEnable: Setting disable to FALSE\n");
+ TPM_SetCapability_Flag(&writeAllNV, /* altered */
+ &(tpm_state->tpm_permanent_flags.disable), /* flag */
+ FALSE); /* value */
+ /* Store the permanent flags back to NVRAM */
+ returnCode = TPM_PermanentAll_NVStore(tpm_state,
+ writeAllNV,
+ returnCode);
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_PhysicalEnable: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ return rcf;
+}
+
+/* 5.4 TPM_PhysicalDisable rev 87
+
+ Sets the PERMANENT disable flag to TRUE using physical presence as authorization
+*/
+
+TPM_RESULT TPM_Process_PhysicalDisable(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */
+ TPM_BOOL physicalPresence;
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_PhysicalDisable: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_ENABLED |
+ TPM_CHECK_NO_LOCKOUT));
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag0(tag);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_PhysicalDisable: Error, command has %u extra bytes\n", paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /*
+ Processing
+ */
+ /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (!physicalPresence) {
+ printf("TPM_Process_PhysicalDisable: Error, physicalPresence is FALSE\n");
+ returnCode = TPM_BAD_PRESENCE;
+ }
+ }
+ /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.disable value to TRUE. */
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_PhysicalDisable: Setting disable to TRUE\n");
+ TPM_SetCapability_Flag(&writeAllNV, /* altered */
+ &(tpm_state->tpm_permanent_flags.disable ), /* flag */
+ TRUE); /* value */
+ /* Store the permanent flags back to NVRAM */
+ returnCode = TPM_PermanentAll_NVStore(tpm_state,
+ writeAllNV,
+ returnCode);
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_PhysicalDisable: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ return rcf;
+}
+
+/* 5.5 TPM_PhysicalSetDeactivated rev 105
+
+ Changes the TPM persistent deactivated flag using physical presence as authorization.
+*/
+
+TPM_RESULT TPM_Process_PhysicalSetDeactivated(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* input parameters */
+ TPM_BOOL state; /* State to which deactivated flag is to be set. */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */
+ TPM_BOOL physicalPresence;
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_PhysicalSetDeactivated: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* get state parameter */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_LoadBool(&state, &command, &paramSize);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_PhysicalSetDeactivated: state %02x\n", state);
+ }
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_ENABLED |
+ TPM_CHECK_NO_LOCKOUT));
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag0(tag);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_PhysicalSetDeactivated: Error, command has %u extra bytes\n",
+ paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /*
+ Processing
+ */
+ /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (!physicalPresence) {
+ printf("TPM_Process_PhysicalSetDeactivated: Error, physicalPresence is FALSE\n");
+ returnCode = TPM_BAD_PRESENCE;
+ }
+ }
+ /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.deactivated flag to the value in the state
+ parameter. */
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_PhysicalSetDeactivated: Setting deactivated to %u\n", state);
+ TPM_SetCapability_Flag(&writeAllNV, /* altered */
+ &(tpm_state->tpm_permanent_flags.deactivated), /* flag */
+ state); /* value */
+ /* Store the permanent flags back to NVRAM */
+ returnCode = TPM_PermanentAll_NVStore(tpm_state,
+ writeAllNV,
+ returnCode);
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_PhysicalSetDeactivated: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ return rcf;
+}
+
+/* 5.6 TPM_SetTempDeactivated rev 87
+
+ This command allows the operator of the platform to deactivate the TPM until the next boot of the
+ platform.
+
+ This command requires operator authorization. The operator can provide the authorization by
+ either the assertion of physical presence or presenting the operation authorization value.
+*/
+
+TPM_RESULT TPM_Process_SetTempDeactivated(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* input parameters */
+ TPM_AUTHHANDLE authHandle; /* auth handle for operation validation. Session type must
+ be OIAP. */
+ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
+ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the
+ authorization handle */
+ TPM_AUTHDATA operatorAuth; /* HMAC key: operatorAuth */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+ TPM_BOOL authHandleValid = FALSE;
+ TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
+ TPM_SECRET *hmacKey;
+#if TPM_V12
+ TPM_BOOL physicalPresence;
+#endif
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_SetTempDeactivated: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_ACTIVATED |
+ TPM_CHECK_NO_LOCKOUT));
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+#if TPM_V12
+ returnCode = TPM_CheckRequestTag10(tag);
+#else /* v1.1 is always auth0. This check implicitly bypasses the operatorAuth Actions below. */
+ returnCode = TPM_CheckRequestTag0(tag);
+#endif
+ }
+ /* get the optional 'below the line' authorization parameters */
+ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
+ returnCode = TPM_AuthParams_Get(&authHandle,
+ &authHandleValid,
+ nonceOdd,
+ &continueAuthSession,
+ operatorAuth,
+ &command, &paramSize);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_SetTempDeactivated: Error, command has %u extra bytes\n",
+ paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /* do not terminate sessions if the command did not parse correctly */
+ if (returnCode != TPM_SUCCESS) {
+ authHandleValid = FALSE;
+ }
+ /*
+ Processing
+ */
+ /* 1. If tag = TPM_TAG_REQ_AUTH1_COMMAND */
+ /* a. If TPM_PERMANENT_FLAGS -> operator is FALSE return TPM_NOOPERATOR */
+ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
+ if (!tpm_state->tpm_permanent_flags.tpmOperator) {
+ printf("TPM_Process_SetTempDeactivated: Error, no operator\n");
+ returnCode = TPM_NOOPERATOR;
+ }
+ }
+ /* b. Validate command and parameters using operatorAuth, on error return TPM_AUTHFAIL */
+ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
+ printf(" TPM_Process_SetTempDeactivated: authHandle %08x\n", authHandle);
+ /* get the session data */
+ returnCode =
+ TPM_AuthSessions_GetData(&auth_session_data,
+ &hmacKey,
+ tpm_state,
+ authHandle,
+ TPM_PID_OIAP,
+ 0, /* OSAP entity type */
+ ordinal,
+ NULL,
+ &(tpm_state->tpm_permanent_data.operatorAuth), /* OIAP */
+ NULL); /* OSAP */
+ }
+ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
+ returnCode = TPM_Authdata_Check(tpm_state,
+ *hmacKey, /* operator HMAC key */
+ inParamDigest,
+ auth_session_data, /* authorization session */
+ nonceOdd, /* Nonce generated by system
+ associated with authHandle */
+ continueAuthSession,
+ operatorAuth); /* Authorization digest for input */
+
+ }
+#if TPM_V12 /* v1.1 does not require physical presence */
+ /* 2. Else */
+ /* a. If physical presence is not asserted the TPM MUST return TPM_BAD_PRESENCE */
+ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) {
+ returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
+ }
+ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) {
+ if (!physicalPresence) {
+ printf("TPM_Process_SetTempDeactivated: Error, physicalPresence is FALSE\n");
+ returnCode = TPM_BAD_PRESENCE;
+ }
+ }
+#endif
+ /* 3. The TPM SHALL set the TPM_STCLEAR_FLAGS.deactivated flag to the value TRUE. */
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_SetTempDeactivated: Setting deactivated to TRUE\n");
+ tpm_state->tpm_stclear_flags.deactivated = TRUE;
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_SetTempDeactivated: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* calculate and set the below the line parameters */
+ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
+ returnCode = TPM_AuthParams_Set(response,
+ *hmacKey, /* operator HMAC key */
+ auth_session_data,
+ outParamDigest,
+ nonceOdd,
+ continueAuthSession);
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ /* if there was an error, or continueAuthSession is FALSE, terminate the session */
+ if (((rcf != 0) ||
+ ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
+ !continueAuthSession) &&
+ authHandleValid) {
+ TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
+ }
+ /*
+ cleanup
+ */
+ return rcf;
+}
+
+/* 5.7 TPM_SetOperatorAuth rev 87
+
+ This command allows the setting of the operator authorization value.
+
+ There is no confidentiality applied to the operator authorization as the value is sent under the
+ assumption of being local to the platform. If there is a concern regarding the path between the
+ TPM and the keyboard then unless the keyboard is using encryption and a secure channel an
+ attacker can read the values.
+*/
+
+TPM_RESULT TPM_Process_SetOperatorAuth(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* input parameters */
+ TPM_SECRET operatorAuth; /* The operator authorization */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */
+ TPM_BOOL physicalPresence;
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_SetOperatorAuth: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* get operatorAuth parameter */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_Secret_Load(operatorAuth, &command, &paramSize);
+ }
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag0(tag);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_SetOperatorAuth: Error, command has %u extra bytes\n",
+ paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /*
+ Processing
+ */
+ /* 1. If physical presence is not asserted the TPM MUST return TPM_BAD_PRESENCE */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (!physicalPresence) {
+ printf("TPM_Process_SetOperatorAuth: Error, physicalPresence is FALSE\n");
+ returnCode = TPM_BAD_PRESENCE;
+ }
+ }
+ if (returnCode == TPM_SUCCESS) {
+ /* 2. The TPM SHALL set the TPM_PERSISTENT_DATA -> operatorAuth */
+ TPM_Digest_Copy(tpm_state->tpm_permanent_data.operatorAuth, operatorAuth);
+ /* 3. The TPM SHALL set TPM_PERMANENT_FLAGS -> operator to TRUE */
+ printf("TPM_Process_SetOperatorAuth: Setting operator to TRUE\n");
+ TPM_SetCapability_Flag(&writeAllNV, /* altered */
+ &(tpm_state->tpm_permanent_flags.tpmOperator), /* flag */
+ TRUE); /* value */
+ /* Store the permanent data and flags back to NVRAM */
+ returnCode = TPM_PermanentAll_NVStore(tpm_state,
+ TRUE,
+ returnCode);
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_SetOperatorAuth: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ return rcf;
+}
+
+/* 9.3 TPM_ResetLockValue rev 96
+
+ Command that resets the TPM dictionary attack mitigation values
+
+ This allows the TPM owner to cancel the effect of a number of successive authorization failures.
+
+ If this command itself has an authorization failure, it is blocked for the remainder of the lock
+ out period. This prevents a dictionary attack on the owner authorization using this command.
+
+ It is understood that this command allows the TPM owner to perform a dictionary attack on other
+ authorization values by alternating a trial and this command. Similarly, delegating this command
+ allows the owner's delegate to perform a dictionary attack.
+*/
+
+TPM_RESULT TPM_Process_ResetLockValue(tpm_state_t *tpm_state,
+ TPM_STORE_BUFFER *response,
+ TPM_TAG tag,
+ uint32_t paramSize,
+ TPM_COMMAND_CODE ordinal,
+ unsigned char *command,
+ TPM_TRANSPORT_INTERNAL *transportInternal)
+{
+ TPM_RESULT rcf = 0; /* fatal error precluding response */
+ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
+
+ /* input parameters */
+ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for TPM Owner
+ authorization */
+ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
+ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization
+ session handle */
+ TPM_AUTHDATA ownerAuth; /* HMAC key TPM Owner auth */
+
+ /* processing parameters */
+ unsigned char * inParamStart; /* starting point of inParam's */
+ unsigned char * inParamEnd; /* ending point of inParam's */
+ TPM_DIGEST inParamDigest;
+ TPM_BOOL auditStatus; /* audit the ordinal */
+ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
+ TPM_BOOL authHandleValid = FALSE;
+ TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */
+ TPM_SECRET *hmacKey;
+
+ /* output parameters */
+ uint32_t outParamStart; /* starting point of outParam's */
+ uint32_t outParamEnd; /* ending point of outParam's */
+ TPM_DIGEST outParamDigest;
+
+ printf("TPM_Process_ResetLockValue: Ordinal Entry\n");
+ /*
+ get inputs
+ */
+ /* save the starting point of inParam's for authorization and auditing */
+ inParamStart = command;
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ /* Update disableResetLock. Ignore the return code since this command is not locked out */
+ TPM_Authdata_CheckState(tpm_state);
+ /* NOTE No TPM_CHECK_NO_LOCKOUT, since this command proceeds anyway */
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_ENABLED |
+ TPM_CHECK_ACTIVATED |
+ TPM_CHECK_OWNER));
+ }
+ /* check tag */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckRequestTag1(tag);
+ }
+ /* get the 'below the line' authorization parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_AuthParams_Get(&authHandle,
+ &authHandleValid,
+ nonceOdd,
+ &continueAuthSession,
+ ownerAuth,
+ &command, &paramSize);
+ }
+ if (returnCode == TPM_SUCCESS) {
+ if (paramSize != 0) {
+ printf("TPM_Process_ResetLockValue: Error, command has %u extra bytes\n", paramSize);
+ returnCode = TPM_BAD_PARAM_SIZE;
+ }
+ }
+ /* do not terminate sessions if the command did not parse correctly */
+ if (returnCode != TPM_SUCCESS) {
+ authHandleValid = FALSE;
+ }
+ /*
+ Processing
+ */
+ /* 1. If TPM_STCLEAR_DATA -> disableResetLock is TRUE return TPM_AUTHFAIL */
+ if (returnCode == TPM_SUCCESS) {
+ if (tpm_state->tpm_stclear_data.disableResetLock) {
+ printf("TPM_Process_ResetLockValue: Error, command locked out\n");
+ returnCode = TPM_AUTHFAIL;
+ }
+ }
+ /* a. The internal dictionary attack mechanism will set TPM_STCLEAR_DATA -> disableResetLock to
+ FALSE when the timeout period expires */
+ /* NOTE Done by TPM_Authdata_CheckState() */
+ /* Validate the parameters and owner authorization for this command */
+ if (returnCode == TPM_SUCCESS) {
+ if (returnCode == TPM_SUCCESS) {
+ returnCode =
+ TPM_AuthSessions_GetData(&auth_session_data,
+ &hmacKey,
+ tpm_state,
+ authHandle,
+ TPM_PID_NONE,
+ TPM_ET_OWNER,
+ ordinal,
+ NULL,
+ &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */
+ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */
+ }
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_Authdata_Check(tpm_state,
+ *hmacKey, /* owner HMAC key */
+ inParamDigest,
+ auth_session_data, /* authorization session */
+ nonceOdd, /* Nonce generated by system
+ associated with authHandle */
+ continueAuthSession,
+ ownerAuth); /* Authorization digest for input */
+ }
+ /* 2. If the the command and parameters validation using ownerAuth fails */
+ if (returnCode != TPM_SUCCESS) {
+ printf("TPM_Process_ResetLockValue: Error, disabling ordinal\n");
+ /* a. Set TPM_STCLEAR_DATA -> disableResetLock to TRUE */
+ tpm_state->tpm_stclear_data.disableResetLock = TRUE;
+ /* b. Restart the TPM dictionary attack lock out period */
+ /* A failure restarts it anyway with double the period.*/
+ /* c. Return TPM_AUTHFAIL */
+ }
+ }
+ /* 3. Reset the internal TPM dictionary attack mitigation mechanism */
+ /* a. The mechanism is vendor specific and can include time outs, reboots, and other mitigation
+ strategies */
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_ResetLockValue: Resetting the failure counter\n");
+ /* clear the authorization failure counter */
+ tpm_state->tpm_stclear_data.authFailCount = 0;
+ }
+ /*
+ response
+ */
+ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
+ if (rcf == 0) {
+ printf("TPM_Process_ResetLockValue: Ordinal returnCode %08x %u\n",
+ returnCode, returnCode);
+ rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
+ }
+ /* success response, append the rest of the parameters. */
+ if (rcf == 0) {
+ if (returnCode == TPM_SUCCESS) {
+ /* checkpoint the beginning of the outParam's */
+ outParamStart = response->buffer_current - response->buffer;
+ /* checkpoint the end of the outParam's */
+ outParamEnd = response->buffer_current - response->buffer;
+ }
+ /* digest the above the line output parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
+ auditStatus, /* input audit status */
+ transportEncrypt,
+ tag,
+ returnCode,
+ ordinal, /* command ordinal */
+ response->buffer + outParamStart, /* start */
+ outParamEnd - outParamStart); /* length */
+ }
+ /* calculate and set the below the line parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_AuthParams_Set(response,
+ *hmacKey, /* owner HMAC key */
+ auth_session_data,
+ outParamDigest,
+ nonceOdd,
+ continueAuthSession);
+ }
+ /* audit if required */
+ if ((returnCode == TPM_SUCCESS) && auditStatus) {
+ returnCode = TPM_ProcessAudit(tpm_state,
+ transportEncrypt,
+ inParamDigest,
+ outParamDigest,
+ ordinal);
+ }
+ /* adjust the initial response */
+ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
+ }
+ /* if there was an error, terminate the session. */
+ if (((rcf != 0) ||
+ ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
+ !continueAuthSession) &&
+ authHandleValid) {
+ TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
+ }
+ return rcf;
+}
+