/* * Licensed Materials - Property of IBM * * trousers - An open source TCG Software Stack * * (C) Copyright International Business Machines Corp. 2005, 2007 * */ #include #include #include #include #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