| |
| /* |
| * 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_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 |
| |