From: Markus K. <ko...@rr...> - 2013-07-30 09:27:40
|
Hello list, basically I refer to the thread "opensc 0.11.13 and openssl 1.0 oddity" 2010-04-15 http://thread.gmane.org/gmane.comp.encryption.opensc.devel/10038 which ended in these changes https://github.com/OpenSC/OpenSC/commit/46def8b86cae98791049fd648128ad091ffec172 https://github.com/OpenSC/OpenSC/commit/7f3f6dec6b3b092214813ff1a1da86bb26cbda49 having current code look like this: https://github.com/OpenSC/OpenSC/blob/master/src/pkcs11/openssl.c#L154 The problem with this approach is as simple as this: ENGINE_set_default(e, ENGINE_METHOD_ALL); ENGINE_free(e); The gost engine is set as default, and free'd. Not really valid, breaks OpenSSL hard. ENGINE references are slightly more complicated: http://www.openssl.org/docs/crypto/engine.html#Reference_counting_and_handles I had it segfault in/beyond SSL_CTX_new. To reproduce, ... My setup is simple, I got two readers, two cards. One card is used to authenticate to the SOAP API of a CA, thats the RA card, second card is written to, the user card. To issue a certificate, I need to * create a key on the USER card * sign a CSR with the key on the USER card (using engine_pkcs11) * submit the request to the SOAP API * approve the request * authenticate to the SOAP api using the RA cards cert/key pair (engine_pkcs11) * sign the approval with the RA cards cert/key pair (engine_pkcs11) As both cards are interfaced with opensc, loading an engine for both did not work for me as I rely on the PIN parameter for the engine_pkcs11. So I had to serialize access to the openssl engine, which allows reproducing the problems with a single reader/card. Have a single ENGINE running, finish it when not required, init a new engine when required. After loading the Engine to sign the CSR, the engine gets finished, and removed, including all ENGINE_unregister_*. When connecting to the SOAP service, OpenSSL would segfault ~12 frames beyond SSL_CTX_new() as internal data structure was corrupted by the ENGINE_free() introduced in OpenSC in the cited gost patchset. It even segfaults when calling SSL_CTX_new while the pkcs11 engine is loaded, the data corruption takes its toll. My fix is simple, do not load gost. [no_free.diff] It's radical, but I do not have access to gost enabled cards, and therefore can't verify this ever worked correctly, in case it is not, keeping a global reference to the engine and finishing it when done might be better. libp11 had similar problems, it is used in engine_pkcs11, and registers it's ERR strings, but does not provide API to unregister them as well. Unloading the engine resulted in the ERR strings getting unmapped as well, loading the engine again crashed OpenSSL due to access to unmapped memory. Extending libp11 to allow unregistering the ERR strings [add_ERR_unload_PKCS11_strings.diff] and making use of it in engine_pkcs11 [unload_errstrings.diff] was required therefore. Also attached is a testcase [testcase.py], written in python using M2Crypto. run as testcase.py <slot> <pin> <objid> e.g. gdb -ex r --args python /tmp/testcase.py 1 123456 46a808cfd5beafa5e60aefee867bf92025dc2849 You may have to adjust _PATH in the script accordingly to match your settings. This testcase segfaults in SSL_CTX_new due to the gost engine ENGINE_free. Program received signal SIGSEGV, Segmentation fault. 0x0000000000000000 in ?? () (gdb) bt #0 0x0000000000000000 in ?? () #1 0x00007ffff7259f56 in look_str_cb (arg=<optimized out>, sk=<optimized out>, nid=<optimized out>, def=<optimized out>) at tb_asnmth.c:216 #2 look_str_cb (nid=815, sk=0xbb0790, def=<optimized out>, arg=0x7fffffffcf90) at tb_asnmth.c:206 #3 0x00007ffff7266ddf in doall_util_fn (arg=0x7fffffffcf70, func_arg=0x7ffff7258220 <int_cb_LHASH_DOALL_ARG>, func=0, use_arg=1, lh=0xbb0490) at lhash.c:292 #4 lh_doall_arg (lh=0xbb0490, func=0x7ffff7258220 <int_cb_LHASH_DOALL_ARG>, arg=0x7fffffffcf70) at lhash.c:307 #5 0x00007ffff725871c in engine_table_doall (table=<optimized out>, cb=<optimized out>, arg=<optimized out>) at eng_table.c:349 #6 0x00007ffff725a313 in ENGINE_pkey_asn1_find_str (pe=0x7fffffffcfc8, str=<optimized out>, len=<optimized out>) at tb_asnmth.c:236 #7 0x00007ffff728c7c5 in EVP_PKEY_asn1_find_str (pe=0x7fffffffd010, str=0x7ffff75a0377 "gost94", len=6) at ameth_lib.c:213 #8 0x00007ffff75952e4 in get_optional_pkey_id (pkey_name=<optimized out>) at ssl_ciph.c:356 #9 0x00007ffff759641f in ssl_cipher_get_disabled (ssl=<synthetic pointer>, mac=<synthetic pointer>, enc=<synthetic pointer>, auth=<synthetic pointer>, mkey=<synthetic pointer>) at ssl_ciph.c:733 #10 ssl_create_cipher_list (ssl_method=0x7ffff77ade80, cipher_list=0xbadbb8, cipher_list_by_id= 0xbadbc0, rule_str=0x7ffff759ffac "ALL:!aNULL:!eNULL:!SSLv2") at ssl_ciph.c:1371 #11 0x00007ffff758fd30 in SSL_CTX_new (meth=0x7ffff77ade80) at ssl_lib.c:1762 Re-setting the PIN parameter for the engine, depending on the card to use is possible, and allows using multiple cards without ENGINE_finish, avoiding the libp11 ERR strings issue, but the corruption caused by the gost engine free persists, and faults. MfG Markus Kötter |