summaryrefslogtreecommitdiff
path: root/src/tspi/tsp_pcr.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
commitc3649a2def02c41d837ae1f79dda729ccb91e677 (patch)
treebea46dff212fdef977fe9094a70a939e8cc21885 /src/tspi/tsp_pcr.c
downloadtrousers-upstream.tar.gz
Imported Upstream version 0.3.9upstream/0.3.9upstream
Diffstat (limited to 'src/tspi/tsp_pcr.c')
-rw-r--r--src/tspi/tsp_pcr.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/tspi/tsp_pcr.c b/src/tspi/tsp_pcr.c
new file mode 100644
index 0000000..cc562d7
--- /dev/null
+++ b/src/tspi/tsp_pcr.c
@@ -0,0 +1,148 @@
+
+/*
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include "trousers/tss.h"
+#include "trousers/trousers.h"
+#include "trousers_types.h"
+#include "trousers_types.h"
+#include "spi_utils.h"
+#include "capabilities.h"
+#include "tsplog.h"
+#include "obj.h"
+
+
+UINT16
+get_num_pcrs(TSS_HCONTEXT tspContext)
+{
+ TSS_RESULT result;
+ static UINT16 ret = 0;
+ UINT32 subCap;
+ UINT32 respSize;
+ BYTE *resp;
+
+ if (ret != 0)
+ return ret;
+
+ subCap = endian32(TPM_CAP_PROP_PCR);
+ if ((result = TCS_API(tspContext)->GetTPMCapability(tspContext, TPM_CAP_PROPERTY,
+ sizeof(UINT32), (BYTE *)&subCap,
+ &respSize, &resp))) {
+ if ((resp = (BYTE *)getenv("TSS_DEFAULT_NUM_PCRS")) == NULL)
+ return TSS_DEFAULT_NUM_PCRS;
+
+ /* don't set ret here, next time we may be connected */
+ return atoi((char *)resp);
+ }
+
+ ret = (UINT16)Decode_UINT32(resp);
+ free(resp);
+
+ return ret;
+}
+
+TSS_RESULT
+pcrs_calc_composite(TPM_PCR_SELECTION *select, TPM_PCRVALUE *arrayOfPcrs, TPM_DIGEST *digestOut)
+{
+ UINT32 size, index;
+ BYTE mask;
+ BYTE hashBlob[1024];
+ UINT32 numPCRs = 0;
+ UINT64 offset = 0;
+ UINT64 sizeOffset = 0;
+
+ if (select->sizeOfSelect > 0) {
+ sizeOffset = 0;
+ Trspi_LoadBlob_PCR_SELECTION(&sizeOffset, hashBlob, select);
+ offset = sizeOffset + 4;
+
+ for (size = 0; size < select->sizeOfSelect; size++) {
+ for (index = 0, mask = 1; index < 8; index++, mask = mask << 1) {
+ if (select->pcrSelect[size] & mask) {
+ memcpy(&hashBlob[(numPCRs * TPM_SHA1_160_HASH_LEN) + offset],
+ arrayOfPcrs[index + (size << 3)].digest,
+ TPM_SHA1_160_HASH_LEN);
+ numPCRs++;
+ }
+ }
+ }
+
+ if (numPCRs > 0) {
+ offset += (numPCRs * TPM_SHA1_160_HASH_LEN);
+ UINT32ToArray(numPCRs * TPM_SHA1_160_HASH_LEN, &hashBlob[sizeOffset]);
+
+ return Trspi_Hash(TSS_HASH_SHA1, offset, hashBlob, digestOut->digest);
+ }
+ }
+
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+}
+
+TSS_RESULT
+pcrs_sanity_check_selection(TSS_HCONTEXT tspContext,
+ struct tr_pcrs_obj *pcrs,
+ TPM_PCR_SELECTION *select)
+{
+ UINT16 num_pcrs, bytes_to_hold;
+
+ if ((num_pcrs = get_num_pcrs(tspContext)) == 0)
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+
+ bytes_to_hold = num_pcrs / 8;
+
+ /* Is the current select object going to be interpretable by the TPM?
+ * If the select object is of a size greater than the one the TPM
+ * wants, just calculate the composite hash and let the TPM return an
+ * error code to the user. If its less than the size of the one the
+ * TPM wants, add extra zero bytes until its the right size. */
+ if (bytes_to_hold > select->sizeOfSelect) {
+ if ((select->pcrSelect = realloc(select->pcrSelect, bytes_to_hold)) == NULL) {
+ LogError("malloc of %hu bytes failed.", bytes_to_hold);
+ return TSPERR(TSS_E_OUTOFMEMORY);
+ }
+ /* 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 pcr array as well */
+ if ((pcrs->pcrs = realloc(pcrs->pcrs,
+ (bytes_to_hold * 8) * TPM_SHA1_160_HASH_LEN)) == NULL) {
+ LogError("malloc of %d bytes failed.",
+ (bytes_to_hold * 8) * TPM_SHA1_160_HASH_LEN);
+ return TSPERR(TSS_E_OUTOFMEMORY);
+ }
+ }
+
+#ifdef TSS_DEBUG
+ {
+ int i;
+ for (i = 0; i < select->sizeOfSelect * 8; i++) {
+ if (select->pcrSelect[i/8] & (1 << (i % 8))) {
+ LogDebug("PCR%d: Selected", i);
+ LogBlobData(APPID, TPM_SHA1_160_HASH_LEN,
+ (unsigned char *)&pcrs->pcrs[i]);
+ } else {
+ LogDebug("PCR%d: Not Selected", i);
+ }
+ }
+ }
+#endif
+
+ return TSS_SUCCESS;
+}