diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-11-25 14:36:20 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-11-25 14:36:20 +0000 |
commit | c3649a2def02c41d837ae1f79dda729ccb91e677 (patch) | |
tree | bea46dff212fdef977fe9094a70a939e8cc21885 /src/tspi/obj_policy.c | |
download | trousers-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.c | 1667 |
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 + |