]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
pkcs11: improved handling of HSMs without CKU_CONTEXT_SPECIFIC support
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 16 Jun 2017 20:04:49 +0000 (22:04 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 17 Jun 2017 12:04:35 +0000 (14:04 +0200)
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 <nmav@gnutls.org>
lib/pkcs11.c
lib/pkcs11_privkey.c

index b88b5af84681080c6091b2be23e634be5c6d7599..b22d8e8e5bf20fcbbc3b00545a4409ad7e6ebaf9 100644 (file)
@@ -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);
 
index 07dc9e0a793f283609827172779c9ed33a16234b..40def6cff5df9817d1c40f06ccdd68148988220b 100644 (file)
@@ -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;
        }