summaryrefslogtreecommitdiff
path: root/src/tspi/tspi_ps.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
commitc3649a2def02c41d837ae1f79dda729ccb91e677 (patch)
treebea46dff212fdef977fe9094a70a939e8cc21885 /src/tspi/tspi_ps.c
downloadtrousers-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.c581
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;
+}