Decoder passphrase callback not working as expected
#24.108 aberto em 11 de abr. de 2024
Métricas do repositório
- Stars
- (30.157 stars)
- Métricas de merge de PR
- (Nenhuma PRs mesclada em 30d)
Description
When a provider implements a DECODER to decode provider specific data, that provider might need to ask the user for a pass phrase. For decoding an encrypted PEM file this would be a PEM pass phrase, but for an arbitrary provider it might be anything, not necessarily a PEM pass phrase. For example, the pkcs11-provider might need to prompt for the PKCS#11 user pin during decoding.
Decoder function OSSL_FUNC_decoder_decode_fn does get a OSSL_PASSPHRASE_CALLBACK callback function, and it is documented that it can pass a param array containing a OSSL_PASSPHRASE_PARAM_INFO parameter with the info or constructing the prompt text.
Unfortunately, this information is lost during several layers of internal pass phrase callbacks inside OpenSSL code when PEM_read_bio_PrivateKey() or similar is used and processing involves a decoder.
It always ends up with Enter PEM pass phrase: as the prompt text.
The problem starts with the fact that the OSSL_FUNC_decoder_decode_fn is called with ossl_pw_passphrase_callback_dec() as passphrase callback within decoder_process().
ossl_pw_passphrase_callback_dec() then calls ossl_pw_get_passphrase() passing the provider supplied param array. ossl_pw_get_passphrase() then builds a UI_METHOD using UI_UTIL_wrap_read_pem_callback().
However this dummy UI_METHOD returned by UI_UTIL_wrap_read_pem_callback() does ignore the prompt info that was passed via OSSL_PASSPHRASE_PARAM_INFO from the provider.
The dummy UI_METHOD's ui_write() function ignores the prompt to be written (this would be the expected prompt text from the provider), and ui_read() function calls another level of passphrase callback which is ossl_pw_pem_password(). ossl_pw_pem_password() calls ossl_pw_get_password() with hardcoded info = "PEM", and it then constructs its own param array of an OSSL_PASSPHRASE_PARAM_INFO element with that info string, and calls ossl_pw_get_passphrase().
So here the prompt info from the provider is lost.
The further code stack builds its own promot text using "PEM", resulting in Enter pass phrase for PEM:, or if PEM_def_callback is invoked because the user did not supply its own passphrase callback with PEM_read_bio_PrivateKey(), if prompts for Enter PEM pass phrase: if EVP_get_pw_prompt() returns NULL (which is always the case).
Here is an extract of a stack trace showing the call stack of the pass phrase prompt showing 2 levels of ossl_pw_get_passphrase() callbacks, where for the first one (frames 20 and 21) the prompt string from the provider is still there, but the second one (frames 14 and 15) have just "PEM" ad prompt string.
#0 __GI___libc_read (nbytes=4096, buf=0x2aa001eb720, fd=18) at ../sysdeps/unix/sysv/linux/read.c:26
#1 __GI___libc_read (fd=<optimized out>, buf=0x2aa001eb720, nbytes=4096) at ../sysdeps/unix/sysv/linux/read.c:24
#2 0x000003fff728eaba in _IO_new_file_underflow (fp=0x2aa001c7dd0) at libioP.h:946
#3 0x000003fff729006a in __GI__IO_default_uflow (fp=0x2aa001c7dd0) at libioP.h:946
#4 0x000003fff7280bf2 in __GI__IO_getline_info (fp=fp@entry=0x2aa001c7dd0, buf=<optimized out>, buf@entry=0x3ffffff2af8 "", n=8190,
delim=<optimized out>, extract_delim=<optimized out>, eof=0x0) at iogetline.c:60
#5 0x000003fff7280ce8 in __GI__IO_getline (fp=fp@entry=0x2aa001c7dd0, buf=buf@entry=0x3ffffff2af8 "", n=<optimized out>,
delim=delim@entry=10, extract_delim=extract_delim@entry=1) at iogetline.c:34
#6 0x000003fff727f59e in _IO_fgets (buf=0x3ffffff2af8 "", n=<optimized out>, fp=0x2aa001c7dd0) at iofgets.c:53
#7 0x000003fff787af14 in read_string_inner (ui=0x2aa001e5550, uis=0x2aa001e3310, echo=0, strip_nl=1) at crypto/ui/ui_openssl.c:339
#8 0x000003fff787ac38 in read_string (ui=0x2aa001e5550, uis=0x2aa001e3310) at crypto/ui/ui_openssl.c:235
#9 0x000003fff787961a in UI_process (ui=0x2aa001e5550) at crypto/ui/ui_lib.c:496
#10 0x000003fff7759414 in EVP_read_pw_string_min (buf=0x3ffffff6ee7 ",", min=0, len=33,
prompt=0x3fff79cf3e8 "Enter PEM pass phrase:", verify=0) at crypto/evp/evp_key.c:71
#11 0x000003fff77f12b8 in PEM_def_callback (buf=0x3ffffff6ee7 ",", num=33, rwflag=0, userdata=0x0) at crypto/pem/pem_lib.c:60
#12 0x000003fff787bc3c in ui_read (ui=0x2aa001d2000, uis=0x2aa001e33d0) at crypto/ui/ui_util.c:112
#13 0x000003fff787961a in UI_process (ui=0x2aa001d2000) at crypto/ui/ui_lib.c:496
#14 0x000003fff77c0470 in do_ui_passphrase (pass=0x3ffffff788f ",", pass_size=33, pass_len=0x3ffffff76b0,
prompt_info=0x3fff79bf3fa "PEM", verify=0, ui_method=0x2aa001e5360, ui_data=0x0) at crypto/passphrase.c:176
#15 0x000003fff77c099e in ossl_pw_get_passphrase (pass=0x3ffffff788f ",", pass_size=33, pass_len=0x3ffffff76b0, params=0x3ffffff76b8,
verify=0, data=0x3ffffff9080) at crypto/passphrase.c:280
#16 0x000003fff77c0bae in ossl_pw_get_password (buf=0x3ffffff788f ",", size=33, rwflag=0, userdata=0x3ffffff9080,
info=0x3fff79bf3fa "PEM") at crypto/passphrase.c:318
#17 0x000003fff77c0c52 in ossl_pw_pem_password (buf=0x3ffffff788f ",", size=33, rwflag=0, userdata=0x3ffffff9080)
at crypto/passphrase.c:326
#18 0x000003fff787bc3c in ui_read (ui=0x2aa001e48c0, uis=0x2aa001e3470) at crypto/ui/ui_util.c:112
#19 0x000003fff787961a in UI_process (ui=0x2aa001e48c0) at crypto/ui/ui_lib.c:496
#20 0x000003fff77c0470 in do_ui_passphrase (pass=0x3ffffff818f "", pass_size=33, pass_len=0x3ffffff8130,
prompt_info=0x2aa001e4100 "PKCS#11 Token (Slot 4 - Linux)", verify=0, ui_method=0x2aa001e4210, ui_data=0x3ffffff9080)
at crypto/passphrase.c:176
#21 0x000003fff77c099e in ossl_pw_get_passphrase (pass=0x3ffffff818f "", pass_size=33, pass_len=0x3ffffff8130, params=0x3ffffff8138,
verify=0, data=0x2aa001bdc78) at crypto/passphrase.c:280
#22 0x000003fff77c0da4 in ossl_pw_passphrase_callback_dec (pass=0x3ffffff818f "", pass_size=33, pass_len=0x3ffffff8130,
params=0x3ffffff8138, arg=0x2aa001bdc78) at crypto/passphrase.c:345
#23 0x000003fff7e2b4f2 in token_login (session=session@entry=0x2aa001e4fa0, uri=uri@entry=0x2aa001e3590,
pw_cb=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>, pw_cb@entry=<error reading variable: value has been optimized out>,
pw_cbarg=0x2aa001bdc78, pw_cbarg@entry=<error reading variable: value has been optimized out>, slot=slot@entry=0x2aa001e3f50,
user_type=1) at session.c:482
#24 0x000003fff7e2cd62 in slot_login (slot=<optimized out>, slot@entry=0x2aa001e3f50, uri=uri@entry=0x2aa001e3590,
pw_cb=<optimized out>, pw_cb@entry=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>, pw_cbarg=<optimized out>,
pw_cbarg@entry=0x2aa001bdc78, reqlogin=reqlogin@entry=true, _session=0x0) at session.c:788
#25 0x000003fff7e2d2d2 in p11prov_get_session (provctx=0x2aa00139f50, slotid=slotid@entry=0x3ffffff84e0,
next_slotid=next_slotid@entry=0x3ffffff84e8, uri=0x2aa001e3590, mechtype=mechtype@entry=18446744073709551615,
pw_cb=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>, pw_cbarg=0x2aa001bdc78, reqlogin=true, rw=false, _session=0x2aa001bd2c8)
at session.c:922
#26 0x000003fff7e33b30 in store_fetch (pw_cbarg=0x2aa001bdc78, pw_cb=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>,
ctx=0x2aa001bd240) at store.c:123
#27 p11prov_store_load (pctx=pctx@entry=0x2aa001bd240, object_cb=object_cb@entry=0x3fff7e116c0 <filter_for_desired_data_type>,
object_cbarg=<optimized out>, object_cbarg@entry=0x3ffffff8718,
pw_cb=pw_cb@entry=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>, pw_cbarg=0x2aa001bdc78) at store.c:256
#28 0x000003fff7e348ce in p11prov_store_direct_fetch (provctx=0x2aa00139f50,
uri=uri@entry=0x2aa001ad650 "pkcs11:model=EP11;manufacturer=IBM;serial=93AADNDG40671325;token=ep11tok;id=%01%23;object=rsa2k_2:prv;type=private", object_cb=object_cb@entry=0x3fff7e116c0 <filter_for_desired_data_type>, object_cbarg=object_cbarg@entry=0x3ffffff8718,
pw_cb=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>, pw_cb@entry=<error reading variable: value has been optimized out>,
pw_cbarg=0x2aa001bdc78) at store.c:614
#29 0x000003fff7e1191e in load_obj (pw_cbarg=<optimized out>, pw_cb=<optimized out>, cbdata=0x3ffffff8718, der_len=<optimized out>,
der=<optimized out>, ctx=0x2aa001bbc50) at decoder.c:110
#30 p11prov_der_decoder_p11prov_obj_decode (desired_data_type=desired_data_type@entry=0x3fff7e3abbc "ED448", inctx=0x2aa001bbc50,
cin=<optimized out>, selection=<optimized out>, object_cb=object_cb@entry=0x3fff7705248 <decoder_process>,
object_cbarg=0x3ffffff89c0, pw_cb=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>, pw_cbarg=0x2aa001bdc78) at decoder.c:150
#31 0x000003fff7e11d36 in p11prov_der_decoder_p11prov_ed448_decode (inctx=<optimized out>, cin=<optimized out>,
selection=<optimized out>, object_cb=0x3fff7705248 <decoder_process>, object_cbarg=<optimized out>,
pw_cb=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>, pw_cbarg=0x2aa001bdc78) at decoder.c:203
#32 0x000003fff7705990 in decoder_process (params=0x3ffffff8ad8, arg=0x3ffffff8d10) at crypto/encode_decode/decoder_lib.c:1000
#33 0x000003fff7e11634 in p11prov_pem_decoder_p11prov_der_decode (inctx=<optimized out>, cin=<optimized out>,
selection=<optimized out>, object_cb=0x3fff7705248 <decoder_process>, object_cbarg=0x3ffffff8d10,
pw_cb=0x3fff77c0d48 <ossl_pw_passphrase_callback_dec>, pw_cbarg=0x2aa001bdc78) at decoder.c:188
#34 0x000003fff7705990 in decoder_process (params=0x0, arg=0x3ffffff8e58) at crypto/encode_decode/decoder_lib.c:1000
#35 0x000003fff770350e in OSSL_DECODER_from_bio (ctx=0x2aa001bdc40, in=0x2aa001bbe20) at crypto/encode_decode/decoder_lib.c:82
#36 0x000003fff77f5f6e in pem_read_bio_key_decoder (bp=0x2aa001bbe20, x=0x0, cb=0x3fff77c0bf8 <ossl_pw_pem_password>,
u=0x3ffffff9080, libctx=0x0, propq=0x0, selection=135) at crypto/pem/pem_pkey.c:60
#37 0x000003fff77f6962 in pem_read_bio_key (bp=0x2aa001bbe20, x=0x0, cb=0x3fff77f11c0 <PEM_def_callback>, u=0x0, libctx=0x0,
propq=0x0, selection=135) at crypto/pem/pem_pkey.c:246
#38 0x000003fff77f6d50 in PEM_read_bio_PrivateKey_ex (bp=0x2aa001bbe20, x=0x0, cb=0x0, u=0x0, libctx=0x0, propq=0x0)
at crypto/pem/pem_pkey.c:314
#39 0x000003fff77f6dbc in PEM_read_bio_PrivateKey (bp=0x2aa001bbe20, x=0x0, cb=0x0, u=0x0) at crypto/pem/pem_pkey.c:323