summaryrefslogtreecommitdiffstats
path: root/src/tpm12/tpm_owner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tpm12/tpm_owner.c')
-rw-r--r--src/tpm12/tpm_owner.c1968
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, &paramSize);
+ }
+ /* get encOwnerAuth parameter */
+ if (returnCode == TPM_SUCCESS) {
+ printf("TPM_Process_TakeOwnership: protocolID %04hx\n", protocolID);
+ returnCode = TPM_SizedBuffer_Load(&encOwnerAuth, &command, &paramSize);
+ }
+ /* get encSrkAuth parameter */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_SizedBuffer_Load(&encSrkAuth, &command, &paramSize);
+ }
+ /* get srkParams parameter */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_Key_Load(&srkParams, &command, &paramSize);
+ }
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ /* check state */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
+ TPM_CHECK_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, &paramSize);
+ }
+ 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, &paramSize);
+ }
+ 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,
+ &current,
+ 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, &paramSize);
+ }
+ /* save the ending point of inParam's for authorization and auditing */
+ inParamEnd = command;
+ /* digest the input parameters */
+ if (returnCode == TPM_SUCCESS) {
+ returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
+ &auditStatus, /* output */
+ &transportEncrypt, /* output */
+ tpm_state,
+ tag,
+ ordinal,
+ inParamStart,
+ inParamEnd,
+ transportInternal);
+ }
+ 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, &paramSize);
+ }
+ 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;
+}
+