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/tspi_ps.c | |
download | trousers-upstream/0.3.9.tar.gz |
Imported Upstream version 0.3.9upstream/0.3.9upstream
Diffstat (limited to 'src/tspi/tspi_ps.c')
-rw-r--r-- | src/tspi/tspi_ps.c | 581 |
1 files changed, 581 insertions, 0 deletions
diff --git a/src/tspi/tspi_ps.c b/src/tspi/tspi_ps.c new file mode 100644 index 0000000..b6df78c --- /dev/null +++ b/src/tspi/tspi_ps.c @@ -0,0 +1,581 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2004-2006 + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "trousers/tss.h" +#include "trousers/trousers.h" +#include "trousers_types.h" +#include "trousers_types.h" +#include "spi_utils.h" +#include "capabilities.h" +#include "tsplog.h" +#include "tcs_tsp.h" +#include "tspps.h" +#include "hosttable.h" +#include "tcsd_wrap.h" +#include "tcsd.h" +#include "obj.h" + +TSS_UUID owner_evict_uuid = {0, 0, 0, 0, 0, {0, 0, 0, 0, 1, 0}}; + +TSS_RESULT +Tspi_Context_LoadKeyByUUID(TSS_HCONTEXT tspContext, /* in */ + TSS_FLAG persistentStorageType, /* in */ + TSS_UUID uuidData, /* in */ + TSS_HKEY * phKey) /* out */ +{ + TSS_RESULT result; + TSS_UUID parentUUID; + UINT32 keyBlobSize, parentPSType; + BYTE *keyBlob = NULL; + TCS_KEY_HANDLE tcsKeyHandle; + TSS_HKEY parentTspHandle; + TCS_LOADKEY_INFO info; + UINT32 ulPubKeyLength; + BYTE *rgbPubKey; + TPM_COMMAND_CODE ordinal; + + if (phKey == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if ((!obj_is_context(tspContext))) + return TSPERR(TSS_E_INVALID_HANDLE); + + if ((result = obj_context_get_loadkey_ordinal(tspContext, &ordinal))) + return result; + + /* This key is in the System Persistant storage */ + if (persistentStorageType == TSS_PS_TYPE_SYSTEM) { +#if 1 + memset(&info, 0, sizeof(TCS_LOADKEY_INFO)); + + result = RPC_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, ordinal, hPolicy, FALSE, + &info.paramDigest, &info.authData)) + return result; + + if ((result = RPC_LoadKeyByUUID(tspContext, uuidData, &info, + &tcsKeyHandle))) + return result; + } else if (result) + return result; + + /*check if provided UUID has an owner evict key UUID prefix */ + if (!memcmp(&uuidData, &owner_evict_uuid, sizeof(TSS_UUID)-1)) { + if ((result = obj_rsakey_add(tspContext, TSS_RSAKEY_FLAG_OWNEREVICT, + phKey))) + return result; + if ((result = obj_rsakey_set_tcs_handle(*phKey, tcsKeyHandle))) + return result; + + //The cached public key portion of the owner evict key is used + //further by TPM_KEY_CONTROLOWNER command for sanity check + if ((result = Tspi_Key_GetPubKey(*phKey, &ulPubKeyLength, &rgbPubKey))) + return result; + + result = obj_rsakey_set_pubkey(*phKey, FALSE, rgbPubKey); + + free(rgbPubKey); + if (result != TSS_SUCCESS) + return result; + } else { + if ((result = RPC_GetRegisteredKeyBlob(tspContext, uuidData, &keyBlobSize, + &keyBlob))) + return result; + + if ((result = obj_rsakey_add_by_key(tspContext, &uuidData, keyBlob, + TSS_OBJ_FLAG_SYSTEM_PS, phKey))) { + free (keyBlob); + return result; + } + + result = obj_rsakey_set_tcs_handle(*phKey, tcsKeyHandle); + + free (keyBlob); + } +#else + if ((result = load_from_system_ps(tspContext, &uuidData, phKey))) + return result; +#endif + } else if (persistentStorageType == TSS_PS_TYPE_USER) { + if ((result = ps_get_parent_uuid_by_uuid(&uuidData, &parentUUID))) + return result; + + /* If the parent is not in memory, recursively call ourselves on it */ + if (obj_rsakey_get_by_uuid(&parentUUID, &parentTspHandle) != TSS_SUCCESS) { + if ((result = ps_get_parent_ps_type_by_uuid(&uuidData, &parentPSType))) + return result; + + if ((result = Tspi_Context_LoadKeyByUUID(tspContext, parentPSType, + parentUUID, &parentTspHandle))) + return result; + } + + if ((result = ps_get_key_by_uuid(tspContext, &uuidData, phKey))) + return result; + + /* The parent is loaded and we have the parent key handle, so call the TCS to + * actually load the child. */ + return Tspi_Key_LoadKey(*phKey, parentTspHandle); + } else { + return TSPERR(TSS_E_BAD_PARAMETER); + } + + return TSS_SUCCESS; +} + +TSS_RESULT +Tspi_Context_RegisterKey(TSS_HCONTEXT tspContext, /* in */ + TSS_HKEY hKey, /* in */ + TSS_FLAG persistentStorageType, /* in */ + TSS_UUID uuidKey, /* in */ + TSS_FLAG persistentStorageTypeParent, /* in */ + TSS_UUID uuidParentKey) /* in */ +{ + BYTE *keyBlob; + UINT32 keyBlobSize; + TSS_RESULT result; + TSS_BOOL answer; + + if (!obj_is_context(tspContext) || !obj_is_rsakey(hKey)) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (persistentStorageType == TSS_PS_TYPE_SYSTEM) { + if (persistentStorageTypeParent == TSS_PS_TYPE_USER) { + return TSPERR(TSS_E_NOTIMPL); + } else if (persistentStorageTypeParent == TSS_PS_TYPE_SYSTEM) { + if ((result = obj_rsakey_get_blob(hKey, &keyBlobSize, + &keyBlob))) + return result; + + if ((result = RPC_RegisterKey(tspContext, uuidParentKey, uuidKey, + keyBlobSize, keyBlob, + strlen(PACKAGE_STRING) + 1, + (BYTE *)PACKAGE_STRING))) + return result; + } else { + return TSPERR(TSS_E_BAD_PARAMETER); + } + } else if (persistentStorageType == TSS_PS_TYPE_USER) { + if ((result = ps_is_key_registered(&uuidKey, &answer))) + return result; + + if (answer == TRUE) + return TSPERR(TSS_E_KEY_ALREADY_REGISTERED); + + if ((result = obj_rsakey_get_blob (hKey, &keyBlobSize, &keyBlob))) + return result; + + if ((result = ps_write_key(&uuidKey, &uuidParentKey, + persistentStorageTypeParent, + keyBlobSize, keyBlob))) + return result; + } else { + return TSPERR(TSS_E_BAD_PARAMETER); + } + + if ((result = obj_rsakey_set_uuid(hKey, persistentStorageType, &uuidKey))) + return result; + + return TSS_SUCCESS; +} + +TSS_RESULT +Tspi_Context_UnregisterKey(TSS_HCONTEXT tspContext, /* in */ + TSS_FLAG persistentStorageType, /* in */ + TSS_UUID uuidKey, /* in */ + TSS_HKEY *phKey) /* out */ +{ + BYTE *keyBlob = NULL; + UINT32 keyBlobSize; + TSS_RESULT result; + + if (phKey == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if ((!obj_is_context(tspContext))) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (persistentStorageType == TSS_PS_TYPE_SYSTEM) { + /* get the key first, so it doesn't disappear when we + * unregister it */ + if ((result = RPC_GetRegisteredKeyBlob(tspContext, uuidKey, &keyBlobSize, + &keyBlob))) + return result; + + if ((obj_rsakey_add_by_key(tspContext, &uuidKey, keyBlob, TSS_OBJ_FLAG_SYSTEM_PS, + phKey))) { + free(keyBlob); + return result; + } + + free(keyBlob); + + /* now unregister it */ + if ((result = RPC_UnregisterKey(tspContext, uuidKey))) + return result; + } else if (persistentStorageType == TSS_PS_TYPE_USER) { + /* get the key first, so it doesn't disappear when we + * unregister it */ + if ((result = ps_get_key_by_uuid(tspContext, &uuidKey, phKey))) + return result; + + /* now unregister it */ + if ((result = ps_remove_key(&uuidKey))) + return result; + } else { + return TSPERR(TSS_E_BAD_PARAMETER); + } + + return TSS_SUCCESS; +} + +TSS_RESULT +Tspi_Context_GetKeyByUUID(TSS_HCONTEXT tspContext, /* in */ + TSS_FLAG persistentStorageType, /* in */ + TSS_UUID uuidData, /* in */ + TSS_HKEY * phKey) /* out */ +{ + TCPA_RESULT result; + UINT32 keyBlobSize = 0; + BYTE *keyBlob = NULL; + + if (phKey == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if ((!obj_is_context(tspContext))) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (persistentStorageType == TSS_PS_TYPE_SYSTEM) { + if ((result = RPC_GetRegisteredKeyBlob(tspContext, uuidData, &keyBlobSize, + &keyBlob))) + return result; + + if ((obj_rsakey_add_by_key(tspContext, &uuidData, keyBlob, TSS_OBJ_FLAG_SYSTEM_PS, + phKey))) { + free(keyBlob); + return result; + } + + free(keyBlob); + } else if (persistentStorageType == TSS_PS_TYPE_USER) { + if (!obj_is_context(tspContext)) + return TSPERR(TSS_E_INVALID_HANDLE); + + if ((result = ps_get_key_by_uuid(tspContext, &uuidData, phKey))) + return result; + } else + return TSPERR(TSS_E_BAD_PARAMETER); + + return TSS_SUCCESS; +} + +TSS_RESULT +Tspi_Context_GetKeyByPublicInfo(TSS_HCONTEXT tspContext, /* in */ + TSS_FLAG persistentStorageType, /* in */ + TSS_ALGORITHM_ID algID, /* in */ + UINT32 ulPublicInfoLength, /* in */ + BYTE * rgbPublicInfo, /* in */ + TSS_HKEY * phKey) /* out */ +{ + TCPA_ALGORITHM_ID tcsAlgID; + UINT32 keyBlobSize; + BYTE *keyBlob; + TSS_RESULT result; + TSS_HKEY keyOutHandle; + UINT32 flag = 0; + TSS_KEY keyContainer; + UINT64 offset; + + if (phKey == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if (!obj_is_context(tspContext)) + return TSPERR(TSS_E_INVALID_HANDLE); + + switch (algID) { + case TSS_ALG_RSA: + tcsAlgID = TCPA_ALG_RSA; + break; + default: + LogError("Algorithm ID was not type RSA."); + return TSPERR(TSS_E_BAD_PARAMETER); + } + + if (persistentStorageType == TSS_PS_TYPE_SYSTEM) { + if ((result = RPC_GetRegisteredKeyByPublicInfo(tspContext, tcsAlgID, + ulPublicInfoLength, rgbPublicInfo, + &keyBlobSize, &keyBlob))) + return result; + + } else if (persistentStorageType == TSS_PS_TYPE_USER) { + return ps_get_key_by_pub(tspContext, ulPublicInfoLength, rgbPublicInfo, + phKey); + } else + return TSPERR(TSS_E_BAD_PARAMETER); + + /* need to setup the init flags of the create object based on + * the size of the blob's pubkey */ + offset = 0; + if ((result = UnloadBlob_TSS_KEY(&offset, keyBlob, &keyContainer))) { + free(keyBlob); + return result; + } + + /* begin setting up the key object */ + switch (keyContainer.pubKey.keyLength) { + case 16384/8: + flag |= TSS_KEY_SIZE_16384; + break; + case 8192/8: + flag |= TSS_KEY_SIZE_8192; + break; + case 4096/8: + flag |= TSS_KEY_SIZE_4096; + break; + case 2048/8: + flag |= TSS_KEY_SIZE_2048; + break; + case 1024/8: + flag |= TSS_KEY_SIZE_1024; + break; + case 512/8: + flag |= TSS_KEY_SIZE_512; + break; + default: + LogError("Key was not a known keylength."); + free(keyBlob); + free_key_refs(&keyContainer); + return TSPERR(TSS_E_INTERNAL_ERROR); + } + + if (keyContainer.keyUsage == TPM_KEY_SIGNING) + flag |= TSS_KEY_TYPE_SIGNING; + else if (keyContainer.keyUsage == TPM_KEY_STORAGE) + flag |= TSS_KEY_TYPE_STORAGE; + else if (keyContainer.keyUsage == TPM_KEY_IDENTITY) + flag |= TSS_KEY_TYPE_IDENTITY; + else if (keyContainer.keyUsage == TPM_KEY_AUTHCHANGE) + flag |= TSS_KEY_TYPE_AUTHCHANGE; + else if (keyContainer.keyUsage == TPM_KEY_BIND) + flag |= TSS_KEY_TYPE_BIND; + else if (keyContainer.keyUsage == TPM_KEY_LEGACY) + flag |= TSS_KEY_TYPE_LEGACY; + + if (keyContainer.authDataUsage == TPM_AUTH_NEVER) + flag |= TSS_KEY_NO_AUTHORIZATION; + else + flag |= TSS_KEY_AUTHORIZATION; + + if (keyContainer.keyFlags & TPM_MIGRATABLE) + flag |= TSS_KEY_MIGRATABLE; + else + flag |= TSS_KEY_NOT_MIGRATABLE; + + if (keyContainer.keyFlags & TPM_VOLATILE) + flag |= TSS_KEY_VOLATILE; + else + flag |= TSS_KEY_NON_VOLATILE; + +#ifdef TSS_BUILD_CMK + if (keyContainer.keyFlags & TPM_MIGRATEAUTHORITY) + flag |= TSS_KEY_CERTIFIED_MIGRATABLE; + else + flag |= TSS_KEY_NOT_CERTIFIED_MIGRATABLE; +#endif + + /* Create a new Key Object */ + if ((result = obj_rsakey_add(tspContext, flag, &keyOutHandle))) { + free(keyBlob); + free_key_refs(&keyContainer); + return result; + } + /* Stick the info into this net KeyObject */ + if ((result = obj_rsakey_set_tcpakey(keyOutHandle, keyBlobSize, keyBlob))) { + free(keyBlob); + free_key_refs(&keyContainer); + return result; + } + + free(keyBlob); + free_key_refs(&keyContainer); + *phKey = keyOutHandle; + + return TSS_SUCCESS; +} + +TSS_RESULT +Tspi_Context_GetRegisteredKeysByUUID(TSS_HCONTEXT tspContext, /* in */ + TSS_FLAG persistentStorageType, /* in */ + TSS_UUID * pUuidData, /* in */ + UINT32 * pulKeyHierarchySize, /* out */ + TSS_KM_KEYINFO ** ppKeyHierarchy) /* out */ +{ + TSS_RESULT result; + TSS_KM_KEYINFO *tcsHier, *tspHier; + UINT32 tcsHierSize, tspHierSize; + TSS_UUID tcs_uuid; + + if (pulKeyHierarchySize == NULL || ppKeyHierarchy == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if (!obj_is_context(tspContext)) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (pUuidData) { + if (persistentStorageType == TSS_PS_TYPE_SYSTEM) { + if ((result = RPC_EnumRegisteredKeys(tspContext, pUuidData, + pulKeyHierarchySize, + ppKeyHierarchy))) + return result; + } else if (persistentStorageType == TSS_PS_TYPE_USER) { + if ((result = ps_get_registered_keys(pUuidData, &tcs_uuid, + &tspHierSize, &tspHier))) + return result; + + if ((result = RPC_EnumRegisteredKeys(tspContext, &tcs_uuid, &tcsHierSize, + &tcsHier))) { + free(tspHier); + return result; + } + + result = merge_key_hierarchies(tspContext, tspHierSize, tspHier, + tcsHierSize, tcsHier, pulKeyHierarchySize, + ppKeyHierarchy); + free(tcsHier); + free(tspHier); + } else + return TSPERR(TSS_E_BAD_PARAMETER); + } else { + if ((result = RPC_EnumRegisteredKeys(tspContext, pUuidData, &tcsHierSize, + &tcsHier))) + return result; + + if ((result = ps_get_registered_keys(pUuidData, NULL, &tspHierSize, &tspHier))) { + free(tcsHier); + return result; + } + + result = merge_key_hierarchies(tspContext, tspHierSize, tspHier, tcsHierSize, + tcsHier, pulKeyHierarchySize, ppKeyHierarchy); + free(tcsHier); + free(tspHier); + } + + if ((result = __tspi_add_mem_entry(tspContext, *ppKeyHierarchy))) { + free(*ppKeyHierarchy); + *ppKeyHierarchy = NULL; + *pulKeyHierarchySize = 0; + } + + return result; +} + +TSS_RESULT +Tspi_Context_GetRegisteredKeysByUUID2(TSS_HCONTEXT tspContext, /* in */ + TSS_FLAG persistentStorageType, /* in */ + TSS_UUID * pUuidData, /* in */ + UINT32 * pulKeyHierarchySize, /* out */ + TSS_KM_KEYINFO2 ** ppKeyHierarchy) /* out */ +{ + TSS_RESULT result; + TSS_KM_KEYINFO2 *tcsHier, *tspHier; + UINT32 tcsHierSize, tspHierSize; + TSS_UUID tcs_uuid; + + /* If out parameters are NULL, return error */ + if (pulKeyHierarchySize == NULL || ppKeyHierarchy == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if (!obj_is_context(tspContext)) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (pUuidData) { + /* TSS 1.2 Spec: If a certain key UUID is provided, the returned array of + * TSS_KM_KEYINFO2 structures only contains data reflecting the path of the key + * hierarchy regarding that key. The first array entry is the key addressed by the + * given UUID followed by its parent key up to and including the root key. */ + if (persistentStorageType == TSS_PS_TYPE_SYSTEM) { + if ((result = RPC_EnumRegisteredKeys2(tspContext, pUuidData, + pulKeyHierarchySize, ppKeyHierarchy))) + return result; + } else if (persistentStorageType == TSS_PS_TYPE_USER) { + if ((result = ps_get_registered_keys2(pUuidData, &tcs_uuid, &tspHierSize, + &tspHier))) + return result; + /* The tcs_uuid returned by ps_get_registered_key2 will always be a parent + * of some key into the system ps of a user key into the user ps. This key + * needs to be searched for in the system ps to be merged */ + if ((result = RPC_EnumRegisteredKeys2(tspContext, &tcs_uuid, &tcsHierSize, + &tcsHier))) { + free(tspHier); + return result; + } + + result = merge_key_hierarchies2(tspContext, tspHierSize, tspHier, + tcsHierSize, tcsHier, pulKeyHierarchySize, + ppKeyHierarchy); + free(tcsHier); + free(tspHier); + } else + return TSPERR(TSS_E_BAD_PARAMETER); + } else { + /* If this field is set to NULL, the returned array of TSS_KM_KEYINFO2 structures + * contains data reflecting the entire key hierarchy starting with root key. The + * array will include keys from both the user and the system TSS key store. The + * persistentStorageType field will be ignored. */ + if ((result = RPC_EnumRegisteredKeys2(tspContext, pUuidData, &tcsHierSize, + &tcsHier))) + return result; + + if ((result = ps_get_registered_keys2(pUuidData, NULL, &tspHierSize, &tspHier))) { + free(tcsHier); + return result; + } + + result = merge_key_hierarchies2(tspContext, tspHierSize, tspHier, tcsHierSize, + tcsHier, pulKeyHierarchySize, ppKeyHierarchy); + free(tcsHier); + free(tspHier); + } + + if ((result = __tspi_add_mem_entry(tspContext, *ppKeyHierarchy))) { + free(*ppKeyHierarchy); + *ppKeyHierarchy = NULL; + *pulKeyHierarchySize = 0; + } + + return result; +} |