diff options
Diffstat (limited to 'src/tpm12/tpm_owner.c')
-rw-r--r-- | src/tpm12/tpm_owner.c | 1968 |
1 files changed, 1968 insertions, 0 deletions
diff --git a/src/tpm12/tpm_owner.c b/src/tpm12/tpm_owner.c new file mode 100644 index 0000000..4360505 --- /dev/null +++ b/src/tpm12/tpm_owner.c @@ -0,0 +1,1968 @@ +/********************************************************************************/ +/* */ +/* Ownership Processing */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: tpm_owner.c 4620 2011-09-07 21:43:19Z 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 <stdlib.h> + +#include "tpm_audit.h" +#include "tpm_auth.h" +#include "tpm_counter.h" +#include "tpm_crypto.h" +#include "tpm_cryptoh.h" +#include "tpm_debug.h" +#include "tpm_delegate.h" +#include "tpm_error.h" +#include "tpm_init.h" +#include "tpm_io.h" +#include "tpm_key.h" +#include "tpm_nonce.h" +#include "tpm_nvram.h" +#include "tpm_pcr.h" +#include "tpm_permanent.h" +#include "tpm_process.h" +#include "tpm_secret.h" +#include "tpm_session.h" +#include "tpm_sizedbuffer.h" +#include "tpm_transport.h" + +#include "tpm_owner.h" + +/* Flags involved with clearing an owner: + + pFlags.disableOwnerClear + set by TPM_DisableOwnerClear + clear by successful owner clear + vFlags.disableForceClear + set by TPM_DisableForceClear + clear by TPM_Init + + TPM_OwnerClear + requires ownerAuth + pFlags.disableOwnerClear == FALSE + TPM_ForceClear + requires physical presence + vFlags.disableForceClear == FALSE +*/ + +/* 6.1 TPM_TakeOwnership rev 114 + + This command inserts the TPM Ownership value into the TPM. +*/ + +TPM_RESULT TPM_Process_TakeOwnership(tpm_state_t *tpm_state, + TPM_STORE_BUFFER *response, + TPM_TAG tag, + uint32_t paramSize, /* bytes left in command */ + 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_PROTOCOL_ID protocolID; /* The ownership protocol in use */ + TPM_SIZED_BUFFER encOwnerAuth; /* The owner authorization data encrypted with PUBEK */ + TPM_SIZED_BUFFER encSrkAuth; /* The SRK authorization data encrypted with PUBEK */ + TPM_KEY srkParams; /* Structure containing all parameters of new SRK. + pubKey.keyLength & encSize are both 0. This structure + MAY be TPM_KEY12. */ + TPM_AUTHHANDLE authHandle; /* The authorization handle used for this command */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession; /* The continue use flag for the authorization handle */ + TPM_AUTHDATA ownerAuth; /* Authorization digest for input params. HMAC key: the new + 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_SECRET a1Auth; /* decrypt of encOwnerAuth */ + uint32_t a1Auth_length; /* length of decrypted A1 */ + TPM_SECRET a2SrkAuth; /* decrypt of encSrkAuth */ + uint32_t a2SrkAuth_length; /* length of decrypted A2 */ + TPM_RSA_KEY_PARMS *srkRSAKeyParms; + TPM_STORE_ASYMKEY *srkStoreAsymkey; + TPM_STORE_BUFFER asymKeySbuffer; /* serialized SRK asymkey */ + TPM_KEY *srk; /* pointer to SRK in permanent data */ + TPM_SIZED_BUFFER exponent; /* default exponent */ + TPM_BOOL writeAllNV1 = FALSE; /* flags to write back NV */ + TPM_BOOL writeAllNV2 = FALSE; /* flags to write back NV */ + int ver; /* TPM_KEY or TPM_KEY12 */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + TPM_KEY srkPub; /* Structure containing all parameters of new SRK, + srkPub.encData is set to 0. */ + + printf("TPM_Process_TakeOwnership: Ordinal Entry\n"); + srk = &(tpm_state->tpm_permanent_data.srk); /* get pointer to SRK in permanent data */ + + /* so that Delete's are safe */ + TPM_SizedBuffer_Init(&encOwnerAuth); /* freed @1 */ + TPM_SizedBuffer_Init(&encSrkAuth); /* freed @2 */ + TPM_Key_Init(&srkParams); /* freed @3 */ + TPM_Key_Init(&srkPub); /* freed @5 */ + TPM_SizedBuffer_Init(&exponent); /* freed @6 */ + TPM_Sbuffer_Init(&asymKeySbuffer); /* freed @7 */ + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get protocolID parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&protocolID, &command, ¶mSize); + } + /* get encOwnerAuth parameter */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: protocolID %04hx\n", protocolID); + returnCode = TPM_SizedBuffer_Load(&encOwnerAuth, &command, ¶mSize); + } + /* get encSrkAuth parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_Load(&encSrkAuth, &command, ¶mSize); + } + /* get srkParams parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_Load(&srkParams, &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_ENABLED | + 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_TakeOwnership: 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_PERMANENT_DATA -> ownerAuth is valid return TPM_OWNER_SET */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Checking TPM state\n"); + if (tpm_state->tpm_permanent_data.ownerInstalled) { + printf("TPM_Process_TakeOwnership: Error, owner already installed\n"); + returnCode = TPM_OWNER_SET; + } + } + /* 2. If TPM_PERMANENT_FLAGS -> ownership is FALSE return TPM_INSTALL_DISABLED */ + if (returnCode == TPM_SUCCESS) { + if (!(tpm_state->tpm_permanent_flags.ownership)) { + printf("TPM_Process_TakeOwnership: Error, ownership is false\n"); + returnCode = TPM_INSTALL_DISABLED; + } + } + /* 3. If TPM_PERMANENT_DATA -> endorsementKey is invalid return TPM_NO_ENDORSEMENT */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_permanent_data.endorsementKey.keyUsage == TPM_KEY_UNINITIALIZED) { + printf("TPM_Process_TakeOwnership: Error, endorsement key is invalid\n"); + returnCode = TPM_NO_ENDORSEMENT; + } + } + /* 4. Verify that authHandle is of type OIAP on error return TPM_AUTHFAIL */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_AuthSessions_GetData(&auth_session_data, + &hmacKey, + tpm_state, + authHandle, + TPM_PID_OIAP, + 0, /* OSAP entity type */ + ordinal, + NULL, + NULL, /* no OIAP authorization */ + NULL); + } + /* 5. If protocolID is not TPM_PID_OWNER, the TPM MAY return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (protocolID != TPM_PID_OWNER) { + printf("TPM_Process_TakeOwnership: Error, bad protocolID\n"); + returnCode = TPM_BAD_PARAMETER; + + } + } + /* 6. Create A1 a TPM_SECRET by decrypting encOwnerAuth using PRIVEK as the key */ + /* a. This requires that A1 was encrypted using the PUBEK */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPrivateDecryptH(a1Auth, /* decrypted data */ + &a1Auth_length, /* actual size of A1 */ + TPM_SECRET_SIZE, /* size of A1 buffer */ + encOwnerAuth.buffer, /* encrypted data */ + encOwnerAuth.size, /* encrypted data size */ + &(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* b. Validate that A1 is a length of 20 bytes, on error return TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (a1Auth_length != TPM_SECRET_SIZE) { + printf("TPM_Process_TakeOwnership: Error, A1 length %u, should be %u\n", + a1Auth_length, TPM_SECRET_SIZE); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* 7. Validate the command and parameters using A1 and ownerAuth, on error return TPM_AUTHFAIL + */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_TakeOwnership: A1 secret", a1Auth); + returnCode = TPM_Authdata_Check(tpm_state, + a1Auth, /* HMAC key */ + inParamDigest, + auth_session_data, /* authorization session */ + nonceOdd, /* Nonce generated by system + associated with authHandle */ + continueAuthSession, + ownerAuth); /* Authorization digest for input */ + } + /* + 8. Validate srkParams + */ + /* a. If srkParams -> keyUsage is not TPM_KEY_STORAGE return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Validating SRK parameters\n"); + if (srkParams.keyUsage != TPM_KEY_STORAGE) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->keyUsage is not TPM_KEY_STORAGE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* b. If srkParams -> migratable is TRUE return TPM_INVALID_KEYUSAGE */ + if (returnCode == TPM_SUCCESS) { + if (srkParams.keyFlags & TPM_MIGRATABLE) { + printf("TPM_Process_TakeOwnership: Error, srkParams->keyFlags migratable is TRUE\n"); + returnCode = TPM_INVALID_KEYUSAGE; + } + } + /* c. If srkParams -> algorithmParms -> algorithmID is NOT TPM_ALG_RSA return + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (srkParams.algorithmParms.algorithmID != TPM_ALG_RSA) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->algorithmID is NOT TPM_ALG_RSA\n"); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* d. If srkParams -> algorithmParms -> encScheme is NOT TPM_ES_RSAESOAEP_SHA1_MGF1 return + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (srkParams.algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->encScheme is NOT TPM_ES_RSAESOAEP_SHA1_MGF1\n"); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* e. If srkParams -> algorithmParms -> sigScheme is NOT TPM_SS_NONE return + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (srkParams.algorithmParms.sigScheme != TPM_SS_NONE) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->sigScheme is NOT TPM_SS_NONE\n"); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* f. srkParams -> algorithmParms -> parms -> keyLength MUST be greater than or equal to + 2048, on error return TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_KeyParms_GetRSAKeyParms(&srkRSAKeyParms, &(srkParams.algorithmParms)); + } + if (returnCode == TPM_SUCCESS) { + if (srkRSAKeyParms->keyLength < 2048) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->parms->keyLength " + "MUST be greater than or equal to 2048\n"); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* g .If srkParams -> algorithmParms -> parms -> exponentSize is not 0, return + TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (srkRSAKeyParms->exponent.size != 0) { + printf("TPM_Process_TakeOwnership: Error, " + "srkParams->algorithmParms->parms->exponentSize %u is not zero\n", + srkRSAKeyParms->exponent.size); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* h. If TPM_PERMANENT_FLAGS -> FIPS is TRUE */ + /* i. If srkParams -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state -> tpm_permanent_flags.FIPS) { + if (srkParams.authDataUsage == TPM_AUTH_NEVER) { + printf("TPM_Process_TakeOwnership: Error, " + "FIPS and authDataUsage is TPM_AUTH_NEVER\n"); + returnCode = TPM_NOTFIPS; + } + } + } + /* check that srkParams is TPM_KEY or TPM_KEY12 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Key_CheckStruct(&ver, &srkParams); + } + /* 9. Generate K1 (SRK) according to the srkParams on error return TPM_BAD_KEY_PROPERTY */ + /* a.This includes copying PCRInfo from srkParams to K1 */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: SRK key length %u\n", srkRSAKeyParms->keyLength); + if (ver == 1) { + if (srkParams.tpm_pcr_info != NULL) { + TPM_PCRInfo_Trace("TPM_Process_TakeOwnership: SRK PCRs", + srkParams.tpm_pcr_info->pcrSelection, + srkParams.tpm_pcr_info->digestAtRelease); + } + else { + printf("TPM_Process_TakeOwnership: No SRK PCRs\n"); + } + } + else { + if (srkParams.tpm_pcr_info_long != NULL) { + TPM_PCRInfo_Trace("TPM_Process_TakeOwnership: SRK PCRs", + srkParams.tpm_pcr_info_long->releasePCRSelection, + srkParams.tpm_pcr_info_long->digestAtRelease); + } + else { + printf("TPM_Process_TakeOwnership: No SRK PCRs\n"); + } + } + printf("TPM_Process_TakeOwnership: Creating SRK, authDataUsage %u\n", + srkParams.authDataUsage); + /* The old keys should already be deleted from an OwnerClear, but it can't hurt to do it + again to prevent memory leaks on errors. */ + TPM_Key_Delete(srk); /* not freed, in permanent store */ + returnCode = TPM_Key_GenerateRSA(srk, + tpm_state, + NULL, /* parent key */ + tpm_state->tpm_stclear_data.PCRS, /* PCR array */ + ver, + TPM_KEY_STORAGE, /* keyUsage */ + srkParams.keyFlags, + srkParams.authDataUsage, + &(srkParams.algorithmParms), /* TPM_KEY_PARMS */ + srkParams.tpm_pcr_info, + srkParams.tpm_pcr_info_long); + writeAllNV1 = TRUE; + } + /* 15. Create TPM_PERMANENT_DATA -> tpmProof by using the TPM RNG */ + /* NOTE: Moved here so tpmProof can be inserted into SRK -> migrationAuth */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Creating tpmProof\n"); + returnCode = TPM_Secret_Generate(tpm_state->tpm_permanent_data.tpmProof); + } + /* 10. Create A2 a TPM_SECRET by decrypting encSrkAuth using the PRIVEK */ + /* a. This requires A2 to be encrypted using the PUBEK */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_RSAPrivateDecryptH(a2SrkAuth, /* decrypted data */ + &a2SrkAuth_length, /* actual size of A2 */ + TPM_SECRET_SIZE, /* size of A2 buffer */ + encSrkAuth.buffer, /* encrypted data */ + encSrkAuth.size, /* encrypted data size */ + &(tpm_state->tpm_permanent_data.endorsementKey)); + } + /* b. Validate that A2 is a length of 20 bytes, on error return TPM_BAD_KEY_PROPERTY */ + if (returnCode == TPM_SUCCESS) { + if (a2SrkAuth_length != TPM_SECRET_SIZE) { + printf("TPM_Process_TakeOwnership: Error, A2 length %u, should be %u\n", + a2SrkAuth_length, TPM_SECRET_SIZE); + returnCode = TPM_BAD_KEY_PROPERTY; + } + } + /* c. Store A2 in K1 (SRK) -> usageAuth */ + if (returnCode == TPM_SUCCESS) { + TPM_PrintFour("TPM_Process_TakeOwnership: Insert usageAuth into SRK", a2SrkAuth); + /* get the TPM_STORE_ASYMKEY from the TPM_KEY srk */ + returnCode = TPM_Key_GetStoreAsymkey(&srkStoreAsymkey, srk); + } + if (returnCode == TPM_SUCCESS) { + /* insert the authData into the TPM_STORE_ASYMKEY */ + TPM_Secret_Copy(srkStoreAsymkey->usageAuth, a2SrkAuth); + /* store tpmProof in migrationAuth to indicate that this is a non-migratable key */ + TPM_Secret_Copy(srkStoreAsymkey->migrationAuth, tpm_state->tpm_permanent_data.tpmProof); + /* serialize the TPM_STORE_ASYMKEY object */ + returnCode = TPM_StoreAsymkey_Store(&asymKeySbuffer, FALSE, srkStoreAsymkey); + } + /* store the serialized TPM_STORE_ASYMKEY as encData */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_SizedBuffer_SetFromStore(&(srk->encData), &asymKeySbuffer); + } + /* 11. Store K1 in TPM_PERMANENT_DATA -> srk */ + /* NOTE Generated directly in srk */ + /* 12. Store A1 in TPM_PERMANENT_DATA -> ownerAuth */ + if (returnCode == TPM_SUCCESS) { + TPM_Secret_Copy(tpm_state->tpm_permanent_data.ownerAuth, a1Auth); + tpm_state->tpm_permanent_data.ownerInstalled = TRUE; + } + /* 13. Create TPM_PERMANENT_DATA -> contextKey according to the rules for the algorithm in use + by the TPM to save context blobs */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Creating contextKey\n"); + returnCode = TPM_SymmetricKeyData_GenerateKey(tpm_state->tpm_permanent_data.contextKey); + } + /* 14. Create TPM_PERMANENT_DATA -> delegateKey according to the rules for the algorithm in use + by the TPM to save delegate blobs */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Creating delegateKey\n"); + returnCode = TPM_SymmetricKeyData_GenerateKey(tpm_state->tpm_permanent_data.delegateKey); + } + /* 15. Create TPM_PERMANENT_DATA -> tpmProof by using the TPM RNG */ + /* NOTE: This Action done earlier */ + /* 16. Export TPM_PERMANENT_DATA -> srk as srkPub */ + if (returnCode == TPM_SUCCESS) { + /* copy the srk */ + printf("TPM_Process_TakeOwnership: Creating srkPub for response\n"); + returnCode = TPM_Key_Copy(&srkPub, srk, FALSE); /* don't copy encData */ + } + /* 17. Set TPM_PERMANENT_FLAGS -> readPubek to FALSE */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_TakeOwnership: Clear readPubek\n"); + TPM_SetCapability_Flag(&writeAllNV2, /* altered */ + &(tpm_state->tpm_permanent_flags.readPubek), /* flag */ + FALSE); /* value */ + } + /* Store the permanent data and flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + (TPM_BOOL)(writeAllNV1 || writeAllNV2), + returnCode); + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_TakeOwnership: 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; + /* append srkPub */ + returnCode = TPM_Key_Store(response, &srkPub); + /* 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 */ + /* 18. Calculate resAuth using the newly established TPM_PERMANENT_DATA -> ownerAuth */ + if (returnCode == TPM_SUCCESS) { + returnCode = + TPM_AuthParams_Set(response, + tpm_state->tpm_permanent_data.ownerAuth, /* 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, 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); + } + TPM_SizedBuffer_Delete(&encOwnerAuth); /* @1 */ + TPM_SizedBuffer_Delete(&encSrkAuth); /* @2 */ + TPM_Key_Delete(&srkParams); /* @3 */ + TPM_Key_Delete(&srkPub); /* @5 */ + TPM_SizedBuffer_Delete(&exponent); /* @6 */ + TPM_Sbuffer_Delete(&asymKeySbuffer); /* @7 */ + return rcf; +} + +/* 6.2 TPM_OwnerClear rev 101 + + The OwnerClear command performs the clear operation under authorization. This command is + available until the Owner executes the DisableOwnerClear, at which time any further invocation of + this command returns TPM_CLEAR_DISABLED. +*/ + +TPM_RESULT TPM_Process_OwnerClear(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 handle used for owner authorization */ + TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ + TPM_BOOL continueAuthSession = TRUE; /* Ignored */ + TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner + authorization. HMAC key: permanent_data.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 = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey; + TPM_SECRET oldOwnerAuth; /* saved copy for response */ + TPM_BOOL writeAllNV = FALSE; /* flag to write back permanent */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_OwnerClear: 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_ALL); + } + /* 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_OwnerClear: 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. Verify that the TPM Owner authorizes the command and all of the input, on error 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) { + /* make a copy of the TPM_PERMANENT_DATA.ownerAuth for the response, since it gets + invalidated in step 5. */ + TPM_Secret_Copy(oldOwnerAuth, *hmacKey); + TPM_PrintFour("TPM_Process_OwnerClear: ownerAuth secret", *hmacKey); + 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 TPM_PERMANENT_FLAGS -> disableOwnerClear is TRUE then return TPM_CLEAR_DISABLED. */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_permanent_flags.disableOwnerClear) { + printf("TPM_Process_OwnerClear: Error, disableOwnerClear is TRUE\n"); + returnCode = TPM_CLEAR_DISABLED; + } + } + /* owner clear common code */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_OwnerClearCommon(tpm_state, + FALSE); /* don't delete if D bit set */ + continueAuthSession = FALSE; /* Fixed value FALSE */ + writeAllNV = TRUE; + } + /* Store the permanent data and 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_OwnerClear: 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, + oldOwnerAuth, /* old 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. NOTE: Normally this will fail because all + sessions have been closed. */ + 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; +} + +/* 6.3 TPM_ForceClear rev 109 + + The ForceClear command performs the Clear operation under physical access. This command is + available until the execution of the DisableForceClear, at which time any further invocation of + this command returns TPM_CLEAR_DISABLED. + + TPM_ForceClear can succeed even if no owner is installed. In that case, it does whatever + TPM_OwnerClear actions that it can. +*/ + +TPM_RESULT TPM_Process_ForceClear(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 */ + + /* 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 data */ + 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_ForceClear: 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_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_ForceClear: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM SHALL check for the assertion of physical presence, if not present return + TPM_BAD_PRESENCE */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); + } + if (returnCode == TPM_SUCCESS) { + if (!physicalPresence) { + printf("TPM_Process_ForceClear: Error, physicalPresence is FALSE\n"); + returnCode = TPM_BAD_PRESENCE; + } + } + /* 2. If TPM_STCLEAR_FLAGS -> disableForceClear is TRUE return TPM_CLEAR_DISABLED */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_stclear_flags.disableForceClear) { + printf("TPM_Process_ForceClear: Error, disableForceClear is TRUE\n"); + returnCode = TPM_CLEAR_DISABLED; + } + } + /* 3. The TPM SHALL execute the actions of TPM_OwnerClear (except for the TPM Owner + authentication check) */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_OwnerClearCommon(tpm_state, + FALSE); /* don't delete if D bit set */ + writeAllNV = TRUE; + } + /* Store the permanent data and 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_ForceClear: 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; +} + +/* TPM_OwnerClearCommon() rev 116 + + Performs owner clear operations common to TPM_OwnerClear, TPM_ForceClear, and TPM_RevokeTrust. + + It assumes that any required authorization is performed by the caller + + If deleteAllNvram is TRUE, all NVRAM is deleted. If it is FALSE, indexes with the D bit set are + not cleared. + + Data is not written back to NV space here. It is written by the caller. +*/ + +TPM_RESULT TPM_OwnerClearCommon(tpm_state_t *tpm_state, + TPM_BOOL deleteAllNvram) +{ + TPM_RESULT rc = 0; + size_t start; + size_t current; + TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; + + /* 3. Unload all loaded keys. */ + /* a. If TPM_PERMANENT_FLAGS -> FIPS is TRUE, the memory locations containing secret or private + keys MUST be set to all zeros. */ + start = 0; + while ((rc == 0) && + /* returns TPM_RETRY when at the end of the table, terminates loop */ + (TPM_KeyHandleEntries_GetNextEntry(&tpm_key_handle_entry, + ¤t, + tpm_state->tpm_key_handle_entries, + start)) == 0) { + printf("TPM_OwnerClearCommon: Flushing key handle %08x\n", + tpm_key_handle_entry->handle); + rc = TPM_KeyHandleEntry_FlushSpecific(tpm_state, tpm_key_handle_entry); + start = current + 1; + } +#ifdef TPM_V11 + /* 5. The TPM sets all DIR registers to their default value. */ + if (rc == 0) { + TPM_Digest_Init(tpm_state->tpm_permanent_data.authDIR); + } +#endif + /* a.This includes owner evict keys */ + if (rc == 0) { + printf("TPM_OwnerClearCommon: Deleting owner evict keys\n"); + TPM_KeyHandleEntries_OwnerEvictDelete(tpm_state->tpm_key_handle_entries); + } + /* 4. The TPM MUST NOT modify the following TPM_PERMANENT_DATA items + a. endorsementKey + b. revMajor + c. revMinor + d. manuMaintPub + e. auditMonotonicCounter + NOTE: TPMWG email: Don't touch the base value. + f. monotonicCounter + g. pcrAttrib + h. rngState + i. EKReset + j. lastFamilyID + k. tpmDAASeed + l. DIR[1] + m. daaProof + n. daaBlobKey + */ + /* 5. The TPM MUST invalidate the following TPM_PERMANENT_DATA items and + any internal resources associated with these items */ + if (rc == 0) { + printf("TPM_OwnerClearCommon: Invalidate TPM_PERMANENT_DATA items\n"); + /* a. ownerAuth */ + TPM_Secret_Init(tpm_state->tpm_permanent_data.ownerAuth); + tpm_state->tpm_permanent_data.ownerInstalled = FALSE; + /* b. srk */ + TPM_Key_Delete(&(tpm_state->tpm_permanent_data.srk)); + /* c. delegateKey */ + printf("TPM_OwnerClearCommon: Invalidate delegateKey\n"); + TPM_SymmetricKeyData_Init(tpm_state->tpm_permanent_data.delegateKey); + /* d. delegateTable */ + TPM_DelegateTable_Delete(&(tpm_state->tpm_permanent_data.delegateTable)); + /* e. contextKey */ + printf("TPM_OwnerClearCommon: Invalidate contextKey\n"); + TPM_SymmetricKeyData_Init(tpm_state->tpm_permanent_data.contextKey); + /* f. tpmProof */ + TPM_Secret_Init(tpm_state->tpm_permanent_data.tpmProof); + /* g. operatorAuth */ + TPM_Secret_Init(tpm_state->tpm_permanent_data.operatorAuth); + /* 6. The TPM MUST reset to manufacturing defaults the following TPM_PERMANENT_DATA items */ + /* a. noOwnerNVWrite MUST be set to 0 */ + tpm_state->tpm_permanent_data.noOwnerNVWrite = 0; + /* b. ordinalAuditStatus */ + rc = TPM_OrdinalAuditStatus_Init(&(tpm_state->tpm_permanent_data)); + /* c. restrictDelegate */ + tpm_state->tpm_permanent_data.restrictDelegate = 0; + } + if (rc == 0) { + /* 7. The TPM MUST invalidate or reset all fields of TPM_STANY_DATA + a. Nonces SHALL be reset + b. Lists (e.g. contextList) SHALL be invalidated + NOTE This also terminates all sessions + */ + printf("TPM_OwnerClearCommon: Invalidate TPM_STANY_DATA\n"); + TPM_StanyData_Delete(&(tpm_state->tpm_stany_data)); + /* 8. The TPM MUST invalidate all fields of TPM_STCLEAR_DATA except the PCR's + a. Nonces SHALL be reset + b. Lists (e.g. contextList) SHALL be invalidated + c. deferredPhysicalPresence MUST be set to 0 + */ + printf("TPM_OwnerClearCommon: Invalidate TPM_STCLEAR_DATA\n"); + TPM_StclearData_Delete(&(tpm_state->tpm_stclear_data), + tpm_state->tpm_permanent_data.pcrAttrib, + FALSE); /* don't reset the PCR's */ + /* 9. The TPM MUST set the following TPM_PERMANENT_FLAGS to their default values */ + /* a. disable */ + printf("TPM_OwnerClearCommon: Set disable TRUE\n"); + tpm_state->tpm_permanent_flags.disable = TRUE; + /* b. deactivated */ + printf("TPM_OwnerClearCommon: Set deactivated TRUE\n"); + tpm_state->tpm_permanent_flags.deactivated = TRUE; + /* c. readPubek */ + printf("TPM_OwnerClearCommon: Set readPubek TRUE\n"); + tpm_state->tpm_permanent_flags.readPubek = TRUE; + /* d. disableOwnerClear */ + tpm_state->tpm_permanent_flags.disableOwnerClear = FALSE; +#if (TPM_REVISION >= 103) /* added for rev 103 */ + /* e. disableFullDALogicInfo */ + tpm_state->tpm_permanent_flags.disableFullDALogicInfo = FALSE; +#endif + /* f. allowMaintenance */ +#if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) + tpm_state->tpm_permanent_flags.allowMaintenance = FALSE; +#else + tpm_state->tpm_permanent_flags.allowMaintenance = TRUE; +#endif + + /* #if (TPM_REVISION >= 104) This was added in rev 104, but was implemented by vendors + earlier */ + /* g. readSRKPub */ + tpm_state->tpm_permanent_flags.readSRKPub = FALSE; + /* 10. The TPM MUST set the following TPM_PERMANENT_FLAGS */ + /* a. ownership to TRUE */ + tpm_state->tpm_permanent_flags.ownership = TRUE; + /* b. operator to FALSE */ + tpm_state->tpm_permanent_flags.tpmOperator = FALSE; + /* c. maintenanceDone to FALSE */ + tpm_state->tpm_permanent_flags.maintenanceDone = FALSE; + /* 11. The TPM releases all TPM_PERMANENT_DATA -> monotonicCounter settings + + a. This includes invalidating all currently allocated counters. The result will be no + currently allocated counters and the new owner will need to allocate counters. The actual + count value will continue to increase. + */ + rc = TPM_Counters_Release(tpm_state->tpm_permanent_data.monotonicCounter); + /* NOTE: v1.1 says to set all TPM_PERSISTENT_FLAGS to the default value, but I doubt this is + correct. I assume that physicalPresenceLifetimeLock which is a one-way flag, should not + be reset. A similar comment goes for tpmPost and tpmPostLock. */ + } + /* TPM_OwnerClear 12. The TPM MUST deallocate all defined NV storage areas where + a. TPM_NV_PER_OWNERWRITE is TRUE if nvIndex does not have the "D" bit set + b. TPM_NV_PER_OWNERREAD is TRUE if nvIndex does not have the "D" bit set + c. The TPM MUST NOT deallocate any other currently defined NV storage areas. + d.This default behavior MAY be superseded for GPIO indexes by the platform specific + specification. + + TPM_RevokeTrust: a. NV items with the pubInfo -> nvIndex D value set MUST be deleted. This + changes the TPM_OwnerClear handling of the same NV areas + */ + if (rc == 0) { + rc = TPM_NVIndexEntries_DeleteOwnerAuthorized(&(tpm_state->tpm_nv_index_entries), + deleteAllNvram); + } +#if defined TPM_PCCLIENT + /* From the PC Client TIS + + 1.When there is no TPM Owner, the TPM_NV_INDEX_GPIO_00 area MUST be deallocated (see main + specification part 3 on TPM_OwnerClear). + */ + if (rc == 0) { + TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; + rc = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, + &(tpm_state->tpm_nv_index_entries), + TPM_NV_INDEX_GPIO_00); + /* if found, delete */ + if (rc == 0) { + TPM_NVDataSensitive_Delete(tpm_nv_data_sensitive); + } + else if (rc == TPM_BADINDEX) { + rc = TPM_SUCCESS; /* non-existent index is not an error */ + } + } +#endif + /* 13. The TPM MUST invalidate all familyTable entries */ + if (rc == 0) { + TPM_FamilyTable_Delete(&(tpm_state->tpm_permanent_data.familyTable)); + } + /* 14. The TPM MUST terminate all sessions, active or saved. */ + /* NOTE: Done by TPM_StclearData_Delete() */ + /* NOTE The TPM_PERMANENT_DATA and TPM_PERMANENT_FLAGS NVRAM store cannot be factored out here, + since some callers do other functions before the store. */ + return rc; +} + +/* 6.6 TSC_PhysicalPresence rev 87 + + Some TPM operations require the indication of a human's physical presence at the platform. The + presence of the human either provides another indication of platform ownership or a mechanism to + ensure that the execution of the command is not the result of a remote software process. + + This command allows a process on the platform to indicate the assertion of physical presence. As + this command is executable by software there must be protections against the improper invocation + of this command. + + The physicalPresenceHWEnable and physicalPresenceCMDEnable indicate the ability for either SW or + HW to indicate physical presence. These flags can be reset until the physicalPresenceLifetimeLock + is set. The platform manufacturer should set these flags to indicate the capabilities of the + platform the TPM is bound to. The command provides two sets of functionality. The first is to + enable, permanently, either the HW or the SW ability to assert physical presence. The second is + to allow SW, if enabled, to assert physical presence. +*/ + +TPM_RESULT TPM_Process_PhysicalPresence(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_PHYSICAL_PRESENCE physicalPresence; /* The state to set the TPM's Physical Presence + flags */ + /* processing parameters */ + unsigned char * inParamStart; /* starting point of inParam's */ + unsigned char * inParamEnd; /* ending point of inParam's */ + TPM_DIGEST inParamDigest; + TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ + TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport + session */ +#ifdef TPM_V12 + uint16_t a1 = TRUE; /* lifetime settings */ + uint16_t a2 = TRUE; /* assertion settings */ +#endif + TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_PhysicalPresence: Ordinal Entry\n"); + /* + get inputs + */ + /* save the starting point of inParam's for authorization and auditing */ + inParamStart = command; + /* get physicalPresence parameter */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Load16(&physicalPresence, &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); + } + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_PhysicalPresence: physicalPresence parameter %04x\n", physicalPresence); + } + /* 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_PhysicalPresence: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ +#ifdef TPM_V12 + if (returnCode == TPM_SUCCESS) { + if (physicalPresence & TPM_PHYSICAL_PRESENCE_MASK) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresence extra bits\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* 1. For documentation ease, the bits break into two categories. The first is the lifetime + settings and the second is the assertion settings. */ + if (returnCode == TPM_SUCCESS) { + /* a. Define A1 to be the lifetime settings: TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK, + TPM_PHYSICAL_PRESENCE_HW_ENABLE, TPM_PHYSICAL_make contingent!!!PRESENCE_CMD_ENABLE, + TPM_PHYSICAL_PRESENCE_HW_DISABLE, and TPM_PHYSICAL_PRESENCE_CMD_DISABLE */ + a1 = physicalPresence & (TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK | + TPM_PHYSICAL_PRESENCE_HW_ENABLE | + TPM_PHYSICAL_PRESENCE_CMD_ENABLE | + TPM_PHYSICAL_PRESENCE_HW_DISABLE | + TPM_PHYSICAL_PRESENCE_CMD_DISABLE); + + /* b. Define A2 to be the assertion settings: TPM_PHYSICAL_PRESENCE_LOCK, + TPM_PHYSICAL_PRESENCE_PRESENT, and TPM_PHYSICAL_PRESENCE_NOTPRESENT */ + a2 = physicalPresence & (TPM_PHYSICAL_PRESENCE_LOCK | + TPM_PHYSICAL_PRESENCE_PRESENT | + TPM_PHYSICAL_PRESENCE_NOTPRESENT); + printf("TPM_Process_PhysicalPresence: a1 %04x a2 %04x\n", a1, a2); + } + /* + Lifetime lock settings + */ + /* 2. If any A1 setting is present */ + if ((returnCode == TPM_SUCCESS) && a1) { + if (returnCode == TPM_SUCCESS) { + /* a. If TPM_PERMANENT_FLAGS -> physicalPresenceLifetimeLock is TRUE, return + TPM_BAD_PARAMETER */ + if (tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock) { + printf("TPM_Process_PhysicalPresence: Error, " + "physicalPresenceLifetimeLock is TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* b. If any A2 setting is present return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (a2) { + printf("TPM_Process_PhysicalPresence: Error, a1 and a2 TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* c. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_ENABLE and physicalPresence -> + TPM_PHYSICAL_PRESENCE_HW_DISABLE are TRUE, return TPM_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_DISABLE)) { + printf("TPM_Process_PhysicalPresence: Error, HW enable and disable both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* d. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_ENABLE and physicalPresence + -> TPM_PHYSICAL_PRESENCE_CMD_DISABLE are TRUE, return TPM_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE ) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_DISABLE )) { + printf("TPM_Process_PhysicalPresence: Error, CMD enable and disable both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + /* e. If physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_ENABLE is TRUE Set + TPM_PERMANENT_FLAGS -> physicalPresenceHWEnable to TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), + TRUE); /* value */ + } + /* f. If physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_DISABLE is TRUE Set + TPM_PERMANENT_FLAGS -> physicalPresenceHWEnable to FALSE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_DISABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable FALSE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), + FALSE); /* value */ + } + /* g. If physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_ENABLE is TRUE, Set + TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable to TRUE. */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), + TRUE); /* value */ + } + /* h. If physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_DISABLE is TRUE, Set + TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable to FALSE. */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_DISABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable FALSE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), + FALSE); /* value */ + } + /* i. If physicalPresence -> TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK is TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK) { + /* i. Set TPM_PERMANENT_FLAGS -> physicalPresenceLifetimeLock to TRUE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLifetimeLock\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock), + TRUE); /* value */ + } + } + /* j. Return TPM_SUCCESS */ + } + /* + SW physical presence assertion + */ + /* 3. If any A2 setting is present */ + if ((returnCode == TPM_SUCCESS) && a2) { + /* a. If any A1 setting is present return TPM_BAD_PARAMETER */ + /* i. This check here just for consistency, the prior checks would have already ensured that + this was OK */ + if (returnCode == TPM_SUCCESS) { + if (a1) { + printf("TPM_Process_PhysicalPresence: Error, a1 and a2 TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* b. If TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable is FALSE, return TPM_BAD_PARAMETER + */ + if (returnCode == TPM_SUCCESS) { + if (!tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceCMDEnable is FALSE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* c. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_LOCK and physicalPresence -> + TPM_PHYSICAL_PRESENCE_PRESENT are TRUE, return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK ) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT)) { + printf("TPM_Process_PhysicalPresence: Error, LOCK and PRESENT both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* d. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_PRESENT and physicalPresence -> + TPM_PHYSICAL_PRESENCE_NOTPRESENT are TRUE, return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT)) { + printf("TPM_Process_PhysicalPresence: Error, PRESENT and NOT_PRESENT both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + } + /* e. If TPM_STCLEAR_FLAGS -> physicalPresenceLock is TRUE, return TPM_BAD_PARAMETER */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_stclear_flags.physicalPresenceLock) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLock is TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } + if (returnCode == TPM_SUCCESS) { + /* f. If physicalPresence -> TPM_PHYSICAL_PRESENCE_LOCK is TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK) { + /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to FALSE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = FALSE; + /* ii. Set TPM_STCLEAR_FLAGS -> physicalPresenceLock to TRUE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLock TRUE\n"); + tpm_state->tpm_stclear_flags.physicalPresenceLock = TRUE; + /* iii. Return TPM_SUCCESS */ + } + /* g. If physicalPresence -> TPM_PHYSICAL_PRESENCE_PRESENT is TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) { + /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to TRUE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresence TRUE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = TRUE; + } + /* h. If physicalPresence -> TPM_PHYSICAL_PRESENCE_NOTPRESENT is TRUE */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT) { + /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to FALSE */ + printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = FALSE; + } + /* i. Return TPM_SUCCESS */ + } + } + /* 4. Else There were no A1 or A2 parameters set */ + if (returnCode == TPM_SUCCESS) { + if (!a1 && !a2) { + /* a. Return TPM_BAD_PARAMETER */ + printf("TPM_Process_PhysicalPresence: Error, a1 and a2 FALSE\n"); + returnCode = TPM_BAD_PARAMETER; + } + } +#else /* TPM v1.1 */ + /* 2. Once the PhysicalPresenceLock flag is set to TRUE, the TPM MUST not modify the + PhysicalPresence flag until a TPM_Init followed by TPM_Startup(stType = TCPA_ST_CLEAR). Upon + a TPM_Init and TPM_Startup(stType = TCPA_ST_STATE) the TPM MUST set the PhysicalPresenceLock + flag to FALSE. */ + /* NOTE: I assume this is a typo, that PhysicalPresenceLock is restored by TPM_ST_STATE and set + false on TPM_ST_CLEAR. Other places in the specification certainly say that. */ + /* 3.If the PhysicalPresenceLock flag is set to TRUE upon any call to this operation, the TPM + MUST cause no action and MUST return the error TCPA_BAD_PARAMETER. */ + if (returnCode == TPM_SUCCESS) { + if (tpm_state->tpm_stclear_flags.physicalPresenceLock) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLock is TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + /* NOTE: The specification doesn't say what to do if both flags are set. Following the 1.2 + specification seems reasonable. */ + if ((physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) && + (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT)) { + printf("TPM_Process_PhysicalPresence: Error, PRESENT and NOT_PRESENT both TRUE \n"); + returnCode = TPM_BAD_PARAMETER; + } + if ((tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock) && + (physicalPresence & (TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK | + TPM_PHYSICAL_PRESENCE_HW_ENABLE | + TPM_PHYSICAL_PRESENCE_CMD_ENABLE))) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLifetimeLock is TRUE\n"); + returnCode = TPM_BAD_PARAMETER; + } + if ((!tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable) && + (physicalPresence & (TPM_PHYSICAL_PRESENCE_LOCK | + TPM_PHYSICAL_PRESENCE_PRESENT | + TPM_PHYSICAL_PRESENCE_NOTPRESENT))) { + printf("TPM_Process_PhysicalPresence: Error, physicalPresenceCMDEnable is FALSE\n"); + returnCode = TPM_BAD_PARAMETER; + } + + } + /* 1. This operation MUST be implemented to process the values in the following order: */ + if (returnCode == TPM_SUCCESS) { + /* a. physicalPresenceHWEnable and physicalPresenceCMDEnable */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), + TRUE); /* value */ + } + if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable TRUE\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), + TRUE); /* value */ + } + /* b. physicalPresenceLifetimeLock */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLifetimeLock\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock), + TRUE); /* value */ + } + /* c. PhysicalPresence */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresence TRUE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = TRUE; + } + if (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); + tpm_state->tpm_stclear_flags.physicalPresence = FALSE; + } + /* d. PhysicalPresenceLock */ + if (physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK) { + printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLock TRUE\n"); + tpm_state->tpm_stclear_flags.physicalPresenceLock = TRUE; + } + } +#endif + /* 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_PhysicalPresence: 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; +} + +/* 6.4 TPM_DisableOwnerClear rev 87 + + The DisableOwnerClear command disables the ability to execute the TPM_OwnerClear command + permanently. Once invoked the only method of clearing the TPM will require physical access to the + TPM. + + After the execution of TPM_ForceClear, ownerClear is re-enabled and must be explicitly disabled + again by the new TPM Owner. +*/ + +TPM_RESULT TPM_Process_DisableOwnerClear(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 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 + authentication. 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 = NULL; /* session data for authHandle */ + TPM_SECRET *hmacKey = NULL; + 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_DisableOwnerClear: 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_ALL); + } + /* 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_DisableOwnerClear: 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 verifies that the authHandle properly authorizes the owner. */ + 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 sets the TPM_PERMANENT_FLAGS -> disableOwnerClear flag to TRUE. */ + /* 3. When this flag is TRUE the only mechanism that can clear the TPM is the TPM_ForceClear + command. The TPM_ForceClear command requires physical access to the TPM to execute. */ + if (returnCode == TPM_SUCCESS) { + printf("TPM_Process_DisableOwnerClear: Set disableOwnerClear\n"); + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.disableOwnerClear), /* 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_DisableOwnerClear: 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; +} + +/* 6.5 TPM_DisableForceClear rev 97 + + The DisableForceClear command disables the execution of the ForceClear command until the next + startup cycle. Once this command is executed, the TPM_ForceClear is disabled until another + startup cycle is run. +*/ + +TPM_RESULT TPM_Process_DisableForceClear(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 */ + + /* 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_DisableForceClear: 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_ALLOW_NO_OWNER); + } + /* check tag */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_CheckRequestTag0(tag); + } + if (returnCode == TPM_SUCCESS) { + if (paramSize != 0) { + printf("TPM_Process_DisableForceClear: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. The TPM sets the TPM_STCLEAR_FLAGS.disableForceClear flag in the TPM that disables the + execution of the TPM_ForceClear command. */ + if (returnCode == TPM_SUCCESS) { + tpm_state->tpm_stclear_flags.disableForceClear = TRUE; + } + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_DisableForceClear: 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; +} + +/* 6.7 TSC_ResetEstablishmentBit rev 98 + + The PC TPM Interface Specification (TIS) specifies setting tpmEstablished to TRUE upon execution + of the HASH_START sequence. The setting implies the creation of a Trusted Operating System on the + platform. Platforms will use the value of tpmEstablished to determine if operations necessary to + maintain the security perimeter are necessary. + + The tpmEstablished bit provides a non-volatile, secure reporting that a HASH_START was previously + run on the platform. When a platform makes use of the tpmEstablished bit, the platform can reset + tpmEstablished as the operation is no longer necessary. + + For example, a platform could use tpmEstablished to ensure that, if HASH_START had ever been, + executed the platform could use the value to invoke special processing. Once the processing is + complete the platform will wish to reset tpmEstablished to avoid invoking the special process + again. + + The TPM_PERMANENT_FLAGS -> tpmEstablished bit described in the TPM specifications uses positive + logic. The TPM_ACCESS register uses negative logic, so that TRUE is reflected as a 0. +*/ + +TPM_RESULT TPM_Process_ResetEstablishmentBit(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 */ + + /* 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 flags */ + + /* output parameters */ + uint32_t outParamStart; /* starting point of outParam's */ + uint32_t outParamEnd; /* ending point of outParam's */ + TPM_DIGEST outParamDigest; + + printf("TPM_Process_ResetEstablishmentBit: 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_ResetEstablishmentBit: Error, command has %u extra bytes\n", + paramSize); + returnCode = TPM_BAD_PARAM_SIZE; + } + } + /* + Processing + */ + /* 1. Validate the assertion of locality 3 or locality 4 */ + if (returnCode == TPM_SUCCESS) { + returnCode = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, /* BYTE bitmap */ + tpm_state->tpm_stany_flags.localityModifier); + } + /* 2. Set TPM_PERMANENT_FLAGS -> tpmEstablished to FALSE */ + if (returnCode == TPM_SUCCESS) { + TPM_SetCapability_Flag(&writeAllNV, /* altered */ + &(tpm_state->tpm_permanent_flags.tpmEstablished), /* flag */ + FALSE); /* value */ + + } + /* Store the permanent flags back to NVRAM */ + returnCode = TPM_PermanentAll_NVStore(tpm_state, + writeAllNV, + returnCode); + /* 3. Return TPM_SUCCESS */ + /* + response + */ + /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ + if (rcf == 0) { + printf("TPM_Process_ResetEstablishmentBit: 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; +} + |