/* * Licensed Materials - Property of IBM * * trousers - An open source TCG Software Stack * * (C) Copyright International Business Machines Corp. 2007 * */ #include #include #include #include #include "trousers/tss.h" #include "trousers/trousers.h" #include "trousers_types.h" #include "spi_utils.h" #include "obj.h" #include "tsplog.h" TSS_RESULT Tspi_TPM_CMKSetRestrictions(TSS_HTPM hTpm, /* in */ TSS_CMK_DELEGATE CmkDelegate) /* in */ { TSS_HCONTEXT hContext; TSS_HPOLICY hPolicy; Trspi_HashCtx hashCtx; TPM_DIGEST digest; TPM_AUTH ownerAuth; TSS_RESULT result; if ((result = obj_tpm_get_tsp_context(hTpm, &hContext))) return result; if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy))) return result; result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_SetRestrictions); result |= Trspi_Hash_UINT32(&hashCtx, CmkDelegate); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) return result; if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_CMK_SetRestrictions, hPolicy, FALSE, &digest, &ownerAuth))) return result; if ((result = RPC_CMK_SetRestrictions(hContext, CmkDelegate, &ownerAuth))) return result; result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, result); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_SetRestrictions); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) return result; if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &ownerAuth))) return result; return result; } TSS_RESULT Tspi_TPM_CMKApproveMA(TSS_HTPM hTpm, /* in */ TSS_HMIGDATA hMaAuthData) /* in */ { TSS_HCONTEXT hContext; TSS_HPOLICY hPolicy; UINT32 blobSize; BYTE *blob; TPM_DIGEST msaDigest; TPM_HMAC msaHmac; Trspi_HashCtx hashCtx; TPM_DIGEST digest; TPM_AUTH ownerAuth; TSS_RESULT result; if ((result = obj_tpm_get_tsp_context(hTpm, &hContext))) return result; if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy))) return result; if ((result = obj_migdata_get_msa_digest(hMaAuthData, &blobSize, &blob))) return result; memcpy(msaDigest.digest, blob, sizeof(msaDigest.digest)); free_tspi(hContext, blob); result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_ApproveMA); result |= Trspi_Hash_DIGEST(&hashCtx, msaDigest.digest); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) return result; if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_CMK_ApproveMA, hPolicy, FALSE, &digest, &ownerAuth))) return result; if ((result = RPC_CMK_ApproveMA(hContext, msaDigest, &ownerAuth, &msaHmac))) return result; result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, result); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_ApproveMA); result |= Trspi_Hash_HMAC(&hashCtx, msaHmac.digest); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) return result; if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &ownerAuth))) return result; if ((result = obj_migdata_set_msa_hmac(hMaAuthData, sizeof(msaHmac.digest), msaHmac.digest))) return result; return result; } TSS_RESULT Tspi_TPM_CMKCreateTicket(TSS_HTPM hTpm, /* in */ TSS_HKEY hVerifyKey, /* in */ TSS_HMIGDATA hSigData) /* in */ { TSS_HCONTEXT hContext; TSS_HPOLICY hPolicy; UINT32 pubKeySize; BYTE *pubKey = NULL; UINT32 blobSize; BYTE *blob; TPM_DIGEST sigData; UINT32 sigSize; BYTE *sig = NULL; TPM_HMAC sigTicket; Trspi_HashCtx hashCtx; TPM_DIGEST digest; TPM_AUTH ownerAuth; TSS_RESULT result; if ((result = obj_tpm_get_tsp_context(hTpm, &hContext))) return result; if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy))) return result; if ((result = obj_rsakey_get_pub_blob(hVerifyKey, &pubKeySize, &pubKey))) return result; if ((result = obj_migdata_get_sig_data(hSigData, &blobSize, &blob))) goto done; memcpy(sigData.digest, blob, sizeof(sigData.digest)); free_tspi(hContext, blob); if ((result = obj_migdata_get_sig_value(hSigData, &sigSize, &sig))) goto done; result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_CreateTicket); result |= Trspi_HashUpdate(&hashCtx, pubKeySize, pubKey); result |= Trspi_Hash_DIGEST(&hashCtx, sigData.digest); result |= Trspi_Hash_UINT32(&hashCtx, sigSize); result |= Trspi_HashUpdate(&hashCtx, sigSize, sig); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) goto done; if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_CMK_CreateTicket, hPolicy, FALSE, &digest, &ownerAuth))) goto done; if ((result = RPC_CMK_CreateTicket(hContext, pubKeySize, pubKey, sigData, sigSize, sig, &ownerAuth, &sigTicket))) goto done; result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, result); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_CreateTicket); result |= Trspi_Hash_HMAC(&hashCtx, sigTicket.digest); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) goto done; if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &ownerAuth))) goto done; if ((result = obj_migdata_set_sig_ticket(hSigData, sizeof(sigTicket.digest), sigTicket.digest))) goto done; done: free_tspi(hContext, pubKey); free_tspi(hContext, sig); return result; } TSS_RESULT Tspi_Key_CMKCreateBlob(TSS_HKEY hKeyToMigrate, /* in */ TSS_HKEY hParentKey, /* in */ TSS_HMIGDATA hMigrationData, /* in */ UINT32* pulRandomLength, /* out */ BYTE** prgbRandom) /* out */ { TSS_HCONTEXT hContext; TSS_HPOLICY hPolicy; TSS_BOOL usageAuth; TCS_KEY_HANDLE tcsKeyHandle; TSS_MIGRATE_SCHEME migScheme; UINT32 migTicketSize; BYTE *migTicket = NULL; TPM_MIGRATIONKEYAUTH tpmMigKeyAuth; UINT32 msaListSize, restrictTicketSize, sigTicketSize, blobSize; BYTE *msaList = NULL, *restrictTicket = NULL, *blob = NULL; BYTE *sigTicket = NULL; UINT32 pubBlobSize; BYTE *pubBlob = NULL; TPM_DIGEST srcPubKeyDigest; TSS_KEY tssKey; UINT32 randomDataSize, outDataSize, newBlobSize; BYTE *randomData = NULL, *outData = NULL, *newBlob = NULL; Trspi_HashCtx hashCtx; TPM_DIGEST digest; TPM_AUTH parentAuth, *pAuth; UINT64 offset; TSS_RESULT result; memset(&tssKey, 0, sizeof(tssKey)); if (!pulRandomLength || !prgbRandom) return TSPERR(TSS_E_BAD_PARAMETER); if (!obj_rsakey_is_cmk(hKeyToMigrate)) return TSPERR(TSS_E_BAD_PARAMETER); if ((result = obj_rsakey_get_tsp_context(hKeyToMigrate, &hContext))) return result; if ((result = obj_rsakey_get_policy(hParentKey, TSS_POLICY_USAGE, &hPolicy, &usageAuth))) return result; if ((result = obj_rsakey_get_tcs_handle(hParentKey, &tcsKeyHandle))) return result; if ((result = obj_migdata_get_ticket_blob(hMigrationData, &migTicketSize, &migTicket))) return result; /* Just to get the migration scheme... */ offset = 0; if ((result = Trspi_UnloadBlob_MIGRATIONKEYAUTH(&offset, migTicket, &tpmMigKeyAuth))) goto done; /* ... so free everything now */ free(tpmMigKeyAuth.migrationKey.algorithmParms.parms); free(tpmMigKeyAuth.migrationKey.pubKey.key); migScheme = tpmMigKeyAuth.migrationScheme; if ((result = obj_rsakey_get_pub_blob(hKeyToMigrate, &pubBlobSize, &pubBlob))) goto done; if ((result = obj_migdata_calc_pubkey_digest(pubBlobSize, pubBlob, &srcPubKeyDigest))) goto done; if ((result = obj_migdata_get_msa_list_blob(hMigrationData, &msaListSize, &msaList))) goto done; if (tpmMigKeyAuth.migrationScheme == TPM_MS_RESTRICT_APPROVE_DOUBLE) { if ((result = obj_migdata_get_cmk_auth_blob(hMigrationData, &restrictTicketSize, &restrictTicket))) goto done; if ((result = obj_migdata_get_sig_ticket(hMigrationData, &sigTicketSize, &sigTicket))) goto done; } else { restrictTicketSize = 0; sigTicketSize = 0; } if ((result = obj_rsakey_get_blob(hKeyToMigrate, &blobSize, &blob))) goto done; offset = 0; if ((result = UnloadBlob_TSS_KEY(&offset, blob, &tssKey))) goto done; if (usageAuth) { pAuth = &parentAuth; result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_CreateBlob); result |= Trspi_Hash_UINT16(&hashCtx, migScheme); result |= Trspi_HashUpdate(&hashCtx, migTicketSize, migTicket); result |= Trspi_Hash_DIGEST(&hashCtx, srcPubKeyDigest.digest); result |= Trspi_Hash_UINT32(&hashCtx, msaListSize); result |= Trspi_HashUpdate(&hashCtx, msaListSize, msaList); result |= Trspi_Hash_UINT32(&hashCtx, restrictTicketSize); result |= Trspi_HashUpdate(&hashCtx, restrictTicketSize, restrictTicket); result |= Trspi_Hash_UINT32(&hashCtx, sigTicketSize); result |= Trspi_HashUpdate(&hashCtx, sigTicketSize, sigTicket); result |= Trspi_Hash_UINT32(&hashCtx, tssKey.encSize); result |= Trspi_HashUpdate(&hashCtx, tssKey.encSize, tssKey.encData); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) goto done; if ((result = secret_PerformAuth_OIAP(hParentKey, TPM_ORD_CMK_CreateBlob, hPolicy, FALSE, &digest, pAuth))) goto done; } else pAuth = NULL; if ((result = RPC_CMK_CreateBlob(hContext, tcsKeyHandle, migScheme, migTicketSize, migTicket, srcPubKeyDigest, msaListSize, msaList, restrictTicketSize, restrictTicket, sigTicketSize, sigTicket, tssKey.encSize, tssKey.encData, pAuth, &randomDataSize, &randomData, &outDataSize, &outData))) goto done; if (pAuth) { result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, result); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_CreateBlob); result |= Trspi_Hash_UINT32(&hashCtx, randomDataSize); result |= Trspi_HashUpdate(&hashCtx, randomDataSize, randomData); result |= Trspi_Hash_UINT32(&hashCtx, outDataSize); result |= Trspi_HashUpdate(&hashCtx, outDataSize, outData); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) goto done; } if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth))) goto done; /* Create the migdata key blob */ free(tssKey.encData); tssKey.encSize = outDataSize; tssKey.encData = outData; /* Set outData to null since it will now be freed during key ref freeing */ outData = NULL; offset = 0; LoadBlob_TSS_KEY(&offset, NULL, &tssKey); newBlobSize = offset; if ((newBlob = malloc(newBlobSize)) == NULL) { LogError("malloc of %u bytes failed.", newBlobSize); result = TSPERR(TSS_E_OUTOFMEMORY); goto done; } offset = 0; LoadBlob_TSS_KEY(&offset, newBlob, &tssKey); if ((result = obj_migdata_set_blob(hMigrationData, newBlobSize, newBlob))) goto done; if ((*prgbRandom = calloc_tspi(hContext, randomDataSize)) == NULL) { LogError("malloc of %u bytes failed.", randomDataSize); result = TSPERR(TSS_E_OUTOFMEMORY); goto done; } memcpy(*prgbRandom, randomData, randomDataSize); *pulRandomLength = randomDataSize; done: free_tspi(hContext, migTicket); free_tspi(hContext, pubBlob); free_tspi(hContext, msaList); free_tspi(hContext, restrictTicket); free_tspi(hContext, sigTicket); free_tspi(hContext, blob); free(randomData); free(outData); free(newBlob); free_key_refs(&tssKey); return result; } TSS_RESULT Tspi_Key_CMKConvertMigration(TSS_HKEY hKeyToMigrate, /* in */ TSS_HKEY hParentKey, /* in */ TSS_HMIGDATA hMigrationData, /* in */ UINT32 ulRandomLength, /* in */ BYTE* rgbRandom) /* in */ { TSS_HCONTEXT hContext; TSS_HPOLICY hPolicy; TSS_BOOL usageAuth; TCS_KEY_HANDLE tcsKeyHandle; TPM_CMK_AUTH restrictTicket; UINT32 blobSize; BYTE *blob; TPM_HMAC sigTicket; UINT32 migDataSize, msaListSize; BYTE *migData = NULL, *msaList = NULL; UINT32 outDataSize; BYTE *outData = NULL; Trspi_HashCtx hashCtx; TPM_DIGEST digest; TPM_AUTH parentAuth, *pAuth; TSS_RESULT result; if ((result = obj_rsakey_get_tsp_context(hKeyToMigrate, &hContext))) return result; if ((result = obj_rsakey_get_policy(hParentKey, TSS_POLICY_USAGE, &hPolicy, &usageAuth))) return result; if ((result = obj_rsakey_get_tcs_handle(hParentKey, &tcsKeyHandle))) return result; if ((result = obj_migdata_get_cmk_auth(hMigrationData, &restrictTicket))) return result; if ((result = obj_migdata_get_sig_ticket(hMigrationData, &blobSize, &blob))) return result; memcpy(sigTicket.digest, blob, sizeof(sigTicket.digest)); free_tspi(hContext, blob); if ((result = obj_migdata_get_blob(hMigrationData, &migDataSize, &migData))) goto done; if ((result = obj_migdata_get_msa_list_blob(hMigrationData, &msaListSize, &msaList))) goto done; if (usageAuth) { pAuth = &parentAuth; result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_ConvertMigration); result |= Trspi_HashUpdate(&hashCtx, sizeof(restrictTicket), (BYTE *)&restrictTicket); result |= Trspi_Hash_HMAC(&hashCtx, sigTicket.digest); result |= Trspi_HashUpdate(&hashCtx, migDataSize, migData); result |= Trspi_Hash_UINT32(&hashCtx, msaListSize); result |= Trspi_HashUpdate(&hashCtx, msaListSize, msaList); result |= Trspi_Hash_UINT32(&hashCtx, ulRandomLength); result |= Trspi_HashUpdate(&hashCtx, ulRandomLength, rgbRandom); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) goto done; if ((result = secret_PerformAuth_OIAP(hParentKey, TPM_ORD_CMK_ConvertMigration, hPolicy, FALSE, &digest, pAuth))) goto done; } else pAuth = NULL; if ((result = RPC_CMK_ConvertMigration(hContext, tcsKeyHandle, restrictTicket, sigTicket, migDataSize, migData, msaListSize, msaList, ulRandomLength, rgbRandom, pAuth, &outDataSize, &outData))) goto done; if (pAuth) { result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, result); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CMK_ConvertMigration); result |= Trspi_Hash_UINT32(&hashCtx, outDataSize); result |= Trspi_HashUpdate(&hashCtx, outDataSize, outData); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) goto done; } if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth))) goto done; /* Set the key object to the now migrated key */ if ((result = obj_rsakey_set_tcpakey(hKeyToMigrate, migDataSize, migData))) goto done; if ((result = obj_rsakey_set_privkey(hKeyToMigrate, TRUE, outDataSize, outData))) goto done; result = obj_rsakey_set_tcs_handle(hKeyToMigrate, 0); done: free_tspi(hContext, migData); free_tspi(hContext, msaList); free(outData); return result; }