/* * Licensed Materials - Property of IBM * * trousers - An open source TCG Software Stack * * (C) Copyright International Business Machines Corp. 2004-2006 * */ #include #include #include #include #include #include #include #include #include #include "trousers/tss.h" #include "trousers/trousers.h" #include "trousers_types.h" #include "spi_utils.h" #include "tcs_tsp.h" #include "tspps.h" #include "tsplog.h" #include "obj.h" /* * tsp_ps.c * * Functions used to query the user persistent storage file. * * Since other apps may be altering the file, all operations must be atomic WRT the file and no * cache will be kept, since another app could delete keys from the file out from under us. * * Atomicity is guaranteed for operations inbetween calls to get_file() and put_file(). * * A PS file will have the lifetime of the TSP context. For instance, this code will store hKeyA * and hKeyB in the file "a": * * setenv("TSS_USER_PS_FILE=a"); * Tspi_Context_Create(&hContext); * Tspi_Context_RegisterKey(hKeyA); * setenv("TSS_USER_PS_FILE=b"); * Tspi_Context_RegisterKey(hKeyB); * * but this code will store hKeyA in file "a" and hKeyB in file "b": * * setenv("TSS_USER_PS_FILE=a"); * Tspi_Context_Create(&hContext); * Tspi_Context_RegisterKey(hKeyA); * Tspi_Context_Close(hContext); * * setenv("TSS_USER_PS_FILE=b"); * Tspi_Context_Create(&hContext); * Tspi_Context_RegisterKey(hKeyB); * */ TSS_RESULT ps_get_registered_keys(TSS_UUID *uuid, TSS_UUID *tcs_uuid, UINT32 *size, TSS_KM_KEYINFO **keys) { int fd; UINT32 result; if ((result = get_file(&fd))) return result; result = psfile_get_registered_keys(fd, uuid, tcs_uuid, size, keys); put_file(fd); return result; } TSS_RESULT ps_get_registered_keys2(TSS_UUID *uuid, TSS_UUID *tcs_uuid, UINT32 *size, TSS_KM_KEYINFO2 **keys) { int fd; UINT32 result; if ((result = get_file(&fd))) return result; /* Sets the proper TSS_KM_KEYINFO2 fields according to the UUID type */ result = psfile_get_registered_keys2(fd, uuid, tcs_uuid, size, keys); put_file(fd); return result; } TSS_RESULT ps_is_key_registered(TSS_UUID *uuid, TSS_BOOL *answer) { int fd; TSS_RESULT result; if ((result = get_file(&fd))) return result; result = psfile_is_key_registered(fd, uuid, answer); put_file(fd); return result; } TSS_RESULT ps_write_key(TSS_UUID *uuid, TSS_UUID *parent_uuid, UINT32 parent_ps, UINT32 blob_size, BYTE *blob) { int fd; TSS_RESULT result; UINT16 short_blob_size = (UINT16)blob_size; if (blob_size > USHRT_MAX) { LogError("Blob data being written to disk is too large(%u bytes)!", blob_size); return TSPERR(TSS_E_INTERNAL_ERROR); } if ((result = get_file(&fd))) return result; result = psfile_write_key(fd, uuid, parent_uuid, parent_ps, blob, short_blob_size); put_file(fd); return result; } TSS_RESULT ps_remove_key(TSS_UUID *uuid) { int fd; TSS_RESULT result; if ((result = get_file(&fd))) return result; result = psfile_remove_key(fd, uuid); put_file(fd); return result; } TSS_RESULT ps_get_key_by_pub(TSS_HCONTEXT tspContext, UINT32 pub_size, BYTE *pub, TSS_HKEY *hKey) { int fd; TSS_RESULT result = TSS_SUCCESS; BYTE key[4096]; TSS_UUID uuid; if ((result = get_file(&fd))) return result; if ((result = psfile_get_key_by_pub(fd, &uuid, pub_size, pub, key))) { put_file(fd); return result; } put_file(fd); result = obj_rsakey_add_by_key(tspContext, &uuid, key, TSS_OBJ_FLAG_USER_PS, hKey); return result; } TSS_RESULT ps_get_key_by_uuid(TSS_HCONTEXT tspContext, TSS_UUID *uuid, TSS_HKEY *hKey) { int fd; TSS_RESULT result = TSS_SUCCESS; BYTE key[4096]; if ((result = get_file(&fd))) return result; if ((result = psfile_get_key_by_uuid(fd, uuid, key))) { put_file(fd); return result; } put_file(fd); result = obj_rsakey_add_by_key(tspContext, uuid, key, TSS_OBJ_FLAG_USER_PS, hKey); return result; } TSS_RESULT ps_get_parent_uuid_by_uuid(TSS_UUID *uuid, TSS_UUID *parent_uuid) { int fd; TSS_RESULT result; if ((result = get_file(&fd))) return result; result = psfile_get_parent_uuid_by_uuid(fd, uuid, parent_uuid); put_file(fd); return result; } TSS_RESULT ps_get_parent_ps_type_by_uuid(TSS_UUID *uuid, UINT32 *type) { int fd; TSS_RESULT result; if ((result = get_file(&fd))) return result; result = psfile_get_parent_ps_type(fd, uuid, type); put_file(fd); return result; } TSS_RESULT ps_close() { TSS_RESULT result; int fd; if ((result = get_file(&fd))) return result; psfile_close(fd); /* No need to call put_file() here, the file is closed */ return TSS_SUCCESS; } TSS_RESULT merge_key_hierarchies(TSS_HCONTEXT tspContext, UINT32 tsp_size, TSS_KM_KEYINFO *tsp_hier, UINT32 tcs_size, TSS_KM_KEYINFO *tcs_hier, UINT32 *merged_size, TSS_KM_KEYINFO **merged_hier) { UINT32 i, j; *merged_hier = malloc((tsp_size + tcs_size) * sizeof(TSS_KM_KEYINFO)); if (*merged_hier == NULL) { LogError("malloc of %zu bytes failed.", (tsp_size + tcs_size) * sizeof(TSS_KM_KEYINFO)); return TSPERR(TSS_E_OUTOFMEMORY); } for (i = 0; i < tsp_size; i++) memcpy(&((*merged_hier)[i]), &tsp_hier[i], sizeof(TSS_KM_KEYINFO)); for (j = 0; j < tcs_size; j++) memcpy(&((*merged_hier)[i + j]), &tcs_hier[j], sizeof(TSS_KM_KEYINFO)); *merged_size = i + j; return TSS_SUCCESS; } TSS_RESULT merge_key_hierarchies2(TSS_HCONTEXT tspContext, UINT32 tsp_size, TSS_KM_KEYINFO2 *tsp_hier, UINT32 tcs_size, TSS_KM_KEYINFO2 *tcs_hier, UINT32 *merged_size, TSS_KM_KEYINFO2 **merged_hier) { UINT32 i, j; *merged_hier = malloc((tsp_size + tcs_size) * sizeof(TSS_KM_KEYINFO2)); if (*merged_hier == NULL) { LogError("malloc of %zu bytes failed.", (tsp_size + tcs_size) * sizeof(TSS_KM_KEYINFO2)); return TSPERR(TSS_E_OUTOFMEMORY); } for (i = 0; i < tsp_size; i++) memcpy(&((*merged_hier)[i]), &tsp_hier[i], sizeof(TSS_KM_KEYINFO2)); for (j = 0; j < tcs_size; j++) memcpy(&((*merged_hier)[i + j]), &tcs_hier[j], sizeof(TSS_KM_KEYINFO2)); *merged_size = i + j; return TSS_SUCCESS; } #if 0 TSS_RESULT load_from_system_ps(TSS_HCONTEXT tspContext, TSS_UUID *uuid, TSS_HKEY *phKey) { TCS_KEY_HANDLE tcsKeyHandle; TCS_LOADKEY_INFO info; BYTE *keyBlob = NULL; __tspi_memset(&info, 0, sizeof(TCS_LOADKEY_INFO)); result = TCSP_LoadKeyByUUID(tspContext, uuidData, &info, &tcsKeyHandle); if (TSS_ERROR_CODE(result) == TCS_E_KM_LOADFAILED) { TSS_HKEY keyHandle; TSS_HPOLICY hPolicy; /* load failed, due to some key in the chain needing auth * which doesn't yet exist at the TCS level. However, the * auth may already be set in policies at the TSP level. * To find out, get the key handle of the key requiring * auth. First, look at the list of keys in memory. */ if ((obj_rsakey_get_by_uuid(&info.parentKeyUUID, &keyHandle))) { /* If that failed, look on disk, in User PS. */ if (ps_get_key_by_uuid(tspContext, &info.parentKeyUUID, &keyHandle)) return result; } if (obj_rsakey_get_policy(keyHandle, TSS_POLICY_USAGE, &hPolicy, NULL)) return result; if (secret_PerformAuth_OIAP(keyHandle, TPM_ORD_LoadKey, hPolicy, &info.paramDigest, &info.authData)) return result; if ((result = TCSP_LoadKeyByUUID(tspContext, *uuid, &info, &tcsKeyHandle))) return result; } else if (result) return result; if ((result = TCS_GetRegisteredKeyBlob(tspContext, *uuid, &keyBlobSize, &keyBlob))) return result; if ((result = obj_rsakey_add_by_key(tspContext, uuid, keyBlob, TSS_OBJ_FLAG_SYSTEM_PS, phKey))) { free(keyBlob); return result; } result = obj_rsakey_set_tcs_handle(*phKey, tcsKeyHandle); free(keyBlob); return result; } #endif