blob: 06c270d18936abadab79f54313a9f9e56c8cd3f0 [file] [log] [blame]
/* Software-based Trusted Platform Module (TPM) Emulator
* Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
* 2005-2008 Heiko Stamer <stamer@gaos.org>
*
* This module is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This module is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* $Id: tpm_identity.c 364 2010-02-11 10:24:45Z mast $
*/
#include "tpm_emulator.h"
#include "tpm_commands.h"
#include "tpm_data.h"
#include "crypto/sha1.h"
#include "crypto/rsa.h"
#include "tpm_handles.h"
#include "tpm_marshalling.h"
#define LOCALITY tpmData.stany.flags.localityModifier
/*
* Identity Creation and Activation ([TPM_Part3], Section 15)
*/
TPM_RESULT TPM_MakeIdentity(
TPM_ENCAUTH *identityAuth,
TPM_CHOSENID_HASH *labelPrivCADigest,
TPM_KEY *idKeyParams,
TPM_AUTH *auth1,
TPM_AUTH *auth2,
TPM_KEY *idKey,
UINT32 *identityBindingSize,
BYTE **identityBinding
)
{
TPM_RESULT res;
TPM_SESSION_DATA *ownerAuth_sessionData;
TPM_SECRET A1;
tpm_rsa_private_key_t tpm_signature_key;
UINT32 key_length;
TPM_STORE_ASYMKEY store;
TPM_IDENTITY_CONTENTS idContents;
UINT32 len;
BYTE *buf, *ptr;
info("TPM_MakeIdentity()");
/* 1. Validate the idKeyParams parameters for the key description */
if (idKeyParams->algorithmParms.encScheme != TPM_ES_NONE
|| idKeyParams->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1)
return TPM_BAD_KEY_PROPERTY;
/* a. If the algorithm type is RSA the key length MUST be a minimum of 2048.
* For interoperability the key length SHOULD be 2048 */
/* b. If the algorithm type is other than RSA the strength provided by the
* key MUST be comparable to RSA 2048 */
/* c. If the TPM is not designed to create a key of the requested type,
* return the error code TPM_BAD_KEY_PROPERTY */
switch (idKeyParams->algorithmParms.algorithmID) {
case TPM_ALG_RSA:
if (idKeyParams->algorithmParms.parmSize == 0
|| idKeyParams->algorithmParms.parms.rsa.keyLength != 2048
|| idKeyParams->algorithmParms.parms.rsa.numPrimes != 2
|| idKeyParams->algorithmParms.parms.rsa.exponentSize != 0)
return TPM_BAD_KEY_PROPERTY;
break;
default:
return TPM_BAD_KEY_PROPERTY;
}
/* d. If TPM_PERMANENT_FLAGS->FIPS is TRUE then */
if (tpmData.permanent.flags.FIPS == TRUE) {
/* i. If authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */
if (idKeyParams->authDataUsage == TPM_AUTH_NEVER)
return TPM_NOTFIPS;
}
/* 2. Use authHandle to verify that the Owner authorized all TPM_MakeIdentity
* input parameters. */
if (auth2->authHandle != TPM_INVALID_HANDLE) {
res = tpm_verify_auth(auth2, tpmData.permanent.data.ownerAuth,
TPM_KH_OWNER);
if (res != TPM_SUCCESS) return res;
} else {
res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth,
TPM_KH_OWNER);
if (res != TPM_SUCCESS) return res;
}
/* 3. Use srkAuthHandle to verify that the SRK owner authorized all
* TPM_MakeIdentity input parameters. */
if (auth2->authHandle != TPM_INVALID_HANDLE) {
res = tpm_verify_auth(auth1, tpmData.permanent.data.srk.usageAuth,
TPM_KH_SRK);
if (res != TPM_SUCCESS) return res;
}
/* 4. Verify that idKeyParams->keyUsage is TPM_KEY_IDENTITY. If it is not,
* return TPM_INVALID_KEYUSAGE */
if (idKeyParams->keyUsage != TPM_KEY_IDENTITY)
return TPM_INVALID_KEYUSAGE;
/* 5. Verify that idKeyParams->keyFlags->migratable is FALSE. If it is not,
* return TPM_INVALID_KEYUSAGE */
if ((idKeyParams->keyFlags & TPM_KEY_FLAG_MIGRATABLE) ==
TPM_KEY_FLAG_MIGRATABLE)
return TPM_INVALID_KEYUSAGE;
/* 6. If ownerAuth indicates XOR encryption for the AuthData secrets */
ownerAuth_sessionData = tpm_get_auth(auth2->authHandle);
if (ownerAuth_sessionData == NULL) return TPM_INVALID_AUTHHANDLE;
if ((ownerAuth_sessionData->entityType & 0xFF00) == TPM_ET_XOR) {
/* a. Create X1 the SHA-1 of the concatenation of (ownerAuth->sharedSecret
* || authLastNonceEven) */
/* b. Create A1 by XOR X1 and identityAuth */
tpm_decrypt_auth_secret(*identityAuth, ownerAuth_sessionData->sharedSecret,
&ownerAuth_sessionData->lastNonceEven, A1);
} else {
/* 7. Else */
/* a. Create A1 by decrypting identityAuth using the algorithm indicated
* in the OSAP session */
/* b. Key is from ownerAuth->sharedSecret */
/* c. IV is SHA-1 of (authLastNonceEven || nonceOdd) */
debug("TPM_MakeIdentity() does not support entityType=%.8x yet.",
ownerAuth_sessionData->entityType);
return TPM_FAIL;
}
/* 8. Set continueAuthSession and continueSRKSession to FALSE. */
auth2->continueAuthSession = FALSE, auth1->continueAuthSession = FALSE;
/* 9. Determine the structure version */
/* a. If idKeyParms->tag is TPM_TAG_KEY12 */
if (idKeyParams->tag == TPM_TAG_KEY12) {
/* i. Set V1 to 2 */
/* ii. Create idKey a TPM_KEY12 structure using idKeyParams as the
* default values for the structure */
idKey->tag = TPM_TAG_KEY12;
idKey->fill = 0x0000;
idKey->keyUsage = TPM_KEY_IDENTITY;
idKey->keyFlags = idKeyParams->keyFlags;
idKey->authDataUsage = idKeyParams->authDataUsage;
idKey->algorithmParms.algorithmID =
idKeyParams->algorithmParms.algorithmID;
idKey->algorithmParms.encScheme = idKeyParams->algorithmParms.encScheme;
idKey->algorithmParms.sigScheme = idKeyParams->algorithmParms.sigScheme;
idKey->algorithmParms.parmSize = idKeyParams->algorithmParms.parmSize;
switch (idKeyParams->algorithmParms.algorithmID) {
case TPM_ALG_RSA:
idKey->algorithmParms.parms.rsa.keyLength =
idKeyParams->algorithmParms.parms.rsa.keyLength;
idKey->algorithmParms.parms.rsa.numPrimes =
idKeyParams->algorithmParms.parms.rsa.numPrimes;
idKey->algorithmParms.parms.rsa.exponentSize =
idKeyParams->algorithmParms.parms.rsa.exponentSize;
break;
default:
return TPM_BAD_KEY_PROPERTY;
}
idKey->PCRInfoSize = idKeyParams->PCRInfoSize;
idKey->PCRInfo.tag = TPM_TAG_PCR_INFO_LONG;
idKey->PCRInfo.localityAtCreation =
idKeyParams->PCRInfo.localityAtCreation;
idKey->PCRInfo.localityAtRelease =
idKeyParams->PCRInfo.localityAtRelease;
idKey->PCRInfo.creationPCRSelection =
idKeyParams->PCRInfo.creationPCRSelection;
idKey->PCRInfo.releasePCRSelection =
idKeyParams->PCRInfo.releasePCRSelection;
idKey->PCRInfo.digestAtCreation =
idKeyParams->PCRInfo.digestAtCreation;
idKey->PCRInfo.digestAtRelease =
idKeyParams->PCRInfo.digestAtRelease;
} else if (idKeyParams->tag == 0x0101) {
/* b. If idKeyParms->ver is 1.1 */
/* i. Set V1 to 1 */
/* ii. Create idKey a TPM_KEY structure using idKeyParams as the
* default values for the structure */
idKey->tag = 0x0101;
idKey->fill = 0x0000;
idKey->keyUsage = TPM_KEY_IDENTITY;
idKey->keyFlags = idKeyParams->keyFlags;
idKey->authDataUsage = idKeyParams->authDataUsage;
idKey->algorithmParms.algorithmID =
idKeyParams->algorithmParms.algorithmID;
idKey->algorithmParms.encScheme = idKeyParams->algorithmParms.encScheme;
idKey->algorithmParms.sigScheme = idKeyParams->algorithmParms.sigScheme;
idKey->algorithmParms.parmSize = idKeyParams->algorithmParms.parmSize;
switch (idKeyParams->algorithmParms.algorithmID) {
case TPM_ALG_RSA:
idKey->algorithmParms.parms.rsa.keyLength =
idKeyParams->algorithmParms.parms.rsa.keyLength;
idKey->algorithmParms.parms.rsa.numPrimes =
idKeyParams->algorithmParms.parms.rsa.numPrimes;
idKey->algorithmParms.parms.rsa.exponentSize =
idKeyParams->algorithmParms.parms.rsa.exponentSize;
break;
default:
return TPM_BAD_KEY_PROPERTY;
}
idKey->PCRInfoSize = idKeyParams->PCRInfoSize;
idKey->PCRInfo.tag = 0x0000;
idKey->PCRInfo.creationPCRSelection =
idKeyParams->PCRInfo.creationPCRSelection;
idKey->PCRInfo.digestAtRelease =
idKeyParams->PCRInfo.digestAtRelease;
idKey->PCRInfo.digestAtCreation =
idKeyParams->PCRInfo.digestAtCreation;
} else {
debug("TPM_MakeIdentity(): unsupport this TPM_KEY structure.");
return TPM_FAIL;
}
/* 10. Set the digestAtCreation values for pcrInfo */
if (idKey->PCRInfoSize > 0) {
res = tpm_compute_pcr_digest(&idKey->PCRInfo.creationPCRSelection,
&idKey->PCRInfo.digestAtCreation, NULL);
if (res != TPM_SUCCESS) return res;
/* a. For PCR_INFO_LONG include the locality of the current command */
if (idKey->PCRInfo.tag == TPM_TAG_PCR_INFO_LONG)
idKey->PCRInfo.localityAtCreation = (1 << LOCALITY);
}
/* 11. Create an asymmetric key pair (identityPubKey and tpm_signature_key)
* using a TPM-protected capability, in accordance with the algorithm
* specified in idKeyParams */
key_length = idKeyParams->algorithmParms.parms.rsa.keyLength;
if (tpm_rsa_generate_key(&tpm_signature_key, key_length)) {
debug("TPM_MakeIdentity(): tpm_rsa_generate_key() failed.");
return TPM_FAIL;
}
/* 12. Ensure that the AuthData information in A1 is properly stored in the
* idKey as usageAuth. */
memcpy(store.usageAuth, A1, sizeof(TPM_SECRET));
/* 13. Attach identityPubKey and tpm_signature_key to idKey */
idKey->pubKey.keyLength = key_length >> 3;
idKey->pubKey.key = tpm_malloc(idKey->pubKey.keyLength);
if (idKey->pubKey.key == NULL) {
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_NOSPACE;
}
store.privKey.keyLength = key_length >> 4;
store.privKey.key = tpm_malloc(store.privKey.keyLength);
if (store.privKey.key == NULL) {
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_NOSPACE;
}
idKey->encDataSize = tpmData.permanent.data.srk.key.size >> 3;
idKey->encData = tpm_malloc(idKey->encDataSize);
if (idKey->encData == NULL) {
tpm_free(store.privKey.key);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_NOSPACE;
}
tpm_rsa_export_modulus(&tpm_signature_key, idKey->pubKey.key, NULL);
tpm_rsa_export_prime1(&tpm_signature_key, store.privKey.key, NULL);
/* 14. Set idKey->migrationAuth to TPM_PERMANENT_DATA->tpmProof */
memcpy(store.migrationAuth, tpmData.permanent.data.tpmProof.nonce,
sizeof(TPM_SECRET));
/* 15. Ensure that all TPM_PAYLOAD_TYPE structures identify this key as
* TPM_PT_ASYM */
store.payload = TPM_PT_ASYM;
/* compute the digest on all public data of this key */
if (tpm_compute_key_digest(idKey, &store.pubDataDigest)) {
debug("TPM_MakeIdentity(): tpm_compute_key_digest() failed.");
tpm_free(idKey->encData);
tpm_free(store.privKey.key);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_FAIL;
}
/* 16. Encrypt the private portion of idKey using the SRK as the parent key */
if (tpm_encrypt_private_key(&tpmData.permanent.data.srk, &store, idKey->encData,
&idKey->encDataSize)) {
tpm_free(idKey->encData);
tpm_free(store.privKey.key);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_ENCRYPT_ERROR;
}
tpm_free(store.privKey.key);
/* 17. Create a TPM_IDENTITY_CONTENTS structure named idContents using
* labelPrivCADigest and the information from idKey */
idContents.ver.major = 1, idContents.ver.minor = 1; /* MUST BE 1.1, (Spec) */
idContents.ver.revMajor = 0, idContents.ver.revMinor = 0;
idContents.ordinal = TPM_ORD_MakeIdentity;
memcpy(&idContents.labelPrivCADigest, labelPrivCADigest,
sizeof(TPM_CHOSENID_HASH));
idContents.identityPubKey.algorithmParms.algorithmID =
idKey->algorithmParms.algorithmID;
idContents.identityPubKey.algorithmParms.encScheme =
idKey->algorithmParms.encScheme;
idContents.identityPubKey.algorithmParms.sigScheme =
idKey->algorithmParms.sigScheme;
idContents.identityPubKey.algorithmParms.parmSize =
idKey->algorithmParms.parmSize;
switch (idKey->algorithmParms.algorithmID) {
case TPM_ALG_RSA:
idContents.identityPubKey.algorithmParms.parms.rsa.keyLength =
idKey->algorithmParms.parms.rsa.keyLength;
idContents.identityPubKey.algorithmParms.parms.rsa.numPrimes =
idKey->algorithmParms.parms.rsa.numPrimes;
idContents.identityPubKey.algorithmParms.parms.rsa.exponentSize =
idKey->algorithmParms.parms.rsa.exponentSize;
break;
default:
tpm_free(idKey->encData);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_BAD_KEY_PROPERTY;
}
idContents.identityPubKey.pubKey.keyLength = key_length >> 3;
idContents.identityPubKey.pubKey.key =
tpm_malloc(idContents.identityPubKey.pubKey.keyLength);
if (idContents.identityPubKey.pubKey.key == NULL) {
tpm_free(idKey->encData);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_NOSPACE;
}
tpm_rsa_export_modulus(&tpm_signature_key, idContents.identityPubKey.pubKey.key, NULL);
len = sizeof_TPM_IDENTITY_CONTENTS((idContents));
buf = ptr = tpm_malloc(len);
if (buf == NULL) {
tpm_free(idContents.identityPubKey.pubKey.key);
tpm_free(idKey->encData);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_NOSPACE;
}
if (tpm_marshal_TPM_IDENTITY_CONTENTS(&ptr, &len, &idContents)) {
debug("TPM_MakeIdentity(): tpm_marshal_TPM_IDENTITY_CONTENTS() failed.");
tpm_free(buf);
tpm_free(idContents.identityPubKey.pubKey.key);
tpm_free(idKey->encData);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_FAIL;
}
/* 18. Sign idContents using tpm_signature_key and
* TPM_SS_RSASSAPKCS1v15_SHA1. Store the result in identityBinding. */
*identityBindingSize = tpm_signature_key.size >> 3;
*identityBinding = tpm_malloc(*identityBindingSize);
if (*identityBinding == NULL) {
tpm_free(buf);
tpm_free(idContents.identityPubKey.pubKey.key);
tpm_free(idKey->encData);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_NOSPACE;
}
if (tpm_rsa_sign(&tpm_signature_key, RSA_SSA_PKCS1_SHA1, buf,
sizeof_TPM_IDENTITY_CONTENTS((idContents)), *identityBinding)) {
debug("TPM_MakeIdentity(): tpm_rsa_sign() failed.");
tpm_free(*identityBinding);
tpm_free(buf);
tpm_free(idContents.identityPubKey.pubKey.key);
tpm_free(idKey->encData);
tpm_free(idKey->pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_FAIL;
}
tpm_free(buf);
tpm_free(idContents.identityPubKey.pubKey.key);
tpm_rsa_release_private_key(&tpm_signature_key);
return TPM_SUCCESS;
}
TPM_RESULT TPM_ActivateIdentity(
TPM_KEY_HANDLE idKeyHandle,
UINT32 blobSize,
BYTE *blob,
TPM_AUTH *auth1,
TPM_AUTH *auth2,
TPM_SYMMETRIC_KEY *symmetricKey
)
{
TPM_RESULT res;
TPM_KEY_DATA *idKey = NULL;
TPM_PUBKEY pubKey;
TPM_DIGEST H1;
BYTE *B1 = NULL;
size_t sizeB1 = 0;
UINT32 len;
BYTE *ptr;
BYTE B1__what = 0x00;
TPM_EK_BLOB B1__ekBlob;
TPM_ASYM_CA_CONTENTS B1__asymCaContents;
TPM_SYMMETRIC_KEY *K1 = NULL;
TPM_EK_BLOB_ACTIVATE A1;
TPM_COMPOSITE_HASH C1;
info("TPM_ActivateIdentity()");
/* 1. Using the authHandle field, validate the owner's AuthData to execute
* the command and all of the incoming parameters. */
if (auth2->authHandle != TPM_INVALID_HANDLE) {
res = tpm_verify_auth(auth2, tpmData.permanent.data.ownerAuth,
TPM_KH_OWNER);
if (res != TPM_SUCCESS) return res;
} else {
res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth,
TPM_KH_OWNER);
if (res != TPM_SUCCESS) return res;
}
/* 2. Using the idKeyAuthHandle, validate the AuthData to execute command
* and all of the incoming parameters */
idKey = tpm_get_key(idKeyHandle);
if (idKey == NULL)
return TPM_INVALID_KEYHANDLE;
if (auth2->authHandle != TPM_INVALID_HANDLE) {
if (idKey->authDataUsage != TPM_AUTH_NEVER) {
res = tpm_verify_auth(auth1, idKey->usageAuth, idKeyHandle);
if (res != TPM_SUCCESS) return res;
}
}
/* 3. Validate that the idKey is the public key of a valid TPM identity by
* checking that idKeyHandle->keyUsage is TPM_KEY_IDENTITY.
* Return TPM_BAD_PARAMETER on mismatch */
if (idKey->keyUsage != TPM_KEY_IDENTITY)
return TPM_BAD_PARAMETER;
/* 4. Create H1 the digest of a TPM_PUBKEY derived from idKey */
pubKey.pubKey.keyLength = idKey->key.size >> 3;
pubKey.pubKey.key = tpm_malloc(pubKey.pubKey.keyLength);
if (pubKey.pubKey.key == NULL)
return TPM_NOSPACE;
tpm_rsa_export_modulus(&idKey->key, pubKey.pubKey.key, NULL);
if (tpm_setup_key_parms(idKey, &pubKey.algorithmParms) != 0) {
debug("TPM_ActivateIdentity(): tpm_setup_key_parms() failed.");
tpm_free(pubKey.pubKey.key);
return TPM_FAIL;
}
tpm_free(pubKey.algorithmParms.parms.rsa.exponent);
pubKey.algorithmParms.parms.rsa.exponentSize = 0;
pubKey.algorithmParms.parmSize = 12;
if (tpm_compute_pubkey_digest(&pubKey, &H1)) {
debug("TPM_ActivateIdentity(): tpm_compute_pubkey_digest() failed.");
tpm_free(pubKey.pubKey.key);
return TPM_FAIL;
}
/* 5. Decrypt blob creating B1 using PRIVEK as the decryption key */
B1 = tpm_malloc(blobSize);
if (B1 == NULL) {
tpm_free(pubKey.pubKey.key);
return TPM_NOSPACE;
}
if (tpm_rsa_decrypt(&tpmData.permanent.data.endorsementKey, RSA_ES_OAEP_SHA1,
blob, blobSize, B1, &sizeB1)) {
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_DECRYPT_ERROR;
}
/* 6. Determine the type and version of B1 */
if ((((UINT16)B1[0] << 8) | B1[1]) == TPM_TAG_EK_BLOB) {
/* a. If B1->tag is TPM_TAG_EK_BLOB then */
/* i. B1 is a TPM_EK_BLOB */
ptr = B1;
len = sizeB1;
if (tpm_unmarshal_TPM_EK_BLOB(&ptr, &len, &B1__ekBlob)) {
debug("TPM_ActivateIdentity(): tpm_unmarshal_TPM_EK_BLOB() failed.");
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_FAIL;
}
B1__what = 0x02;
} else {
/* b. Else */
/* i. B1 is a TPM_ASYM_CA_CONTENTS. As there is no tag for this
* structure it is possible for the TPM to make a mistake here but
* other sections of the structure undergo validation */
ptr = B1;
len = sizeB1;
if (tpm_unmarshal_TPM_ASYM_CA_CONTENTS(&ptr, &len, &B1__asymCaContents)) {
debug("TPM_ActivateIdentity(): tpm_unmarshal_TPM_ASYM_CA_CONTENTS() failed.");
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_FAIL;
}
B1__what = 0x01;
}
/* 7. If B1 is a version 1.1 TPM_ASYM_CA_CONTENTS then */
if (B1__what == 0x01) {
/* a. Compare H1 to B1->idDigest on mismatch return TPM_BAD_PARAMETER */
if (memcmp(H1.digest, B1__asymCaContents.idDigest.digest,
sizeof(H1.digest))) {
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_BAD_PARAMETER;
}
/* b. Set K1 to B1->sessionKey */
K1 = &B1__asymCaContents.sessionKey;
}
/* 8. If B1 is a TPM_EK_BLOB then */
if (B1__what == 0x02) {
/* a. Validate that B1->ekType is TPM_EK_TYPE_ACTIVATE,
* return TPM_BAD_TYPE if not. */
if (B1__ekBlob.ekType != TPM_EK_TYPE_ACTIVATE) {
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_BAD_TYPE;
}
/* b. Assign A1 as a TPM_EK_BLOB_ACTIVATE structure from B1->blob */
ptr = B1__ekBlob.blob;
len = B1__ekBlob.blobSize;
if (tpm_unmarshal_TPM_EK_BLOB_ACTIVATE(&ptr, &len, &A1)) {
debug("TPM_ActivateIdentity(): tpm_unmarshal_TPM_EK_BLOB_ACTIVATE() failed.");
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_FAIL;
}
/* c. Compare H1 to A1->idDigest on mismatch return TPM_BAD_PARAMETER */
if (memcmp(H1.digest, A1.idDigest.digest, sizeof(H1.digest))) {
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_BAD_PARAMETER;
}
/* d. If A1->pcrSelection is not NULL */
if (A1.pcrInfo.pcrSelection.sizeOfSelect > 0) {
/* i. Compute a composite hash C1 using the PCR selection
* A1->pcrSelection */
if (tpm_compute_pcr_digest(&A1.pcrInfo.pcrSelection, &C1, NULL) !=
TPM_SUCCESS) {
debug("TPM_ActivateIdentity(): tpm_compute_pcr_digest() failed.");
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_FAIL;
}
/* ii. Compare C1 to A1->pcrInfo->digestAtRelease and return
* TPM_WRONGPCRVAL on a mismatch */
if (memcmp(&C1, &A1.pcrInfo.digestAtRelease,
sizeof(TPM_COMPOSITE_HASH))) {
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_WRONGPCRVAL;
}
/* iii. If A1->pcrInfo specifies a locality ensure that the
* appropriate locality has been asserted, return TPM_BAD_LOCALITY
* on error */
if (!(A1.pcrInfo.localityAtRelease & (1 << LOCALITY))) {
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_BAD_LOCALITY;
}
}
/* e. Set K1 to A1->sessionKey */
K1 = &A1.sessionKey;
}
/* 9. Return K1 */
if (K1 != NULL) {
symmetricKey->algId = K1->algId;
symmetricKey->encScheme = K1->encScheme;
symmetricKey->size = K1->size;
memcpy(symmetricKey->data, K1->data, K1->size);
}
tpm_free(pubKey.pubKey.key);
tpm_free(B1);
return TPM_SUCCESS;
}