From ba7db5662d3dba6ac19daa0494ad1b31f16d2bea Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 16 Nov 2023 15:31:48 +0100 Subject: [PATCH] session: Implement interactive fallback PIN prompt when none provided Fixes: #295 Signed-off-by: Jakub Jelen --- src/provider.h | 1 + src/session.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/provider.h b/src/provider.h index 6d092c24..ad43051c 100644 --- a/src/provider.h +++ b/src/provider.h @@ -22,6 +22,7 @@ #include #include #include +#include #define UNUSED __attribute__((unused)) #define RET_OSSL_OK 1 diff --git a/src/session.c b/src/session.c index a869c8fa..9f7420b0 100644 --- a/src/session.c +++ b/src/session.c @@ -387,6 +387,44 @@ CK_SLOT_ID p11prov_session_slotid(P11PROV_SESSION *session) return session->slotid; } + +static int p11prov_session_get_pin(struct p11prov_slot *slot, char *cb_pin, size_t *cb_pin_len) +{ + char *prompt = NULL; + UI *ui = UI_new_method(NULL); + const char *login_info = p11prov_slot_get_login_info(slot); + int ret; + + P11PROV_debug("Starting internal PIN prompt slot=%p", slot); + + if (ui == NULL) { + ret = RET_OSSL_ERR; + goto err; + } + prompt = UI_construct_prompt(ui, "PIN", login_info); + if (!prompt) { + ret = RET_OSSL_ERR; + goto err; + } + ret = UI_dup_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD, cb_pin, 4, MAX_PIN_LENGTH); + if (ret <= 0) { + ret = RET_OSSL_ERR; + goto err; + } + + if (UI_process(ui)) { + ret = RET_OSSL_ERR; + goto err; + } + + *cb_pin_len = strlen(cb_pin); + +err: + OPENSSL_free(prompt); + UI_free(ui); + return ret; +} + /* returns a locked login_session if _session is not NULL */ static CK_RV token_login(P11PROV_SESSION *session, P11PROV_URI *uri, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg, @@ -400,6 +438,9 @@ static CK_RV token_login(P11PROV_SESSION *session, P11PROV_URI *uri, bool cache = false; CK_RV ret; + P11PROV_debug("Log into the token session=%p uri=%p slot=%p type=%d", + session, uri, slot, user_type); + token = p11prov_slot_get_token(slot); if (!(token->flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { const char *cached_pin = p11prov_slot_get_cached_pin(slot); @@ -431,8 +472,14 @@ static CK_RV token_login(P11PROV_SESSION *session, P11PROV_URI *uri, }; ret = pw_cb(cb_pin, sizeof(cb_pin), &cb_pin_len, params, pw_cbarg); if (ret != RET_OSSL_OK) { - ret = CKR_GENERAL_ERROR; - goto done; + /* this error can mean anything from the user canceling the prompt to no UI method provided + * Fall back to our prompt here */ + ret = p11prov_session_get_pin(slot, (char *)cb_pin, &cb_pin_len); + if (ret != RET_OSSL_OK) { + /* give up */ + ret = CKR_GENERAL_ERROR; + goto done; + } } if (cb_pin_len == 0) { ret = CKR_CANCEL; @@ -443,10 +490,19 @@ static CK_RV token_login(P11PROV_SESSION *session, P11PROV_URI *uri, pinlen = cb_pin_len; cache = p11prov_ctx_cache_pins(session->provctx); - } else { - ret = CKR_CANCEL; - goto done; + /* We are asking the user off-band for the user consent -- from store + * we will always receive non-null (but unusable) callback */ + ret = p11prov_session_get_pin(slot, (char *)cb_pin, &cb_pin_len); + if (ret != RET_OSSL_OK) { + ret = CKR_GENERAL_ERROR; + goto done; + } + + pin = (CK_UTF8CHAR_PTR)cb_pin; + pinlen = strlen(cb_pin); + + cache = p11prov_ctx_cache_pins(session->provctx); } }