summaryrefslogtreecommitdiff
path: root/src/tspi/obj_policy.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/obj_policy.c
downloadtrousers-upstream.tar.gz
Imported Upstream version 0.3.9upstream/0.3.9upstream
Diffstat (limited to 'src/tspi/obj_policy.c')
-rw-r--r--src/tspi/obj_policy.c1667
1 files changed, 1667 insertions, 0 deletions
diff --git a/src/tspi/obj_policy.c b/src/tspi/obj_policy.c
new file mode 100644
index 0000000..e76681b
--- /dev/null
+++ b/src/tspi/obj_policy.c
@@ -0,0 +1,1667 @@
+
+/*
+ * 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"
+#include "tsp_delegate.h"
+#include "authsess.h"
+
+
+TSS_RESULT
+obj_policy_add(TSS_HCONTEXT tsp_context, UINT32 type, TSS_HOBJECT *phObject)
+{
+ struct tr_policy_obj *policy;
+ TSS_RESULT result;
+
+ if ((policy = calloc(1, sizeof(struct tr_policy_obj))) == NULL) {
+ LogError("malloc of %zd bytes failed", sizeof(struct tr_policy_obj));
+ return TSPERR(TSS_E_OUTOFMEMORY);
+ }
+
+ policy->type = type;
+#ifndef TSS_SPEC_COMPLIANCE
+ policy->SecretMode = TSS_SECRET_MODE_NONE;
+#else
+ policy->SecretMode = TSS_SECRET_MODE_POPUP;
+#endif
+ /* The policy object will inherit this attribute from the context */
+ if ((result = obj_context_get_hash_mode(tsp_context, &policy->hashMode))) {
+ free(policy);
+ return result;
+ }
+ policy->SecretLifetime = TSS_TSPATTRIB_POLICYSECRET_LIFETIME_ALWAYS;
+#ifdef TSS_BUILD_DELEGATION
+ policy->delegationType = TSS_DELEGATIONTYPE_NONE;
+#endif
+
+ if ((result = obj_list_add(&policy_list, tsp_context, 0, policy, phObject))) {
+ free(policy);
+ return result;
+ }
+
+ return TSS_SUCCESS;
+}
+
+void
+__tspi_policy_free(void *data)
+{
+ struct tr_policy_obj *policy = (struct tr_policy_obj *)data;
+
+ free(policy->popupString);
+#ifdef TSS_BUILD_DELEGATION
+ free(policy->delegationBlob);
+#endif
+ free(policy);
+}
+
+TSS_RESULT
+obj_policy_remove(TSS_HOBJECT hObject, TSS_HCONTEXT tspContext)
+{
+ TSS_RESULT result;
+
+ if ((result = obj_list_remove(&policy_list, &__tspi_policy_free, hObject, tspContext)))
+ return result;
+
+ obj_lists_remove_policy_refs(hObject, tspContext);
+
+ return TSS_SUCCESS;
+}
+
+TSS_BOOL
+obj_is_policy(TSS_HOBJECT hObject)
+{
+ TSS_BOOL answer = FALSE;
+
+ if ((obj_list_get_obj(&policy_list, hObject))) {
+ answer = TRUE;
+ obj_list_put(&policy_list);
+ }
+
+ return answer;
+}
+
+TSS_RESULT
+obj_policy_get_type(TSS_HPOLICY hPolicy, UINT32 *type)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+ *type = policy->type;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_set_type(TSS_HPOLICY hPolicy, UINT32 type)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+ policy->type = type;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_get_tsp_context(TSS_HPOLICY hPolicy, TSS_HCONTEXT *tspContext)
+{
+ struct tsp_object *obj;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ *tspContext = obj->tspContext;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_do_hmac(TSS_HPOLICY hPolicy, TSS_HOBJECT hAuthorizedObject,
+ TSS_BOOL returnOrVerify, UINT32 ulPendingFunction,
+ TSS_BOOL continueUse, UINT32 ulSizeNonces,
+ BYTE *rgbNonceEven, BYTE *rgbNonceOdd,
+ BYTE *rgbNonceEvenOSAP, BYTE *rgbNonceOddOSAP,
+ UINT32 ulSizeDigestHmac, BYTE *rgbParamDigest,
+ BYTE *rgbHmacData)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ result = policy->Tspicb_CallbackHMACAuth(
+ policy->hmacAppData, hAuthorizedObject,
+ returnOrVerify,
+ ulPendingFunction,
+ continueUse,
+ ulSizeNonces,
+ rgbNonceEven,
+ rgbNonceOdd,
+ rgbNonceEvenOSAP, rgbNonceOddOSAP, ulSizeDigestHmac,
+ rgbParamDigest,
+ rgbHmacData);
+
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_secret(TSS_HPOLICY hPolicy, TSS_BOOL ctx, TCPA_SECRET *secret)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+ TCPA_SECRET null_secret;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ memset(&null_secret, 0, sizeof(TCPA_SECRET));
+
+ switch (policy->SecretMode) {
+ case TSS_SECRET_MODE_POPUP:
+ /* if the secret is still NULL, grab it using the GUI */
+ if (policy->SecretSet == FALSE) {
+ if ((result = popup_GetSecret(ctx,
+ policy->hashMode,
+ policy->popupString,
+ policy->Secret)))
+ break;
+ }
+ policy->SecretSet = TRUE;
+ /* fall through */
+ case TSS_SECRET_MODE_PLAIN:
+ case TSS_SECRET_MODE_SHA1:
+ if (policy->SecretSet == FALSE) {
+ result = TSPERR(TSS_E_POLICY_NO_SECRET);
+ break;
+ }
+
+ memcpy(secret, policy->Secret, sizeof(TCPA_SECRET));
+ break;
+ case TSS_SECRET_MODE_NONE:
+ memcpy(secret, &null_secret, sizeof(TCPA_SECRET));
+ break;
+ default:
+ result = TSPERR(TSS_E_POLICY_NO_SECRET);
+ break;
+ }
+#ifdef TSS_DEBUG
+ if (!result) {
+ LogDebug("Got a secret:");
+ LogDebugData(20, (BYTE *)secret);
+ }
+#endif
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_flush_secret(TSS_HPOLICY hPolicy)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ memset(&policy->Secret, 0, policy->SecretSize);
+ policy->SecretSet = FALSE;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_set_secret_object(TSS_HPOLICY hPolicy, TSS_FLAG mode, UINT32 size,
+ TCPA_DIGEST *digest, TSS_BOOL set)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ /* if this is going to be a callback policy, the
+ * callbacks need to already be set. (See TSS 1.1b
+ * spec pg. 62). */
+ if (mode == TSS_SECRET_MODE_CALLBACK) {
+ if (policy->Tspicb_CallbackHMACAuth == NULL) {
+ result = TSPERR(TSS_E_FAIL);
+ goto done;
+ }
+ }
+
+ if (policy->SecretLifetime == TSS_TSPATTRIB_POLICYSECRET_LIFETIME_COUNTER) {
+ policy->SecretCounter = policy->SecretTimeStamp;
+ } else if (policy->SecretLifetime == TSS_TSPATTRIB_POLICYSECRET_LIFETIME_TIMER) {
+ time_t t = time(NULL);
+ if (t == ((time_t)-1)) {
+ LogError("time failed: %s", strerror(errno));
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ policy->SecretTimeStamp = t;
+ }
+
+ memcpy(policy->Secret, digest, size);
+ policy->SecretMode = mode;
+ policy->SecretSize = size;
+ policy->SecretSet = set;
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_is_secret_set(TSS_HPOLICY hPolicy, TSS_BOOL *secretSet)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ *secretSet = policy->SecretSet;
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+
+TSS_RESULT
+obj_policy_set_secret(TSS_HPOLICY hPolicy, TSS_FLAG mode, UINT32 size, BYTE *data)
+{
+ TCPA_DIGEST digest;
+ UINT32 secret_size = 0;
+ TSS_BOOL secret_set = TRUE;
+ TSS_RESULT result;
+
+ memset(&digest.digest, 0, sizeof(TCPA_DIGEST));
+
+ switch (mode) {
+ case TSS_SECRET_MODE_PLAIN:
+ if ((result = Trspi_Hash(TSS_HASH_SHA1, size, data,
+ (BYTE *)&digest.digest)))
+ return result;
+ secret_size = TCPA_SHA1_160_HASH_LEN;
+ break;
+ case TSS_SECRET_MODE_SHA1:
+ if (size != TCPA_SHA1_160_HASH_LEN)
+ return TSPERR(TSS_E_BAD_PARAMETER);
+
+ memcpy(&digest.digest, data, size);
+ secret_size = TCPA_SHA1_160_HASH_LEN;
+ break;
+ case TSS_SECRET_MODE_POPUP:
+ case TSS_SECRET_MODE_NONE:
+ secret_set = FALSE;
+ case TSS_SECRET_MODE_CALLBACK:
+ break;
+ default:
+ return TSPERR(TSS_E_BAD_PARAMETER);
+ }
+
+ return obj_policy_set_secret_object(hPolicy, mode, secret_size,
+ &digest, secret_set);
+}
+
+TSS_RESULT
+obj_policy_get_cb11(TSS_HPOLICY hPolicy, TSS_FLAG type, UINT32 *cb)
+{
+#ifndef __LP64__
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ switch (type) {
+ case TSS_TSPATTRIB_POLICY_CALLBACK_HMAC:
+ *cb = (UINT32)policy->Tspicb_CallbackHMACAuth;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_XOR_ENC:
+ *cb = (UINT32)policy->Tspicb_CallbackXorEnc;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_TAKEOWNERSHIP:
+ *cb = (UINT32)policy->Tspicb_CallbackTakeOwnership;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_CHANGEAUTHASYM:
+ *cb = (UINT32)policy->Tspicb_CallbackChangeAuthAsym;
+ break;
+ default:
+ result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
+ break;
+ }
+
+ obj_list_put(&policy_list);
+
+ return result;
+#else
+ return TSPERR(TSS_E_FAIL);
+#endif
+}
+
+TSS_RESULT
+obj_policy_set_cb11(TSS_HPOLICY hPolicy, TSS_FLAG type, TSS_FLAG app_data, UINT32 cb)
+{
+#ifndef __LP64__
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ switch (type) {
+ case TSS_TSPATTRIB_POLICY_CALLBACK_HMAC:
+ policy->Tspicb_CallbackHMACAuth = (PVOID)cb;
+ policy->hmacAppData = (PVOID)app_data;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_XOR_ENC:
+ policy->Tspicb_CallbackXorEnc = (PVOID)cb;
+ policy->xorAppData = (PVOID)app_data;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_TAKEOWNERSHIP:
+ policy->Tspicb_CallbackTakeOwnership = (PVOID)cb;
+ policy->takeownerAppData = (PVOID)app_data;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_CHANGEAUTHASYM:
+ policy->Tspicb_CallbackChangeAuthAsym = (PVOID)cb;
+ policy->changeauthAppData = (PVOID)app_data;
+ break;
+ default:
+ result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
+ break;
+ }
+
+ obj_list_put(&policy_list);
+
+ return result;
+#else
+ return TSPERR(TSS_E_FAIL);
+#endif
+}
+
+TSS_RESULT
+obj_policy_set_cb12(TSS_HPOLICY hPolicy, TSS_FLAG flag, BYTE *in)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+ TSS_CALLBACK *cb = (TSS_CALLBACK *)in;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ switch (flag) {
+ case TSS_TSPATTRIB_POLICY_CALLBACK_HMAC:
+ if (!cb) {
+ policy->Tspicb_CallbackHMACAuth = NULL;
+ break;
+ }
+
+ policy->Tspicb_CallbackHMACAuth =
+ (TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_BOOL,
+ UINT32, TSS_BOOL, UINT32, BYTE *, BYTE *,
+ BYTE *, BYTE *, UINT32, BYTE *, BYTE *))
+ cb->callback;
+ policy->hmacAppData = cb->appData;
+ policy->hmacAlg = cb->alg;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_XOR_ENC:
+ if (!cb) {
+ policy->Tspicb_CallbackXorEnc = NULL;
+ break;
+ }
+
+ policy->Tspicb_CallbackXorEnc =
+ (TSS_RESULT (*)(PVOID, TSS_HOBJECT,
+ TSS_HOBJECT, TSS_FLAG, UINT32, BYTE *, BYTE *,
+ BYTE *, BYTE *, UINT32, BYTE *, BYTE *))
+ cb->callback;
+ policy->xorAppData = cb->appData;
+ policy->xorAlg = cb->alg;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_TAKEOWNERSHIP:
+ if (!cb) {
+ policy->Tspicb_CallbackTakeOwnership = NULL;
+ break;
+ }
+
+ policy->Tspicb_CallbackTakeOwnership =
+ (TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_HKEY,
+ UINT32, BYTE *))cb->callback;
+ policy->takeownerAppData = cb->appData;
+ policy->takeownerAlg = cb->alg;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_CHANGEAUTHASYM:
+ if (!cb) {
+ policy->Tspicb_CallbackChangeAuthAsym = NULL;
+ break;
+ }
+
+ policy->Tspicb_CallbackChangeAuthAsym =
+ (TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_HKEY,
+ UINT32, UINT32, BYTE *, BYTE *))cb->callback;
+ policy->changeauthAppData = cb->appData;
+ policy->changeauthAlg = cb->alg;
+ break;
+#ifdef TSS_BUILD_SEALX
+ case TSS_TSPATTRIB_POLICY_CALLBACK_SEALX_MASK:
+ if (!cb) {
+ policy->Tspicb_CallbackSealxMask = NULL;
+ policy->sealxAppData = NULL;
+ policy->sealxAlg = 0;
+ break;
+ }
+
+ policy->Tspicb_CallbackSealxMask =
+ (TSS_RESULT (*)(PVOID, TSS_HKEY, TSS_HENCDATA,
+ TSS_ALGORITHM_ID, UINT32, BYTE *, BYTE *, BYTE *, BYTE *,
+ UINT32, BYTE *, BYTE *))cb->callback;
+ policy->sealxAppData = cb->appData;
+ policy->sealxAlg = cb->alg;
+ break;
+#endif
+ default:
+ result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
+ break;
+ }
+
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_cb12(TSS_HPOLICY hPolicy, TSS_FLAG flag, UINT32 *size, BYTE **out)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+ TSS_CALLBACK *cb;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if ((cb = calloc_tspi(obj->tspContext, sizeof(TSS_CALLBACK))) == NULL) {
+ LogError("malloc of %zd bytes failed.", sizeof(TSS_CALLBACK));
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ switch (flag) {
+ case TSS_TSPATTRIB_POLICY_CALLBACK_HMAC:
+ cb->callback = policy->Tspicb_CallbackHMACAuth;
+ cb->appData = policy->hmacAppData;
+ cb->alg = policy->hmacAlg;
+ *size = sizeof(TSS_CALLBACK);
+ *out = (BYTE *)cb;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_XOR_ENC:
+ cb->callback = policy->Tspicb_CallbackXorEnc;
+ cb->appData = policy->xorAppData;
+ cb->alg = policy->xorAlg;
+ *size = sizeof(TSS_CALLBACK);
+ *out = (BYTE *)cb;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_TAKEOWNERSHIP:
+ cb->callback = policy->Tspicb_CallbackTakeOwnership;
+ cb->appData = policy->takeownerAppData;
+ cb->alg = policy->takeownerAlg;
+ *size = sizeof(TSS_CALLBACK);
+ *out = (BYTE *)cb;
+ break;
+ case TSS_TSPATTRIB_POLICY_CALLBACK_CHANGEAUTHASYM:
+ cb->callback = policy->Tspicb_CallbackChangeAuthAsym;
+ cb->appData = policy->changeauthAppData;
+ cb->alg = policy->changeauthAlg;
+ *size = sizeof(TSS_CALLBACK);
+ *out = (BYTE *)cb;
+ break;
+#ifdef TSS_BUILD_SEALX
+ case TSS_TSPATTRIB_POLICY_CALLBACK_SEALX_MASK:
+ cb->callback = policy->Tspicb_CallbackSealxMask;
+ cb->appData = policy->sealxAppData;
+ cb->alg = policy->sealxAlg;
+ *size = sizeof(TSS_CALLBACK);
+ *out = (BYTE *)cb;
+ break;
+#endif
+ default:
+ free_tspi(obj->tspContext, cb);
+ result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
+ break;
+ }
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_lifetime(TSS_HPOLICY hPolicy, UINT32 *lifetime)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+ *lifetime = policy->SecretLifetime;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_set_lifetime(TSS_HPOLICY hPolicy, UINT32 type, UINT32 value)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+ time_t t;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ switch (type) {
+ case TSS_TSPATTRIB_POLICYSECRET_LIFETIME_ALWAYS:
+ policy->SecretCounter = 0;
+ policy->SecretLifetime = TSS_TSPATTRIB_POLICYSECRET_LIFETIME_ALWAYS;
+ policy->SecretTimeStamp = 0;
+ break;
+ case TSS_TSPATTRIB_POLICYSECRET_LIFETIME_COUNTER:
+ /* Both SecretCounter and SecretTimeStamp will receive value. Every time the
+ * policy is used, SecretCounter will be decremented. Each time SetSecret is
+ * called, SecretCounter will get the value stored in SecretTimeStamp */
+ policy->SecretCounter = value;
+ policy->SecretLifetime = TSS_TSPATTRIB_POLICYSECRET_LIFETIME_COUNTER;
+ policy->SecretTimeStamp = value;
+ break;
+ case TSS_TSPATTRIB_POLICYSECRET_LIFETIME_TIMER:
+ t = time(NULL);
+ if (t == ((time_t)-1)) {
+ LogError("time failed: %s", strerror(errno));
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ break;
+ }
+
+ /* For mode time, we'll use the SecretCounter variable to hold the number
+ * of seconds we're valid and the SecretTimeStamp var to record the current
+ * timestamp. This should protect against overflows. */
+ policy->SecretCounter = value;
+ policy->SecretLifetime = TSS_TSPATTRIB_POLICYSECRET_LIFETIME_TIMER;
+ policy->SecretTimeStamp = t;
+ break;
+ default:
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ break;
+ }
+
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_mode(TSS_HPOLICY hPolicy, UINT32 *mode)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+ *mode = policy->SecretMode;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_get_counter(TSS_HPOLICY hPolicy, UINT32 *counter)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->SecretLifetime == TSS_TSPATTRIB_POLICYSECRET_LIFETIME_COUNTER)
+ *counter = policy->SecretCounter;
+ else
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_dec_counter(TSS_HPOLICY hPolicy)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ /* Only decrement if SecretCounter > 0, otherwise it could loop and become valid again */
+ if (policy->SecretLifetime == TSS_TSPATTRIB_POLICYSECRET_LIFETIME_COUNTER &&
+ policy->SecretCounter > 0) {
+ policy->SecretCounter--;
+ }
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+/* return a unicode string to the Tspi_GetAttribData function */
+TSS_RESULT
+obj_policy_get_string(TSS_HPOLICY hPolicy, UINT32 *size, BYTE **data)
+{
+ TSS_RESULT result = TSS_SUCCESS;
+ BYTE *utf_string;
+ UINT32 utf_size;
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ *size = policy->popupStringLength;
+ if (policy->popupStringLength == 0) {
+ *data = NULL;
+ } else {
+ utf_size = policy->popupStringLength;
+ utf_string = Trspi_Native_To_UNICODE(policy->popupString,
+ &utf_size);
+ if (utf_string == NULL) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ *data = calloc_tspi(obj->tspContext, utf_size);
+ if (*data == NULL) {
+ free(utf_string);
+ LogError("malloc of %d bytes failed.", utf_size);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ *size = utf_size;
+ memcpy(*data, utf_string, utf_size);
+ free(utf_string);
+ }
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_set_string(TSS_HPOLICY hPolicy, UINT32 size, BYTE *data)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ free(policy->popupString);
+ policy->popupString = data;
+ policy->popupStringLength = size;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_get_secs_until_expired(TSS_HPOLICY hPolicy, UINT32 *secs)
+{
+ TSS_RESULT result = TSS_SUCCESS;
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ int seconds_elapsed;
+ time_t t;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->SecretLifetime != TSS_TSPATTRIB_POLICYSECRET_LIFETIME_TIMER) {
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ }
+
+ if ((t = time(NULL)) == ((time_t)-1)) {
+ LogError("time failed: %s", strerror(errno));
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+ /* curtime - SecretTimeStamp is the number of seconds elapsed since we started the timer.
+ * SecretCounter is the number of seconds the secret is valid. If
+ * seconds_elspased > SecretCounter, we've expired. */
+ seconds_elapsed = t - policy->SecretTimeStamp;
+ if ((UINT32)seconds_elapsed >= policy->SecretCounter) {
+ *secs = 0;
+ } else {
+ *secs = policy->SecretCounter - seconds_elapsed;
+ }
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+policy_has_expired(struct tr_policy_obj *policy, TSS_BOOL *answer)
+{
+ switch (policy->SecretLifetime) {
+ case TSS_TSPATTRIB_POLICYSECRET_LIFETIME_ALWAYS:
+ *answer = FALSE;
+ break;
+ case TSS_TSPATTRIB_POLICYSECRET_LIFETIME_COUNTER:
+ *answer = (policy->SecretCounter == 0 ? TRUE : FALSE);
+ break;
+ case TSS_TSPATTRIB_POLICYSECRET_LIFETIME_TIMER:
+ {
+ int seconds_elapsed;
+ time_t t = time(NULL);
+
+ if (t == ((time_t)-1)) {
+ LogError("time failed: %s", strerror(errno));
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+ }
+ /* curtime - SecretTimer is the number of seconds elapsed since we
+ * started the timer. SecretCounter is the number of seconds the
+ * secret is valid. If seconds_elspased > SecretCounter, we've
+ * expired.
+ */
+ seconds_elapsed = t - policy->SecretTimeStamp;
+ *answer = ((UINT32)seconds_elapsed >= policy->SecretCounter ? TRUE : FALSE);
+ break;
+ }
+ default:
+ LogError("policy has an undefined secret lifetime!");
+ return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ }
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_has_expired(TSS_HPOLICY hPolicy, TSS_BOOL *answer)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ result = policy_has_expired(policy, answer);
+
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_xsap_params(TSS_HPOLICY hPolicy,
+ TPM_COMMAND_CODE command,
+ TPM_ENTITY_TYPE *et,
+ UINT32 *entity_value_size,
+ BYTE **entity_value,
+ BYTE *secret,
+ TSS_CALLBACK *cb_xor,
+ TSS_CALLBACK *cb_hmac,
+ TSS_CALLBACK *cb_sealx,
+ UINT32 *mode,
+ TSS_BOOL new_secret)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result;
+ TSS_BOOL answer = FALSE;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if ((result = policy_has_expired(policy, &answer)))
+ goto done;
+
+ if (answer) {
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ }
+#ifdef TSS_BUILD_DELEGATION
+ /* if the delegation index or blob is set, check to see if the command is delegated, if so,
+ * return the blob or index as the secret data */
+ if (command && (policy->delegationType != TSS_DELEGATIONTYPE_NONE)) {
+ if (policy->delegationBlob) {
+ if ((*entity_value = malloc(policy->delegationBlobLength)) == NULL) {
+ LogError("malloc of %u bytes failed.",
+ policy->delegationBlobLength);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ memcpy(*entity_value, policy->delegationBlob, policy->delegationBlobLength);
+ *entity_value_size = policy->delegationBlobLength;
+ if (policy->delegationType == TSS_DELEGATIONTYPE_OWNER)
+ *et = TPM_ET_DEL_OWNER_BLOB;
+ else
+ *et = TPM_ET_DEL_KEY_BLOB;
+ } else {
+ if ((*entity_value = malloc(sizeof(UINT32))) == NULL) {
+ LogError("malloc of %zd bytes failed.", sizeof(UINT32));
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ *(UINT32 *)entity_value = policy->delegationIndex;
+ *entity_value_size = sizeof(UINT32);
+ *et = TPM_ET_DEL_ROW;
+ }
+ }
+#endif
+ /* Either this is a policy set to mode callback, in which case both xor and hmac addresses
+ * must be set, or this is an encrypted data object's policy, where its mode is independent
+ * of whether a sealx callback is set */
+ if (policy->SecretMode == TSS_SECRET_MODE_CALLBACK && cb_xor && cb_hmac) {
+ if ((policy->Tspicb_CallbackXorEnc && !policy->Tspicb_CallbackHMACAuth) ||
+ (!policy->Tspicb_CallbackXorEnc && policy->Tspicb_CallbackHMACAuth)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ cb_xor->callback = policy->Tspicb_CallbackXorEnc;
+ cb_xor->appData = policy->xorAppData;
+ cb_xor->alg = policy->xorAlg;
+
+ cb_hmac->callback = policy->Tspicb_CallbackHMACAuth;
+ cb_hmac->appData = policy->hmacAppData;
+ cb_hmac->alg = policy->hmacAlg;
+#ifdef TSS_BUILD_SEALX
+ } else if (cb_sealx && policy->Tspicb_CallbackSealxMask) {
+ cb_sealx->callback = policy->Tspicb_CallbackSealxMask;
+ cb_sealx->appData = policy->sealxAppData;
+ cb_sealx->alg = policy->sealxAlg;
+#endif
+ }
+
+ if ((policy->SecretMode == TSS_SECRET_MODE_POPUP) &&
+ (policy->SecretSet == FALSE)) {
+ if ((result = popup_GetSecret(new_secret,
+ policy->hashMode,
+ policy->popupString,
+ policy->Secret)))
+ goto done;
+ policy->SecretSet = TRUE;
+ }
+ memcpy(secret, policy->Secret, TPM_SHA1_160_HASH_LEN);
+ *mode = policy->SecretMode;
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_do_xor(TSS_HPOLICY hPolicy,
+ TSS_HOBJECT hOSAPObject, TSS_HOBJECT hObject,
+ TSS_FLAG PurposeSecret, UINT32 ulSizeNonces,
+ BYTE *rgbNonceEven, BYTE *rgbNonceOdd,
+ BYTE *rgbNonceEvenOSAP, BYTE *rgbNonceOddOSAP,
+ UINT32 ulSizeEncAuth, BYTE *rgbEncAuthUsage,
+ BYTE *rgbEncAuthMigration)
+{
+ TSS_RESULT result;
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ result = policy->Tspicb_CallbackXorEnc(policy->xorAppData,
+ hOSAPObject, hObject,
+ PurposeSecret, ulSizeNonces,
+ rgbNonceEven, rgbNonceOdd,
+ rgbNonceEvenOSAP, rgbNonceOddOSAP,
+ ulSizeEncAuth,
+ rgbEncAuthUsage, rgbEncAuthMigration);
+
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_do_takeowner(TSS_HPOLICY hPolicy,
+ TSS_HOBJECT hObject, TSS_HKEY hObjectPubKey,
+ UINT32 ulSizeEncAuth, BYTE *rgbEncAuth)
+{
+ TSS_RESULT result;
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ result = policy->Tspicb_CallbackTakeOwnership(
+ policy->takeownerAppData,
+ hObject, hObjectPubKey, ulSizeEncAuth,
+ rgbEncAuth);
+
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_hash_mode(TSS_HPOLICY hPolicy, UINT32 *mode)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+ *mode = policy->hashMode;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_set_hash_mode(TSS_HPOLICY hPolicy, UINT32 mode)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ switch (mode) {
+ case TSS_TSPATTRIB_HASH_MODE_NULL:
+ case TSS_TSPATTRIB_HASH_MODE_NOT_NULL:
+ break;
+ default:
+ return TSPERR(TSS_E_INVALID_ATTRIB_DATA);
+ }
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+ policy->hashMode = mode;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+#ifdef TSS_BUILD_DELEGATION
+TSS_RESULT
+obj_policy_set_delegation_type(TSS_HPOLICY hPolicy, UINT32 type)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ switch (type) {
+ case TSS_DELEGATIONTYPE_NONE:
+ obj_policy_clear_delegation(policy);
+ break;
+ case TSS_DELEGATIONTYPE_OWNER:
+ case TSS_DELEGATIONTYPE_KEY:
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ }
+ break;
+ }
+
+ policy->delegationType = type;
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+
+TSS_RESULT
+obj_policy_get_delegation_type(TSS_HPOLICY hPolicy, UINT32 *type)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ *type = policy->delegationType;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+obj_policy_set_delegation_index(TSS_HPOLICY hPolicy, UINT32 index)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ TSS_RESULT result;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if ((result = get_delegate_index(obj->tspContext, index, &public)))
+ goto done;
+
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+
+ obj_policy_clear_delegation(policy);
+ switch (public.permissions.delegateType) {
+ case TPM_DEL_OWNER_BITS:
+ policy->delegationType = TSS_DELEGATIONTYPE_OWNER;
+ break;
+ case TPM_DEL_KEY_BITS:
+ policy->delegationType = TSS_DELEGATIONTYPE_KEY;
+ break;
+ default:
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+ policy->delegationIndex = index;
+ policy->delegationIndexSet = TRUE;
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_delegation_index(TSS_HPOLICY hPolicy, UINT32 *index)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (!policy->delegationIndexSet) {
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ }
+
+ *index = policy->delegationIndex;
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT obj_policy_set_delegation_per1(TSS_HPOLICY hPolicy, UINT32 per1)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ }
+
+ policy->delegationPer1 = per1;
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT obj_policy_get_delegation_per1(TSS_HPOLICY hPolicy, UINT32 *per1)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ if ((result = obj_policy_get_delegate_public(obj, &public)))
+ goto done;
+ *per1 = public.permissions.per1;
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ } else
+ *per1 = policy->delegationPer1;
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT obj_policy_set_delegation_per2(TSS_HPOLICY hPolicy, UINT32 per2)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ }
+
+ policy->delegationPer2 = per2;
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT obj_policy_get_delegation_per2(TSS_HPOLICY hPolicy, UINT32 *per2)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ if ((result = obj_policy_get_delegate_public(obj, &public)))
+ goto done;
+ *per2 = public.permissions.per2;
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ } else
+ *per2 = policy->delegationPer2;
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_set_delegation_blob(TSS_HPOLICY hPolicy, UINT32 type, UINT32 blobLength, BYTE *blob)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ UINT16 tag;
+ UINT64 offset;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ obj_policy_clear_delegation(policy);
+
+ if (blobLength == 0) {
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+
+ offset = 0;
+ Trspi_UnloadBlob_UINT16(&offset, &tag, blob);
+ switch (tag) {
+ case TPM_TAG_DELEGATE_OWNER_BLOB:
+ if (type && (type != TSS_DELEGATIONTYPE_OWNER)) {
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+ policy->delegationType = TSS_DELEGATIONTYPE_OWNER;
+ break;
+ case TPM_TAG_DELG_KEY_BLOB:
+ if (type && (type != TSS_DELEGATIONTYPE_KEY)) {
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+ policy->delegationType = TSS_DELEGATIONTYPE_KEY;
+ break;
+ default:
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+
+ if ((policy->delegationBlob = malloc(blobLength)) == NULL) {
+ LogError("malloc of %u bytes failed.", blobLength);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ policy->delegationBlobLength = blobLength;
+ memcpy(policy->delegationBlob, blob, blobLength);
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_delegation_blob(TSS_HPOLICY hPolicy, UINT32 type, UINT32 *blobLength, BYTE **blob)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationBlobLength == 0) {
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+ goto done;
+ }
+
+ if (type && (type != policy->delegationType)) {
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+
+ if ((*blob = calloc_tspi(obj->tspContext, policy->delegationBlobLength)) == NULL) {
+ LogError("malloc of %u bytes failed.", policy->delegationBlobLength);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ memcpy(*blob, policy->delegationBlob, policy->delegationBlobLength);
+ *blobLength = policy->delegationBlobLength;
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_delegation_label(TSS_HPOLICY hPolicy, BYTE *label)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ if ((result = obj_policy_get_delegate_public(obj, &public)))
+ goto done;
+ *label = public.label.label;
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ } else
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_delegation_familyid(TSS_HPOLICY hPolicy, UINT32 *familyID)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ if ((result = obj_policy_get_delegate_public(obj, &public)))
+ goto done;
+ *familyID = public.familyID;
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ } else
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_delegation_vercount(TSS_HPOLICY hPolicy, UINT32 *verCount)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ if ((result = obj_policy_get_delegate_public(obj, &public)))
+ goto done;
+ *verCount = public.verificationCount;
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ } else
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_delegation_pcr_locality(TSS_HPOLICY hPolicy, UINT32 *locality)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ if ((result = obj_policy_get_delegate_public(obj, &public)))
+ goto done;
+ *locality = public.pcrInfo.localityAtRelease;
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ } else
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_delegation_pcr_digest(TSS_HPOLICY hPolicy, UINT32 *digestLength, BYTE **digest)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ if ((result = obj_policy_get_delegate_public(obj, &public)))
+ goto done;
+ *digest = calloc_tspi(obj->tspContext, TPM_SHA1_160_HASH_LEN);
+ if (*digest == NULL) {
+ LogError("malloc of %u bytes failed.", TPM_SHA1_160_HASH_LEN);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ memcpy(*digest, &public.pcrInfo.digestAtRelease.digest, TPM_SHA1_160_HASH_LEN);
+ *digestLength = TPM_SHA1_160_HASH_LEN;
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ } else
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_get_delegation_pcr_selection(TSS_HPOLICY hPolicy, UINT32 *selectionLength,
+ BYTE **selection)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+ TPM_DELEGATE_PUBLIC public;
+ UINT64 offset;
+ TSS_RESULT result = TSS_SUCCESS;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet || policy->delegationBlob) {
+ if ((result = obj_policy_get_delegate_public(obj, &public)))
+ goto done;
+ offset = 0;
+ Trspi_LoadBlob_PCR_SELECTION(&offset, NULL, &public.pcrInfo.pcrSelection);
+ *selection = calloc_tspi(obj->tspContext, offset);
+ if (*selection == NULL) {
+ LogError("malloc of %u bytes failed.", (UINT32)offset);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ offset = 0;
+ Trspi_LoadBlob_PCR_SELECTION(&offset, *selection, &public.pcrInfo.pcrSelection);
+ *selectionLength = offset;
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ } else
+ result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
+
+done:
+ obj_list_put(&policy_list);
+
+ return result;
+}
+
+TSS_RESULT
+obj_policy_is_delegation_index_set(TSS_HPOLICY hPolicy, TSS_BOOL *indexSet)
+{
+ struct tsp_object *obj;
+ struct tr_policy_obj *policy;
+
+ if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ *indexSet = policy->delegationIndexSet;
+
+ obj_list_put(&policy_list);
+
+ return TSS_SUCCESS;
+}
+
+void
+obj_policy_clear_delegation(struct tr_policy_obj *policy)
+{
+ free(policy->delegationBlob);
+ policy->delegationType = TSS_DELEGATIONTYPE_NONE;
+ policy->delegationPer1 = 0;
+ policy->delegationPer2 = 0;
+ policy->delegationIndexSet = FALSE;
+ policy->delegationIndex = 0;
+ policy->delegationBlobLength = 0;
+ policy->delegationBlob = NULL;
+}
+
+TSS_RESULT
+obj_policy_get_delegate_public(struct tsp_object *obj, TPM_DELEGATE_PUBLIC *public)
+{
+ struct tr_policy_obj *policy;
+ UINT16 tag;
+ TPM_DELEGATE_OWNER_BLOB ownerBlob;
+ TPM_DELEGATE_KEY_BLOB keyBlob;
+ UINT64 offset;
+ TSS_RESULT result;
+
+ policy = (struct tr_policy_obj *)obj->data;
+
+ if (policy->delegationIndexSet) {
+ if ((result = get_delegate_index(obj->tspContext, policy->delegationIndex,
+ public)))
+ return result;
+ } else if (policy->delegationBlob) {
+ offset = 0;
+ Trspi_UnloadBlob_UINT16(&offset, &tag, policy->delegationBlob);
+
+ offset = 0;
+ switch (tag) {
+ case TPM_TAG_DELEGATE_OWNER_BLOB:
+ if ((result = Trspi_UnloadBlob_TPM_DELEGATE_OWNER_BLOB(&offset,
+ policy->delegationBlob,
+ &ownerBlob)))
+ return result;
+ *public = ownerBlob.pub;
+ free(ownerBlob.additionalArea);
+ free(ownerBlob.sensitiveArea);
+ break;
+ case TPM_TAG_DELG_KEY_BLOB:
+ if ((result = Trspi_UnloadBlob_TPM_DELEGATE_KEY_BLOB(&offset,
+ policy->delegationBlob,
+ &keyBlob)))
+ return result;
+ *public = keyBlob.pub;
+ free(keyBlob.additionalArea);
+ free(keyBlob.sensitiveArea);
+ break;
+ default:
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+ }
+ } else
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+
+ return TSS_SUCCESS;
+}
+#endif
+