summaryrefslogtreecommitdiff
path: root/src/tspi/obj_pcrs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tspi/obj_pcrs.c')
-rw-r--r--src/tspi/obj_pcrs.c904
1 files changed, 904 insertions, 0 deletions
diff --git a/src/tspi/obj_pcrs.c b/src/tspi/obj_pcrs.c
new file mode 100644
index 0000000..5408302
--- /dev/null
+++ b/src/tspi/obj_pcrs.c
@@ -0,0 +1,904 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2005, 2007
+ *
+ */
+
+
+#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_pcrs_add(TSS_HCONTEXT tspContext, UINT32 type, TSS_HOBJECT *phObject)
+{
+ TSS_RESULT result;
+ UINT32 ver;
+ struct tr_pcrs_obj *pcrs;
+
+ if ((pcrs = calloc(1, sizeof(struct tr_pcrs_obj))) == NULL) {
+ LogError("malloc of %zd bytes failed.", sizeof(struct tr_pcrs_obj));
+ return TSPERR(TSS_E_OUTOFMEMORY);
+ }
+
+ if (type == TSS_PCRS_STRUCT_DEFAULT) {
+ if ((result = obj_context_get_connection_version(tspContext, &ver))) {
+ free(pcrs);
+ return result;
+ }
+
+ switch (ver) {
+ case TSS_TSPATTRIB_CONTEXT_VERSION_V1_2:
+ pcrs->type = TSS_PCRS_STRUCT_INFO_LONG;
+ pcrs->info.infolong.localityAtRelease = TSS_LOCALITY_ALL;
+ break;
+ case TSS_TSPATTRIB_CONTEXT_VERSION_V1_1:
+ /* fall through */
+ default:
+ pcrs->type = TSS_PCRS_STRUCT_INFO;
+ break;
+ }
+ } else
+ pcrs->type = type;
+
+ if ((result = obj_list_add(&pcrs_list, tspContext, 0, pcrs, phObject))) {
+ free(pcrs);
+ return result;
+ }
+
+ return TSS_SUCCESS;
+}
+
+void
+pcrs_free(void *data)
+{
+ struct tr_pcrs_obj *pcrs = (struct tr_pcrs_obj *)data;
+
+ switch (pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ free(pcrs->info.info11.pcrSelection.pcrSelect);
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ free(pcrs->info.infoshort.pcrSelection.pcrSelect);
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ free(pcrs->info.infolong.creationPCRSelection.pcrSelect);
+ free(pcrs->info.infolong.releasePCRSelection.pcrSelect);
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ break;
+ }
+
+ free(pcrs);
+}
+
+TSS_RESULT
+obj_pcrs_remove(TSS_HOBJECT hObject, TSS_HCONTEXT tspContext)
+{
+ TSS_RESULT result;
+
+ if ((result = obj_list_remove(&pcrs_list, &pcrs_free, hObject, tspContext)))
+ return result;
+
+ return TSS_SUCCESS;
+}
+
+TSS_BOOL
+obj_is_pcrs(TSS_HOBJECT hObject)
+{
+ TSS_BOOL answer = FALSE;
+
+ if ((obj_list_get_obj(&pcrs_list, hObject))) {
+ answer = TRUE;
+ obj_list_put(&pcrs_list);
+ }
+
+ return answer;
+}
+
+TSS_RESULT
+obj_pcrs_get_tsp_context(TSS_HPCRS hPcrs, TSS_HCONTEXT *tspContext)
+{
+ struct tsp_object *obj;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ *tspContext = obj->tspContext;
+
+ obj_list_put(&pcrs_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_pcrs_get_type(TSS_HPCRS hPcrs, UINT32 *type)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ *type = pcrs->type;
+
+ obj_list_put(&pcrs_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_pcrs_get_selection(TSS_HPCRS hPcrs, UINT32 *size, BYTE *out)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_SELECTION *tmp;
+ UINT64 offset = 0;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch (pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ tmp = &pcrs->info.info11.pcrSelection;
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ tmp = &pcrs->info.infoshort.pcrSelection;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ tmp = &pcrs->info.infolong.creationPCRSelection;
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ Trspi_LoadBlob_PCR_SELECTION(&offset, out, tmp);
+ *size = offset;
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_set_values(TSS_HPCRS hPcrs, TPM_PCR_COMPOSITE *pcrComp)
+{
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_SELECTION *select = &(pcrComp->select);
+ UINT16 i, val_idx = 0;
+
+ for (i = 0; i < select->sizeOfSelect * 8; i++) {
+ if (select->pcrSelect[i / 8] & (1 << (i % 8))) {
+ if ((result = obj_pcrs_set_value(hPcrs, i, TCPA_SHA1_160_HASH_LEN,
+ (BYTE *)&pcrComp->pcrValue[val_idx])))
+ return result;
+
+ val_idx++;
+ }
+ }
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_set_value(TSS_HPCRS hPcrs, UINT32 idx, UINT32 size, BYTE *value)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_SELECTION *select;
+ TPM_COMPOSITE_HASH *compHash;
+ UINT16 bytes_to_hold = (idx / 8) + 1;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch(pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ bytes_to_hold = (bytes_to_hold < 2) ? 2 : bytes_to_hold;
+ select = &pcrs->info.info11.pcrSelection;
+ compHash = &pcrs->info.info11.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ bytes_to_hold = (bytes_to_hold < 3) ? 3 : bytes_to_hold;
+ select = &pcrs->info.infoshort.pcrSelection;
+ compHash = &pcrs->info.infoshort.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ bytes_to_hold = (bytes_to_hold < 3) ? 3 : bytes_to_hold;
+ select = &pcrs->info.infolong.releasePCRSelection;
+ compHash = &pcrs->info.infolong.digestAtRelease;
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ break;
+ }
+
+ /* allocate the selection structure */
+ if (select->pcrSelect == NULL) {
+ if ((select->pcrSelect = malloc(bytes_to_hold)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ select->sizeOfSelect = bytes_to_hold;
+ memset(select->pcrSelect, 0, bytes_to_hold);
+
+ /* allocate the pcr array */
+ if ((pcrs->pcrs = malloc(bytes_to_hold * 8 *
+ TCPA_SHA1_160_HASH_LEN)) == NULL) {
+ LogError("malloc of %d bytes failed.",
+ bytes_to_hold * 8 * TCPA_SHA1_160_HASH_LEN);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ } else if (select->sizeOfSelect < bytes_to_hold) {
+ if ((select->pcrSelect = realloc(select->pcrSelect, bytes_to_hold)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ /* set the newly allocated bytes to 0 */
+ memset(&select->pcrSelect[select->sizeOfSelect], 0,
+ bytes_to_hold - select->sizeOfSelect);
+ select->sizeOfSelect = bytes_to_hold;
+
+ /* realloc the pcrs array */
+ if ((pcrs->pcrs = realloc(pcrs->pcrs, bytes_to_hold * 8 *
+ sizeof(TPM_PCRVALUE))) == NULL) {
+ LogError("malloc of %d bytes failed.",
+ bytes_to_hold * 8 * TCPA_SHA1_160_HASH_LEN);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ }
+
+ /* set the bit in the selection structure */
+ select->pcrSelect[idx / 8] |= (1 << (idx % 8));
+
+ /* set the value in the pcrs array */
+ memcpy(&(pcrs->pcrs[idx]), value, size);
+
+ result = pcrs_calc_composite(select, pcrs->pcrs, compHash);
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_get_value(TSS_HPCRS hPcrs, UINT32 idx, UINT32 *size, BYTE **value)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_SELECTION *select;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch(pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ select = &pcrs->info.info11.pcrSelection;
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ select = &pcrs->info.infoshort.pcrSelection;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ select = &pcrs->info.infolong.creationPCRSelection;
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ break;
+ }
+
+ if (select->sizeOfSelect < (idx / 8) + 1) {
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+
+ if ((*value = calloc_tspi(obj->tspContext, TCPA_SHA1_160_HASH_LEN)) == NULL) {
+ LogError("malloc of %d bytes failed.", TCPA_SHA1_160_HASH_LEN);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ *size = TCPA_SHA1_160_HASH_LEN;
+ memcpy(*value, &pcrs->pcrs[idx], TCPA_SHA1_160_HASH_LEN);
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_get_digest_at_release(TSS_HPCRS hPcrs, UINT32 *size, BYTE **out)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ BYTE *digest;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch(pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ digest = (BYTE *)&pcrs->info.infoshort.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ digest = (BYTE *)&pcrs->info.infolong.digestAtRelease;
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ break;
+ }
+
+ if ((*out = calloc_tspi(obj->tspContext, sizeof(TPM_COMPOSITE_HASH))) == NULL) {
+ LogError("malloc of %zd bytes failed.", sizeof(TPM_COMPOSITE_HASH));
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ memcpy(*out, digest, sizeof(TPM_COMPOSITE_HASH));
+ *size = sizeof(TPM_COMPOSITE_HASH);
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_select_index(TSS_HPCRS hPcrs, UINT32 idx)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_SELECTION *select;
+ UINT16 bytes_to_hold = (idx / 8) + 1;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch(pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ bytes_to_hold = (bytes_to_hold < 2) ? 2 : bytes_to_hold;
+ select = &pcrs->info.info11.pcrSelection;
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ break;
+ }
+
+ /* allocate the selection structure */
+ if (select->pcrSelect == NULL) {
+ if ((select->pcrSelect = malloc(bytes_to_hold)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ select->sizeOfSelect = bytes_to_hold;
+ memset(select->pcrSelect, 0, bytes_to_hold);
+
+ /* alloc the pcrs array */
+ if ((pcrs->pcrs = malloc(bytes_to_hold * 8 * TCPA_SHA1_160_HASH_LEN)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold * 8 *
+ TCPA_SHA1_160_HASH_LEN);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ } else if (select->sizeOfSelect < bytes_to_hold) {
+ if ((select->pcrSelect = realloc(select->pcrSelect, bytes_to_hold)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ /* set the newly allocated bytes to 0 */
+ memset(&select->pcrSelect[select->sizeOfSelect], 0,
+ bytes_to_hold - select->sizeOfSelect);
+ select->sizeOfSelect = bytes_to_hold;
+
+ /* realloc the pcrs array */
+ if ((pcrs->pcrs = realloc(pcrs->pcrs,
+ bytes_to_hold * 8 * TCPA_SHA1_160_HASH_LEN)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold * 8 *
+ TCPA_SHA1_160_HASH_LEN);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ }
+
+ /* set the bit in the selection structure */
+ select->pcrSelect[idx / 8] |= (1 << (idx % 8));
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_select_index_ex(TSS_HPCRS hPcrs, UINT32 dir, UINT32 idx)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_SELECTION *select;
+ UINT16 bytes_to_hold = (idx / 8) + 1;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch(pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ if (dir == TSS_PCRS_DIRECTION_CREATION) {
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ }
+ bytes_to_hold = (bytes_to_hold < 3) ? 3 : bytes_to_hold;
+ select = &pcrs->info.infoshort.pcrSelection;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ bytes_to_hold = (bytes_to_hold < 3) ? 3 : bytes_to_hold;
+ if (dir == TSS_PCRS_DIRECTION_CREATION)
+ select = &pcrs->info.infolong.creationPCRSelection;
+ else
+ select = &pcrs->info.infolong.releasePCRSelection;
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ break;
+ }
+
+ /* allocate the selection structure */
+ if (select->pcrSelect == NULL) {
+ if ((select->pcrSelect = malloc(bytes_to_hold)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ select->sizeOfSelect = bytes_to_hold;
+ memset(select->pcrSelect, 0, bytes_to_hold);
+
+ /* alloc the pcrs array */
+ if ((pcrs->pcrs = malloc(bytes_to_hold * 8 * TCPA_SHA1_160_HASH_LEN)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold * 8 *
+ TCPA_SHA1_160_HASH_LEN);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ } else if (select->sizeOfSelect < bytes_to_hold) {
+ if ((select->pcrSelect = realloc(select->pcrSelect, bytes_to_hold)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ /* set the newly allocated bytes to 0 */
+ memset(&select->pcrSelect[select->sizeOfSelect], 0,
+ bytes_to_hold - select->sizeOfSelect);
+ select->sizeOfSelect = bytes_to_hold;
+
+ /* realloc the pcrs array */
+ if ((pcrs->pcrs = realloc(pcrs->pcrs,
+ bytes_to_hold * 8 * TCPA_SHA1_160_HASH_LEN)) == NULL) {
+ LogError("malloc of %d bytes failed.", bytes_to_hold * 8 *
+ TCPA_SHA1_160_HASH_LEN);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ }
+
+ /* set the bit in the selection structure */
+ select->pcrSelect[idx / 8] |= (1 << (idx % 8));
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_create_info_type(TSS_HPCRS hPcrs, UINT32 *type, UINT32 *size, BYTE **info)
+{
+ TSS_RESULT result;
+
+ /* If type equals 0, then we create the structure
+ based on how the object was created */
+ if (*type == 0) {
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+ *type = pcrs->type;
+
+ obj_list_put(&pcrs_list);
+ }
+
+ switch (*type) {
+ case TSS_PCRS_STRUCT_INFO:
+ result = obj_pcrs_create_info(hPcrs, size, info);
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ result = obj_pcrs_create_info_long(hPcrs, size, info);
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ result = obj_pcrs_create_info_short(hPcrs, size, info);
+ break;
+ default:
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ return result;
+}
+
+/* Create a PCR info struct based on the hPcrs object */
+TSS_RESULT
+obj_pcrs_create_info(TSS_HPCRS hPcrs, UINT32 *size, BYTE **info)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_INFO info11;
+ UINT64 offset;
+ UINT32 ret_size;
+ BYTE *ret;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ /* Set everything that is not assigned to be all zeroes */
+ memset(&info11, 0, sizeof(info11));
+
+ switch (pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ info11 = pcrs->info.info11;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ info11.pcrSelection = pcrs->info.infolong.releasePCRSelection;
+ info11.digestAtRelease = pcrs->info.infolong.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ info11.pcrSelection = pcrs->info.infoshort.pcrSelection;
+ info11.digestAtRelease = pcrs->info.infoshort.digestAtRelease;
+ break;
+ default:
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ offset = 0;
+ Trspi_LoadBlob_PCR_INFO(&offset, NULL, &info11);
+ ret_size = offset;
+
+ if ((ret = calloc(1, ret_size)) == NULL) {
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ LogDebug("malloc of %u bytes failed.", ret_size);
+ goto done;
+ }
+
+ offset = 0;
+ Trspi_LoadBlob_PCR_INFO(&offset, ret, &info11);
+
+ *info = ret;
+ *size = ret_size;
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_create_info_long(TSS_HPCRS hPcrs, UINT32 *size, BYTE **info)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_INFO_LONG infolong;
+ BYTE dummyBits[3] = { 0, 0, 0 };
+ TPM_PCR_SELECTION dummySelection = { 3, dummyBits };
+ UINT64 offset;
+ UINT32 ret_size;
+ BYTE *ret;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ /* Set everything that is not assigned to be all zeroes */
+ memset(&infolong, 0, sizeof(infolong));
+
+ infolong.tag = TPM_TAG_PCR_INFO_LONG;
+ /* localityAtCreation and creationPCRSelection certainly do not need to be set here, but
+ * some chips such as Winbond do not ignore them on input, so we must give them dummy
+ * "good" values */
+ infolong.localityAtCreation = TPM_LOC_ZERO;
+ infolong.creationPCRSelection = dummySelection;
+ switch (pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ infolong.localityAtRelease = TSS_LOCALITY_ALL;
+ infolong.releasePCRSelection = pcrs->info.info11.pcrSelection;
+ infolong.digestAtRelease = pcrs->info.info11.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ infolong.localityAtRelease = pcrs->info.infolong.localityAtRelease;
+ infolong.releasePCRSelection = pcrs->info.infolong.releasePCRSelection;
+ infolong.digestAtRelease = pcrs->info.infolong.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ infolong.localityAtRelease = pcrs->info.infoshort.localityAtRelease;
+ infolong.releasePCRSelection = pcrs->info.infoshort.pcrSelection;
+ infolong.digestAtRelease = pcrs->info.infoshort.digestAtRelease;
+ break;
+ default:
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ offset = 0;
+ Trspi_LoadBlob_PCR_INFO_LONG(&offset, NULL, &infolong);
+ ret_size = offset;
+
+ if ((ret = calloc(1, ret_size)) == NULL) {
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ LogDebug("malloc of %u bytes failed.", ret_size);
+ goto done;
+ }
+
+ offset = 0;
+ Trspi_LoadBlob_PCR_INFO_LONG(&offset, ret, &infolong);
+
+ *info = ret;
+ *size = ret_size;
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_create_info_short(TSS_HPCRS hPcrs, UINT32 *size, BYTE **info)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_PCR_INFO_SHORT infoshort;
+ BYTE select[] = { 0, 0, 0 };
+ UINT64 offset;
+ UINT32 ret_size;
+ BYTE *ret;
+
+ /* Set everything that is not assigned to be all zeroes */
+ memset(&infoshort, 0, sizeof(infoshort));
+
+ if (hPcrs != NULL_HPCRS) {
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch (pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ infoshort.pcrSelection = pcrs->info.info11.pcrSelection;
+ infoshort.localityAtRelease = TSS_LOCALITY_ALL;
+ infoshort.digestAtRelease = pcrs->info.info11.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ infoshort.pcrSelection = pcrs->info.infolong.releasePCRSelection;
+ infoshort.localityAtRelease = pcrs->info.infolong.localityAtRelease;
+ infoshort.digestAtRelease = pcrs->info.infolong.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ infoshort = pcrs->info.infoshort;
+ break;
+ default:
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+ } else {
+ infoshort.pcrSelection.sizeOfSelect = sizeof(select);
+ infoshort.pcrSelection.pcrSelect = select;
+ infoshort.localityAtRelease = TSS_LOCALITY_ALL;
+ }
+
+ offset = 0;
+ Trspi_LoadBlob_PCR_INFO_SHORT(&offset, NULL, &infoshort);
+ ret_size = offset;
+
+ if ((ret = calloc(1, ret_size)) == NULL) {
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ LogDebug("malloc of %u bytes failed.", ret_size);
+ goto done;
+ }
+
+ offset = 0;
+ Trspi_LoadBlob_PCR_INFO_SHORT(&offset, ret, &infoshort);
+
+ *info = ret;
+ *size = ret_size;
+
+done:
+ if (hPcrs != NULL_HPCRS)
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_get_locality(TSS_HPCRS hPcrs, UINT32 *out)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ BYTE *locality;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch(pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ locality = &pcrs->info.infoshort.localityAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ locality = &pcrs->info.infolong.localityAtRelease;
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ *out = (UINT32)*locality;
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_set_locality(TSS_HPCRS hPcrs, UINT32 locality)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ BYTE *loc;
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch(pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ loc = &pcrs->info.infoshort.localityAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ loc = &pcrs->info.infolong.localityAtRelease;
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ *loc = locality;
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_pcrs_set_digest_at_release(TSS_HPCRS hPcrs, TPM_COMPOSITE_HASH digest)
+{
+ struct tsp_object *obj;
+ struct tr_pcrs_obj *pcrs;
+ TSS_RESULT result = TSS_SUCCESS;
+ TPM_COMPOSITE_HASH *dig;
+
+ LogDebugFn("######## Digest to be set on TSS object:");
+ LogDebugData(TCPA_SHA1_160_HASH_LEN, digest.digest);
+
+ if ((obj = obj_list_get_obj(&pcrs_list, hPcrs)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ pcrs = (struct tr_pcrs_obj *)obj->data;
+
+ switch(pcrs->type) {
+ case TSS_PCRS_STRUCT_INFO:
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ case TSS_PCRS_STRUCT_INFO_SHORT:
+ dig = &pcrs->info.infoshort.digestAtRelease;
+ break;
+ case TSS_PCRS_STRUCT_INFO_LONG:
+ dig = &pcrs->info.infolong.digestAtRelease;
+ break;
+ default:
+ LogDebugFn("Undefined type of PCRs object");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ /* Copy the digest information */
+ memcpy(dig->digest,&digest.digest,TPM_SHA1_160_HASH_LEN);
+
+ LogDebugFn("######## Digest SET on TSS object:");
+ LogDebugData(TCPA_SHA1_160_HASH_LEN,pcrs->info.infoshort.digestAtRelease.digest);
+
+done:
+ obj_list_put(&pcrs_list);
+
+ return result;
+}
+