/*
* The Initial Developer of the Original Code is International
* Business Machines Corporation. Portions created by IBM
* Corporation are Copyright (C) 2005 International Business
* Machines Corporation. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the Common Public License as published by
* IBM Corporation; either version 1 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Common Public License for more details.
*
* You should have received a copy of the Common Public License
* along with this program; if not, a copy can be viewed at
* http://www.opensource.org/licenses/cpl1.0.php.
*/
#include "tpm_tspi.h"
TSS_UUID SRK_UUID = TSS_UUID_SRK;
extern TSS_HCONTEXT hContext;
const char *mapUnknown = "Unknown";
const char *usageSigning = "Signing";
const char *usageStorage = "Storage";
const char *usageIdentity = "Identity";
const char *usageAuthChange = "AuthChange";
const char *usageBind = "Bind";
const char *usageLegacy = "Legacy";
const int flagMax = 7;
const char *flagMap[] = {
"!VOLATILE, !MIGRATABLE, !REDIRECTION",
"!VOLATILE, !MIGRATABLE, REDIRECTION",
"!VOLATILE, MIGRATABLE, !REDIRECTION",
"!VOLATILE, MIGRATABLE, REDIRECTION",
" VOLATILE, !MIGRATABLE, !REDIRECTION",
" VOLATILE, !MIGRATABLE, REDIRECTION",
" VOLATILE, MIGRATABLE, !REDIRECTION",
" VOLATILE, MIGRATABLE, REDIRECTION",
};
const char *authUsageNever = "Never";
const char *authUsageAlways = "Always";
const char *algRsa = "RSA";
const char *algDes = "DES";
const char *alg3Des = "3DES";
const char *algSha = "SHA";
const char *algHmac = "HMAC";
const char *algAes = "AES";
const char *encNone = "None";
const char *encRsaPkcs15 = "RSAESPKCSv15";
const char *encRsaOaepSha1Mgf1 = "RSAESOAEP_SHA1_MGF1";
const char *sigNone = "None";
const char *sigRsaPkcs15Sha1 = "RSASSAPKCS1v15_SHA1";
const char *sigRsaPkcs15Der = "RSASSAPKCS1v15_DER";
const char *displayKeyUsageMap(UINT32 a_uiData)
{
switch (a_uiData) {
case TSS_KEYUSAGE_SIGN:
return usageSigning;
case TSS_KEYUSAGE_STORAGE:
return usageStorage;
case TSS_KEYUSAGE_IDENTITY:
return usageIdentity;
case TSS_KEYUSAGE_AUTHCHANGE:
return usageAuthChange;
case TSS_KEYUSAGE_BIND:
return usageBind;
case TSS_KEYUSAGE_LEGACY:
return usageLegacy;
}
return mapUnknown;
}
const char *displayKeyFlagsMap(UINT32 a_uiFlags)
{
int iPos = a_uiFlags & flagMax;
return flagMap[iPos];
}
const char *displayAuthUsageMap(UINT32 a_uiData)
{
switch (a_uiData) {
case TPM_AUTH_NEVER:
return authUsageNever;
case TPM_AUTH_ALWAYS:
return authUsageAlways;
}
return mapUnknown;
}
const char *displayAlgorithmMap(UINT32 a_uiData)
{
switch (a_uiData) {
case TSS_ALG_RSA:
return algRsa;
case TSS_ALG_DES:
return algDes;
case TSS_ALG_3DES:
return alg3Des;
case TSS_ALG_SHA:
return algSha;
case TSS_ALG_HMAC:
return algHmac;
case TSS_ALG_AES:
return algAes;
}
return mapUnknown;
}
const char *displayEncSchemeMap(UINT32 a_uiData)
{
switch (a_uiData) {
case TSS_ES_NONE:
return encNone;
case TSS_ES_RSAESPKCSV15:
return encRsaPkcs15;
case TSS_ES_RSAESOAEP_SHA1_MGF1:
return encRsaOaepSha1Mgf1;
}
return mapUnknown;
}
const char *displaySigSchemeMap(UINT32 a_uiData)
{
switch (a_uiData) {
case TSS_SS_NONE:
return sigNone;
case TSS_SS_RSASSAPKCS1V15_SHA1:
return sigRsaPkcs15Sha1;
case TSS_SS_RSASSAPKCS1V15_DER:
return sigRsaPkcs15Der;
}
return mapUnknown;
}
TSS_RESULT displayKey(TSS_HKEY a_hKey)
{
TSS_RESULT result;
UINT32 uiAttr, uiAttrSize;
BYTE *pAttr;
UINT32 uiAlg;
result =
getAttribData(a_hKey, TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_VERSION, &uiAttrSize,
&pAttr);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" Version: "));
logHex(uiAttrSize, pAttr);
result =
getAttribUint32(a_hKey, TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_USAGE, &uiAttr);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" Usage: 0x%04x (%s)\n"), uiAttr, displayKeyUsageMap(uiAttr));
result =
getAttribUint32(a_hKey, TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_KEYFLAGS, &uiAttr);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" Flags: 0x%08x (%s)\n"), uiAttr, displayKeyFlagsMap(uiAttr));
result =
getAttribUint32(a_hKey, TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_AUTHUSAGE, &uiAttr);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" AuthUsage: 0x%02x (%s)\n"), uiAttr, displayAuthUsageMap(uiAttr));
result =
getAttribUint32(a_hKey, TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_ALGORITHM, &uiAlg);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" Algorithm: 0x%08x (%s)\n"), uiAlg, displayAlgorithmMap(uiAlg));
result =
getAttribUint32(a_hKey, TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_ENCSCHEME, &uiAttr);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" Encryption Scheme: 0x%08x (%s)\n"), uiAttr, displayEncSchemeMap(uiAttr));
result =
getAttribUint32(a_hKey, TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_SIGSCHEME, &uiAttr);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" Signature Scheme: 0x%08x (%s)\n"), uiAttr, displaySigSchemeMap(uiAttr));
if (uiAlg == TSS_ALG_RSA) {
result =
getAttribUint32(a_hKey, TSS_TSPATTRIB_RSAKEY_INFO,
TSS_TSPATTRIB_KEYINFO_RSA_KEYSIZE,
&uiAttr);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" Key Size: %d bits\n"), uiAttr);
}
result =
getAttribData(a_hKey, TSS_TSPATTRIB_RSAKEY_INFO,
TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &uiAttrSize,
&pAttr);
if (result != TSS_SUCCESS)
return result;
logMsg(_(" Public Key:"));
logHex(uiAttrSize, pAttr);
return result;
}
/*
* Not always reliable as this depends on the TSS system.data being intact
*/
BOOL isTpmOwned(TSS_HCONTEXT hContext)
{
TSS_HKEY hSrk;
BOOL iRc = FALSE;
if (keyGetKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSrk)
!= TSS_SUCCESS)
goto out;
iRc = TRUE;
out:
return iRc;
}
void tspiDebug(const char *a_szName, TSS_RESULT a_iResult)
{
logDebug(_("%s success\n"), a_szName);
}
void tspiError(const char *a_szName, TSS_RESULT a_iResult)
{
logError(_("%s failed: 0x%08x - layer=%s, code=%04x (%d), %s\n"),
a_szName, a_iResult, Trspi_Error_Layer(a_iResult),
Trspi_Error_Code(a_iResult),
Trspi_Error_Code(a_iResult),
Trspi_Error_String(a_iResult));
}
void tspiResult(const char *a_szName, TSS_RESULT a_tResult)
{
if (a_tResult == TSS_SUCCESS)
tspiDebug(a_szName, a_tResult);
else
tspiError(a_szName, a_tResult);
}
BOOL mapTssBool(TSS_BOOL a_bValue)
{
BOOL bRc;
bRc = a_bValue ? TRUE : FALSE;
return bRc;
}
TSS_RESULT contextCreate(TSS_HCONTEXT * a_hContext)
{
TSS_RESULT result = Tspi_Context_Create(a_hContext);
tspiResult("Tspi_Context_Create", result);
return result;
}
TSS_RESULT contextClose(TSS_HCONTEXT a_hContext)
{
TSS_RESULT result = Tspi_Context_FreeMemory(a_hContext, NULL);
tspiResult("Tspi_Context_FreeMemory", result);
result = Tspi_Context_Close(a_hContext);
tspiResult("Tspi_Context_Close", result);
return result;
}
TSS_RESULT contextConnect(TSS_HCONTEXT a_hContext)
{
TSS_RESULT result = Tspi_Context_Connect(a_hContext, NULL);
tspiResult("Tspi_Context_Connect", result);
return result;
}
TSS_RESULT
contextCreateObject(TSS_HCONTEXT a_hContext,
TSS_FLAG a_fType,
TSS_FLAG a_fAttrs, TSS_HOBJECT * a_hObject)
{
TSS_RESULT result =
Tspi_Context_CreateObject(a_hContext, a_fType, a_fAttrs,
a_hObject);
tspiResult("Tspi_Context_CreateObject", result);
return result;
}
TSS_RESULT
contextCloseObject(TSS_HCONTEXT a_hContext, TSS_HOBJECT a_hObject)
{
TSS_RESULT result =
Tspi_Context_CloseObject(a_hContext, a_hObject);
tspiResult("Tspi_Context_CloseObject", result);
return result;
}
TSS_RESULT contextGetTpm(TSS_HCONTEXT a_hContext, TSS_HTPM * a_hTpm)
{
TSS_RESULT result = Tspi_Context_GetTpmObject(a_hContext, a_hTpm);
tspiResult("Tspi_Context_GetTpmObject", result);
return result;
}
TSS_RESULT policyGet(TSS_HOBJECT a_hObject, TSS_HPOLICY * a_hPolicy)
{
TSS_RESULT result =
Tspi_GetPolicyObject(a_hObject, TSS_POLICY_USAGE, a_hPolicy);
tspiResult("Tspi_GetPolicyObject", result);
return result;
}
TSS_RESULT policyAssign(TSS_HPOLICY a_hPolicy, TSS_HOBJECT a_hObject)
{
TSS_RESULT result =
Tspi_Policy_AssignToObject(a_hPolicy, a_hObject);
tspiResult("Tspi_Policy_AssignToObject", result);
return result;
}
TSS_RESULT
policySetSecret(TSS_HPOLICY a_hPolicy,
UINT32 a_uiSecretLen, BYTE * a_chSecret)
{
TSS_RESULT result;
BYTE wellKnown[] = TSS_WELL_KNOWN_SECRET;
//If secret is TSS_WELL_KNOWN_SECRET, change secret mode to TSS_SECRET_MODE_SHA1
if (a_chSecret &&
a_uiSecretLen == sizeof(wellKnown) &&
!memcmp(a_chSecret, (BYTE *)wellKnown, sizeof(wellKnown)))
result =
Tspi_Policy_SetSecret(a_hPolicy, TSS_SECRET_MODE_SHA1,
a_uiSecretLen, a_chSecret);
else
result =
Tspi_Policy_SetSecret(a_hPolicy, TSS_SECRET_MODE_PLAIN,
a_uiSecretLen, a_chSecret);
tspiResult("Tspi_Policy_SetSecret", result);
return result;
}
TSS_RESULT policyFlushSecret(TSS_HPOLICY a_hPolicy)
{
TSS_RESULT result = Tspi_Policy_FlushSecret(a_hPolicy);
tspiResult("Tspi_Policy_FlushSecret", result);
return result;
}
TSS_RESULT
tpmGetPubEk(TSS_HTPM a_hTpm,
TSS_BOOL a_fOwner,
TSS_VALIDATION * a_pValData, TSS_HKEY * a_phEPubKey)
{
TSS_RESULT result = Tspi_TPM_GetPubEndorsementKey(a_hTpm, a_fOwner,
a_pValData,
a_phEPubKey);
tspiResult("Tspi_TPM_GetPubEndorsementKey", result);
return result;
}
TSS_RESULT
tpmSetStatus(TSS_HTPM a_hTpm, TSS_FLAG a_fStatus, TSS_BOOL a_bValue)
{
TSS_RESULT result =
Tspi_TPM_SetStatus(a_hTpm, a_fStatus, a_bValue);
tspiResult("Tspi_TPM_SetStatus", result);
return result;
}
TSS_RESULT
tpmGetStatus(TSS_HTPM a_hTpm, TSS_FLAG a_fStatus, TSS_BOOL * a_bValue)
{
TSS_RESULT result =
Tspi_TPM_GetStatus(a_hTpm, a_fStatus, a_bValue);
tspiResult("Tspi_TPM_GetStatus", result);
return result;
}
TSS_RESULT tpmGetRandom(TSS_HTPM a_hTpm, UINT32 a_length, BYTE ** a_data)
{
TSS_RESULT result = Tspi_TPM_GetRandom(a_hTpm, a_length, a_data);
tspiResult("Tspi_TPM_GetRandom", result);
return result;
}
TSS_RESULT keyLoadKey(TSS_HKEY a_hKey, TSS_HKEY a_hWrapKey)
{
TSS_RESULT result = Tspi_Key_LoadKey(a_hKey, a_hWrapKey);
tspiResult("Tspi_Key_LoadKey", result);
return result;
}
TSS_RESULT
keyLoadKeyByUUID(TSS_HCONTEXT a_hContext,
TSS_FLAG a_fStoreType,
TSS_UUID a_uKeyId, TSS_HKEY * a_hKey)
{
TSS_RESULT result =
Tspi_Context_LoadKeyByUUID(a_hContext, a_fStoreType, a_uKeyId,
a_hKey);
tspiResult("Tspi_Context_LoadKeyByUUID", result);
return result;
}
TSS_RESULT
keyGetPubKey(TSS_HKEY a_hKey, UINT32 * a_uiKeyLen, BYTE ** a_pKey)
{
TSS_RESULT result = Tspi_Key_GetPubKey(a_hKey, a_uiKeyLen, a_pKey);
tspiResult("Tspi_Key_GetPubKey", result);
return result;
}
TSS_RESULT
keyGetKeyByUUID(TSS_HCONTEXT a_hContext,
TSS_FLAG a_fStoreType,
TSS_UUID a_uKeyId, TSS_HKEY * a_hKey)
{
TSS_RESULT result =
Tspi_Context_GetKeyByUUID(a_hContext, a_fStoreType, a_uKeyId,
a_hKey);
tspiResult("Tspi_Context_GetKeyByUUID", result);
return result;
}
TSS_RESULT
getAttribData(TSS_HOBJECT a_hObject,
TSS_FLAG a_fAttr,
TSS_FLAG a_fSubAttr, UINT32 * a_uiSize, BYTE ** a_pData)
{
TSS_RESULT result =
Tspi_GetAttribData(a_hObject, a_fAttr, a_fSubAttr, a_uiSize,
a_pData);
tspiResult("Tspi_GetAttribData", result);
return result;
}
TSS_RESULT
getAttribUint32(TSS_HOBJECT a_hObject,
TSS_FLAG a_fAttr, TSS_FLAG a_fSubAttr, UINT32 * a_uiData)
{
TSS_RESULT result =
Tspi_GetAttribUint32(a_hObject, a_fAttr, a_fSubAttr, a_uiData);
tspiResult("Tspi_GetAttribUint32", result);
return result;
}
TSS_RESULT
getCapability(TSS_HTPM a_hTpm,
TSS_FLAG a_fCapArea,
UINT32 a_uiSubCapLen,
BYTE * a_pSubCap, UINT32 * a_uiResultLen, BYTE ** a_pResult)
{
TSS_RESULT result =
Tspi_TPM_GetCapability(a_hTpm, a_fCapArea, a_uiSubCapLen,
a_pSubCap, a_uiResultLen, a_pResult);
tspiResult("Tspi_TPM_GetCapability", result);
return result;
}
TSS_RESULT
keyCreateKey(TSS_HKEY a_hKey, TSS_HKEY a_hWrapKey,
TSS_HPCRS a_hPcrs)
{
TSS_RESULT result = Tspi_Key_CreateKey(a_hKey, a_hWrapKey, a_hPcrs);
tspiResult("Tspi_Key_CreateKey", result);
return result;
}
TSS_RESULT dataSeal(TSS_HENCDATA a_hEncdata, TSS_HKEY a_hKey,
UINT32 a_len, BYTE * a_data,
TSS_HPCRS a_hPcrs)
{
TSS_RESULT result =
Tspi_Data_Seal(a_hEncdata, a_hKey, a_len, a_data, a_hPcrs);
tspiResult("Tspi_Data_Seal", result);
return result;
}
TSS_RESULT
tpmPcrRead(TSS_HTPM a_hTpm, UINT32 a_Idx,
UINT32 *a_PcrSize, BYTE **a_PcrValue)
{
TSS_RESULT result =
Tspi_TPM_PcrRead(a_hTpm, a_Idx, a_PcrSize, a_PcrValue);
tspiResult("Tspi_TPM_PcrRead", result);
return result;
}
TSS_RESULT
pcrcompositeSetPcrValue(TSS_HPCRS a_hPcrs, UINT32 a_Idx,
UINT32 a_PcrSize, BYTE *a_PcrValue)
{
TSS_RESULT result =
Tspi_PcrComposite_SetPcrValue(a_hPcrs, a_Idx, a_PcrSize, a_PcrValue);
tspiResult("Tspi_PcrComposite_SetPcrValue", result);
return result;
}
#ifdef TSS_LIB_IS_12
/*
* These getPasswd functions will wrap calls to the other functions and check to see if the TSS
* library's context tells us to remove the NULL terminating chars from the end of the password
* when unicode is on.
*/
char *
getPasswd12(const char *a_pszPrompt, int* a_iLen, BOOL a_bConfirm)
{
return _getPasswd12( a_pszPrompt, a_iLen, a_bConfirm, useUnicode);
}
char *_getPasswd12(const char *a_pszPrompt, int* a_iLen, BOOL a_bConfirm, BOOL a_bUseUnicode)
{
UINT32 status;
char *passwd;
passwd = _getPasswd(a_pszPrompt, a_iLen, a_bConfirm, a_bUseUnicode);
if (passwd && a_bUseUnicode) {
/* If we're running against a 1.2 TSS, it will include the null terminating
* characters based on the TSS_TSPATTRIB_SECRET_HASH_MODE attribute of the
* context. If this is set to TSS_TSPATTRIB_HASH_MODE_NOT_NULL, we need to
* trim the two zeros off the end of the unicode string returned by
* Trspi_Native_To_UNICODE. */
if (getAttribUint32(hContext, TSS_TSPATTRIB_SECRET_HASH_MODE,
TSS_TSPATTRIB_SECRET_HASH_MODE_POPUP, &status))
goto out;
if (status == TSS_TSPATTRIB_HASH_MODE_NOT_NULL)
*a_iLen -= sizeof(TSS_UNICODE);
}
out:
return passwd;
}
TSS_RESULT
unloadVersionInfo(UINT64 *offset, BYTE *blob, TPM_CAP_VERSION_INFO *v)
{
TSS_RESULT result = Trspi_UnloadBlob_CAP_VERSION_INFO(offset, blob, v);
tspiResult("Trspi_UnloadBlob_CAP_VERSION_INFO", result);
return result;
}
TSS_RESULT
pcrcompositeSetPcrLocality(TSS_HPCRS a_hPcrs, UINT32 localityValue)
{
TSS_RESULT result =
Tspi_PcrComposite_SetPcrLocality(a_hPcrs, localityValue);
tspiResult("Tspi_PcrComposite_SetPcrLocality", result);
return result;
}
TSS_RESULT
NVDefineSpace(TSS_HNVSTORE hNVStore, TSS_HPCRS hReadPcrComposite ,
TSS_HPCRS hWritePcrComposite)
{
TSS_RESULT result =
Tspi_NV_DefineSpace(hNVStore, hReadPcrComposite,
hWritePcrComposite);
tspiResult("Tspi_NV_DefineSpace", result);
return result;
}
TSS_RESULT
NVReleaseSpace(TSS_HNVSTORE hNVStore)
{
TSS_RESULT result =
Tspi_NV_ReleaseSpace(hNVStore);
tspiResult("Tspi_NV_ReleaseSpace", result);
return result;
}
TSS_RESULT
NVWriteValue(TSS_HNVSTORE hNVStore, UINT32 offset,
UINT32 ulDataLength, BYTE *rgbDataToWrite)
{
TSS_RESULT result =
Tspi_NV_WriteValue(hNVStore, offset,
ulDataLength, rgbDataToWrite);
tspiResult("Tspi_NV_WriteValue", result);
return result;
}
TSS_RESULT
NVReadValue(TSS_HNVSTORE hNVStore, UINT32 offset,
UINT32 *ulDataLength, BYTE **rgbDataRead)
{
TSS_RESULT result =
Tspi_NV_ReadValue(hNVStore, offset,
ulDataLength, rgbDataRead);
tspiResult("Tspi_NV_ReadValue", result);
return result;
}
TSS_RESULT
unloadNVDataPublic(UINT64 *offset, BYTE *blob, UINT32 blob_len, TPM_NV_DATA_PUBLIC *v)
{
UINT64 off = *offset;
TSS_RESULT result;
result = Trspi_UnloadBlob_NV_DATA_PUBLIC(&off, blob, NULL);
if (result == TSS_SUCCESS) {
if (off > blob_len)
return TSS_E_BAD_PARAMETER;
result = Trspi_UnloadBlob_NV_DATA_PUBLIC(offset, blob, v);
}
tspiResult("Trspi_UnloadBlob_NV_DATA_PUBLIC", result);
return result;
}
#endif