/* This function computes the qualified name of an object. */ void ComputeQualifiedName( TPM_HANDLE parentHandle, // IN: parent's handle TPM_ALG_ID nameAlg, // IN: name hash TPM2B_NAME *name, // IN: name of the object TPM2B_NAME *qualifiedName // OUT: qualified name of the object ) { HASH_STATE hashState; // hash state TPM2B_NAME parentName; if(parentHandle == TPM_RH_UNASSIGNED) { MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name)); *qualifiedName = *name; } else { GetQualifiedName(parentHandle, &parentName); // QN_A = hash_A (QN of parent || NAME_A) // Start hash qualifiedName->t.size = CryptHashStart(&hashState, nameAlg); // Add parent's qualified name CryptDigestUpdate2B(&hashState, &parentName.b); // Add self name CryptDigestUpdate2B(&hashState, &name->b); // Complete hash leaving room for the name algorithm CryptHashEnd(&hashState, qualifiedName->t.size, &qualifiedName->t.name[2]); UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name); qualifiedName->t.size += 2; } return; }
/* This does the name computation from a public area (can be marshaled or not). */ TPM2B_NAME * ObjectComputeName( UINT32 size, // IN: the size of the area to digest BYTE *publicArea, // IN: the public area to digest TPM_ALG_ID nameAlg, // IN: the hash algorithm to use TPM2B_NAME *name // OUT: Computed name ) { // Hash the publicArea into the name buffer leaving room for the nameAlg name->t.size = CryptHashBlock(nameAlg, size, publicArea, sizeof(name->t.name) - 2, &name->t.name[2]); // set the nameAlg UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name); name->t.size += 2; return name; }
static uint32_t TpmUtilIssueBootPolicy( ANY_OBJECT* platformAuthority, TPM2B_MAX_NV_BUFFER* policy, TPM2B_NAME* deviceId, TPMT_SIGNATURE* authorizationSignature ) { DEFINE_CALL_BUFFERS; UINT32 result = TPM_RC_SUCCESS; union { PolicyAuthorize_In policyAuthorize; PolicyGetDigest_In policyGetDigest; PolicyCpHash_In policyCpHash; Sign_In sign; } in; union { Sign_Out sign; } out; TPM2B_NV_PUBLIC nvPublicInfo = {0}; TPM2B_NAME nvIndexName = {0}; const TPM_CC commandCode = TPM_CC_NV_Write; const UINT16 offset = 0; TPM2B_DIGEST cpHash = {0}; TPM2B_DIGEST approvedPolicy = {0}; TPM2B_DIGEST authorization = {0}; HASH_STATE hash = {0}; // Next we predict the NV storage Name that this policy will be hosted in nvPublicInfo.t.nvPublic.dataSize = policy->t.size; nvPublicInfo.t.nvPublic.nameAlg = TPM_ALG_SHA256; nvPublicInfo.t.nvPublic.nvIndex = TPM_PLATFORM_LOCKDOWN_POLICY_NV_INDEX; nvPublicInfo.t.nvPublic.attributes.TPMA_NV_AUTHREAD = SET; nvPublicInfo.t.nvPublic.attributes.TPMA_NV_OWNERREAD = SET; nvPublicInfo.t.nvPublic.attributes.TPMA_NV_NO_DA = SET; nvPublicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE = SET; nvPublicInfo.t.nvPublic.attributes.TPMA_NV_POLICYWRITE = SET; // Calculate the authPolicy for the index MemorySet(&in.policyAuthorize, 0x00, sizeof(in.policyAuthorize)); in.policyAuthorize.approvedPolicy.t.size = SHA256_DIGEST_SIZE; in.policyAuthorize.policyRef.t.size = SHA256_DIGEST_SIZE; MemoryCopy(in.policyAuthorize.policyRef.t.buffer, &deviceId->t.name[sizeof(UINT16)], in.policyAuthorize.policyRef.t.size, sizeof(in.policyAuthorize.policyRef.t.buffer)); in.policyAuthorize.keySign = platformAuthority->obj.name; in.policyAuthorize.checkTicket.tag = TPM_ST_VERIFIED; in.policyAuthorize.checkTicket.hierarchy = TPM_RH_NULL; nvPublicInfo.t.nvPublic.authPolicy.t.size = SHA256_DIGEST_SIZE; TPM2_PolicyAuthorize_CalculateUpdate(TPM_ALG_SHA256, &nvPublicInfo.t.nvPublic.authPolicy, &in.policyAuthorize); // Serialize the public index to get it's name buffer = pbCmd; size = sizeof(pbCmd); if(TPMS_NV_PUBLIC_Marshal(&nvPublicInfo.t.nvPublic, &buffer, &size) < 0) { result = TPM_RC_FAILURE; goto Cleanup; } UINT16_TO_BYTE_ARRAY(TPM_ALG_SHA256, nvIndexName.t.name); nvIndexName.t.size = sizeof(UINT16) + CryptHashBlock(TPM_ALG_SHA256, sizeof(pbCmd) - size, pbCmd, sizeof(nvIndexName.t.name) - sizeof(UINT16), &nvIndexName.t.name[sizeof(UINT16)]); // Next we are calculating cpHash for the write command we want to execute later cpHash.t.size = CryptStartHash(TPM_ALG_SHA256, &hash); CryptUpdateDigestInt(&hash, sizeof(commandCode), (void*)&commandCode); CryptUpdateDigest2B(&hash, &nvIndexName.b); CryptUpdateDigest2B(&hash, &nvIndexName.b); CryptUpdateDigestInt(&hash, sizeof(UINT16), &policy->t.size); CryptUpdateDigest2B(&hash, (TPM2B*)policy); CryptUpdateDigestInt(&hash, sizeof(UINT16), (void*)&offset); CryptCompleteHash2B(&hash, &cpHash.b); // We calculate the policy digest of PolicyCpHash(cpHash) MemorySet(&in.policyCpHash, 0x00, sizeof(in.policyCpHash)); approvedPolicy.t.size = SHA256_DIGEST_SIZE; in.policyCpHash.cpHashA = cpHash; TPM2_PolicyCpHash_CalculateUpdate(TPM_ALG_SHA256, &approvedPolicy, &in.policyCpHash); // Calculate the authorization authorization.t.size = CryptStartHash(TPM_ALG_SHA256, &hash); CryptUpdateDigest2B(&hash, (TPM2B*)&approvedPolicy); CryptUpdateDigest(&hash, SHA256_DIGEST_SIZE, &deviceId->t.name[sizeof(UINT16)]); CryptCompleteHash2B(&hash, &authorization.b); // Sign the authorization INITIALIZE_CALL_BUFFERS(TPM2_Sign, &in.sign, &out.sign); parms.objectTableIn[TPM2_Sign_HdlIn_KeyHandle] = *platformAuthority; in.sign.digest = authorization; in.sign.inScheme.scheme = TPM_ALG_NULL; // Use whatever the key demands in.sign.validation.tag = TPM_ST_HASHCHECK; in.sign.validation.hierarchy = TPM_RH_NULL; EXECUTE_TPM_CALL(FALSE, TPM2_Sign); *authorizationSignature = out.sign.signature; Cleanup: return result; }