static uint32_t TpmUtilCreateAuthority( char* authorityName, ANY_OBJECT* sigkey ) { DEFINE_CALL_BUFFERS; UINT32 result = TPM_RC_SUCCESS; union { CreatePrimary_In createPrimary; } in; union { CreatePrimary_Out createPrimary; } out; // This is set up to create an SM2 key that is using SM3 payload hashing INITIALIZE_CALL_BUFFERS(TPM2_CreatePrimary, &in.createPrimary, &out.createPrimary); parms.objectTableIn[TPM2_CreatePrimary_HdlIn_PrimaryHandle].entity.handle = TPM_RH_ENDORSEMENT; in.createPrimary.inPublic.t.publicArea.nameAlg = TPM_ALG_SHA256; in.createPrimary.inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin = SET; in.createPrimary.inPublic.t.publicArea.objectAttributes.userWithAuth = SET; in.createPrimary.inPublic.t.publicArea.objectAttributes.noDA = SET; in.createPrimary.inPublic.t.publicArea.objectAttributes.sign = SET; #ifdef NTZTPM in.createPrimary.inPublic.t.publicArea.type = TPM_ALG_ECC; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_SM2; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = TPM_ALG_SM3_256; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.curveID = TPM_ECC_SM2_P256; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL; #else in.createPrimary.inPublic.t.publicArea.type = TPM_ALG_ECC; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_ECDSA; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = TPM_ALG_SHA256; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; in.createPrimary.inPublic.t.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL; // in.createPrimary.inPublic.t.publicArea.type = TPM_ALG_RSA; // in.createPrimary.inPublic.t.publicArea.parameters.rsaDetail.keyBits = MAX_RSA_KEY_BITS; // in.createPrimary.inPublic.t.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_RSAPSS; // in.createPrimary.inPublic.t.publicArea.parameters.rsaDetail.scheme.details.rsapss.hashAlg = TPM_ALG_SHA256; // in.createPrimary.inPublic.t.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL; #endif in.createPrimary.inPublic.t.publicArea.unique.ecc.x.t.size = CryptHashBlock(TPM_ALG_SHA256, strlen(authorityName), (BYTE*)authorityName, sizeof(in.createPrimary.inPublic.t.publicArea.unique.ecc.x.t.buffer), in.createPrimary.inPublic.t.publicArea.unique.ecc.x.t.buffer); EXECUTE_TPM_CALL(FALSE, TPM2_CreatePrimary); *sigkey = parms.objectTableOut[TPM2_CreatePrimary_HdlOut_ObjectHandle]; Cleanup: return result; }
/* 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; }
UINT32 CreatePlatformDataProtectionKey( void ) { DEFINE_CALL_BUFFERS; UINT32 result = TPM_RC_SUCCESS; union { PolicyPCR_In policyPcr; PolicyAuthValue_In policyAuthValue; StartAuthSession_In startAuthSession; CreatePrimary_In createPrimary; EvictControl_In evictControl; } in; union { CreatePrimary_Out createPrimary; EvictControl_Out evictControl; } out; SESSION policySession = {0}; TPM2B_DIGEST policyDigest = {0}; HASH_STATE hash = {0}; TPM2B_DIGEST pcrDigest = {0}; TPML_PCR_SELECTION pcrs = {0}; TPML_DIGEST pcrValues = {0}; ANY_OBJECT aesDpkObject = {0}; // Best effort free the NV index if there is already a key INITIALIZE_CALL_BUFFERS(TPM2_EvictControl, &in.evictControl, &out.evictControl); parms.objectTableIn[TPM2_EvictControl_HdlIn_Auth].entity.handle = TPM_RH_PLATFORM; parms.objectTableIn[TPM2_EvictControl_HdlIn_ObjectHandle].obj.handle = TPM_PLATFORM_DPK_HANDLE; in.evictControl.persistentHandle = TPM_PLATFORM_DPK_HANDLE; TRY_TPM_CALL(FALSE, TPM2_EvictControl); // Calculate the expected PCR table for the policy pcrs.count = 1; pcrs.pcrSelections[0].hash = TPM_ALG_SHA256; pcrs.pcrSelections[0].sizeofSelect = 3; pcrs.pcrSelections[0].pcrSelect[0] = 0xFF; pcrs.pcrSelections[0].pcrSelect[1] = 0x00; pcrs.pcrSelections[0].pcrSelect[2] = 0x00; pcrValues.count = 8; for(UINT32 n = 0; n < pcrValues.count; n++) { pcrValues.digests[n].t.size = SHA256_DIGEST_SIZE; } pcrValues.digests[0].t.size = CryptStartHash(TPM_ALG_SHA256, &hash); CryptUpdateDigest2B(&hash, (TPM2B*)&pcrValues.digests[0]); CryptHashBlock(TPM_ALG_SHA256, persistedData.compoundIdentity.t.size, persistedData.compoundIdentity.t.buffer, pcrValues.digests[0].t.size, pcrValues.digests[0].t.buffer); CryptUpdateDigest2B(&hash, (TPM2B*)&pcrValues.digests[0]); CryptCompleteHash2B(&hash, (TPM2B*)&pcrValues.digests[0]); pcrDigest.t.size = CryptStartHash(TPM_ALG_SHA256, &hash); for(UINT32 n = 0; n < pcrValues.count; n++) { CryptUpdateDigest(&hash, pcrValues.digests[n].t.size, pcrValues.digests[n].t.buffer); } CryptCompleteHash2B(&hash, (TPM2B*)&pcrDigest); // Calculate the PCR policy - Any change here will result in a different key // policydigest = PolicyAuthValue() || PolicyPCR(PCR[0..7]) policyDigest.t.size = SHA256_DIGEST_SIZE; TPM2_PolicyAuthValue_CalculateUpdate(TPM_ALG_SHA256, &policyDigest, &in.policyAuthValue); in.policyPcr.pcrs = pcrs; in.policyPcr.pcrDigest = pcrDigest; TPM2_PolicyPCR_CalculateUpdate(TPM_ALG_SHA256, &policyDigest, &in.policyPcr); // Create the PCR bound AES key sessionTable[0] = volatileData.ekSeededSession; sessionTable[0].attributes.decrypt = YES; INITIALIZE_CALL_BUFFERS(TPM2_CreatePrimary, &in.createPrimary, &out.createPrimary); parms.objectTableIn[TPM2_CreatePrimary_HdlIn_PrimaryHandle].entity.handle = TPM_RH_PLATFORM; UINT32_TO_BYTE_ARRAY(parms.objectTableIn[TPM2_CreatePrimary_HdlIn_PrimaryHandle].entity.handle, parms.objectTableIn[TPM2_CreatePrimary_HdlIn_PrimaryHandle].entity.name.t.name); parms.objectTableIn[TPM2_CreatePrimary_HdlIn_PrimaryHandle].entity.name.t.size = sizeof(parms.objectTableIn[TPM2_CreatePrimary_HdlIn_PrimaryHandle].entity.handle); in.createPrimary.inSensitive.t.sensitive.data.t.size = CryptGenerateRandom(16, in.createPrimary.inSensitive.t.sensitive.data.t.buffer); in.createPrimary.inSensitive.t.sensitive.userAuth = persistedData.compoundIdentity; in.createPrimary.inPublic.t.publicArea.type = TPM_ALG_SYMCIPHER; in.createPrimary.inPublic.t.publicArea.nameAlg = TPM_ALG_SHA256; in.createPrimary.inPublic.t.publicArea.objectAttributes.fixedTPM = SET; in.createPrimary.inPublic.t.publicArea.objectAttributes.fixedParent = SET; in.createPrimary.inPublic.t.publicArea.objectAttributes.adminWithPolicy = SET; in.createPrimary.inPublic.t.publicArea.objectAttributes.noDA = SET; in.createPrimary.inPublic.t.publicArea.objectAttributes.decrypt = SET; #ifndef NTZTPM in.createPrimary.inPublic.t.publicArea.objectAttributes.sign = SET; #endif in.createPrimary.inPublic.t.publicArea.parameters.symDetail.algorithm = TPM_ALG_AES; in.createPrimary.inPublic.t.publicArea.parameters.symDetail.keyBits.sym = 128; in.createPrimary.inPublic.t.publicArea.parameters.symDetail.mode.sym = TPM_ALG_CFB; in.createPrimary.inPublic.t.publicArea.authPolicy = policyDigest; EXECUTE_TPM_CALL(FALSE, TPM2_CreatePrimary); sessionTable[0].attributes = volatileData.ekSeededSession.attributes; volatileData.ekSeededSession = sessionTable[0]; aesDpkObject = parms.objectTableOut[TPM2_CreatePrimary_HdlOut_ObjectHandle]; PrintTPM2B("PlatformDPKeyName", (TPM2B*)&aesDpkObject.obj.name); // Persist the key sessionTable[0] = volatileData.ekSeededSession; INITIALIZE_CALL_BUFFERS(TPM2_EvictControl, &in.evictControl, &out.evictControl); parms.objectTableIn[TPM2_EvictControl_HdlIn_Auth].entity.handle = TPM_RH_PLATFORM; parms.objectTableIn[TPM2_EvictControl_HdlIn_ObjectHandle] = aesDpkObject; in.evictControl.persistentHandle = TPM_PLATFORM_DPK_HANDLE; EXECUTE_TPM_CALL(FALSE, TPM2_EvictControl); volatileData.ekSeededSession = sessionTable[0]; Cleanup: if(aesDpkObject.obj.handle != 0) { FlushContext(&aesDpkObject); } if(result != TPM_RC_SUCCESS) { // Copy the EKSeeded session back out in case of an error volatileData.ekSeededSession = sessionTable[0]; } return result; }