/
githubmirror
/
libtpms
Обзор
Документация
Войти
/
githubmirror
/
libtpms
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/tpm12/tpm_admin.c
2 009 строк
71 KB
Stefan Berger
tpm12: Get rid of usage of sprintf and use snprintf instead
17 окт 2019, 18:06
17 окт 2019, 18:06
57d628a
Код
Авторство
О чём код?
/********************************************************************************/ /* */ /* 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, ¶mSize); } /* 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, ¶mSize); } /* 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, ¶mSize); } 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, ¶mSize); } 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, ¶mSize); } 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, ¶mSize); } /* 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, ¶mSize); } 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; }