Closed geobra closed 4 years ago
Maybe you could run your program with valgrind ? That should give us some hint on whether the write or the read leads to the segfault.
here you go:
developer@debian10:~/Documents/KeyPairTpm/build-kpt-Desktop-Default$ valgrind --leak-check=full ./kpt
==19966== Memcheck, a memory error detector
==19966== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==19966== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==19966== Command: ./kpt
==19966==
Engine name: TPM2-TSS engine for OpenSSL
Init result: 1
Creating RSA key object.
==19966== Invalid read of size 8
==19966== at 0x4A173A4: RSA_set_method (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==19966== by 0x4B50AE2: tpm2tss_rsa_makekey (in /home/developer/Documents/KeyPairTpm/kpt/tpm2-tss-engine-1.0.1/.libs/libtpm2tss.so)
==19966== by 0x4848CB7: loadkey (tpm2-tss-engine.c:230)
==19966== by 0x49C2CBE: ENGINE_load_private_key (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==19966== by 0x10AC2C: OpensslTk::generatePubPemFromPrivTss(std::cxx11::basic_string<char, std::char_traits
Address 0x38
looks like junk data...
Could you check and validate that init_rsa()
is executed ?
Also I'm wondering where this read could come from. The code in openssl is
int RSA_set_method(RSA *rsa, const RSA_METHOD *meth)
{
/*
* NB: The caller is specifically setting a method, so it's not up to us
* to deal with which ENGINE it comes from.
*/
const RSA_METHOD *mtmp;
mtmp = rsa->meth;
if (mtmp->finish)
mtmp->finish(rsa);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(rsa->engine);
rsa->engine = NULL;
#endif
rsa->meth = meth;
if (meth->init)
meth->init(rsa);
return 1;
}
which seems harmless enough...
Yes, a breakpoint in the #else branch get hit. The branch is complete and successfull executed.
int
init_rsa(ENGINE *e)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000
default_rsa = RSA_PKCS1_SSLeay();
if (default_rsa == NULL)
return 0;
rsa_methods.rsa_pub_enc = default_rsa->rsa_pub_enc;
rsa_methods.rsa_pub_dec = default_rsa->rsa_pub_dec;
rsa_methods.rsa_mod_exp = default_rsa->rsa_mod_exp;
rsa_methods.bn_mod_exp = default_rsa->bn_mod_exp;
return ENGINE_set_RSA(e, &rsa_methods);
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
default_rsa = RSA_PKCS1_OpenSSL();
if (default_rsa == NULL)
return 0;
rsa_methods = RSA_meth_dup(default_rsa);
RSA_meth_set1_name(rsa_methods, "TPM2TSS RSA methods");
RSA_meth_set_priv_enc(rsa_methods, rsa_priv_enc);
RSA_meth_set_priv_dec(rsa_methods, rsa_priv_dec);
return ENGINE_set_RSA(e, rsa_methods);
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
}
Ok, that's even more weird. So you know how to use a debugger ? Would you single-step through the RSA_set_method function and maybe find the problematic line ?
This was my very first idea. But there is not -dbg package available for openssl in buster. This requires me to build openssl by myself with debug symbols and link against this version. Or do you know of any 'quicker' solution?
Unfortunately not. But openssl building is not as painful as one might think, thankfully. I've build it into a separate prefix and set the LD_LIBRARY_PATH and that worked. So you don't have to clutter your system.
Are there any special ./config options for openssl? If I just use './config' it determinse my system correct as:
Operating system: x86_64-whatever-linux2 Configuring OpenSSL version 1.1.1d (0x1010104fL) for linux-x86_64
But if I use LD_LIBRARY_PATH to point to the compiled libcrypto.so.1.1, the tpm2tss engine refuses to load at all. I verified the used libs by ldd. Without the LD_LIB... path I get the obvious segfault again.
You need to set the LD_LIBARAY_PATH before building the engine already so it links to the correct version of openssl.
That does not seem to work, despite ldd shows the correct file in the correct path. Does I 'only' have to recompile the engine? Or do I need to recompile the complete tpm2-tss stack?
right, tpm2-tss also uses libcrypto in the backend...
Okay, I set up a new VM with debian 10, compiled openssl with debug info. Compiled the complete tss stack against my openssl lib. tpmsim, abrmd, and tpm2tools running fine. tpm2tss-genkey as well as my own application refuses to load the engine. I am stuck here :-(.
Ok.... maybe strace -e file <youapplication> 2>&1 | grep open
will help you to see where it searches for which file.
That's what I usually use.
Yes, that does the trick.
Here are my lessosns learned:
int RSA_set_method(RSA *rsa, const RSA_METHOD *meth)
{
/*
* NB: The caller is specifically setting a method, so it's not up to us
* to deal with which ENGINE it comes from.
*/
const RSA_METHOD *mtmp;
mtmp = rsa->meth;
if (mtmp->finish)
mtmp->finish(rsa);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(rsa->engine);
rsa->engine = NULL;
#endif
rsa->meth = meth; // segfault, because meth = 0x0
if (meth->init)
meth->init(rsa);
return 1;
}
I double checked that init_rsa is called and made some debbugging there. All should be ok. Then I tried to make an additional copy of the RSA_METHOD struct with RSA_dup. In the init func, the structure is valid. But also that structure is NULL if I use it at the call to RSA_set_method.
Obviously, if I create the structure again before the call to RSA_set_method and pass it in, the segfault is gone. But that is not a solution.
What I had observed during the strace hunting: My application is linked to libtpm2tss and is searching for it during start. But this is not enough. It searches it again at /usr/local/lib/engines-1.1/. Only if there is also a copy of that lib, my programm is able to start.
My assumption: The ENGINE_load_dynamic and ENGINE_by_id forces the lib to get loaded a second time? And during that second loading, the init function does not get triggered?
Why is your application linked against libtpm2tss anyways ? The calling of init should happen. However you can set the init=0/1 parameter for each engine individually in the openssl config file.
If I remove libtpm2tss.so as a linkage dependency and only use the ENGINE* calls, which loads the tpm2tss engine during runtime, the segfault is gone.
I used the tpm2tss-genkey.c file as a base for my use case. This application also links against libtpm2tss and uses ENGINE* calls. What is the difference there?
I have no idea... :-(
Okay, thank you for your support here! From this point on I try to get forward by myself :-).
Anytime
Hello
I tried the following by use of tpm2-tss-engine-1.0.1:
Create a new tss key via command line: tpm2tss-genkey /tmp/privkey.tss
Now i tried to use the engine with openssl to read in this key. Here are the basic steps. I don't know if I missed some fundamental stuff, but what I read from the documentation, it should work:
The last step causes the SEGFAULT. Here is the stack trace:
0 0x00007ffff7e8c3a4 in RSA_set_method () from /lib/x86_64-linux-gnu/libcrypto.so.1.1
1 0x00007ffff7cc3ae3 in tpm2tss_rsa_makekey () from /home/developer/Documents/KeyPairTpm/kpt/tpm2-tss-engine-1.0.1/.libs/libtpm2tss.so
2 0x00007ffff7fc7cb8 in loadkey (e=, key_id=, ui=, cb_data=0x0) at src/tpm2-tss-engine.c:230
3 0x00007ffff7e37cbf in ENGINE_load_private_key () from /lib/x86_64-linux-gnu/libcrypto.so.1.1
And the specific sourc in from /tpm2-tss-engine-rsa.c: tpm2tss_rsa_makekey
if OPENSSL_VERSION_NUMBER < 0x10100000
else / OPENSSL_VERSION_NUMBER < 0x10100000 /
endif / OPENSSL_VERSION_NUMBER < 0x10100000 /
it seems to me that rsa_methods is not propperly set up. But maybe I am wrong here and I use the functionality in a wrong way? Any hints on that issue is appreciated :-).
Tested on a Debian 10.
Best regards Geobra