summaryrefslogtreecommitdiff
path: root/src/tcs/tcs_caps.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcs/tcs_caps.c')
-rw-r--r--src/tcs/tcs_caps.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/src/tcs/tcs_caps.c b/src/tcs/tcs_caps.c
new file mode 100644
index 0000000..c4cff7c
--- /dev/null
+++ b/src/tcs/tcs_caps.c
@@ -0,0 +1,195 @@
+
+/*
+ * 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/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "trousers/tss.h"
+#include "trousers_types.h"
+#include "tcs_tsp.h"
+#include "tcs_utils.h"
+#include "tcs_int_literals.h"
+#include "capabilities.h"
+#include "tcsps.h"
+#include "tcslog.h"
+#include "tddl.h"
+#include "req_mgr.h"
+
+
+TSS_RESULT
+get_current_version(TPM_VERSION *version)
+{
+ TCPA_CAPABILITY_AREA capArea = TPM_CAP_VERSION_VAL;
+ UINT32 respSize;
+ BYTE *resp;
+ TSS_RESULT result;
+ UINT64 offset;
+
+ /* try the 1.2 way first */
+ result = TCSP_GetCapability_Internal(InternalContext, capArea, 0, NULL, &respSize, &resp);
+ if (result == TSS_SUCCESS) {
+ offset = sizeof(UINT16); // XXX hack
+ UnloadBlob_VERSION(&offset, resp, version);
+ free(resp);
+ } else if (result == TCPA_E_BAD_MODE) {
+ /* if the TPM doesn't understand VERSION_VAL, try the 1.1 way */
+ capArea = TCPA_CAP_VERSION;
+ result = TCSP_GetCapability_Internal(InternalContext, capArea, 0, NULL, &respSize,
+ &resp);
+ if (result == TSS_SUCCESS) {
+ offset = 0;
+ UnloadBlob_VERSION(&offset, resp, version);
+ free(resp);
+ }
+ }
+
+ return result;
+}
+
+TSS_RESULT
+get_cap_uint32(TCPA_CAPABILITY_AREA capArea, BYTE *subCap, UINT32 subCapSize, UINT32 *v)
+{
+ UINT32 respSize;
+ BYTE *resp;
+ TSS_RESULT result;
+ UINT64 offset;
+
+ result = TCSP_GetCapability_Internal(InternalContext, capArea, subCapSize, subCap,
+ &respSize, &resp);
+ if (!result) {
+ offset = 0;
+ switch (respSize) {
+ case 1:
+ UnloadBlob_BYTE(&offset, (BYTE *)v, resp);
+ break;
+ case sizeof(UINT16):
+ UnloadBlob_UINT16(&offset, (UINT16 *)v, resp);
+ break;
+ case sizeof(UINT32):
+ UnloadBlob_UINT32(&offset, v, resp);
+ break;
+ default:
+ LogDebug("TCSP_GetCapability_Internal returned"
+ " %u bytes", respSize);
+ result = TCSERR(TSS_E_FAIL);
+ break;
+ }
+ free(resp);
+ }
+
+ return result;
+}
+
+
+TSS_RESULT
+get_max_auths(UINT32 *auths)
+{
+ TCS_AUTHHANDLE handles[TSS_MAX_AUTHS_CAP];
+ TCPA_NONCE nonce;
+ UINT32 subCap;
+ TSS_RESULT result;
+ int i;
+
+ if (TPM_VERSION_IS(1,2)) {
+ UINT32ToArray(TPM_CAP_PROP_MAX_AUTHSESS, (BYTE *)(&subCap));
+ result = get_cap_uint32(TPM_CAP_PROPERTY, (BYTE *)&subCap, sizeof(subCap), auths);
+ } else if (TPM_VERSION_IS(1,1)) {
+ /* open auth sessions until we get a failure */
+ for (i = 0; i < TSS_MAX_AUTHS_CAP; i++) {
+ result = TCSP_OIAP_Internal(InternalContext, &(handles[i]), &nonce);
+ if (result != TSS_SUCCESS) {
+ /* this is not off by one since we're 0 indexed */
+ *auths = i;
+ break;
+ }
+ }
+
+ if (i == TSS_MAX_AUTHS_CAP)
+ *auths = TSS_MAX_AUTHS_CAP;
+
+ /* close the auth sessions */
+ for (i = 0; (UINT32)i < *auths; i++) {
+ internal_TerminateHandle(handles[i]);
+ }
+ } else {
+ result = TCSERR(TSS_E_INTERNAL_ERROR);
+ *auths = 0;
+ }
+
+ if (*auths < 2) {
+ LogError("%s reported only %u auth available!", __FUNCTION__, *auths);
+ LogError("Your TPM must be reset before the TCSD can be started.");
+ } else {
+ LogDebug("get_max_auths reports %u auth contexts found", *auths);
+ result = TSS_SUCCESS;
+ }
+
+ return result;
+}
+
+/* This is only called from init paths, so printing an error message is
+ * appropriate if something goes wrong */
+TSS_RESULT
+get_tpm_metrics(struct tpm_properties *p)
+{
+ TSS_RESULT result;
+ UINT32 subCap, rv = 0;
+
+ if ((result = get_current_version(&p->version)))
+ goto err;
+
+ UINT32ToArray(TPM_ORD_SaveKeyContext, (BYTE *)&subCap);
+ if ((result = get_cap_uint32(TCPA_CAP_ORD, (BYTE *)&subCap, sizeof(UINT32), &rv)))
+ goto err;
+ p->keyctx_swap = rv ? TRUE : FALSE;
+
+ rv = 0;
+ UINT32ToArray(TPM_ORD_SaveAuthContext, (BYTE *)&subCap);
+ if ((result = get_cap_uint32(TCPA_CAP_ORD, (BYTE *)&subCap, sizeof(UINT32), &rv)))
+ goto err;
+ p->authctx_swap = rv ? TRUE : FALSE;
+
+ UINT32ToArray(TPM_CAP_PROP_PCR, (BYTE *)&subCap);
+ if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
+ &p->num_pcrs)))
+ goto err;
+
+ UINT32ToArray(TPM_CAP_PROP_DIR, (BYTE *)&subCap);
+ if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
+ &p->num_dirs)))
+ goto err;
+
+ UINT32ToArray(TPM_CAP_PROP_SLOTS, (BYTE *)&subCap);
+ if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
+ &p->num_keys)))
+ goto err;
+
+ UINT32ToArray(TPM_CAP_PROP_MANUFACTURER, (BYTE *)&subCap);
+ if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
+ (UINT32 *)&p->manufacturer)))
+ goto err;
+
+ result = get_max_auths(&(p->num_auths));
+
+err:
+ if (result)
+ LogError("TCS GetCapability failed with result = 0x%x", result);
+
+ return result;
+}
+