After using the key, I free the key and ENGINE by calling the appropriate free/finish functions. However, what I notice is that the neither the key nor the ENGINE are actually free’d. When I step through the code with gdb I get after the last line:
(gdb) p e->struct_ref
$1 = 2
(gdb) p e->funct_ref
$2 = 1
(gdb) p key->references
$1 = 1
So the ref counts of the ENGINE (structural and functional) and of the key are > 0. So neither the ENGINE nor the key are actually free’d.
After a quick look at the libp11 code, I got the impression that the ENGINE holds a reference to the key and the key holds a reference to the ENGINE (in the pmeth_engine field). If this is the case, it would be a cyclic reference that prevents ENGINE and key from being free’d.
If I add the line EVP_PKEY_set1_engine(key, NULL); just before the line EVP_PKEY_free(key); everything seems to work as expected. The EVP_PKEY_set1_engine function finishes the ENGINE referenced in the pmeth_engine field (reduces the ref counts of the ENGINE) and sets the pmeth_engine field to NULL, thus breaking the cycle.
After calling the free/finish functions as before, the ENGINE is free’d first, which ultimately also frees the key via its internal reference.
Am I missing some obvious point here? If so, could you please show me how to clean up correctly?
If my interpretation is correct and there is no straightforward cleanup strategy, I would find it irritating to be responsible for manually breaking the cycle to get a the desired cleanup.
The observed behavior could be produced with openSSL 1.1.1w and openSSL 3.0.2 and libp11 0.4.12.
Hi, I get an EVP_PKEY from the pkcs11 ENGINE using the following code:
After using the key, I free the key and ENGINE by calling the appropriate free/finish functions. However, what I notice is that the neither the key nor the ENGINE are actually free’d. When I step through the code with gdb I get after the last line:
So the ref counts of the ENGINE (structural and functional) and of the key are > 0. So neither the ENGINE nor the key are actually free’d.
After a quick look at the libp11 code, I got the impression that the ENGINE holds a reference to the key and the key holds a reference to the ENGINE (in the
pmeth_engine
field). If this is the case, it would be a cyclic reference that prevents ENGINE and key from being free’d.If I add the line
EVP_PKEY_set1_engine(key, NULL);
just before the lineEVP_PKEY_free(key);
everything seems to work as expected. TheEVP_PKEY_set1_engine
function finishes the ENGINE referenced in thepmeth_engine
field (reduces the ref counts of the ENGINE) and sets thepmeth_engine
field to NULL, thus breaking the cycle.After calling the free/finish functions as before, the ENGINE is free’d first, which ultimately also frees the key via its internal reference.
Am I missing some obvious point here? If so, could you please show me how to clean up correctly?
If my interpretation is correct and there is no straightforward cleanup strategy, I would find it irritating to be responsible for manually breaking the cycle to get a the desired cleanup.
The observed behavior could be produced with openSSL 1.1.1w and openSSL 3.0.2 and libp11 0.4.12.
I appreciate your help.