/*
* Licensed Materials - Property of IBM
*
* trousers - An open source TCG Software Stack
*
* (C) Copyright International Business Machines Corp. 2004-2006
*
*/
#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 "capabilities.h"
#include "tsplog.h"
#include "obj.h"
TSS_RESULT
Tspi_TPM_SelfTestFull(TSS_HTPM hTPM) /* in */
{
TSS_RESULT result;
TSS_HCONTEXT tspContext;
if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
return result;
return TCS_API(tspContext)->SelfTestFull(tspContext);
}
TSS_RESULT
Tspi_TPM_CertifySelfTest(TSS_HTPM hTPM, /* in */
TSS_HKEY hKey, /* in */
TSS_VALIDATION *pValidationData) /* in, out */
{
TCPA_RESULT result;
TPM_AUTH keyAuth;
UINT64 offset = 0;
TCPA_DIGEST digest;
TCPA_NONCE antiReplay;
UINT32 outDataSize;
BYTE *outData;
TSS_HPOLICY hPolicy;
TCS_KEY_HANDLE keyTCSKeyHandle;
BYTE *keyData = NULL;
UINT32 keyDataSize;
TSS_KEY keyContainer;
TPM_AUTH *pKeyAuth;
TSS_BOOL useAuth;
TSS_HCONTEXT tspContext;
Trspi_HashCtx hashCtx;
if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
return result;
if ((result = obj_rsakey_get_policy(hKey, TSS_POLICY_USAGE,
&hPolicy, &useAuth)))
return result;
if ((result = obj_rsakey_get_tcs_handle(hKey, &keyTCSKeyHandle)))
return result;
if (pValidationData == NULL) {
if ((result = get_local_random(tspContext, FALSE, sizeof(TCPA_NONCE),
(BYTE **)antiReplay.nonce))) {
LogError("Failed creating random nonce");
return TSPERR(TSS_E_INTERNAL_ERROR);
}
} else {
if (pValidationData->ulExternalDataLength < sizeof(antiReplay.nonce))
return TSPERR(TSS_E_BAD_PARAMETER);
memcpy(antiReplay.nonce, pValidationData->rgbExternalData,
sizeof(antiReplay.nonce));
}
if (useAuth) {
LogDebug("Uses Auth");
result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CertifySelfTest);
result |= Trspi_HashUpdate(&hashCtx, sizeof(TCPA_NONCE), antiReplay.nonce);
if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
return result;
if ((result = secret_PerformAuth_OIAP(hKey, TPM_ORD_CertifySelfTest, hPolicy, FALSE,
&digest, &keyAuth)))
return result;
pKeyAuth = &keyAuth;
} else {
LogDebug("No Auth");
pKeyAuth = NULL;
}
if ((result = TCS_API(tspContext)->CertifySelfTest(tspContext, keyTCSKeyHandle, antiReplay,
pKeyAuth, &outDataSize, &outData)))
return result;
/* validate auth */
if (useAuth) {
result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
result |= Trspi_Hash_UINT32(&hashCtx, result);
result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CertifySelfTest);
result |= Trspi_Hash_UINT32(&hashCtx, outDataSize);
result |= Trspi_HashUpdate(&hashCtx, outDataSize, outData);
if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
return result;
if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &keyAuth)))
return result;
}
if (pValidationData == NULL) {
if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
TSS_TSPATTRIB_KEYBLOB_BLOB, &keyDataSize, &keyData))) {
LogError("Failed call to GetAttribData to get key blob");
return TSPERR(TSS_E_INTERNAL_ERROR);
}
offset = 0;
__tspi_memset(&keyContainer, 0, sizeof(TSS_KEY));
if ((result = UnloadBlob_TSS_KEY(&offset, keyData, &keyContainer)))
return result;
result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
result |= Trspi_HashUpdate(&hashCtx, strlen("Test Passed"), (BYTE *)"Test Passed");
result |= Trspi_HashUpdate(&hashCtx, sizeof(TCPA_NONCE), antiReplay.nonce);
result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CertifySelfTest);
if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
return result;
if ((result = Trspi_Verify(TSS_HASH_SHA1, digest.digest, 20,
keyContainer.pubKey.key, keyContainer.pubKey.keyLength,
outData, outDataSize))) {
free(outData);
free_key_refs(&keyContainer);
return TSPERR(TSS_E_VERIFICATION_FAILED);
}
} else {
pValidationData->ulDataLength = sizeof(TCPA_NONCE) + sizeof(UINT32) +
strlen("Test Passed");
pValidationData->rgbData = calloc_tspi(tspContext, pValidationData->ulDataLength);
if (pValidationData->rgbData == NULL) {
LogError("malloc of %u bytes failed.", pValidationData->ulDataLength);
pValidationData->ulDataLength = 0;
return TSPERR(TSS_E_OUTOFMEMORY);
}
offset = 0;
Trspi_LoadBlob(&offset, strlen("Test Passed"), pValidationData->rgbData,
(BYTE *)"Test Passed");
Trspi_LoadBlob(&offset, sizeof(TCPA_NONCE), pValidationData->rgbData,
antiReplay.nonce);
Trspi_LoadBlob_UINT32(&offset, TPM_ORD_CertifySelfTest, pValidationData->rgbData);
pValidationData->ulValidationDataLength = outDataSize;
pValidationData->rgbValidationData = calloc_tspi(tspContext, outDataSize);
if (pValidationData->rgbValidationData == NULL) {
free_tspi(tspContext, pValidationData->rgbData);
pValidationData->rgbData = NULL;
pValidationData->ulDataLength = 0;
LogError("malloc of %u bytes failed.",
pValidationData->ulValidationDataLength);
pValidationData->ulValidationDataLength = 0;
return TSPERR(TSS_E_OUTOFMEMORY);
}
memcpy(pValidationData->rgbValidationData, outData, outDataSize);
free(outData);
}
return TSS_SUCCESS;
}
TSS_RESULT
Tspi_TPM_GetTestResult(TSS_HTPM hTPM, /* in */
UINT32 * pulTestResultLength, /* out */
BYTE ** prgbTestResult) /* out */
{
TSS_HCONTEXT tspContext;
TSS_RESULT result;
if (pulTestResultLength == NULL || prgbTestResult == NULL)
return TSPERR(TSS_E_BAD_PARAMETER);
if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
return result;
if ((result = TCS_API(tspContext)->GetTestResult(tspContext, pulTestResultLength,
prgbTestResult)))
return result;
if ((result = __tspi_add_mem_entry(tspContext, *prgbTestResult))) {
free(*prgbTestResult);
*prgbTestResult = NULL;
*pulTestResultLength = 0;
}
return TSS_SUCCESS;
}