diff options
Diffstat (limited to 'src/tspi/obj_rsakey.c')
-rw-r--r-- | src/tspi/obj_rsakey.c | 2136 |
1 files changed, 2136 insertions, 0 deletions
diff --git a/src/tspi/obj_rsakey.c b/src/tspi/obj_rsakey.c new file mode 100644 index 0000000..3f509f1 --- /dev/null +++ b/src/tspi/obj_rsakey.c @@ -0,0 +1,2136 @@ + +/* + * 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 <inttypes.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_rsakey_add(TSS_HCONTEXT tspContext, TSS_FLAG initFlags, TSS_HOBJECT *phObject) +{ + UINT64 offset; + TSS_RESULT result; + TCPA_RSA_KEY_PARMS rsaKeyParms; + TSS_FLAG flags = 0; + struct tr_rsakey_obj *rsakey = calloc(1, sizeof(struct tr_rsakey_obj)); + TPM_STRUCT_VER ver = { 1, 1, 0, 0 }; // Must be 1.1.0.0 for 1.2 TPMs + UINT32 ctx_ver; + + if (rsakey == NULL) { + LogError("malloc of %zd bytes failed.", sizeof(struct tr_rsakey_obj)); + return TSPERR(TSS_E_OUTOFMEMORY); + } + + if ((result = obj_context_get_policy(tspContext, TSS_POLICY_USAGE, &rsakey->usagePolicy))) { + free(rsakey); + return result; + } + + if ((initFlags & TSS_KEY_STRUCT_BITMASK) == TSS_KEY_STRUCT_DEFAULT) { + /* Its not set, go with the context's default */ + if ((result = obj_context_get_connection_version(tspContext, &ctx_ver))) { + free(rsakey); + return result; + } + + switch (ctx_ver) { + case TSS_TSPATTRIB_CONTEXT_VERSION_V1_2: + initFlags |= TSS_KEY_STRUCT_KEY12; + break; + case TSS_TSPATTRIB_CONTEXT_VERSION_V1_1: + /* fall through */ + default: + initFlags |= TSS_KEY_STRUCT_KEY; + break; + } + } + + offset = 0; + switch (initFlags & TSS_KEY_STRUCT_BITMASK) { + case TSS_KEY_STRUCT_KEY: + rsakey->key.hdr.key11.ver = ver; + rsakey->type = TSS_KEY_STRUCT_KEY; + rsakey->pcrInfoType = TSS_PCRS_STRUCT_INFO; + rsakey->key.keyFlags = 0; + break; + case TSS_KEY_STRUCT_KEY12: + rsakey->key.hdr.key12.tag = TPM_TAG_KEY12; + rsakey->key.hdr.key12.fill = 0; + rsakey->type = TSS_KEY_STRUCT_KEY12; + rsakey->pcrInfoType = TSS_PCRS_STRUCT_INFO_LONG; + rsakey->key.keyFlags = TPM_PCRIGNOREDONREAD; + break; + default: + free(rsakey); + return TSPERR(TSS_E_INVALID_OBJECT_INITFLAG); + break; + } + + if (initFlags == TSS_KEY_EMPTY_KEY) + goto add_key; + + memset(&rsaKeyParms, 0, sizeof(TCPA_RSA_KEY_PARMS)); + + rsakey->key.algorithmParms.algorithmID = TCPA_ALG_RSA; + rsakey->key.algorithmParms.parmSize = sizeof(TCPA_RSA_KEY_PARMS); + + rsakey->key.algorithmParms.parms = calloc(1, sizeof(TCPA_RSA_KEY_PARMS)); + if (rsakey->key.algorithmParms.parms == NULL) { + LogError("calloc of %u bytes failed.", rsakey->key.algorithmParms.parmSize); + free(rsakey); + return TSPERR(TSS_E_OUTOFMEMORY); + } + rsaKeyParms.exponentSize = 0; + rsaKeyParms.numPrimes = 2; + + rsakey->key.pubKey.keyLength = 0; + rsakey->key.encSize = 0; + rsakey->key.PCRInfoSize = 0; + + /* End of all the default stuff */ + + if (initFlags & TSS_KEY_VOLATILE) + rsakey->key.keyFlags |= TPM_VOLATILE; + if (initFlags & TSS_KEY_MIGRATABLE) + rsakey->key.keyFlags |= TPM_MIGRATABLE; + if (initFlags & TSS_KEY_AUTHORIZATION) { + rsakey->key.authDataUsage = TPM_AUTH_ALWAYS; + flags |= TSS_OBJ_FLAG_USAGEAUTH; + } + +#ifdef TSS_BUILD_CMK + if (initFlags & TSS_KEY_CERTIFIED_MIGRATABLE) { + if (rsakey->type == TSS_KEY_STRUCT_KEY) { + free(rsakey); + return TSPERR(TSS_E_BAD_PARAMETER); + } + rsakey->key.keyFlags |= TPM_MIGRATEAUTHORITY; + } +#endif + + /* set the key length */ + if ((initFlags & TSS_KEY_SIZE_MASK) == TSS_KEY_SIZE_512) { + rsaKeyParms.keyLength = 512; + } else if ((initFlags & TSS_KEY_SIZE_MASK) == TSS_KEY_SIZE_1024) { + rsaKeyParms.keyLength = 1024; + } else if ((initFlags & TSS_KEY_SIZE_MASK) == TSS_KEY_SIZE_2048) { + rsaKeyParms.keyLength = 2048; + } else if ((initFlags & TSS_KEY_SIZE_MASK) == TSS_KEY_SIZE_4096) { + rsaKeyParms.keyLength = 4096; + } else if ((initFlags & TSS_KEY_SIZE_MASK) == TSS_KEY_SIZE_8192) { + rsaKeyParms.keyLength = 8192; + } else if ((initFlags & TSS_KEY_SIZE_MASK) == TSS_KEY_SIZE_16384) { + rsaKeyParms.keyLength = 16384; + } + + /* assign encryption and signature schemes */ + if ((initFlags & TSS_KEY_TYPE_MASK) == TSS_KEY_TYPE_SIGNING) { + rsakey->key.keyUsage = TPM_KEY_SIGNING; + rsakey->key.algorithmParms.encScheme = TCPA_ES_NONE; + rsakey->key.algorithmParms.sigScheme = TCPA_SS_RSASSAPKCS1v15_SHA1; + } else if ((initFlags & TSS_KEY_TYPE_MASK) == TSS_KEY_TYPE_BIND) { + rsakey->key.keyUsage = TPM_KEY_BIND; + rsakey->key.algorithmParms.encScheme = TCPA_ES_RSAESOAEP_SHA1_MGF1; + rsakey->key.algorithmParms.sigScheme = TCPA_SS_NONE; + } else if ((initFlags & TSS_KEY_TYPE_MASK) == TSS_KEY_TYPE_LEGACY) { + rsakey->key.keyUsage = TPM_KEY_LEGACY; + rsakey->key.algorithmParms.encScheme = TCPA_ES_RSAESOAEP_SHA1_MGF1; + rsakey->key.algorithmParms.sigScheme = TCPA_SS_RSASSAPKCS1v15_SHA1; + } else if ((initFlags & TSS_KEY_TYPE_MASK) == TSS_KEY_TYPE_STORAGE) { + rsakey->key.keyUsage = TPM_KEY_STORAGE; + rsakey->key.algorithmParms.encScheme = TCPA_ES_RSAESOAEP_SHA1_MGF1; + rsakey->key.algorithmParms.sigScheme = TCPA_SS_NONE; + } else if ((initFlags & TSS_KEY_TYPE_MASK) == TSS_KEY_TYPE_IDENTITY) { + rsakey->key.keyUsage = TPM_KEY_IDENTITY; + rsakey->key.algorithmParms.encScheme = TCPA_ES_NONE; + rsakey->key.algorithmParms.sigScheme = TCPA_SS_RSASSAPKCS1v15_SHA1; + } else if ((initFlags & TSS_KEY_TYPE_MASK) == TSS_KEY_TYPE_AUTHCHANGE) { + rsakey->key.keyUsage = TPM_KEY_AUTHCHANGE; + rsakey->key.algorithmParms.encScheme = TCPA_ES_RSAESOAEP_SHA1_MGF1; + rsakey->key.algorithmParms.sigScheme = TCPA_SS_NONE; + } + + /* Load the RSA key parms into the blob in the TCPA_KEY_PARMS pointer. + * If the exponent is left NULL, the parmSize variable will change + * here */ + offset = 0; + Trspi_LoadBlob_RSA_KEY_PARMS(&offset, rsakey->key.algorithmParms.parms, &rsaKeyParms); + rsakey->key.algorithmParms.parmSize = offset; + +add_key: + if ((result = obj_list_add(&rsakey_list, tspContext, flags, rsakey, phObject))) { + free(rsakey->key.algorithmParms.parms); + free(rsakey); + return result; + } + + return TSS_SUCCESS; +} + +/* Add a new rsakey to the list when its pulled from user PS */ +TSS_RESULT +obj_rsakey_add_by_key(TSS_HCONTEXT tspContext, TSS_UUID *uuid, BYTE *key, TSS_FLAG flags, + TSS_HKEY *phKey) +{ + TSS_RESULT result; + UINT64 offset; + struct tr_rsakey_obj *rsakey = calloc(1, sizeof(struct tr_rsakey_obj)); + + if (rsakey == NULL) { + LogError("malloc of %zd bytes failed.", sizeof(struct tr_rsakey_obj)); + return TSPERR(TSS_E_OUTOFMEMORY); + } + + memcpy(&rsakey->uuid, uuid, sizeof(TSS_UUID)); + + offset = 0; + if ((result = UnloadBlob_TSS_KEY(&offset, key, &rsakey->key))) { + free(rsakey); + return result; + } + if (rsakey->key.hdr.key12.tag == TPM_TAG_KEY12) + rsakey->type = TSS_KEY_STRUCT_KEY12; + else + rsakey->type = TSS_KEY_STRUCT_KEY; + + flags |= TSS_OBJ_FLAG_KEY_SET; + if (rsakey->key.authDataUsage) + flags |= TSS_OBJ_FLAG_USAGEAUTH; + + if ((result = obj_context_get_policy(tspContext, TSS_POLICY_USAGE, &rsakey->usagePolicy))) { + free(rsakey); + return result; + } + + if ((result = obj_list_add(&rsakey_list, tspContext, flags, rsakey, phKey))) { + free_key_refs(&rsakey->key); + free(rsakey); + return result; + } + + return TSS_SUCCESS; +} + +TSS_BOOL +obj_is_rsakey(TSS_HOBJECT hObject) +{ + TSS_BOOL answer = FALSE; + + if ((obj_list_get_obj(&rsakey_list, hObject))) { + answer = TRUE; + obj_list_put(&rsakey_list); + } + + return answer; +} + +TSS_RESULT +obj_rsakey_set_flags(TSS_HKEY hKey, UINT32 flags) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + rsakey->key.keyFlags = flags; +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_size(TSS_HKEY hKey, UINT32 len) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + rsakey->key.pubKey.keyLength = len/8; +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_key_parms(TSS_HKEY hKey, TCPA_KEY_PARMS *parms) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + + free(rsakey->key.algorithmParms.parms); + + memcpy(&rsakey->key.algorithmParms, parms, sizeof(TCPA_KEY_PARMS)); + + if (parms->parmSize > 0) { + if ((rsakey->key.algorithmParms.parms = + malloc(parms->parmSize)) == NULL) { + LogError("calloc of %d bytes failed.", parms->parmSize); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + + memcpy(rsakey->key.algorithmParms.parms, parms->parms, + parms->parmSize); + } else { + rsakey->key.algorithmParms.parms = NULL; + } + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_policy(TSS_HKEY hKey, TSS_HPOLICY hPolicy) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + UINT32 policyType; + TSS_RESULT result = TSS_SUCCESS; + + if ((result = obj_policy_get_type(hPolicy, &policyType))) + return result; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + switch (policyType) { + case TSS_POLICY_USAGE: + rsakey->usagePolicy = hPolicy; + break; + case TSS_POLICY_MIGRATION: + rsakey->migPolicy = hPolicy; + break; + default: + result = TSPERR(TSS_E_BAD_PARAMETER); + } + + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_pstype(TSS_HKEY hKey, UINT32 type) +{ + struct tsp_object *obj; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + switch (type) { + case TSS_PS_TYPE_USER: + obj->flags |= TSS_OBJ_FLAG_USER_PS; + obj->flags &= ~TSS_OBJ_FLAG_SYSTEM_PS; + break; + case TSS_PS_TYPE_SYSTEM: + obj->flags |= TSS_OBJ_FLAG_SYSTEM_PS; + obj->flags &= ~TSS_OBJ_FLAG_USER_PS; + break; + case TSS_PS_TYPE_NO: + default: + obj->flags &= ~TSS_OBJ_FLAG_USER_PS; + obj->flags &= ~TSS_OBJ_FLAG_SYSTEM_PS; + break; + } + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +/* WARN: Nobody should call this function directly except for the + * Get/Set Attrib functions. The TCPA_KEY structure wants values + * for keyUsage to be TPM_KEY_* values, and this function translates + * to TSS_KEYUSAGE_* values for passing to an app. */ +TSS_RESULT +obj_rsakey_get_usage(TSS_HKEY hKey, UINT32 *usage) +{ + TSS_RESULT result = TSS_SUCCESS; + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + switch (rsakey->key.keyUsage) { + case TPM_KEY_SIGNING: + *usage = TSS_KEYUSAGE_SIGN; + break; + case TPM_KEY_BIND: + *usage = TSS_KEYUSAGE_BIND; + break; + case TPM_KEY_LEGACY: + *usage = TSS_KEYUSAGE_LEGACY; + break; + case TPM_KEY_AUTHCHANGE: + *usage = TSS_KEYUSAGE_AUTHCHANGE; + break; + case TPM_KEY_IDENTITY: + *usage = TSS_KEYUSAGE_IDENTITY; + break; + case TPM_KEY_STORAGE: + *usage = TSS_KEYUSAGE_STORAGE; + break; + default: + result = TSPERR(TSS_E_INVALID_ATTRIB_DATA); + break; + } + + obj_list_put(&rsakey_list); + + return result; +} + +/* WARN: Nobody should call this function directly except for the + * Get/Set Attrib functions. The TCPA_KEY structure wants values + * for keyUsage to be TPM_KEY_* values, and this function translates + * to TSS_KEYUSAGE_* values for passing to an app. */ +TSS_RESULT +obj_rsakey_set_usage(TSS_HKEY hKey, UINT32 usage) +{ + TSS_RESULT result = TSS_SUCCESS; + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + + switch (usage) { + case TSS_KEYUSAGE_SIGN: + rsakey->key.keyUsage = TPM_KEY_SIGNING; + break; + case TSS_KEYUSAGE_BIND: + rsakey->key.keyUsage = TPM_KEY_BIND; + break; + case TSS_KEYUSAGE_LEGACY: + rsakey->key.keyUsage = TPM_KEY_LEGACY; + break; + case TSS_KEYUSAGE_AUTHCHANGE: + rsakey->key.keyUsage = TPM_KEY_AUTHCHANGE; + break; + case TSS_KEYUSAGE_IDENTITY: + rsakey->key.keyUsage = TPM_KEY_IDENTITY; + break; + case TSS_KEYUSAGE_STORAGE: + rsakey->key.keyUsage = TPM_KEY_STORAGE; + break; + default: + result = TSPERR(TSS_E_INVALID_ATTRIB_DATA); + break; + } +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_migratable(TSS_HKEY hKey, UINT32 mig) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (mig) + rsakey->key.keyFlags |= TPM_MIGRATABLE; + else + rsakey->key.keyFlags &= (~TPM_MIGRATABLE); +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_redirected(TSS_HKEY hKey, UINT32 redir) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (redir) + rsakey->key.keyFlags |= TPM_REDIRECTION; + else + rsakey->key.keyFlags &= (~TPM_REDIRECTION); +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_volatile(TSS_HKEY hKey, UINT32 vol) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (vol) + rsakey->key.keyFlags |= TPM_VOLATILE; + else + rsakey->key.keyFlags &= (~TPM_VOLATILE); +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_authdata_usage(TSS_HKEY hKey, UINT32 *usage) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + *usage = (UINT32)rsakey->key.authDataUsage ? TRUE : FALSE; + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_set_authdata_usage(TSS_HKEY hKey, UINT32 usage) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + + rsakey->key.authDataUsage = (BYTE)usage; + if (usage) + obj->flags |= TSS_OBJ_FLAG_USAGEAUTH; + else + obj->flags &= ~TSS_OBJ_FLAG_USAGEAUTH; +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_alg(TSS_HKEY hKey, UINT32 *alg) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + switch (rsakey->key.algorithmParms.algorithmID) { + case TCPA_ALG_RSA: + *alg = TSS_ALG_RSA; + break; + default: + *alg = rsakey->key.algorithmParms.algorithmID; + break; + } + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_set_alg(TSS_HKEY hKey, UINT32 alg) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + switch (alg) { + case TSS_ALG_RSA: + rsakey->key.algorithmParms.algorithmID = TCPA_ALG_RSA; + break; + default: + rsakey->key.algorithmParms.algorithmID = alg; + break; + } +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_es(TSS_HKEY hKey, UINT32 *es) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + /* translate TPM numbers to TSS numbers */ + switch (rsakey->key.algorithmParms.encScheme) { + case TCPA_ES_NONE: + *es = TSS_ES_NONE; + break; + case TCPA_ES_RSAESPKCSv15: + *es = TSS_ES_RSAESPKCSV15; + break; + case TCPA_ES_RSAESOAEP_SHA1_MGF1: + *es = TSS_ES_RSAESOAEP_SHA1_MGF1; + break; + default: + *es = rsakey->key.algorithmParms.encScheme; + break; + } + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_set_es(TSS_HKEY hKey, UINT32 es) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + + /* translate TSS numbers to TPM numbers */ + switch (es) { + case TSS_ES_NONE: + rsakey->key.algorithmParms.encScheme = TCPA_ES_NONE; + break; + case TSS_ES_RSAESPKCSV15: + rsakey->key.algorithmParms.encScheme = TCPA_ES_RSAESPKCSv15; + break; + case TSS_ES_RSAESOAEP_SHA1_MGF1: + rsakey->key.algorithmParms.encScheme = TCPA_ES_RSAESOAEP_SHA1_MGF1; + break; + default: + rsakey->key.algorithmParms.encScheme = es; + break; + } +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_ss(TSS_HKEY hKey, UINT32 *ss) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + /* translate TPM numbers to TSS numbers */ + switch (rsakey->key.algorithmParms.sigScheme) { + case TCPA_SS_NONE: + *ss = TSS_SS_NONE; + break; + case TCPA_SS_RSASSAPKCS1v15_SHA1: + *ss = TSS_SS_RSASSAPKCS1V15_SHA1; + break; + case TCPA_SS_RSASSAPKCS1v15_DER: + *ss = TSS_SS_RSASSAPKCS1V15_DER; + break; + case TCPA_SS_RSASSAPKCS1v15_INFO: + *ss = TSS_SS_RSASSAPKCS1V15_INFO; + break; + default: + *ss = rsakey->key.algorithmParms.sigScheme; + break; + } + + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_set_ss(TSS_HKEY hKey, UINT32 ss) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + + /* translate TSS numbers to TPM numbers */ + switch (ss) { + case TSS_SS_NONE: + rsakey->key.algorithmParms.sigScheme = TCPA_SS_NONE; + break; + case TSS_SS_RSASSAPKCS1V15_SHA1: + rsakey->key.algorithmParms.sigScheme = TCPA_SS_RSASSAPKCS1v15_SHA1; + break; + case TSS_SS_RSASSAPKCS1V15_DER: + rsakey->key.algorithmParms.sigScheme = TCPA_SS_RSASSAPKCS1v15_DER; + break; + case TSS_SS_RSASSAPKCS1V15_INFO: + rsakey->key.algorithmParms.sigScheme = TCPA_SS_RSASSAPKCS1v15_INFO; + break; + default: + rsakey->key.algorithmParms.sigScheme = ss; + break; + } +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_num_primes(TSS_HKEY hKey, UINT32 num) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + UINT32ToArray(num, &rsakey->key.algorithmParms.parms[4]); +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_num_primes(TSS_HKEY hKey, UINT32 *num) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TCPA_RSA_KEY_PARMS *parms; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + parms = (TCPA_RSA_KEY_PARMS *)rsakey->key.algorithmParms.parms; + *num = endian32(parms->numPrimes); + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_get_flags(TSS_HKEY hKey, UINT32 *flags) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + *flags = rsakey->key.keyFlags; + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_get_size(TSS_HKEY hKey, UINT32 *len) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + switch (rsakey->key.pubKey.keyLength) { + case 512/8: + *len = TSS_KEY_SIZEVAL_512BIT; + break; + case 1024/8: + *len = TSS_KEY_SIZEVAL_1024BIT; + break; + case 2048/8: + *len = TSS_KEY_SIZEVAL_2048BIT; + break; + default: + *len = rsakey->key.pubKey.keyLength * 8; + break; + } + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_get_pstype(TSS_HKEY hKey, UINT32 *type) +{ + struct tsp_object *obj; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_SYSTEM_PS) + *type = TSS_PS_TYPE_SYSTEM; + else if (obj->flags & TSS_OBJ_FLAG_USER_PS) + *type = TSS_PS_TYPE_USER; + else + *type = TSS_PS_TYPE_NO; + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_BOOL +obj_rsakey_is_migratable(TSS_HKEY hKey) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_BOOL answer = FALSE; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return answer; + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (rsakey->key.keyFlags & TPM_MIGRATABLE) + answer = TRUE; + + obj_list_put(&rsakey_list); + + return answer; +} + +TSS_BOOL +obj_rsakey_is_redirected(TSS_HKEY hKey) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_BOOL answer = FALSE; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return answer; + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (rsakey->key.keyFlags & TPM_REDIRECTION) + answer = TRUE; + + obj_list_put(&rsakey_list); + + return answer; +} + +TSS_BOOL +obj_rsakey_is_volatile(TSS_HKEY hKey) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_BOOL answer = FALSE; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return answer; + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (rsakey->key.keyFlags & TPM_VOLATILE) + answer = TRUE; + + obj_list_put(&rsakey_list); + + return answer; +} + +TSS_RESULT +obj_rsakey_get_tsp_context(TSS_HKEY hKey, TSS_HCONTEXT *tspContext) +{ + struct tsp_object *obj; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + *tspContext = obj->tspContext; + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_get_policies(TSS_HKEY hKey, TSS_HPOLICY *usage, TSS_HPOLICY *mig, TSS_BOOL *auth) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + *mig = rsakey->migPolicy; + *usage = rsakey->usagePolicy; + *auth = rsakey->key.authDataUsage ? TRUE : FALSE; + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_get_policy(TSS_HKEY hKey, UINT32 policyType, + TSS_HPOLICY *phPolicy, TSS_BOOL *auth) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + switch (policyType) { + case TSS_POLICY_USAGE: + *phPolicy = rsakey->usagePolicy; + if (auth != NULL) { + if (obj->flags & TSS_OBJ_FLAG_USAGEAUTH) + *auth = TRUE; + else + *auth = FALSE; + } + break; + case TSS_POLICY_MIGRATION: + if (!rsakey->migPolicy) { + result = TSPERR(TSS_E_KEY_NO_MIGRATION_POLICY); + break; + } + + *phPolicy = rsakey->migPolicy; + if (auth != NULL) { + if (obj->flags & TSS_OBJ_FLAG_MIGAUTH) + *auth = TRUE; + else + *auth = FALSE; + } + break; + default: + result = TSPERR(TSS_E_BAD_PARAMETER); + } + + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_blob(TSS_HKEY hKey, UINT32 *size, BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + UINT64 offset; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + offset = 0; + LoadBlob_TSS_KEY(&offset, NULL, &rsakey->key); + + *data = calloc_tspi(obj->tspContext, offset); + if (*data == NULL) { + LogError("malloc of %" PRIu64 " bytes failed.", offset); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + + offset = 0; + LoadBlob_TSS_KEY(&offset, *data, &rsakey->key); + *size = offset; + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_priv_blob(TSS_HKEY hKey, UINT32 *size, BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + *data = calloc_tspi(obj->tspContext, rsakey->key.encSize); + if (*data == NULL) { + LogError("malloc of %u bytes failed.", rsakey->key.encSize); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + *size = rsakey->key.encSize; + memcpy(*data, rsakey->key.encData, rsakey->key.encSize); + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_modulus(TSS_HKEY hKey, UINT32 *size, BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + /* if this key object represents the SRK and the public key + * data here is all 0's, then we shouldn't return it, we + * should return TSS_E_BAD_PARAMETER. This is part of protecting + * the SRK public key. */ + if (rsakey->tcsHandle == TPM_KEYHND_SRK) { + BYTE zeroBlob[2048] = { 0, }; + + if (!memcmp(rsakey->key.pubKey.key, zeroBlob, rsakey->key.pubKey.keyLength)) { + result = TSPERR(TSS_E_BAD_PARAMETER); + goto done; + } + } + + *data = calloc_tspi(obj->tspContext, rsakey->key.pubKey.keyLength); + if (*data == NULL) { + LogError("malloc of %u bytes failed.", rsakey->key.pubKey.keyLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + *size = rsakey->key.pubKey.keyLength; + memcpy(*data, rsakey->key.pubKey.key, rsakey->key.pubKey.keyLength); + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_modulus(TSS_HKEY hKey, UINT32 size, BYTE *data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + BYTE *free_ptr; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + + free_ptr = rsakey->key.pubKey.key; + + rsakey->key.pubKey.key = malloc(size); + if (rsakey->key.pubKey.key == NULL) { + rsakey->key.pubKey.key = free_ptr; // restore + LogError("malloc of %u bytes failed.", size); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + rsakey->key.pubKey.keyLength = size; + memcpy(rsakey->key.pubKey.key, data, size); + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_pub_blob(TSS_HKEY hKey, UINT32 *size, BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + UINT64 offset; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + /* if this key object represents the SRK and the public key + * data here is all 0's, then we shouldn't return it, we + * should return TSS_E_BAD_PARAMETER. This is part of protecting + * the SRK public key. */ + if (rsakey->tcsHandle == TPM_KEYHND_SRK) { + BYTE zeroBlob[2048] = { 0, }; + + if (!memcmp(rsakey->key.pubKey.key, zeroBlob, rsakey->key.pubKey.keyLength)) { + result = TSPERR(TSS_E_BAD_PARAMETER); + goto done; + } + } + + offset = 0; + Trspi_LoadBlob_KEY_PARMS(&offset, NULL, &rsakey->key.algorithmParms); + Trspi_LoadBlob_STORE_PUBKEY(&offset, NULL, &rsakey->key.pubKey); + + *data = calloc_tspi(obj->tspContext, offset); + if (*data == NULL) { + LogError("malloc of %" PRIu64 " bytes failed.", offset); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + + offset = 0; + Trspi_LoadBlob_KEY_PARMS(&offset, *data, &rsakey->key.algorithmParms); + Trspi_LoadBlob_STORE_PUBKEY(&offset, *data, &rsakey->key.pubKey); + *size = offset; + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_version(TSS_HKEY hKey, UINT32 *size, BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + UINT64 offset; + TPM_STRUCT_VER ver = {1, 2, 0, 0}, *pVer; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (rsakey->key.hdr.key12.tag == TPM_TAG_KEY12) + pVer = &ver; + else + pVer = &rsakey->key.hdr.key11.ver; + + offset = 0; + Trspi_LoadBlob_TCPA_VERSION(&offset, NULL, *pVer); + + *data = calloc_tspi(obj->tspContext, offset); + if (*data == NULL) { + LogError("malloc of %" PRIu64 " bytes failed.", offset); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + + offset = 0; + Trspi_LoadBlob_TCPA_VERSION(&offset, *data, *pVer); + *size = offset; + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_exponent(TSS_HKEY hKey, UINT32 *size, BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + TCPA_RSA_KEY_PARMS *parms; + BYTE default_exp[3] = { 0x1, 0x0, 0x1 }; + UINT32 offset; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + parms = (TCPA_RSA_KEY_PARMS *)rsakey->key.algorithmParms.parms; + offset = parms->exponentSize; + + /* see TPM 1.1b spec pg. 51. If exponentSize is 0, we're using the + * default exponent of 2^16 + 1. */ + if (offset == 0) { + offset = 3; + *data = calloc_tspi(obj->tspContext, offset); + if (*data == NULL) { + LogError("malloc of %u bytes failed.", offset); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + *size = offset; + memcpy(*data, default_exp, offset); + } else { + *data = calloc_tspi(obj->tspContext, offset); + if (*data == NULL) { + LogError("malloc of %u bytes failed.", offset); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + *size = offset; + memcpy(*data, parms->exponent, offset); + } + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_exponent(TSS_HKEY hKey, UINT32 size, BYTE *data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + TCPA_RSA_KEY_PARMS *parms; + BYTE *free_ptr; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + parms = (TCPA_RSA_KEY_PARMS *)rsakey->key.algorithmParms.parms; + + free_ptr = parms->exponent; + + parms->exponent = malloc(size); + if (parms->exponent == NULL) { + parms->exponent = free_ptr; // restore + LogError("malloc of %u bytes failed.", size); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + parms->exponentSize = size; + memcpy(parms->exponent, data, size); +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_uuid(TSS_HKEY hKey, UINT32 *size, BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + UINT64 offset; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + offset = 0; + Trspi_LoadBlob_UUID(&offset, NULL, rsakey->uuid); + + *data = calloc_tspi(obj->tspContext, offset); + if (*data == NULL) { + LogError("malloc of %" PRIu64 " bytes failed.", offset); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + + offset = 0; + Trspi_LoadBlob_UUID(&offset, *data, rsakey->uuid); + *size = offset; + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_uuid(TSS_HKEY hKey, TSS_FLAG ps_type, TSS_UUID *uuid) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + memcpy(&rsakey->uuid, uuid, sizeof(TSS_UUID)); + + switch (ps_type) { + case TSS_PS_TYPE_SYSTEM: + obj->flags |= TSS_OBJ_FLAG_SYSTEM_PS; + obj->flags &= ~TSS_OBJ_FLAG_USER_PS; + break; + case TSS_PS_TYPE_USER: + obj->flags |= TSS_OBJ_FLAG_USER_PS; + obj->flags &= ~TSS_OBJ_FLAG_SYSTEM_PS; + break; + case TSS_PS_TYPE_NO: + default: + obj->flags &= ~TSS_OBJ_FLAG_USER_PS; + obj->flags &= ~TSS_OBJ_FLAG_SYSTEM_PS; + break; + } + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_set_tcs_handle(TSS_HKEY hKey, TCS_KEY_HANDLE tcsHandle) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + rsakey->tcsHandle = tcsHandle; + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_get_tcs_handle(TSS_HKEY hKey, TCS_KEY_HANDLE *tcsHandle) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (rsakey->tcsHandle) + *tcsHandle = rsakey->tcsHandle; + else + result = TSPERR(TSS_E_KEY_NOT_LOADED); + + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_tcpakey(TSS_HKEY hKey, UINT32 size, BYTE *data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + UINT64 offset; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + free_key_refs(&rsakey->key); + + offset = 0; + if ((result = UnloadBlob_TSS_KEY(&offset, data, &rsakey->key))) + goto done; + if (rsakey->key.hdr.key12.tag == TPM_TAG_KEY12) + rsakey->type = TSS_KEY_STRUCT_KEY12; + else + rsakey->type = TSS_KEY_STRUCT_KEY; + + if (rsakey->key.authDataUsage) + obj->flags |= TSS_OBJ_FLAG_USAGEAUTH; + else + obj->flags &= ~TSS_OBJ_FLAG_USAGEAUTH; + + if (rsakey->key.PCRInfoSize && rsakey->key.PCRInfo) { + offset = 0; + if (rsakey->type == TSS_KEY_STRUCT_KEY12) { + if ((result = Trspi_UnloadBlob_PCR_INFO_LONG(&offset, rsakey->key.PCRInfo, + &rsakey->pcrInfo.infolong))) + goto done; + } else { + if ((result = Trspi_UnloadBlob_PCR_INFO(&offset, rsakey->key.PCRInfo, + &rsakey->pcrInfo.info11))) + goto done; + } + } + + obj->flags |= TSS_OBJ_FLAG_KEY_SET; +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_pcr_digest(TSS_HKEY hKey, + TSS_FLAG pcrInfoType, + TSS_FLAG dir, + UINT32 *size, + BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + TPM_DIGEST *digest = NULL; + UINT64 offset; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (pcrInfoType != rsakey->pcrInfoType) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + switch (pcrInfoType) { + case TSS_PCRS_STRUCT_INFO: + if (dir == TSS_TSPATTRIB_KEYPCR_DIGEST_ATCREATION) + digest = &rsakey->pcrInfo.info11.digestAtCreation; + else if (dir == TSS_TSPATTRIB_KEYPCR_DIGEST_ATRELEASE) + digest = &rsakey->pcrInfo.info11.digestAtRelease; + else { + result = TSPERR(TSS_E_BAD_PARAMETER); + goto done; + } + break; + case TSS_PCRS_STRUCT_INFO_LONG: + if (dir == TSS_TSPATTRIB_KEYPCRLONG_DIGEST_ATCREATION) + digest = &rsakey->pcrInfo.infolong.digestAtCreation; + else if (dir == TSS_TSPATTRIB_KEYPCRLONG_DIGEST_ATRELEASE) + digest = &rsakey->pcrInfo.infolong.digestAtRelease; + else { + result = TSPERR(TSS_E_BAD_PARAMETER); + goto done; + } + break; + default: + result = TSPERR(TSS_E_INTERNAL_ERROR); + 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(&rsakey_list); + + return result; +} + + +TSS_RESULT +obj_rsakey_get_pcr_locality(TSS_HKEY hKey, TSS_FLAG dir, UINT32 *locality) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (rsakey->pcrInfoType == TSS_PCRS_STRUCT_INFO_LONG) { + if (dir == TSS_TSPATTRIB_KEYPCRLONG_LOCALITY_ATCREATION) + *locality = rsakey->pcrInfo.infolong.localityAtCreation; + else if (dir == TSS_TSPATTRIB_KEYPCRLONG_LOCALITY_ATRELEASE) + *locality = rsakey->pcrInfo.infolong.localityAtRelease; + else + result = TSPERR(TSS_E_BAD_PARAMETER); + } else + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_pcr_selection(TSS_HKEY hKey, + UINT32 pcrInfoType, + TSS_FLAG dir, + UINT32 *size, + BYTE **data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + UINT64 offset; + TPM_PCR_SELECTION *selection = NULL; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (pcrInfoType != rsakey->pcrInfoType) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + switch (pcrInfoType) { + case TSS_PCRS_STRUCT_INFO: + if (dir == TSS_TSPATTRIB_KEYPCR_SELECTION) + selection = &rsakey->pcrInfo.info11.pcrSelection; + else { + result = TSPERR(TSS_E_BAD_PARAMETER); + goto done; + } + break; + case TSS_PCRS_STRUCT_INFO_LONG: + if (dir == TSS_TSPATTRIB_KEYPCRLONG_CREATION_SELECTION) + selection = &rsakey->pcrInfo.infolong.creationPCRSelection; + else if (dir == TSS_TSPATTRIB_KEYPCRLONG_RELEASE_SELECTION) + selection = &rsakey->pcrInfo.infolong.releasePCRSelection; + else { + result = TSPERR(TSS_E_BAD_PARAMETER); + goto done; + } + break; + default: + result = TSPERR(TSS_E_INTERNAL_ERROR); + 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(&rsakey_list); + + return result; +} + +TSS_RESULT +rsakey_set_pubkey(struct tr_rsakey_obj *rsakey, BYTE *pubkey) +{ + TSS_RESULT result; + UINT64 offset = 0; + TPM_PUBKEY pub; + + if ((result = Trspi_UnloadBlob_PUBKEY(&offset, pubkey, &pub))) + return result; + + free(rsakey->key.pubKey.key); + free(rsakey->key.algorithmParms.parms); + + memcpy(&rsakey->key.pubKey, &pub.pubKey, sizeof(TPM_STORE_PUBKEY)); + memcpy(&rsakey->key.algorithmParms, &pub.algorithmParms, sizeof(TPM_KEY_PARMS)); + + return TSS_SUCCESS; +} + +/* Expect a TPM_PUBKEY as is explained in the portable data section of the spec */ +TSS_RESULT +obj_rsakey_set_pubkey(TSS_HKEY hKey, UINT32 force, BYTE *data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (!force && (obj->flags & TSS_OBJ_FLAG_KEY_SET)) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + result = rsakey_set_pubkey(rsakey, data); +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_srk_pubkey(BYTE *pubkey) +{ + struct tsp_object *obj; + struct obj_list *list = &rsakey_list; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result; + + MUTEX_LOCK(list->lock); + + for (obj = list->head; obj; obj = obj->next) { + rsakey = (struct tr_rsakey_obj *)obj->data; + + /* we found the SRK, set this data as its public key */ + if (rsakey->tcsHandle == TPM_KEYHND_SRK) { + result = rsakey_set_pubkey(rsakey, pubkey); + MUTEX_UNLOCK(list->lock); + return result; + } + } + + MUTEX_UNLOCK(list->lock); + + return TSPERR(TSS_E_INVALID_HANDLE); +} + +TSS_RESULT +obj_rsakey_set_privkey(TSS_HKEY hKey, UINT32 force, UINT32 size, BYTE *data) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + void *to_free; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (!force && (obj->flags & TSS_OBJ_FLAG_KEY_SET)) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + + to_free = rsakey->key.encData; + + rsakey->key.encData = calloc(1, size); + if (rsakey->key.encData == NULL) { + rsakey->key.encData = to_free; // restore + LogError("malloc of %u bytes failed.", size); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + + free(to_free); + rsakey->key.encSize = size; + memcpy(rsakey->key.encData, data, size); +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_pcr_data(TSS_HKEY hKey, TSS_HPCRS hPcrComposite) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + UINT32 pcrType, pcrSize; + BYTE *pcrInfo; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + + /* passing in a pcrType of TSS_PCRS_STRUCT_DEFAULT will tell the pcr routine to create + * a structure matching the type of the hPcrComposite object */ + pcrType = TSS_PCRS_STRUCT_DEFAULT; + if ((result = obj_pcrs_create_info_type(hPcrComposite, &pcrType, &pcrSize, &pcrInfo))) + goto done; + + rsakey->key.PCRInfo = pcrInfo; + rsakey->key.PCRInfoSize = pcrSize; +done: + obj_list_put(&rsakey_list); + + return result; +} + +void +__tspi_rsakey_free(void *data) +{ + struct tr_rsakey_obj *rsakey = (struct tr_rsakey_obj *)data; + + free(rsakey->key.algorithmParms.parms); + free(rsakey->key.encData); + free(rsakey->key.PCRInfo); + free(rsakey->key.pubKey.key); + free(rsakey); +} + +/* Remove an individual rsakey object from the rsakey list with handle + * equal to hObject. Clean up the TSP's key handle table. */ +TSS_RESULT +obj_rsakey_remove(TSS_HOBJECT hObject, TSS_HCONTEXT tspContext) +{ + TSS_RESULT result; + + if ((result = obj_list_remove(&rsakey_list, &__tspi_rsakey_free, hObject, tspContext))) + return result; + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_get_by_pub(UINT32 pub_size, BYTE *pub, TSS_HKEY *hKey) +{ + struct obj_list *list = &rsakey_list; + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + MUTEX_LOCK(list->lock); + + for (obj = list->head; obj; obj = obj->next) { + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (rsakey->key.pubKey.keyLength == pub_size && + !memcmp(&rsakey->key.pubKey.key, pub, pub_size)) { + *hKey = obj->handle; + goto done; + } + } + + *hKey = 0; +done: + MUTEX_UNLOCK(list->lock); + + return result; +} + +TSS_RESULT +obj_rsakey_get_by_uuid(TSS_UUID *uuid, TSS_HKEY *hKey) +{ + struct obj_list *list = &rsakey_list; + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + MUTEX_LOCK(list->lock); + + for (obj = list->head; obj; obj = obj->next) { + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (!memcmp(&rsakey->uuid, uuid, sizeof(TSS_UUID))) { + *hKey = obj->handle; + goto done; + } + } + + result = TSPERR(TSS_E_PS_KEY_NOTFOUND); +done: + MUTEX_UNLOCK(list->lock); + + return result; +} + +void +obj_rsakey_remove_policy_refs(TSS_HPOLICY hPolicy, TSS_HCONTEXT tspContext) +{ + struct tsp_object *obj; + struct obj_list *list = &rsakey_list; + struct tr_rsakey_obj *rsakey; + + MUTEX_LOCK(list->lock); + + for (obj = list->head; obj; obj = obj->next) { + if (obj->tspContext != tspContext) + continue; + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (rsakey->usagePolicy == hPolicy) + rsakey->usagePolicy = NULL_HPOLICY; + + if (rsakey->migPolicy == hPolicy) + rsakey->migPolicy = NULL_HPOLICY; + } + + MUTEX_UNLOCK(list->lock); +} + +#if 0 +TSS_RESULT +obj_rsakey_get_transport_attribs(TSS_HKEY hKey, TCS_KEY_HANDLE *hTCSKey, TPM_DIGEST *pubDigest) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result; + Trspi_HashCtx hashCtx; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + *hTCSKey = rsakey->tcsHandle; + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_STORE_PUBKEY(&hashCtx, &rsakey->key.pubKey); + result |= Trspi_HashFinal(&hashCtx, pubDigest->digest); + + obj_list_put(&rsakey_list); + + return result; +} +#endif + +#ifdef TSS_BUILD_CMK +TSS_BOOL +obj_rsakey_is_cmk(TSS_HKEY hKey) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_BOOL answer = FALSE; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return answer; + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (rsakey->type != TSS_KEY_STRUCT_KEY) { + if (rsakey->key.keyFlags & TPM_MIGRATEAUTHORITY) + answer = TRUE; + } + + obj_list_put(&rsakey_list); + + return answer; +} + +TSS_RESULT +obj_rsakey_set_cmk(TSS_HKEY hKey, UINT32 cmk) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + if (obj->flags & TSS_OBJ_FLAG_KEY_SET) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + rsakey = (struct tr_rsakey_obj *)obj->data; + if (rsakey->type == TSS_KEY_STRUCT_KEY) { + result = TSPERR(TSS_E_INVALID_OBJ_ACCESS); + goto done; + } + + if (cmk) + rsakey->key.keyFlags |= TPM_MIGRATEAUTHORITY; + else + rsakey->key.keyFlags &= (~TPM_MIGRATEAUTHORITY); + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_msa_approval(TSS_HKEY hKey, UINT32 blobSize, BYTE *blob) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (blobSize != sizeof(rsakey->msaApproval.digest)) { + result = TSPERR(TSS_E_BAD_PARAMETER); + goto done; + } + memcpy(rsakey->msaApproval.digest, blob, sizeof(rsakey->msaApproval.digest)); + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_msa_approval(TSS_HKEY hKey, UINT32 *blobSize, BYTE **blob) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if ((*blob = calloc_tspi(obj->tspContext, sizeof(rsakey->msaApproval.digest))) == NULL) { + LogError("malloc of %zd bytes failed.", sizeof(rsakey->msaApproval.digest)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + memcpy(*blob, rsakey->msaApproval.digest, sizeof(rsakey->msaApproval.digest)); + *blobSize = sizeof(rsakey->msaApproval.digest); + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_set_msa_digest(TSS_HKEY hKey, UINT32 blobSize, BYTE *blob) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (blobSize != sizeof(rsakey->msaDigest.digest)) { + result = TSPERR(TSS_E_BAD_PARAMETER); + goto done; + } + memcpy(rsakey->msaDigest.digest, blob, sizeof(rsakey->msaDigest.digest)); + +done: + obj_list_put(&rsakey_list); + + return result; +} + +TSS_RESULT +obj_rsakey_get_msa_digest(TSS_HKEY hKey, UINT32 *blobSize, BYTE **blob) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if ((*blob = calloc_tspi(obj->tspContext, sizeof(rsakey->msaDigest.digest))) == NULL) { + LogError("malloc of %zd bytes failed.", sizeof(rsakey->msaDigest.digest)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto done; + } + memcpy(*blob, rsakey->msaDigest.digest, sizeof(rsakey->msaDigest.digest)); + *blobSize = sizeof(rsakey->msaDigest.digest); + +done: + obj_list_put(&rsakey_list); + + return result; +} +#endif + +TSS_RESULT +obj_rsakey_get_ownerevict(TSS_HKEY hKey, UINT32 *value) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + *value = rsakey->flags & TSS_RSAKEY_FLAG_OWNEREVICT; + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} + +TSS_RESULT +obj_rsakey_set_ownerevict(TSS_HKEY hKey, TSS_BOOL value) +{ + struct tsp_object *obj; + struct tr_rsakey_obj *rsakey; + + if ((obj = obj_list_get_obj(&rsakey_list, hKey)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + rsakey = (struct tr_rsakey_obj *)obj->data; + + if (value) + rsakey->flags |= TSS_RSAKEY_FLAG_OWNEREVICT; + else + rsakey->flags &= ~TSS_RSAKEY_FLAG_OWNEREVICT; + + obj_list_put(&rsakey_list); + + return TSS_SUCCESS; +} |