diff options
Diffstat (limited to 'src/tspi/tspi_changeauth.c')
-rw-r--r-- | src/tspi/tspi_changeauth.c | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/src/tspi/tspi_changeauth.c b/src/tspi/tspi_changeauth.c new file mode 100644 index 0000000..1d6d8f1 --- /dev/null +++ b/src/tspi/tspi_changeauth.c @@ -0,0 +1,434 @@ + +/* + * 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 <time.h> +#include <errno.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 "obj.h" +#include "authsess.h" + +TSS_RESULT +Tspi_ChangeAuth(TSS_HOBJECT hObjectToChange, /* in */ + TSS_HOBJECT hParentObject, /* in */ + TSS_HPOLICY hNewPolicy) /* in */ +{ + UINT32 keyToChangeHandle; + TSS_RESULT result; + TSS_HCONTEXT tspContext; + + if ((result = obj_policy_get_tsp_context(hNewPolicy, &tspContext))) + return result; + + /* if the object to change is the TPM object, then the parent should + * be NULL. If the object to change is not the TPM, then the parent + * object must be either an rsakey or the TPM */ + if (obj_is_tpm(hObjectToChange)) { + if (hParentObject != NULL_HOBJECT) + return TSPERR(TSS_E_BAD_PARAMETER); + } else if (!obj_is_rsakey(hParentObject) && !obj_is_tpm(hParentObject)) { + return TSPERR(TSS_E_INVALID_HANDLE); + } + + if (obj_is_tpm(hObjectToChange)) { + if ((result = changeauth_owner(tspContext, hObjectToChange, NULL_HTPM, hNewPolicy))) + return result; + } else if (obj_is_rsakey(hObjectToChange)) { + if ((result = obj_rsakey_get_tcs_handle(hObjectToChange, &keyToChangeHandle))) + return result; + + if (keyToChangeHandle == TPM_KEYHND_SRK) { + if ((result = changeauth_srk(tspContext, hObjectToChange, hParentObject, + hNewPolicy))) + return result; + } else { + if ((result = changeauth_key(tspContext, hObjectToChange, hParentObject, + hNewPolicy))) + return result; + } + } else if (obj_is_encdata(hObjectToChange)) { + if ((result = changeauth_encdata(tspContext, hObjectToChange, hParentObject, + hNewPolicy))) + return result; + } else if (obj_is_policy(hObjectToChange) || obj_is_hash(hObjectToChange) || + obj_is_pcrs(hObjectToChange) || obj_is_context(hObjectToChange)) { + return TSPERR(TSS_E_BAD_PARAMETER); + } else { + return TSPERR(TSS_E_INVALID_HANDLE); + } + + if ((result = obj_policy_set_type(hNewPolicy, TSS_POLICY_USAGE))) + return result; + + return Tspi_Policy_AssignToObject(hNewPolicy, hObjectToChange); + +} + +TSS_RESULT +Tspi_ChangeAuthAsym(TSS_HOBJECT hObjectToChange, /* in */ + TSS_HOBJECT hParentObject, /* in */ + TSS_HKEY hIdentKey, /* in */ + TSS_HPOLICY hNewPolicy) /* in */ +{ +#if 0 + TPM_AUTH auth; + UINT64 offset; + BYTE hashBlob[0x1000]; + TCPA_DIGEST digest; + TCPA_RESULT result; + UINT32 keyHandle; + UINT32 idHandle; + TSS_HPOLICY hPolicy; + TSS_HPOLICY hParentPolicy; + UINT32 keyToChangeHandle; + TCPA_NONCE antiReplay; + UINT32 bytesRequested; + UINT64 tempSize; + BYTE tempKey[512]; + TCPA_KEY_PARMS keyParms; + /* XXX Wow... */ + BYTE ephParms[] = { 0, 0, 0x08, 0, 0, 0, 0, 0x02, 0, 0, 0, 0 }; + UINT32 KeySizeOut; + BYTE *KeyDataOut; + UINT32 CertifyInfoSize; + BYTE *CertifyInfo; + UINT32 sigSize; + BYTE *sig; + UINT32 ephHandle; + TPM_CHANGEAUTH_VALIDATE caValidate; + TCPA_SECRET newSecret, oldSecret; + BYTE seed[20]; + BYTE a1[256]; + UINT32 a1Size; + TSS_KEY ephemeralKey; + TCPA_DIGEST newAuthLink; + UINT32 encObjectSize; + BYTE *encObject = NULL; + UINT32 encDataSizeOut; + BYTE *encDataOut; + TCPA_NONCE saltNonce; + TCPA_DIGEST changeProof; + TSS_HPOLICY hOldPolicy; + UINT32 caValidSize; + UINT32 keyObjectSize; + BYTE *keyObject; + TSS_KEY keyContainer; + TCPA_STORED_DATA dataContainer; + BYTE *dataObject; + UINT32 dataObjectSize; + UINT16 entityType; + TSS_BOOL useAuth = TRUE; // XXX + TPM_AUTH *pAuth; + BYTE dataBlob[1024]; + TSS_HCONTEXT tspContext; + Trspi_HashCtx hashCtx; + + if ((result = obj_policy_get_tsp_context(hNewPolicy, &tspContext))) + return result; + + /* grab all of the needed handles */ + if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &idHandle))) + return result; + + /* get the secret for the parent */ + if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE, &hPolicy, &useAuth))) + return result; + + /* get the parent secret */ + if ((result = Tspi_GetPolicyObject(hParentObject, TSS_POLICY_USAGE, &hParentPolicy))) + return result; + + if (!obj_is_rsakey(hParentObject) && !obj_is_tpm(hParentObject)) + return TSPERR(TSS_E_INVALID_HANDLE); + + /* get the keyObject */ + if ((result = obj_rsakey_get_tcs_handle(hParentObject, &keyHandle))) + return result; + + if (obj_is_rsakey(hObjectToChange) || + obj_is_encdata(hObjectToChange)) { + + if ((result = obj_rsakey_get_tcs_handle(hObjectToChange, &keyToChangeHandle))) + return result; + + if (keyToChangeHandle == TPM_KEYHND_SRK) { + return TSPERR(TSS_E_BAD_PARAMETER); + } else { + /* generate container for ephemeral key */ + keyParms.algorithmID = 1; /* rsa */ + keyParms.encScheme = 3; + keyParms.sigScheme = 1; + keyParms.parmSize = 12; + keyParms.parms = malloc(12); + if (keyParms.parms == NULL) { + LogError("malloc of %d bytes failed.", 12); + return TSPERR(TSS_E_OUTOFMEMORY); + } + memcpy(keyParms.parms, ephParms, 12); + + tempSize = 0; + Trspi_LoadBlob_KEY_PARMS(&tempSize, tempKey, &keyParms); + + /* generate antireplay nonce */ + bytesRequested = 20; + if ((result = get_local_random(tspContext, FALSE, bytesRequested, + (BYTE **)antiReplay.nonce))) + return result; + + /* caluculate auth data */ + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ChangeAuthAsymStart); + result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN, + antiReplay.nonce); + result |= Trspi_Hash_KEY_PARMS(&hashCtx, &keyParms); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + return result; + + if (useAuth) { + if ((result = secret_PerformAuth_OIAP(hIdentKey, + TPM_ORD_ChangeAuthAsymStart, + hPolicy, FALSE, &digest, + &auth))) + return result; + + pAuth = &auth; + } else { + pAuth = NULL; + } + + if ((result = TCSP_ChangeAuthAsymStart(tspContext, idHandle, antiReplay, + tempSize, tempKey, pAuth, + &KeySizeOut, &KeyDataOut, + &CertifyInfoSize, &CertifyInfo, + &sigSize, &sig, &ephHandle))) + return result; + + /* Validate the Auth's */ + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, result); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ChangeAuthAsymStart); + result |= Trspi_HashUpdate(&hashCtx, CertifyInfoSize, CertifyInfo); + result |= Trspi_Hash_UINT32(&hashCtx, sigSize); + result |= Trspi_HashUpdate(&hashCtx, sigSize, sig); + result |= Trspi_Hash_UINT32(&hashCtx, ephHandle); + result |= Trspi_HashUpdate(&hashCtx, KeySizeOut, KeyDataOut); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + return result; + + if (useAuth) { + if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, + &auth))) + return result; + } + + /* generate random data for asymfinish */ + if ((result = get_local_random(tspContext, FALSE, bytesRequested, + (BYTE **)&caValidate.n1.nonce))) + return result; + + if ((result = get_local_random(tspContext, FALSE, bytesRequested, + (BYTE **)&antiReplay.nonce))) + return result; + + if ((result = get_local_random(tspContext, FALSE, bytesRequested, + (BYTE **)&seed))) + return result; + + if ((result = Tspi_GetPolicyObject(hObjectToChange, TSS_POLICY_USAGE, + &hOldPolicy))) + return result; + + if ((result = obj_policy_get_secret(hNewPolicy, TR_SECRET_CTX_NEW, + &newSecret))) + return result; + if ((result = obj_policy_get_secret(hOldPolicy, TR_SECRET_CTX_NOT_NEW, + &oldSecret))) + return result; + + /* Encrypt the ChangeAuthValidate structure with the + * ephemeral key */ + + memcpy(caValidate.newAuthSecret.authdata, newSecret.authdata, 20); + + offset = 0; + Trspi_LoadBlob_CHANGEAUTH_VALIDATE(&offset, hashBlob, &caValidate); + caValidSize = offset; + + offset = 0; + if ((result = UnloadBlob_TSS_KEY(&offset, KeyDataOut, &ephemeralKey))) + return result; + + Trspi_RSA_Encrypt(hashBlob, caValidSize, a1, &a1Size, + ephemeralKey.pubKey.key, + ephemeralKey.pubKey.keyLength); + + free_key_refs(&ephemeralKey); + + Trspi_HMAC(TSS_HASH_SHA1, 20, oldSecret.authdata, + 20, newSecret.authdata, + newAuthLink.digest); + + if (obj_is_rsakey(hObjectToChange)) { + if ((result = obj_rsakey_get_blob(hObjectToChange, + &keyObjectSize, &keyObject))) + return result; + + memset(&keyContainer, 0, sizeof(TSS_KEY)); + + offset = 0; + if ((result = UnloadBlob_TSS_KEY(&offset, + keyObject, + &keyContainer))) + return result; + + encObjectSize = keyContainer.encSize; + encObject = malloc(encObjectSize); + if (encObject == NULL) { + LogError("malloc of %d bytes failed.", + encObjectSize); + free_key_refs(&keyContainer); + return TSPERR(TSS_E_OUTOFMEMORY); + } + memcpy(encObject, keyContainer.encData, + encObjectSize); + entityType = TCPA_ET_KEY; + } else { + if ((result = obj_encdata_get_data(hObjectToChange, + &dataObjectSize, &dataObject))) + return result; + + offset = 0; + if ((result = Trspi_UnloadBlob_STORED_DATA(&offset, + dataObject, + &dataContainer))) + return result; + + encObjectSize = dataContainer.encDataSize; + encObject = malloc(encObjectSize); + if (encObject == NULL) { + LogError("malloc of %d bytes failed.", encObjectSize); + free(dataContainer.sealInfo); + free(dataContainer.encData); + return TSPERR(TSS_E_OUTOFMEMORY); + } + memcpy(encObject, dataContainer.encData, + encObjectSize); + entityType = TCPA_ET_DATA; + } + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ChangeAuthAsymFinish); + result |= Trspi_Hash_UINT16(&hashCtx, entityType); + result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN, + newAuthLink.digest); + result |= Trspi_Hash_UINT32(&hashCtx, a1Size); + result |= Trspi_HashUpdate(&hashCtx, a1Size, a1); + result |= Trspi_Hash_UINT32(&hashCtx, encObjectSize); + result |= Trspi_HashUpdate(&hashCtx, encObjectSize, encObject); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + return result; + + if (useAuth) { + if ((result = secret_PerformAuth_OIAP(hParentObject, + TPM_ORD_ChangeAuthAsymFinish, + hParentPolicy, FALSE, + &digest, &auth))) { + free(encObject); + free_key_refs(&keyContainer); + return result; + } + pAuth = &auth; + } else { + pAuth = NULL; + } + + if ((result = TCSP_ChangeAuthAsymFinish(tspContext, keyHandle, ephHandle, + entityType, newAuthLink, a1Size, a1, + encObjectSize, encObject, pAuth, + &encDataSizeOut, &encDataOut, + &saltNonce, &changeProof))) { + free_key_refs(&keyContainer); + free(encObject); + return result; + } + + /* --- Validate the Auth's */ + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, result); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ChangeAuthAsymFinish); + result |= Trspi_Hash_UINT32(&hashCtx, encDataSizeOut); + result |= Trspi_HashUpdate(&hashCtx, encDataSizeOut, encDataOut); + result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN, + saltNonce.nonce); + result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN, + changeProof.digest); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + return result; + + if (useAuth) { + if ((result = obj_policy_validate_auth_oiap(hParentPolicy, + &digest, + &auth))) { + free_key_refs(&keyContainer); + free(encObject); + return result; + } + } + + if (entityType == TCPA_ET_KEY || + entityType == TCPA_ET_KEYHANDLE) { + memcpy(keyContainer.encData, encDataOut, encDataSizeOut); + keyContainer.encSize = encDataSizeOut; + + offset = 0; + LoadBlob_TSS_KEY(&offset, keyObject, &keyContainer); + free_key_refs(&keyContainer); + if ((result = obj_rsakey_set_tcpakey(hObjectToChange, offset, + keyObject))) { + free(encObject); + return result; + } + } + + if (entityType == TCPA_ET_DATA) { + memcpy(dataContainer.encData, encDataOut, + encDataSizeOut); + dataContainer.encDataSize = encDataSizeOut; + + offset = 0; + Trspi_LoadBlob_STORED_DATA(&offset, dataBlob, + &dataContainer); + free(dataContainer.sealInfo); + free(dataContainer.encData); + obj_encdata_set_data(hObjectToChange, + offset, dataBlob); + } + } + } else + return TSPERR(TSS_E_BAD_PARAMETER); + + free(encObject); + + return Tspi_Policy_AssignToObject(hNewPolicy, hObjectToChange); +#else + return TSPERR(TSS_E_NOTIMPL); +#endif +} + |