/*
* The Initial Developer of the Original Code is Intel Corporation.
* Portions created by Intel Corporation are Copyright (C) 2007 Intel Corporation.
* All Rights Reserved.
*
* trousers - An open source TCG Software Stack
*
* Author: james.xu@intel.com Rossey.liu@intel.com
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.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
obj_nvstore_add(TSS_HCONTEXT tspContext, TSS_HOBJECT *phObject)
{
TSS_RESULT result;
struct tr_nvstore_obj *nvstore = calloc(1, sizeof(struct tr_nvstore_obj));
if (nvstore == NULL) {
LogError("malloc of %zd bytes failed.",
sizeof(struct tr_nvstore_obj));
return TSPERR(TSS_E_OUTOFMEMORY);
}
if ((result = obj_list_add(&nvstore_list, tspContext, 0, nvstore, phObject))) {
free(nvstore);
return result;
}
return TSS_SUCCESS;
}
TSS_BOOL
obj_is_nvstore(TSS_HOBJECT hObject)
{
TSS_BOOL answer = FALSE;
if ((obj_list_get_obj(&nvstore_list, hObject))) {
answer = TRUE;
obj_list_put(&nvstore_list);
}
return answer;
}
void
nvstore_free(void *data)
{
struct tr_nvstore_obj *nvstore = (struct tr_nvstore_obj *)data;
free(nvstore);
}
TSS_RESULT
obj_nvstore_remove(TSS_HOBJECT hObject, TSS_HCONTEXT tspContext)
{
TSS_RESULT result;
if ((result = obj_list_remove(&nvstore_list, &nvstore_free, hObject, tspContext)))
return result;
return TSS_SUCCESS;
}
TSS_RESULT
obj_nvstore_get_tsp_context(TSS_HNVSTORE hNvstore, TSS_HCONTEXT * tspContext)
{
struct tsp_object *obj;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
*tspContext = obj->tspContext;
obj_list_put(&nvstore_list);
return TSS_SUCCESS;
}
TSS_RESULT
obj_nvstore_set_index(TSS_HNVSTORE hNvstore, UINT32 index)
{
struct tsp_object *obj;
struct tr_nvstore_obj *nvstore;
TSS_RESULT result=TSS_SUCCESS;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
nvstore = (struct tr_nvstore_obj *)obj->data;
nvstore->nvIndex = index;
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_get_index(TSS_HNVSTORE hNvstore, UINT32 * index)
{
struct tsp_object *obj;
struct tr_nvstore_obj *nvstore;
TSS_RESULT result=TSS_SUCCESS;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
nvstore = (struct tr_nvstore_obj *)obj->data;
*index = nvstore->nvIndex;
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_set_datasize(TSS_HNVSTORE hNvstore, UINT32 datasize)
{
struct tsp_object *obj;
struct tr_nvstore_obj *nvstore;
TSS_RESULT result=TSS_SUCCESS;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
nvstore = (struct tr_nvstore_obj *)obj->data;
nvstore->dataSize= datasize;
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_get_datasize(TSS_HNVSTORE hNvstore, UINT32 * datasize)
{
struct tsp_object *obj;
struct tr_nvstore_obj *nvstore;
TSS_RESULT result=TSS_SUCCESS;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
nvstore = (struct tr_nvstore_obj *)obj->data;
*datasize = nvstore->dataSize;
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_set_permission(TSS_HNVSTORE hNvstore, UINT32 permission)
{
struct tsp_object *obj;
struct tr_nvstore_obj *nvstore;
TSS_RESULT result=TSS_SUCCESS;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
nvstore = (struct tr_nvstore_obj *)obj->data;
nvstore->permission.attributes= permission;
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_get_permission_from_tpm(TSS_HNVSTORE hNvstore, UINT32 * permission)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE] = {0};
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
UINT16 pcrwrite_sizeOfSelect;
TPM_NV_ATTRIBUTES nv_attributes_value;
TSS_HCONTEXT tspContext;
TSS_RESULT result;
if((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
if ((result = obj_nvstore_get_tsp_context(hNvstore, &tspContext)))
return result;
offset = 0;
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH);
pcrwrite_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrwrite_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH);
nv_attributes_value.attributes = Decode_UINT32(nv_data_public
+ offset + sizeof(TPM_STRUCTURE_TAG));
*permission = nv_attributes_value.attributes;
return result;
}
TSS_RESULT
obj_nvstore_get_permission(TSS_HNVSTORE hNvstore, UINT32 * permission)
{
struct tsp_object *obj;
struct tr_nvstore_obj *nvstore;
TSS_RESULT result=TSS_SUCCESS;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
nvstore = (struct tr_nvstore_obj *)obj->data;
*permission = nvstore->permission.attributes;
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_set_policy(TSS_HNVSTORE hNvstore, TSS_HPOLICY hPolicy)
{
struct tsp_object *obj;
struct tr_nvstore_obj *nvstore;
UINT32 policyType;
TSS_RESULT result = TSS_SUCCESS;
if ((result = obj_policy_get_type(hPolicy, &policyType)))
return result;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
nvstore = (struct tr_nvstore_obj *)obj->data;
switch (policyType) {
case TSS_POLICY_USAGE:
nvstore->policy = hPolicy;
break;
default:
result = TSPERR(TSS_E_BAD_PARAMETER);
}
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_get_policy(TSS_HNVSTORE hNvstore, UINT32 policyType, TSS_HPOLICY *phPolicy)
{
struct tsp_object *obj;
struct tr_nvstore_obj *nvstore;
TSS_RESULT result=TSS_SUCCESS;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
nvstore = (struct tr_nvstore_obj *)obj->data;
switch (policyType) {
case TSS_POLICY_USAGE:
*phPolicy = nvstore->policy;
break;
default:
result = TSPERR(TSS_E_BAD_PARAMETER);
}
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_get_datapublic(TSS_HNVSTORE hNvstore, UINT32 *size, BYTE *nv_data_public)
{
struct tsp_object *obj;
TSS_HCONTEXT hContext;
TSS_HTPM hTpm;
TSS_RESULT result;
struct tr_nvstore_obj *nvstore;
UINT32 uiResultLen;
BYTE *pResult;
UINT32 i;
TPM_BOOL defined_index = FALSE;
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
hContext = obj->tspContext;
nvstore = (struct tr_nvstore_obj *)obj->data;
if ((result = obj_tpm_get(hContext, &hTpm)))
goto out;
if ((result = Tspi_TPM_GetCapability(hTpm, TSS_TPMCAP_NV_LIST, 0,
NULL, &uiResultLen, &pResult))) {
goto out;
}
for (i = 0; i < uiResultLen/sizeof(UINT32); i++) {
if (nvstore->nvIndex == Decode_UINT32(pResult + i * sizeof(UINT32))) {
defined_index = TRUE;
break;
}
}
free_tspi(hContext, pResult);
if (!defined_index) {
result = TSPERR(TPM_E_BADINDEX);
goto out;
}
if ((result = Tspi_TPM_GetCapability(hTpm, TSS_TPMCAP_NV_INDEX,
sizeof(UINT32), (BYTE *)(&(nvstore->nvIndex)),
&uiResultLen, &pResult))) {
LogDebug("get the index capability error");
goto out;
}
if (uiResultLen > *size) {
free_tspi(hContext, pResult);
result = TSPERR(TSS_E_INTERNAL_ERROR);
goto out;
}
*size = uiResultLen;
memcpy(nv_data_public, pResult, uiResultLen);
free_tspi(hContext, pResult);
out:
obj_list_put(&nvstore_list);
return result;
}
TSS_RESULT
obj_nvstore_get_readdigestatrelease(TSS_HNVSTORE hNvstore, UINT32 *size, BYTE **data)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
TSS_HCONTEXT tspContext;
TSS_RESULT result;
if((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
if ((result = obj_nvstore_get_tsp_context(hNvstore, &tspContext)))
return result;
*size = sizeof(TPM_COMPOSITE_HASH);
*data = calloc_tspi(tspContext, *size);
if (*data == NULL) {
LogError("malloc of %u bytes failed.", *size);
result = TSPERR(TSS_E_OUTOFMEMORY);
return result;
}
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect + sizeof(TPM_LOCALITY_SELECTION);
memcpy(*data, nv_data_public + offset, sizeof(TPM_COMPOSITE_HASH));
return result;
}
TSS_RESULT
obj_nvstore_get_readpcrselection(TSS_HNVSTORE hNvstore, UINT32 *size, BYTE **data)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
TSS_HCONTEXT tspContext;
TSS_RESULT result;
if((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
if ((result = obj_nvstore_get_tsp_context(hNvstore, &tspContext)))
return result;
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
*size = sizeof(UINT16) + pcrread_sizeOfSelect;
*data = calloc_tspi(tspContext, *size);
if (*data == NULL) {
LogError("malloc of %u bytes failed.", *size);
result = TSPERR(TSS_E_OUTOFMEMORY);
return result;
}
memcpy(*data, nv_data_public + offset, *size);
return result;
}
TSS_RESULT
obj_nvstore_get_writedigestatrelease(TSS_HNVSTORE hNvstore, UINT32 *size, BYTE **data)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
TSS_HCONTEXT tspContext;
TSS_RESULT result;
if ((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
if ((result = obj_nvstore_get_tsp_context(hNvstore, &tspContext)))
return result;
*size = sizeof(TPM_COMPOSITE_HASH);
*data = calloc_tspi(tspContext, *size);
if (*data == NULL) {
LogError("malloc of %u bytes failed.", *size);
result = TSPERR(TSS_E_OUTOFMEMORY);
return result;
}
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH);
Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect + sizeof(TPM_LOCALITY_SELECTION);
memcpy(*data, nv_data_public + offset, sizeof(TPM_COMPOSITE_HASH));
return result;
}
TSS_RESULT
obj_nvstore_get_writepcrselection(TSS_HNVSTORE hNvstore, UINT32 *size, BYTE **data)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
UINT16 pcrwrite_sizeOfSelect;
TSS_HCONTEXT tspContext;
TSS_RESULT result;
if((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
if ((result = obj_nvstore_get_tsp_context(hNvstore, &tspContext)))
return result;
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH);
pcrwrite_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
*size = sizeof(UINT16) + pcrwrite_sizeOfSelect;
*data = calloc_tspi(tspContext, *size);
if (*data == NULL) {
LogError("malloc of %u bytes failed.", *size);
result = TSPERR(TSS_E_OUTOFMEMORY);
return result;
}
memcpy(*data, nv_data_public + offset, *size);
return result;
}
TSS_RESULT
obj_nvstore_get_state_readstclear(TSS_HNVSTORE hNvstore, UINT32 * readstclear)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
UINT16 pcrwrite_sizeOfSelect;
TPM_BOOL value;
TSS_RESULT result;
if ((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH);
pcrwrite_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrwrite_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH)
+ sizeof(TPM_NV_ATTRIBUTES);
value = *((TPM_BOOL *)(nv_data_public + offset));
*readstclear = value;
return result;
}
TSS_RESULT
obj_nvstore_get_state_writedefine(TSS_HNVSTORE hNvstore, UINT32 * writedefine)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
UINT16 pcrwrite_sizeOfSelect;
TPM_BOOL value;
TSS_RESULT result;
if ((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH);
pcrwrite_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrwrite_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH)
+ sizeof(TPM_NV_ATTRIBUTES)
+ sizeof(TPM_BOOL)
+ sizeof(TPM_BOOL);
value = *((TPM_BOOL *)(nv_data_public + offset));
*writedefine = value;
return result;
}
TSS_RESULT
obj_nvstore_get_state_writestclear(TSS_HNVSTORE hNvstore, UINT32 * writestclear)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
UINT16 pcrwrite_sizeOfSelect;
TPM_BOOL value;
TSS_RESULT result;
if ((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH);
pcrwrite_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrwrite_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH)
+ sizeof(TPM_NV_ATTRIBUTES)
+ sizeof(TPM_BOOL);
value = *((TPM_BOOL *)(nv_data_public + offset));
*writestclear = value;
return result;
}
TSS_RESULT
obj_nvstore_get_readlocalityatrelease(TSS_HNVSTORE hNvstore, UINT32 * readlocalityatrelease)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
TPM_LOCALITY_SELECTION locality_value;
TSS_RESULT result;
if ((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect;
locality_value = *((TPM_LOCALITY_SELECTION *)(nv_data_public + offset));
*readlocalityatrelease = locality_value;
return result;
}
TSS_RESULT
obj_nvstore_get_writelocalityatrelease(TSS_HNVSTORE hNvstore, UINT32 * writelocalityatrelease)
{
BYTE nv_data_public[MAX_PUBLIC_DATA_SIZE];
UINT32 data_public_size = MAX_PUBLIC_DATA_SIZE;
UINT32 offset;
UINT16 pcrread_sizeOfSelect;
UINT16 pcrwrite_sizeOfSelect;
TPM_LOCALITY_SELECTION locality_value;
TSS_RESULT result;
if ((result = obj_nvstore_get_datapublic(hNvstore, &data_public_size, nv_data_public)))
return result;
offset = sizeof(TPM_STRUCTURE_TAG)+ sizeof(TPM_NV_INDEX);
pcrread_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrread_sizeOfSelect
+ sizeof(TPM_LOCALITY_SELECTION)
+ sizeof(TPM_COMPOSITE_HASH);
pcrwrite_sizeOfSelect = Decode_UINT16(nv_data_public + offset);
offset = offset + sizeof(UINT16) + pcrwrite_sizeOfSelect;
locality_value = *((TPM_LOCALITY_SELECTION *)(nv_data_public + offset));
*writelocalityatrelease = locality_value;
return result;
}
TSS_RESULT
obj_nvstore_create_pcrshortinfo(TSS_HNVSTORE hNvstore,
TSS_HPCRS hPcrComposite,
UINT32 *size,
BYTE **data)
{
struct tsp_object *obj;
BYTE pdata[MAX_PUBLIC_DATA_SIZE];
UINT32 dataLen;
UINT64 offset;
TSS_HCONTEXT tspContext;
TSS_RESULT result = TSS_SUCCESS;
BYTE* ppbHashData;
UINT32 i;
BYTE digAtRelease[TPM_SHA1_160_HASH_LEN] = { 0, };
UINT32 tmp_locAtRelease;
TPM_LOCALITY_SELECTION locAtRelease = TPM_LOC_ZERO | TPM_LOC_ONE
| TPM_LOC_TWO | TPM_LOC_THREE| TPM_LOC_FOUR;
BYTE tmp_pcr_select[3] = {0, 0, 0};
TCPA_PCR_SELECTION pcrSelect = { 3, tmp_pcr_select};
if ((obj = obj_list_get_obj(&nvstore_list, hNvstore)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
tspContext = obj->tspContext;
if (hPcrComposite) {
if ((result = obj_pcrs_get_selection(hPcrComposite, &dataLen, pdata))) {
LogDebug("get_selection error from hReadPcrComposite");
goto out;
}
/* the index should not >= 24, so the sizeofselect should not be >3*/
if (dataLen - sizeof(UINT16) > 3) {
result = TSPERR(TSS_E_BAD_PARAMETER);
goto out;
}
offset = 0;
Trspi_UnloadBlob_PCR_SELECTION(&offset, pdata, &pcrSelect);
if (pcrSelect.sizeOfSelect != 0) {
if ((result = obj_pcrs_get_digest_at_release(hPcrComposite,
&dataLen, &ppbHashData))) {
LogDebug("get_composite error from hReadPcrComposite");
goto out;
}
memcpy(digAtRelease, ppbHashData, dataLen);
free_tspi(tspContext, ppbHashData);
} else {
pcrSelect.sizeOfSelect = 3;
pcrSelect.pcrSelect = tmp_pcr_select;
}
if (pcrSelect.sizeOfSelect < 3) {
for (i = 0; i < pcrSelect.sizeOfSelect; i++) {
tmp_pcr_select[i] = pcrSelect.pcrSelect[i];
}
pcrSelect.sizeOfSelect = 3;
pcrSelect.pcrSelect = tmp_pcr_select;
}
if ((result = obj_pcrs_get_locality(hPcrComposite, &tmp_locAtRelease)))
goto out;
locAtRelease = (TPM_LOCALITY_SELECTION)(tmp_locAtRelease & TSS_LOCALITY_MASK);
}
*size = sizeof(UINT16) + 3 + sizeof(TPM_LOCALITY_SELECTION) + TPM_SHA1_160_HASH_LEN;
*data = calloc_tspi(tspContext, *size);
if (*data == NULL) {
LogError("malloc of %u bytes failed.", *size);
result = TSPERR(TSS_E_OUTOFMEMORY);
goto out;
}
offset = 0;
Trspi_LoadBlob_PCR_SELECTION(&offset, *data, &pcrSelect);
Trspi_LoadBlob_BYTE(&offset, locAtRelease, *data);
Trspi_LoadBlob(&offset, TPM_SHA1_160_HASH_LEN, *data, digAtRelease);
out:
obj_list_put(&nvstore_list);
return result;
}