blob: 6ced20341eb9c7e25127fd4052c3c0b17d02c570 [file] [log] [blame]
/*
* Licensed Materials - Property of IBM
*
* trousers - An open source TCG Software Stack
*
* (C) Copyright International Business Machines Corp. 2007
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#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;
}