How to code your first TPM program
In this document, we will see how to write a simple program which uses a TPM.
I - Initialization
TSPI is the high level library for use TPM. Firstly, we init the TSPI context and after destroy it.
Print error is a simple function to print error message associated with the number error code.TSS_HCONTEXT hContext; TSS_RESULT result; result = Tspi_Context_Create( &hContext ); if ( result != TSS_SUCCESS ) { print_error( "Tspi_Context_Create ", result ); exit( result ); } Tspi_Context_Close( hContext );
Create the TPM object.void print_error(char *function, int result) { printf("\t0 FAIL : %s returned (%d) %s\n", function, result, (char*)Trspi_Error_String( result)); }
After this, you must use Tspi_Context_FreeMemory to clean the memory. Whitout error checking:TSS_HTPM hTPM; Tspi_Context_GetTpmObject(hContext, &hTPM);
II - Load and create keys and set policiesTSS_HCONTEXT hContext; TSS_HTPM hTPM; Tspi_Context_Create( &hContext ); Tspi_Context_GetTpmObject(hContext, &hTPM); // Use TPM Tspi_Context_FreeMemory( hContext, NULL ); Tspi_Context_Close( hContext );
Firstly, we load the Storage Root Key (SRK) which is the root key of all others.
And we set his secret passkey. The secret passkey is the key you entered when you run the tpm_takeownership command.TSS_HKEY hSRK; Tspi_Context_LoadKeyByUUID( hContext, TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSRK );
After this, we create the RSA key we will use the bind the data. This key is wrapped by the SRK.TSS_HPOLICY hSrkPolicy; Tspi_GetPolicyObject( hSRK, TSS_POLICY_USAGE, &hSrkPolicy ); Tspi_Policy_SetSecret( hSrkPolicy, TESTSUITE_SRK_SECRET_MODE, TESTSUITE_SRK_SECRET_LEN, (BYTE*)srk_secret_passkey);
III - Bind the dataTSS_HKEY hKey; Tspi_Context_CreateObject( hContext, TSS_OBJECT_TYPE_RSAKEY, TSS_KEY_SIZE_2048 | TSS_KEY_TYPE_BIND, &hKey ); Tspi_Key_CreateKey( hKey, hSRK, 0); Tspi_Key_LoadKey(hKey, hSRK);
We encrypt the data using the bind function:
You got encrypted data in the encdata variable; this data has the size of encdata_size variable. You can decrypt this blob using the unbind function.TSS_HENCDATA hEncData; uint32_t encdata_size; BYTE *encdata; Tspi_Context_CreateObject( hContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData ); Tspi_Data_Bind( hEncData, hKey, data_size, data ); Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, &encdata_size, &encdata);
pulDataLength: Receives the length of the data at the parameter prgbUnboundData.Tspi_Data_Unbind(hEncData, hKey, &pulDataLength, &prgbUnboundData);
prgbUnboundData: Receives a pointer to a buffer containing the plaintext data.
IV - Code
int main() { TSS_HCONTEXT hContext; TSS_RESULT result; TSS_HTPM hTPM; TSS_HKEY hSRK; TSS_HPOLICY hSrkPolicy; TSS_HKEY hKey; TSS_HENCDATA hEncData; uint32_t encdata_size; BYTE *encdata; char *data = "This text is unencrypted\n"; int pulDataLength int prgbUnboundData; Tspi_Context_Create( &hContext ); Tspi_Context_CreateObject( hContext, TSS_OBJECT_TYPE_RSAKEY, TSS_KEY_SIZE_2048 | TSS_KEY_TYPE_BIND, &hKey ); Tspi_Context_GetTpmObject(hContext, &hTPM); Tspi_Context_LoadKeyByUUID( hContext, TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSRK ); Tspi_GetPolicyObject( hSRK, TSS_POLICY_USAGE, &hSrkPolicy ); Tspi_Policy_SetSecret( hSrkPolicy, TESTSUITE_SRK_SECRET_MODE, TESTSUITE_SRK_SECRET_LEN, (BYTE*)srk_secret_passkey); Tspi_Key_CreateKey( hKey, hSRK, 0); Tspi_Key_LoadKey(hKey, hSRK); Tspi_Context_CreateObject( hContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData ); printf(data); Tspi_Data_Bind( hEncData, hKey, strlen(data) + 1, (BYTE*)data ); Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, &encdata_size, &encdata); hex_print(encdata, encdata_size); Tspi_Data_Unbind(hEncData, hKey, &pulDataLength, &prgbUnboundData) printf(prgbUnboundData); Tspi_Context_FreeMemory( hContext, NULL ); Tspi_Context_Close( hContext ); } void hex_print(char* data, int length) { int ptr = 0; for(;ptr < length;ptr++) { printf("0x%02x ",(unsigned char)*(data+ptr)); } printf("\n"); }