#ifndef libhis_getnvdata_hpp #define libhis_getnvdata_hpp #ifdef WINDOWS #include "tspi.h" #include "tss_error.h" #include "tss_defines.h" #endif #ifdef LINUX #include #include #include #endif #include "libhis_exception.hpp" #include class libhis_getnvdata { public: libhis_getnvdata() { //set defaults nvstore_index = 0; //create a context object result = Tspi_Context_Create(&hcontext); if(result != TSS_SUCCESS) throw libhis_exception("Create Conntext", result); //Create TPM policy result = Tspi_Context_CreateObject(hcontext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hpolicy_tpm); if(result != TSS_SUCCESS) throw libhis_exception("Create TPM Policy", result); //Create NVSTore object result = Tspi_Context_CreateObject(hcontext, TSS_OBJECT_TYPE_NV, 0, &hnvstore); if(result != TSS_SUCCESS) throw libhis_exception("Create NVStore object", result); } void getnvdata( unsigned char *auth_tpm_value, unsigned long auth_tpm_size, bool auth_tpm_sha1, unsigned long nv_index, unsigned char *&nv_value, unsigned long &nv_size) { //set up the index value bool nv_platform = false; if(nv_index == 0) nvstore_index = TPM_NV_INDEX_EKCert; else if(nv_index == 1) nvstore_index = TPM_NV_INDEX_TPM_CC; else if(nv_index == 2) { nvstore_index = TPM_NV_INDEX_PlatformCert; nv_platform = true; } else if(nv_index == 3) { nvstore_index = TPM_NV_INDEX_Platform_CC; nv_platform = true; } else nvstore_index = nv_index; //establish a session result = Tspi_Context_Connect(hcontext, 0); if(result != TSS_SUCCESS) throw libhis_exception("Connect Context", result); //get the TPM object result = Tspi_Context_GetTpmObject(hcontext, &htpm); if(result != TSS_SUCCESS) throw libhis_exception("Get TPM Object", result); //set up TPM auth if(auth_tpm_sha1) { result = Tspi_Policy_SetSecret(hpolicy_tpm, TSS_SECRET_MODE_SHA1, auth_tpm_size, auth_tpm_value); if(result != TSS_SUCCESS) throw libhis_exception("Set TPM Secret SHA1", result); } else { result = Tspi_Policy_SetSecret(hpolicy_tpm, TSS_SECRET_MODE_PLAIN, auth_tpm_size, auth_tpm_value); if(result != TSS_SUCCESS) throw libhis_exception("Set TPM Secret Plain", result); } //assign the TPM auth to the TPM result = Tspi_Policy_AssignToObject(hpolicy_tpm, htpm); if(result != TSS_SUCCESS) throw libhis_exception("Assign TPM Secret to TPM", result); // Check if the NV area is locked. Must be performed after TPM AUTH. TSS_BOOL nvLocked; result = Tspi_TPM_GetStatus(htpm, TSS_TPMSTATUS_NV_LOCK, &nvLocked); if (result != TSS_SUCCESS) throw libhis_exception("Check TPM NV Lock", result); // If locked, set the bit in the index to retrieve the requested data. else, unset that bit. nvstore_index = ((nvLocked == TRUE) && !nv_platform) ? nvstore_index + TSS_NV_DEFINED : nvstore_index & ~TSS_NV_DEFINED; //assign the TPM auth to the NVStore result = Tspi_Policy_AssignToObject(hpolicy_tpm, hnvstore); if(result != TSS_SUCCESS) throw libhis_exception("Assign TPM Secret to NVStore", result); //force NVData to be readable by the owner only result = Tspi_SetAttribUint32(hnvstore, TSS_TSPATTRIB_NV_PERMISSIONS, 0, TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE); if(result != TSS_SUCCESS) throw libhis_exception("Requier owner auth on NVStore read/write", result); //set the read address result = Tspi_SetAttribUint32(hnvstore, TSS_TSPATTRIB_NV_INDEX, 0, nvstore_index); if(result != TSS_SUCCESS) throw libhis_exception("Set NVStore index", result); //get the size UINT32 size = 0; BYTE *value = 0; #ifdef WINDOWS //read the size of the data at the index result = Tspi_GetAttribUint32(hnvstore, TSS_TSPATTRIB_NV_DATASIZE, 0, &size); if(result != TSS_SUCCESS) throw libhis_exception("WINDOWS: Get size of NVStore object", result); #endif #ifdef LINUX UINT32 ulResultLen; // stores the length of the data returned by GetCapability // Retrieves a TPM_NV_DATA_PUBLIC structure that indicates the values for the specified NV area. // The NV area is identified by the nvstore_index. result = Tspi_TPM_GetCapability(htpm, TSS_TPMCAP_NV_INDEX, sizeof(UINT32), (BYTE *)&nvstore_index, &ulResultLen, &value); if(result == TSS_SUCCESS) { UINT64 off = 0; // value which is a BYTE* must be converted into its TSS Data Structure TPM_NV_DATA_PUBLIC *nvDataPublicStruct = new TPM_NV_DATA_PUBLIC(); // Trousers converts the data blob into the struct result = Trspi_UnloadBlob_NV_DATA_PUBLIC(&off, value, nvDataPublicStruct); if(result != TSS_SUCCESS) { delete nvDataPublicStruct; throw libhis_exception("LINUX: Problems converting data blob to NV Public Data object", result); } // Save off the size of the data stored in the NV area. size = nvDataPublicStruct->dataSize; // Free the memory. delete nvDataPublicStruct; } #endif if(size > 0) { //read the nvdata result = Tspi_NV_ReadValue(hnvstore, 0, &size, &value); if(result != TSS_SUCCESS) throw libhis_exception("Read NVStore space", result); //copy out the values nv_size = size; nv_value = new unsigned char[size]; for(unsigned long i = 0; i < size; i++) nv_value[i] = value[i]; } //cleanup result = Tspi_Context_FreeMemory(hcontext, value); // I'm not sure if this error message is useful. But it was stopping the process unnecessarily. //if(result != TSS_SUCCESS) throw libhis_exception("Clean memory", result); } ~libhis_getnvdata() { //clean up NVStoer result = Tspi_Context_CloseObject(hcontext, hnvstore); if(result != TSS_SUCCESS) throw libhis_exception("Close NVStore object", result); //clean up TPM policy result = Tspi_Context_CloseObject(hcontext, hpolicy_tpm); if(result != TSS_SUCCESS) throw libhis_exception("Close TPM Policy", result); //close context result = Tspi_Context_Close(hcontext); if(result != TSS_SUCCESS) throw libhis_exception("Close Context", result); } private: TSS_RESULT result; TSS_HCONTEXT hcontext; TSS_HTPM htpm; TSS_HPOLICY hpolicy_tpm; TSS_HNVSTORE hnvstore; UINT32 nvstore_index; }; #endif