-
Notifications
You must be signed in to change notification settings - Fork 119
Description
Hello,
I have stumpled on some interesting, maybe unintended relation between transient objects and C_DestroyObject() .
I have a test, that essentially does following chain of calls (I cannot provide original code)
C_GenerateKeyPair(session, ...);
C_DestroyObject(session, pubHandle); // Destroy pubKey
C_DestroyObject(session, privHandle); // Destroy privKey
Test is passing, keys are generated, and destroyed right after, however after running this test few times in a row "out of memory for session contexts" error started to appear.
Running tpm2 tpm2_getcap properties-variable before and after the test is showing that after each test run TPM2_PT_HR_TRANSIENT_AVAIL is reduced by 2.
During investigation, I modified this test case calls to:
C_GenerateKeyPair(session, ...);
C_Logout(session);
C_CloseSession(session);
C_OpenSession(..., &session);
C_Login(session, ...);
C_DestroyObject(session, pubHandle); // Destroy pubKey
C_DestroyObject(session, privHandle); // Destroy privKey
This time test was also passing, but TPM2_PT_HR_TRANSIENT_AVAIL was no longer reduced by each call, so test could be performed over and over.
Checking source code I found that during C_Logout() all handles are evicted:
/*
* For each object:
* - Evict the TPM Handles
* - Cleanse CKA_VALUE fields for private values.
*/
if (tok->tobjects.head) {
list *cur = &tok->tobjects.head->l;
while(cur) {
tobject *tobj = list_entry(cur, tobject, l);
cur = cur->next;
/* if it's CKA_PRIVATE == CK_TRUE and it has a CKA_VALUE field, clear it */
CK_BBOOL cka_private = attr_list_get_CKA_PRIVATE(tobj->attrs, CK_FALSE);
CK_ATTRIBUTE_PTR a = attr_get_attribute_by_type(tobj->attrs, CKA_VALUE);
if (cka_private && a && a->pValue && a->ulValueLen) {
attr_pfree_cleanse(a);
}
if (tobj->tpm_handle) {
bool result = tpm_flushcontext(tpm, tobj->tpm_handle);
assert(result);
UNUSED(result);
tobj->tpm_handle = 0;
/* Clear the unwrapped auth value for tertiary objects */
twist_free(tobj->unsealed_auth);
tobj->unsealed_auth = NULL;
}
}
}
However, C_DestroyObject() only removes object but does not evict tpm_handle, as a result by removing tobj it deletes a reference to TPM handle thus if handle exists it is no longer accesible after that and it cannot be evicted during C_Logout().
Is it intended behaviour? At a first glance it looks like a memory leak to me, do I misunderstand something?
I am using tpm2-pkcs11 1.9.1, without abrmd.