/*
* 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"
TSS_RESULT
obj_encdata_add(TSS_HCONTEXT tspContext, UINT32 type, TSS_HOBJECT *phObject)
{
TSS_RESULT result;
struct tr_encdata_obj *encdata = calloc(1, sizeof(struct tr_encdata_obj));
if (encdata == NULL) {
LogError("malloc of %zd bytes failed.",
sizeof(struct tr_encdata_obj));
return TSPERR(TSS_E_OUTOFMEMORY);
}
/* add usage policy */
if ((result = obj_context_get_policy(tspContext, TSS_POLICY_USAGE,
&encdata->usagePolicy))) {
free(encdata);
return result;
}
encdata->type = type;
if ((result = obj_list_add(&encdata_list, tspContext, 0, encdata, phObject))) {
free(encdata);
return result;
}
return TSS_SUCCESS;
}
TSS_BOOL
obj_is_encdata(TSS_HOBJECT hObject)
{
TSS_BOOL answer = FALSE;
if ((obj_list_get_obj(&encdata_list, hObject))) {
answer = TRUE;
obj_list_put(&encdata_list);
}
return answer;
}
TSS_RESULT
obj_encdata_get_tsp_context(TSS_HENCDATA hEncdata, TSS_HCONTEXT *tspContext)
{
struct tsp_object *obj;
if ((obj = obj_list_get_obj(&encdata_list, hEncdata)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
*tspContext = obj->tspContext;
obj_list_put(&encdata_list);
return TSS_SUCCESS;
}
TSS_RESULT
obj_encdata_get_policy(TSS_HENCDATA hEncData, UINT32 policyType, TSS_HPOLICY *phPolicy)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
TSS_RESULT result = TSS_SUCCESS;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
switch (policyType) {
case TSS_POLICY_USAGE:
*phPolicy = encdata->usagePolicy;
break;
default:
result = TSPERR(TSS_E_BAD_PARAMETER);
}
obj_list_put(&encdata_list);
return result;
}
TSS_RESULT
obj_encdata_set_policy(TSS_HENCDATA hEncData, TSS_HPOLICY hPolicy)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
UINT32 policyType;
TSS_RESULT result = TSS_SUCCESS;
if ((result = obj_policy_get_type(hPolicy, &policyType)))
return result;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
switch (policyType) {
case TSS_POLICY_USAGE:
encdata->usagePolicy = hPolicy;
break;
default:
result = TSPERR(TSS_E_BAD_PARAMETER);
}
obj_list_put(&encdata_list);
return result;
}
TSS_RESULT
obj_encdata_get_data(TSS_HENCDATA hEncData, UINT32 *size, BYTE **data)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
TSS_RESULT result = TSS_SUCCESS;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
if (encdata->encryptedDataLength == 0) {
result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
goto done;
} else {
*data = calloc_tspi(obj->tspContext, encdata->encryptedDataLength);
if (*data == NULL) {
LogError("malloc of %d bytes failed.",
encdata->encryptedDataLength);
result = TSPERR(TSS_E_OUTOFMEMORY);
goto done;
}
*size = encdata->encryptedDataLength;
memcpy(*data, encdata->encryptedData, *size);
}
done:
obj_list_put(&encdata_list);
return result;
}
TSS_RESULT
obj_encdata_get_pcr_digest(TSS_HENCDATA hEncData,
TSS_FLAG pcrInfoType,
TSS_FLAG dir,
UINT32 *size,
BYTE **data)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
TSS_RESULT result = TSS_SUCCESS;
TPM_DIGEST *digest;
UINT64 offset;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
if (pcrInfoType != encdata->pcrInfoType) {
result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
goto done;
}
switch (pcrInfoType) {
case TSS_PCRS_STRUCT_INFO:
if (dir == TSS_TSPATTRIB_ENCDATAPCR_DIGEST_ATCREATION)
digest = &encdata->pcrInfo.info11.digestAtCreation;
else if (dir == TSS_TSPATTRIB_ENCDATAPCR_DIGEST_ATRELEASE)
digest = &encdata->pcrInfo.info11.digestAtRelease;
else {
result = TSPERR(TSS_E_BAD_PARAMETER);
goto done;
}
break;
case TSS_PCRS_STRUCT_INFO_LONG:
if (dir == TSS_TSPATTRIB_ENCDATAPCRLONG_DIGEST_ATCREATION)
digest = &encdata->pcrInfo.infolong.digestAtCreation;
else if (dir == TSS_TSPATTRIB_ENCDATAPCRLONG_DIGEST_ATRELEASE)
digest = &encdata->pcrInfo.infolong.digestAtRelease;
else {
result = TSPERR(TSS_E_BAD_PARAMETER);
goto done;
}
break;
default:
result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
goto done;
}
*size = sizeof(TPM_DIGEST);
if ((*data = calloc_tspi(obj->tspContext, *size)) == NULL) {
LogError("malloc of %u bytes failed.", *size);
*size = 0;
result = TSPERR(TSS_E_OUTOFMEMORY);
goto done;
}
offset = 0;
Trspi_LoadBlob_DIGEST(&offset, *data, digest);
done:
obj_list_put(&encdata_list);
return result;
}
TSS_RESULT
obj_encdata_get_pcr_locality(TSS_HENCDATA hEncData, TSS_FLAG dir, UINT32 *locality)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
TSS_RESULT result = TSS_SUCCESS;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
if (encdata->pcrInfoType == TSS_PCRS_STRUCT_INFO_LONG) {
if (dir == TSS_TSPATTRIB_ENCDATAPCRLONG_LOCALITY_ATCREATION)
*locality = encdata->pcrInfo.infolong.localityAtCreation;
else if (dir == TSS_TSPATTRIB_ENCDATAPCRLONG_LOCALITY_ATRELEASE)
*locality = encdata->pcrInfo.infolong.localityAtRelease;
else
result = TSPERR(TSS_E_BAD_PARAMETER);
} else
result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
obj_list_put(&encdata_list);
return result;
}
TSS_RESULT
obj_encdata_get_pcr_selection(TSS_HENCDATA hEncData,
TSS_FLAG pcrInfoType,
TSS_FLAG dir,
UINT32 *size,
BYTE **data)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
TSS_RESULT result = TSS_SUCCESS;
TPM_PCR_SELECTION *selection = NULL;
UINT64 offset;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
if (pcrInfoType != encdata->pcrInfoType) {
result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
goto done;
}
switch (pcrInfoType) {
case TSS_PCRS_STRUCT_INFO:
if (dir == TSS_TSPATTRIB_ENCDATAPCR_SELECTION)
selection = &encdata->pcrInfo.info11.pcrSelection;
break;
case TSS_PCRS_STRUCT_INFO_LONG:
if (dir == TSS_TSPATTRIB_ENCDATAPCRLONG_CREATION_SELECTION)
selection = &encdata->pcrInfo.infolong.creationPCRSelection;
else if (dir == TSS_TSPATTRIB_ENCDATAPCRLONG_RELEASE_SELECTION)
selection = &encdata->pcrInfo.infolong.releasePCRSelection;
else {
result = TSPERR(TSS_E_INTERNAL_ERROR);
goto done;
}
break;
default:
result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
goto done;
}
if (selection == NULL) {
result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
goto done;
}
*size = sizeof(UINT16) + selection->sizeOfSelect;
if ((*data = calloc_tspi(obj->tspContext, *size)) == NULL) {
LogError("malloc of %u bytes failed.", *size);
*size = 0;
result = TSPERR(TSS_E_OUTOFMEMORY);
goto done;
}
offset = 0;
Trspi_LoadBlob_PCR_SELECTION(&offset, *data, selection);
done:
obj_list_put(&encdata_list);
return result;
}
TSS_RESULT
obj_encdata_set_pcr_info(TSS_HENCDATA hEncData, UINT32 pcrInfoType, BYTE *info_blob)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
TSS_RESULT result = TSS_SUCCESS;
UINT64 offset = 0;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
switch (pcrInfoType) {
case TSS_PCRS_STRUCT_INFO_LONG:
result = Trspi_UnloadBlob_PCR_INFO_LONG(&offset, info_blob,
&encdata->pcrInfo.infolong);
break;
case TSS_PCRS_STRUCT_INFO:
result = Trspi_UnloadBlob_PCR_INFO(&offset, info_blob,
&encdata->pcrInfo.info11);
break;
default:
result = TSPERR(TSS_E_INVALID_OBJ_ACCESS);
goto done;
}
encdata->pcrInfoType = pcrInfoType;
/* XXX are we using this anywhere? */
obj->flags |= TSS_OBJ_FLAG_PCRS;
done:
obj_list_put(&encdata_list);
return result;
}
TSS_RESULT
obj_encdata_set_data(TSS_HENCDATA hEncData, UINT32 size, BYTE *data)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
TSS_RESULT result = TSS_SUCCESS;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
free(encdata->encryptedData);
encdata->encryptedData = NULL;
encdata->encryptedDataLength = 0;
if (size > 0) {
if ((encdata->encryptedData = malloc(size)) == NULL) {
LogError("malloc of %u bytes failed.", size);
result = TSPERR(TSS_E_OUTOFMEMORY);
goto done;
}
encdata->encryptedDataLength = size;
memcpy(encdata->encryptedData, data, size);
}
done:
obj_list_put(&encdata_list);
return result;
}
void
encdata_free(void *data)
{
struct tr_encdata_obj *encdata = (struct tr_encdata_obj *)data;
free(encdata->encryptedData);
switch (encdata->pcrInfoType) {
case TSS_PCRS_STRUCT_INFO:
free(encdata->pcrInfo.info11.pcrSelection.pcrSelect);
break;
case TSS_PCRS_STRUCT_INFO_LONG:
free(encdata->pcrInfo.infolong.creationPCRSelection.pcrSelect);
free(encdata->pcrInfo.infolong.releasePCRSelection.pcrSelect);
break;
default:
/* no PCR data was set */
break;
}
free(encdata);
}
/* remove an individual encdata object from the encdata list with handle
* equal to hObject */
TSS_RESULT
obj_encdata_remove(TSS_HOBJECT hObject, TSS_HCONTEXT tspContext)
{
TSS_RESULT result;
if ((result = obj_list_remove(&encdata_list, &encdata_free, hObject, tspContext)))
return result;
return TSS_SUCCESS;
}
void
obj_encdata_remove_policy_refs(TSS_HPOLICY hPolicy, TSS_HCONTEXT tspContext)
{
struct tsp_object *obj;
struct obj_list *list = &encdata_list;
struct tr_encdata_obj *encdata;
pthread_mutex_lock(&list->lock);
for (obj = list->head; obj; obj = obj->next) {
if (obj->tspContext != tspContext)
continue;
encdata = (struct tr_encdata_obj *)obj->data;
if (encdata->usagePolicy == hPolicy)
encdata->usagePolicy = NULL_HPOLICY;
}
pthread_mutex_unlock(&list->lock);
}
#ifdef TSS_BUILD_SEALX
TSS_RESULT
obj_encdata_set_seal_protect_mode(TSS_HENCDATA hEncData, UINT32 protectMode)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
encdata->protectMode = protectMode;
obj_list_put(&encdata_list);
return TSS_SUCCESS;
}
TSS_RESULT
obj_encdata_get_seal_protect_mode(TSS_HENCDATA hEncData, UINT32 *protectMode)
{
struct tsp_object *obj;
struct tr_encdata_obj *encdata;
if ((obj = obj_list_get_obj(&encdata_list, hEncData)) == NULL)
return TSPERR(TSS_E_INVALID_HANDLE);
encdata = (struct tr_encdata_obj *)obj->data;
*protectMode = encdata->protectMode;
obj_list_put(&encdata_list);
return TSS_SUCCESS;
}
#endif