From 41a9cb35b0bcd056fc506f985eb3716bd0c41365 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Fri, 16 Jun 2017 22:04:49 +0200 Subject: pkcs11: improved handling of HSMs without CKU_CONTEXT_SPECIFIC support That is, when the HSM returns CKR_USER_NOT_LOGGED_IN, switch to CKU_USER, instead of relying to a fallback within pkcs11_login(). That simplifies login logic. Signed-off-by: Nikos Mavrogiannopoulos --- lib/pkcs11.c | 34 ++++++++++++++-------------------- lib/pkcs11_privkey.c | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/lib/pkcs11.c b/lib/pkcs11.c index b88b5af846..b22d8e8e5b 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -2583,7 +2583,6 @@ pkcs11_login(struct pkcs11_session_info *sinfo, return 0; } - retry_login: /* For a token with a "protected" (out-of-band) authentication * path, calling login with a NULL username is all that is * required. */ @@ -2597,7 +2596,8 @@ pkcs11_login(struct pkcs11_session_info *sinfo, gnutls_assert(); _gnutls_debug_log ("p11: Protected login failed.\n"); - goto login_finished; + ret = GNUTLS_E_PKCS11_ERROR; + goto cleanup; } } @@ -2607,16 +2607,18 @@ pkcs11_login(struct pkcs11_session_info *sinfo, memcpy(&tinfo, &sinfo->tinfo, sizeof(tinfo)); - /* Check whether the session is already logged in, and if so, just skip */ - rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks, - &session_info); - if (rv == CKR_OK && !(flags & SESSION_CONTEXT_SPECIFIC) && - (session_info.state == CKS_RO_USER_FUNCTIONS - || session_info.state == CKS_RW_USER_FUNCTIONS)) { - ret = 0; - _gnutls_debug_log - ("p11: Already logged in\n"); - goto cleanup; + if (!(flags & SESSION_CONTEXT_SPECIFIC)) { + /* Check whether the session is already logged in, and if so, just skip */ + rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks, + &session_info); + if (rv == CKR_OK && + (session_info.state == CKS_RO_USER_FUNCTIONS + || session_info.state == CKS_RW_USER_FUNCTIONS)) { + ret = 0; + _gnutls_debug_log + ("p11: Already logged in\n"); + goto cleanup; + } } /* If login has been attempted once already, check the token @@ -2651,16 +2653,8 @@ pkcs11_login(struct pkcs11_session_info *sinfo, } while (rv == CKR_PIN_INCORRECT); - login_finished: _gnutls_debug_log("p11: Login result = %s (%lu)\n", (rv==0)?"ok":p11_kit_strerror(rv), rv); - if (unlikely(rv == CKR_USER_TYPE_INVALID && user_type == CKU_CONTEXT_SPECIFIC)) { - _gnutls_debug_log("p11: Retrying login with CKU_USER\n"); - /* PKCS#11 v2.10 don't know about CKU_CONTEXT_SPECIFIC */ - user_type = CKU_USER; - goto retry_login; - } - ret = (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv); diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c index 07dc9e0a79..40def6cff5 100644 --- a/lib/pkcs11_privkey.c +++ b/lib/pkcs11_privkey.c @@ -290,8 +290,8 @@ _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key, gnutls_datum_t tmp = { NULL, 0 }; unsigned long siglen; struct pkcs11_session_info *sinfo; - unsigned retried_login = 0; - unsigned flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC; + unsigned req_login = 0; + unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC; PKCS11_CHECK_INIT_PRIVKEY(key); @@ -315,12 +315,12 @@ _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key, } retry_login: - if (key->reauth || retried_login) { - if (retried_login) - flags |= SESSION_FORCE_LOGIN; + if (key->reauth || req_login) { + if (req_login) + login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN; ret = pkcs11_login(&key->sinfo, &key->pin, - key->uinfo, flags); + key->uinfo, login_flags); if (ret < 0) { gnutls_assert(); _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n"); @@ -331,8 +331,8 @@ _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key, /* Work out how long the signature must be: */ rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size, NULL, &siglen); - if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && retried_login == 0)) { - retried_login = 1; + if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) { + req_login = 1; goto retry_login; } @@ -562,7 +562,7 @@ _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key, int ret; struct ck_mechanism mech; unsigned long siglen; - unsigned retried_login = 0; + unsigned req_login = 0; unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC; PKCS11_CHECK_INIT_PRIVKEY(key); @@ -588,9 +588,9 @@ _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key, } retry_login: - if (key->reauth || retried_login) { - if (retried_login) - login_flags |= SESSION_FORCE_LOGIN; + if (key->reauth || req_login) { + if (req_login) + login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN; ret = pkcs11_login(&key->sinfo, &key->pin, key->uinfo, login_flags); @@ -604,8 +604,8 @@ _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key, /* Work out how long the plaintext must be: */ rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data, ciphertext->size, NULL, &siglen); - if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && retried_login == 0)) { - retried_login = 1; + if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) { + req_login = 1; goto retry_login; } -- cgit v1.2.1