The tcsd causes unnecessary authentication failures when a parent key (SRK) with a password is used and a child key is supposed to be loaded into the TPM. This patch avoids the failures by returning information about the parent key to the caller rather than trying to load the key assuming the parent key has no password (20 bytes of 0x0) and only returning information about the parent key to the caller if the loading has failed. We use the TCS_LOADKEY_INFO structure with all zeros as an indicator of a first call and fill it out and return it to the client. On the client side we then try to determine the password of the parent key and try another call with either the parent key's password set or the parent key's password again empty. This avoids one unnecessary authentication failure.
I noticed this issue when trying to develop an application that uses GnuTLS tpmtool to create TPM keys and certtool for issuing certificates. I noticed that with a hardware TPM I could only run my program once but could run it 5 times when using a vTPM. The vTPM seems to have a higher threshold for engaging the lock out due to failed authentications than the hardware TPM does. The program ran 5 times with the vTPM. My program itself does not cause authentication failures but tcsd caused some, that this patch fixes, and certtool itself causes some that would need to be 'somehow' fixed in certtool itself. The improvement with this patch is so that the program now runs 5 times with a hardware TPM. After that the owner of the TPM has to issue the TPM_ORD_ResetLockValue command. The autentication failures are probably not so severe when the parent key has no password. However, tpmtool (of GnuTLS) currently does not support this and therefore we have to set an explicity password for the parent key. Signed-off-by: Stefan Berger <[email protected]> --- src/tcs/tcsi_ps.c | 60 ++++++++++++++++++++++++++++++++++------------ src/tspi/tspi_ps.c | 10 ++++++-- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/tcs/tcsi_ps.c b/src/tcs/tcsi_ps.c index e7f6245..a0c9df4 100644 --- a/src/tcs/tcsi_ps.c +++ b/src/tcs/tcsi_ps.c @@ -494,6 +494,30 @@ TCS_GetRegisteredKeyBlob_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ return TSS_SUCCESS; } +static TSS_RESULT +CopyKeyInfo_Internal(TCS_LOADKEY_INFO * pLoadKeyInfo, /* in, out */ + TSS_UUID *parentUuid, /* in */ + TSS_UUID *KeyUUID, /* in */ + UINT32 ordinal, /* in */ + UINT32 keySize, /* in */ + BYTE *keyBlob) /* in */ +{ + BYTE blob[1000]; + UINT64 offset = 0; + + /* set up a load key info struct */ + memcpy(&pLoadKeyInfo->parentKeyUUID, parentUuid, sizeof(TSS_UUID)); + memcpy(&pLoadKeyInfo->keyUUID, KeyUUID, sizeof(TSS_UUID)); + + /* calculate the paramDigest */ + LoadBlob_UINT32(&offset, ordinal, blob); + LoadBlob(&offset, keySize, blob, keyBlob); + if (Hash(TSS_HASH_SHA1, offset, blob, + (BYTE *)&pLoadKeyInfo->paramDigest.digest)) + return TCSERR(TSS_E_INTERNAL_ERROR); + return 0; +} + TSS_RESULT TCSP_LoadKeyByUUID_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ TSS_UUID *KeyUUID, /* in */ @@ -508,6 +532,7 @@ TCSP_LoadKeyByUUID_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ UINT16 blobSize = sizeof(keyBlob); UINT64 offset; TCS_KEY_HANDLE parentTCSKeyHandle; + TCS_LOADKEY_INFO nullInfo; if (TPM_VERSION_IS(1,2)) ordinal = TPM_ORD_LoadKey2; @@ -572,27 +597,32 @@ TCSP_LoadKeyByUUID_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ * If no errors have happend up till now, then the parent is loaded and ready for use. * The parent's TCS Handle should be in parentTCSKeyHandle. ******************************************************/ + + memset(&nullInfo, 0, sizeof(nullInfo)); + + if (memcmp(&nullInfo, pLoadKeyInfo, sizeof(nullInfo)) == 0) { + /********************************************************* + * Do not fail by using the wrong auth on loading the key + * rather give the caller the key info and have him call + * again. + ********************************************************/ + result = CopyKeyInfo_Internal(pLoadKeyInfo, &parentUuid, KeyUUID, ordinal, + keySize, keyBlob); + if (result) + return result; + return TCSERR(TCS_E_KM_LOADFAILED); + } + if ((result = LoadKeyByBlob_Internal(ordinal, hContext, parentTCSKeyHandle, keySize, keyBlob, NULL, phKeyTCSI, &keyslot))) { LogDebugFn("LoadKeyByBlob_Internal returned 0x%x", result); if (result == TCPA_E_AUTHFAIL && pLoadKeyInfo) { - BYTE blob[1000]; - - /* set up a load key info struct */ - memcpy(&pLoadKeyInfo->parentKeyUUID, &parentUuid, sizeof(TSS_UUID)); - memcpy(&pLoadKeyInfo->keyUUID, KeyUUID, sizeof(TSS_UUID)); - - /* calculate the paramDigest */ - offset = 0; - LoadBlob_UINT32(&offset, ordinal, blob); - LoadBlob(&offset, keySize, blob, keyBlob); - if (Hash(TSS_HASH_SHA1, offset, blob, - (BYTE *)&pLoadKeyInfo->paramDigest.digest)) - result = TCSERR(TSS_E_INTERNAL_ERROR); - - result = TCSERR(TCS_E_KM_LOADFAILED); + result = CopyKeyInfo_Internal(pLoadKeyInfo, &parentUuid, KeyUUID, ordinal, + keySize, keyBlob); + if (result == 0) + result = TCSERR(TCS_E_KM_LOADFAILED); } } diff --git a/src/tspi/tspi_ps.c b/src/tspi/tspi_ps.c index 237fadf..797f8bb 100644 --- a/src/tspi/tspi_ps.c +++ b/src/tspi/tspi_ps.c @@ -74,8 +74,13 @@ Tspi_Context_LoadKeyByUUID(TSS_HCONTEXT tspContext, /* in */ if ((obj_rsakey_get_by_uuid(&info.parentKeyUUID, &keyHandle))) { /* If that failed, look on disk, in User PS. */ if (ps_get_key_by_uuid(tspContext, &info.parentKeyUUID, - &keyHandle)) - return result; + &keyHandle)) { + result = RPC_LoadKeyByUUID(tspContext, uuidData, + &info, &tcsKeyHandle); + if (result) + return result; + goto cont; + } } if (obj_rsakey_get_policy(keyHandle, TSS_POLICY_USAGE, @@ -92,6 +97,7 @@ Tspi_Context_LoadKeyByUUID(TSS_HCONTEXT tspContext, /* in */ } else if (result) return result; +cont: /*check if provided UUID has an owner evict key UUID prefix */ if (!memcmp(&uuidData, &owner_evict_uuid, sizeof(TSS_UUID)-1)) { if ((result = obj_rsakey_add(tspContext, TSS_RSAKEY_FLAG_OWNEREVICT, -- 2.17.2 _______________________________________________ TrouSerS-tech mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/trousers-tech
