From 594cf139ffb05711e5aa3653d1f84a383dfde9f0 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 | 91 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 76 insertions(+), 16 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 7a8cc9f6..7adcd0ff 100644 --- a/src/session.c +++ b/src/session.c @@ -387,6 +387,45 @@ CK_SLOT_ID p11prov_session_slotid(P11PROV_SESSION *session) return session->slotid; } +static int p11prov_session_prompt_for_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 +439,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); @@ -421,18 +463,39 @@ static CK_RV token_login(P11PROV_SESSION *session, P11PROV_URI *uri, } if (pin) { pinlen = strlen((const char *)pin); - } else if (pw_cb) { - const char *login_info = p11prov_slot_get_login_info(slot); - OSSL_PARAM params[2] = { - OSSL_PARAM_DEFN(OSSL_PASSPHRASE_PARAM_INFO, - OSSL_PARAM_UTF8_STRING, (void *)login_info, - strlen(login_info)), - OSSL_PARAM_END, - }; - 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; + } else { + if (pw_cb) { + const char *login_info = p11prov_slot_get_login_info(slot); + OSSL_PARAM params[2] = { + OSSL_PARAM_DEFN(OSSL_PASSPHRASE_PARAM_INFO, + OSSL_PARAM_UTF8_STRING, (void *)login_info, + strlen(login_info)), + OSSL_PARAM_END, + }; + ret = pw_cb(cb_pin, sizeof(cb_pin), &cb_pin_len, params, + pw_cbarg); + if (ret != RET_OSSL_OK) { + /* 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_prompt_for_pin(slot, (char *)cb_pin, + &cb_pin_len); + if (ret != RET_OSSL_OK) { + /* give up */ + ret = CKR_GENERAL_ERROR; + goto done; + } + } + } else { + /* 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_prompt_for_pin(slot, (char *)cb_pin, + &cb_pin_len); + if (ret != RET_OSSL_OK) { + ret = CKR_GENERAL_ERROR; + goto done; + } } if (cb_pin_len == 0) { ret = CKR_CANCEL; @@ -443,10 +506,6 @@ 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; } }