]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
More PKCS#11 changes.
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Tue, 1 Nov 2005 22:42:58 +0000 (22:42 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Tue, 1 Nov 2005 22:42:58 +0000 (22:42 +0000)
Merged with https://svn.openvpn.net/projects/openvpn/contrib/alon/BETA21@752

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@753 e7ae566f-a301-0410-adde-c780ea21d3b5

openvpn.8
options.c
options.h
pkcs11-helper.c
pkcs11-helper.h
pkcs11.c
pkcs11.h
ssl.c

index 9242ca1b1cb803a205d696a60f9eeccaf390a76e..29df0da0dad4c9b7a2d3fa7747d83a75986b436d 100644 (file)
--- a/openvpn.8
+++ b/openvpn.8
@@ -211,6 +211,7 @@ openvpn \- secure IP tunnel daemon.
 [\ \fB\-\-pkcs11\-id\fR\ \fIname\fR\ ]
 [\ \fB\-\-pkcs11\-pin\-cache\fR\ \fIseconds\fR\ ]
 [\ \fB\-\-pkcs11\-protected\-authentication\fR\ ]
+[\ \fB\-\-pkcs11\-cert\-private\fR\ ]
 [\ \fB\-\-pkcs12\fR\ \fIfile\fR\ ]
 [\ \fB\-\-plugin\fR\ \fImodule\-pathname\ init\-string\fR\ ]
 [\ \fB\-\-port\fR\ \fIport\fR\ ]
@@ -3595,6 +3596,10 @@ Use PKCS#11 protected authentication path, useful for biometric and external
 keypad devices.
 .\"*********************************************************
 .TP
+.B --pkcs11-cert-private
+Set if access to certificate object should be performed after login.
+.\"*********************************************************
+.TP
 .B --cryptoapicert select-string
 Load the certificate and private key from the
 Windows Certificate System Store (Windows Only).
index fbaef42ba306f8decf1a683cb2623c6b08595875..9231110e9b4699c0877a3d6f5185e828244b18fb 100644 (file)
--- a/options.c
+++ b/options.c
@@ -482,6 +482,8 @@ static const char usage_message[] =
   "--pkcs11-pin-cache seconds  : Number of seconds to cache PIN. The default is -1\n"
   "                              cache until token removed.\n"
   "--pkcs11-protected-authentication : Use PKCS#11 protected authentication path.\n"
+  "--pkcs11-cert-private       : Set if login should be performed before\n"
+  "                              certificate can be accessed.\n"
 #endif                 /* ENABLE_PKCS11 */
  "\n"
   "SSL Library information:\n"
@@ -653,6 +655,7 @@ init_options (struct options *o)
 #ifdef ENABLE_PKCS11
   o->pkcs11_pin_cache_period = -1;
   o->pkcs11_protected_authentication = false;
+  o->pkcs11_cert_private = false;
 #endif                 /* ENABLE_PKCS11 */
 }
 
@@ -1223,6 +1226,7 @@ show_settings (const struct options *o)
   SHOW_STR (pkcs11_id);
   SHOW_INT (pkcs11_pin_cache_period);
   SHOW_BOOL (pkcs11_protected_authentication);
+  SHOW_BOOL (pkcs11_cert_private);
 #endif                 /* ENABLE_PKCS11 */
 
 #if P2MP
@@ -4977,6 +4981,12 @@ add_option (struct options *options,
       VERIFY_PERMISSION (OPT_P_GENERAL);
       options->pkcs11_protected_authentication = true;
     }
+  else if (streq (p[0], "pkcs11-cert-private"))
+    {
+      ++i;
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      options->pkcs11_cert_private = true;
+    }
 #endif
 #ifdef TUNSETPERSIST
   else if (streq (p[0], "rmtun"))
index b9f3f127c8cb9d4d8cbc391b32eb29a3af8ab2d5..85f989d2ebe749b83a09e288a3486dc4c8738c1e 100644 (file)
--- a/options.h
+++ b/options.h
@@ -387,6 +387,7 @@ struct options
   const char *pkcs11_id;
   int pkcs11_pin_cache_period;
   bool pkcs11_protected_authentication;
+  bool pkcs11_cert_private;
 #ifdef WIN32
   const char *cryptoapi_cert;
 #endif
index 18fa627e75633f80a0ad5c45da137d6956a110a1..9eb074e009bc6246f6ee4938f25d1af4314f10fd 100644 (file)
@@ -61,6 +61,9 @@ typedef const unsigned char *pkcs11_openssl_d2i_t;
 # endif
 #endif
 
+#define PKCS11H_INVALID_SLOT_ID                ((CK_SLOT_ID)-1)
+#define PKCS11H_INVALID_SESSION_HANDLE ((CK_SESSION_HANDLE)-1)
+#define PKCS11H_INVALID_OBJECT_HANDLE  ((CK_OBJECT_HANDLE)-1)
 
 /*===========================================
  * Low level prototypes
@@ -154,7 +157,8 @@ _pkcs11h_validateSession (
 static
 CK_RV
 _pkcs11h_login (
-       IN const pkcs11h_session_t session
+       IN const pkcs11h_session_t session,
+       IN const bool fPublicOnly
 );
 static
 CK_RV
@@ -175,7 +179,7 @@ _pkcs11h_resetCertificateSession (
 );
 static
 CK_RV
-_pkcs11h_setCertificateSession_Key (
+_pkcs11h_getCertificateKeyAttributes (
        IN const pkcs11h_certificate_t pkcs11h_certificate
 );
 
@@ -718,7 +722,7 @@ _pkcs11h_getSession (
        OUT pkcs11h_session_t * const session
 ) {
        CK_TOKEN_INFO info;
-       CK_SLOT_ID slot = (CK_SLOT_ID)-1;
+       CK_SLOT_ID slot = PKCS11H_INVALID_SLOT_ID;
        CK_RV rv = CKR_OK;
 
        pkcs11h_provider_t provider = NULL;
@@ -819,9 +823,10 @@ _pkcs11h_getSession (
                        if (rv == CKR_OK) {
                                memset (*session, 0, sizeof (struct pkcs11h_session_s));
 
+                               (*session)->fValid = true;
                                (*session)->nReferenceCount = 1;
                                (*session)->fProtectedAuthentication = fProtectedAuthentication;
-                               (*session)->hSession = (CK_SESSION_HANDLE)-1;
+                               (*session)->hSession = PKCS11H_INVALID_SESSION_HANDLE;
                                
                                (*session)->provider = provider;
 
@@ -1031,6 +1036,16 @@ _pkcs11h_getObjectById (
                (void *)handle
        );
 
+       /*
+        * Don't try invalid session
+        */
+       if (
+               rv == CKR_OK &&
+               session->hSession == PKCS11H_INVALID_SESSION_HANDLE
+       ) {
+               rv = CKR_SESSION_HANDLE_INVALID;
+       }
+
        if (rv == CKR_OK) {
                rv = session->provider->f->C_FindObjectsInit (
                        session->hSession,
@@ -1096,20 +1111,24 @@ _pkcs11h_validateSession (
 static
 CK_RV
 _pkcs11h_login (
-       IN const pkcs11h_session_t session
+       IN const pkcs11h_session_t session,
+       IN const bool fPublicOnly
 ) {
-       CK_SLOT_ID slot = (CK_SLOT_ID)-1;
+       CK_SLOT_ID slot = PKCS11H_INVALID_SLOT_ID;
        CK_RV rv = CKR_OK;
 
        PKCS11ASSERT (session!=NULL);
 
        PKCS11DLOG (
                PKCS11_LOG_DEBUG2,
-               "PKCS#11: _pkcs11h_login entry session=%p",
-               (void *)session
+               "PKCS#11: _pkcs11h_login entry session=%p, fPublicOnly=%d",
+               (void *)session,
+               fPublicOnly ? 1 : 0
        );
 
-       _pkcs11h_logout (session);
+       if (rv == CKR_OK) {
+               rv = _pkcs11h_logout (session);
+       }
 
        if (rv == CKR_OK) {
                rv = _pkcs11h_resetSession (session, &slot);
@@ -1126,84 +1145,86 @@ _pkcs11h_login (
        }
 
        if (rv == CKR_OK) {
-               int nRetryCount = 0;
-               do {
-                       CK_UTF8CHAR_PTR utfPIN = NULL;
-                       CK_ULONG lPINLength = 0;
-                       char szPIN[1024];
-
-                       /*
-                        * Assume OK for next iteration
-                        */
-                       rv = CKR_OK;
+               if (!fPublicOnly) {
+                       int nRetryCount = 0;
+                       do {
+                               CK_UTF8CHAR_PTR utfPIN = NULL;
+                               CK_ULONG lPINLength = 0;
+                               char szPIN[1024];
+
+                               /*
+                                * Assume OK for next iteration
+                                */
+                               rv = CKR_OK;
 
-                       if (
-                               rv == CKR_OK &&
-                               !session->fProtectedAuthentication
-                       ) {
-                               PKCS11DLOG (
-                                       PKCS11_LOG_DEBUG1,
-                                       "Calling pin_prompt hook for %s",
-                                       session->szLabel
-                               );
-       
                                if (
-                                       !pkcs11h_data->hooks->pin_prompt (
-                                               pkcs11h_data->hooks->pin_prompt_data,
-                                               session->szLabel,
-                                               szPIN,
-                                               sizeof (szPIN)
-                                       )
+                                       rv == CKR_OK &&
+                                       !session->fProtectedAuthentication
                                ) {
-                                       rv = CKR_FUNCTION_FAILED;
-                               }
-                               else {
-                                       utfPIN = (CK_UTF8CHAR_PTR)szPIN;
-                                       lPINLength = strlen (szPIN);
-                               }
+                                       PKCS11DLOG (
+                                               PKCS11_LOG_DEBUG1,
+                                               "Calling pin_prompt hook for %s",
+                                               session->szLabel
+                                       );
+       
+                                       if (
+                                               !pkcs11h_data->hooks->pin_prompt (
+                                                       pkcs11h_data->hooks->pin_prompt_data,
+                                                       session->szLabel,
+                                                       szPIN,
+                                                       sizeof (szPIN)
+                                               )
+                                       ) {
+                                               rv = CKR_FUNCTION_FAILED;
+                                       }
+                                       else {
+                                               utfPIN = (CK_UTF8CHAR_PTR)szPIN;
+                                               lPINLength = strlen (szPIN);
+                                       }
 
-                               PKCS11DLOG (
-                                       PKCS11_LOG_DEBUG1,
-                                       "pin_prompt hook return rv=%ld",
-                                       rv
-                               );
+                                       PKCS11DLOG (
+                                               PKCS11_LOG_DEBUG1,
+                                               "pin_prompt hook return rv=%ld",
+                                               rv
+                                       );
        
-                       }
+                               }
 
-                       if (session->nPINCachePeriod == PKCS11H_PIN_CACHE_INFINITE) {
-                               session->timePINExpire = 0;
-                       }
-                       else {
-                               session->timePINExpire = (
-                                       time (NULL) +
-                                       (time_t)session->nPINCachePeriod
-                               );
-                       }
-                       if (
-                               rv == CKR_OK &&
-                               (rv = session->provider->f->C_Login (
-                                       session->hSession,
-                                       CKU_USER,
-                                       utfPIN,
-                                       lPINLength
-                               )) != CKR_OK
-                       ) {
-                               if (rv == CKR_USER_ALREADY_LOGGED_IN) {
-                                       rv = CKR_OK;
+                               if (session->nPINCachePeriod == PKCS11H_PIN_CACHE_INFINITE) {
+                                       session->timePINExpire = 0;
+                               }
+                               else {
+                                       session->timePINExpire = (
+                                               time (NULL) +
+                                               (time_t)session->nPINCachePeriod
+                                       );
+                               }
+                               if (
+                                       rv == CKR_OK &&
+                                       (rv = session->provider->f->C_Login (
+                                               session->hSession,
+                                               CKU_USER,
+                                               utfPIN,
+                                               lPINLength
+                                       )) != CKR_OK
+                               ) {
+                                       if (rv == CKR_USER_ALREADY_LOGGED_IN) {
+                                               rv = CKR_OK;
+                                       }
                                }
-                       }
 
-                       /*
-                        * Clean PIN buffer
-                        */
-                       memset (szPIN, 0, sizeof (szPIN));
-               } while (
-                       ++nRetryCount < 3 &&
-                       (
-                               rv == CKR_PIN_INCORRECT ||
-                               rv == CKR_PIN_INVALID
-                       )
-               );
+                               /*
+                                * Clean PIN buffer
+                                */
+                               memset (szPIN, 0, sizeof (szPIN));
+                       } while (
+                               ++nRetryCount < 3 &&
+                               (
+                                       rv == CKR_PIN_INCORRECT ||
+                                       rv == CKR_PIN_INVALID
+                               )
+                       );
+               }
        }
 
        PKCS11DLOG (
@@ -1229,10 +1250,10 @@ _pkcs11h_logout (
                (void *)session
        );
 
-       if (session->hSession != (CK_SESSION_HANDLE)-1) {
+       if (session->hSession != PKCS11H_INVALID_SESSION_HANDLE) {
                session->provider->f->C_Logout (session->hSession);
                session->provider->f->C_CloseSession (session->hSession);
-               session->hSession = (CK_SESSION_HANDLE)-1;
+               session->hSession = PKCS11H_INVALID_SESSION_HANDLE;
        }
 
        PKCS11DLOG (
@@ -1458,45 +1479,9 @@ _pkcs11h_setCertificateSession_Certificate (
        return rv;
 }
 
-CK_RV
-_pkcs11h_resetCertificateSession (
-       IN const pkcs11h_certificate_t pkcs11h_certificate
-) {
-       CK_RV rv = CKR_OK;
-       
-       PKCS11DLOG (
-               PKCS11_LOG_DEBUG2,
-               "PKCS#11: pkcs11h_resetCertificateSession entry pkcs11h_certificate=%p",
-               (void *)pkcs11h_certificate
-       );
-
-       if (rv == CKR_OK) {
-               rv = _pkcs11h_login (
-                       pkcs11h_certificate->session
-               );
-       }
-
-       if (rv == CKR_OK) {
-               rv = _pkcs11h_getObjectById (
-                       pkcs11h_certificate->session,
-                       CKO_PRIVATE_KEY,
-                       pkcs11h_certificate->certificate_id,
-                       pkcs11h_certificate->certificate_id_size,
-                       &pkcs11h_certificate->hKey
-               );
-       }
-
-       PKCS11DLOG (
-               PKCS11_LOG_DEBUG2,
-               "PKCS#11: pkcs11h_freeCertificateSession return"
-       );
-
-       return CKR_OK;
-}
-
 static
 CK_RV
-_pkcs11h_setCertificateSession_Key (
+_pkcs11h_getCertificateKeyAttributes (
        IN const pkcs11h_certificate_t pkcs11h_certificate
 ) {
        CK_RV rv = CKR_OK;
@@ -1508,62 +1493,91 @@ _pkcs11h_setCertificateSession_Key (
                {CKA_SIGN_RECOVER, &key_attrs_sign, sizeof (key_attrs_sign)}
        };
 
+       bool fOpSuccess = false;
+       bool fLoginRetry = false;
+
        PKCS11ASSERT (pkcs11h_certificate!=NULL);
 
        PKCS11DLOG (
                PKCS11_LOG_DEBUG2,
-               "PKCS#11: _pkcs11h_setCertificateSession_Key entry pkcs11h_certificate=%p",
+               "PKCS#11: _pkcs11h_getCertificateKeyAttributes entry pkcs11h_certificate=%p",
                (void *)pkcs11h_certificate
        );
 
-       if (rv == CKR_OK) {
-               rv = _pkcs11h_getObjectById (
-                       pkcs11h_certificate->session,
-                       CKO_PRIVATE_KEY,
-                       pkcs11h_certificate->certificate_id,
-                       pkcs11h_certificate->certificate_id_size,
-                       &pkcs11h_certificate->hKey
-               );
-       }
+       while (rv == CKR_OK && !fOpSuccess) {
 
-       if (!strcmp (pkcs11h_certificate->session->provider->szSignMode, "recover")) {
-               pkcs11h_certificate->signmode = pkcs11h_signmode_recover;
-       }
-       else if (!strcmp (pkcs11h_certificate->session->provider->szSignMode, "sign")) {
-               pkcs11h_certificate->signmode = pkcs11h_signmode_sign;
-       }
-       else {
                if (rv == CKR_OK) {
-                       rv = pkcs11h_certificate->session->provider->f->C_GetAttributeValue (
-                               pkcs11h_certificate->session->hSession,
-                               pkcs11h_certificate->hKey,
-                               key_attrs,
-                               sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
+                       rv = _pkcs11h_getObjectById (
+                               pkcs11h_certificate->session,
+                               CKO_PRIVATE_KEY,
+                               pkcs11h_certificate->certificate_id,
+                               pkcs11h_certificate->certificate_id_size,
+                               &pkcs11h_certificate->hKey
                        );
                }
-               
-               if (rv == CKR_OK) {
-                       if (key_attrs_sign != CK_FALSE) {
-                               pkcs11h_certificate->signmode = pkcs11h_signmode_sign;
-                       }
-                       else if (key_attrs_sign_recover != CK_FALSE) {
+
+               if (pkcs11h_certificate->signmode == pkcs11h_signmode_none) {
+                       if (!strcmp (pkcs11h_certificate->session->provider->szSignMode, "recover")) {
                                pkcs11h_certificate->signmode = pkcs11h_signmode_recover;
                        }
+                       else if (!strcmp (pkcs11h_certificate->session->provider->szSignMode, "sign")) {
+                               pkcs11h_certificate->signmode = pkcs11h_signmode_sign;
+                       }
                        else {
-                               rv = CKR_KEY_TYPE_INCONSISTENT;
+                               if (rv == CKR_OK) {
+                                       rv = pkcs11h_certificate->session->provider->f->C_GetAttributeValue (
+                                               pkcs11h_certificate->session->hSession,
+                                               pkcs11h_certificate->hKey,
+                                               key_attrs,
+                                               sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
+                                       );
+                               }
+               
+                               if (rv == CKR_OK) {
+                                       if (key_attrs_sign != CK_FALSE) {
+                                               pkcs11h_certificate->signmode = pkcs11h_signmode_sign;
+                                       }
+                                       else if (key_attrs_sign_recover != CK_FALSE) {
+                                               pkcs11h_certificate->signmode = pkcs11h_signmode_recover;
+                                       }
+                                       else {
+                                               rv = CKR_KEY_TYPE_INCONSISTENT;
+                                       }
+
+                                       PKCS11DLOG (
+                                               PKCS11_LOG_DEBUG1,
+                                               "PKCS#11: Signature mode selected: %d",
+                                               pkcs11h_certificate->signmode
+                                       );
+                               }
                        }
+               }
 
-                       PKCS11DLOG (
-                               PKCS11_LOG_DEBUG1,
-                               "PKCS#11: Signature mode selected: %d",
-                               pkcs11h_certificate->signmode
-                       );
+
+               if (rv == CKR_OK) {
+                       fOpSuccess = true;
+               }
+               else {
+                       if (!fLoginRetry) {
+                               PKCS11DLOG (
+                                       PKCS11_LOG_DEBUG1,
+                                       "PKCS#11: Get key attributes failed: %ld:'%s'",
+                                       rv,
+                                       pkcs11h_getMessage (rv)
+                               );
+
+                               rv = _pkcs11h_login (
+                                       pkcs11h_certificate->session,
+                                       false
+                               );
+                               fLoginRetry = true;
+                       }
                }
        }
        
        PKCS11DLOG (
                PKCS11_LOG_DEBUG2,
-               "PKCS#11: _pkcs11h_setCertificateSession_Key return rv=%ld-'%s'",
+               "PKCS#11: _pkcs11h_getCertificateKeyAttributes return rv=%ld-'%s'",
                rv,
                pkcs11h_getMessage (rv)
        );
@@ -1571,6 +1585,40 @@ _pkcs11h_setCertificateSession_Key (
        return rv;
 }
 
+CK_RV
+_pkcs11h_resetCertificateSession (
+       IN const pkcs11h_certificate_t pkcs11h_certificate
+) {
+       CK_RV rv = CKR_OK;
+       
+       PKCS11DLOG (
+               PKCS11_LOG_DEBUG2,
+               "PKCS#11: pkcs11h_resetCertificateSession entry pkcs11h_certificate=%p",
+               (void *)pkcs11h_certificate
+       );
+
+       if (rv == CKR_OK) {
+               rv = _pkcs11h_login (
+                       pkcs11h_certificate->session,
+                       false
+               );
+       }
+
+       if (rv == CKR_OK) {
+               /*
+                * Will be performed only once
+                */
+               rv = _pkcs11h_getCertificateKeyAttributes (pkcs11h_certificate); 
+       }
+
+       PKCS11DLOG (
+               PKCS11_LOG_DEBUG2,
+               "PKCS#11: pkcs11h_freeCertificateSession return"
+       );
+
+       return CKR_OK;
+}
+
 /*=======================================
  * Simplified PKCS#11 functions
  */
@@ -1677,15 +1725,21 @@ pkcs11h_terminate () {
                        pkcs11h_data->sessions = pkcs11h_data->sessions->next
                ) {
                        if (s_last != NULL) {
-                               free (s_last);
+                               if (s_last->nReferenceCount == 0) {
+                                       free (s_last);
+                               }
                        }
                        s_last = pkcs11h_data->sessions;
                        
-                       _pkcs11h_logout (pkcs11h_data->sessions);
+                       _pkcs11h_logout (s_last);
+                       s_last->fValid = false;
+                       s_last->provider = NULL;
                }
 
                if (s_last != NULL) {
-                       free (s_last);
+                       if (s_last->nReferenceCount == 0) {
+                               free (s_last);
+                       }
                }
 
                for (
@@ -1698,32 +1752,32 @@ pkcs11h_terminate () {
                        }
                        p_last = pkcs11h_data->providers;
                
-                       if (pkcs11h_data->providers->szName != NULL) {
-                               free (pkcs11h_data->providers->szName);
-                               pkcs11h_data->providers->szName = NULL;
+                       if (p_last->szName != NULL) {
+                               free (p_last->szName);
+                               p_last->szName = NULL;
                        }
 
-                       if (pkcs11h_data->providers->szSignMode != NULL) {
-                               free (pkcs11h_data->providers->szSignMode);
-                               pkcs11h_data->providers->szSignMode = NULL;
+                       if (p_last->szSignMode != NULL) {
+                               free (p_last->szSignMode);
+                               p_last->szSignMode = NULL;
                        }
        
-                       if (pkcs11h_data->providers->fShouldFinalize) {
-                               pkcs11h_data->providers->f->C_Finalize (NULL);
-                               pkcs11h_data->providers->fShouldFinalize = false;
+                       if (p_last->fShouldFinalize) {
+                               p_last->f->C_Finalize (NULL);
+                               p_last->fShouldFinalize = false;
                        }
 
-                       if (pkcs11h_data->providers->f != NULL) {
-                               pkcs11h_data->providers->f = NULL;
+                       if (p_last->f != NULL) {
+                               p_last->f = NULL;
                        }
        
-                       if (pkcs11h_data->providers->hLibrary != NULL) {
+                       if (p_last->hLibrary != NULL) {
 #if defined(WIN32)
-                               FreeLibrary (pkcs11h_data->providers->hLibrary);
+                               FreeLibrary (p_last->hLibrary);
 #else
-                               dlclose (pkcs11h_data->providers->hLibrary);
+                               dlclose (p_last->hLibrary);
 #endif
-                               pkcs11h_data->providers->hLibrary = NULL;
+                               p_last->hLibrary = NULL;
                        }
                }
 
@@ -1961,6 +2015,7 @@ pkcs11h_createCertificateSession (
        IN const char * const szIdType,
        IN const char * const szId,
        IN const bool fProtectedAuthentication,
+       IN const bool fCertPrivate,
        IN const int nPINCachePeriod,
        OUT pkcs11h_certificate_t * const p_pkcs11h_certificate
 ) {
@@ -1980,12 +2035,14 @@ pkcs11h_createCertificateSession (
 
        PKCS11DLOG (
                PKCS11_LOG_DEBUG2,
-               "PKCS#11: pkcs11h_createSession entry szSlotType=%s, szSlot=%s, szIdType=%s, szId=%s, fProtectedAuthentication=%d, p_pkcs11h_certificate=%p",
+               "PKCS#11: pkcs11h_createSession entry szSlotType=%s, szSlot=%s, szIdType=%s, szId=%s, fProtectedAuthentication=%d, fCertPrivate=%d, nPINCachePeriod=%d, p_pkcs11h_certificate=%p",
                szSlotType,
                szSlot,
                szIdType,
                szId,
                fProtectedAuthentication ? 1 : 0,
+               fCertPrivate ? 1 : 0,
+               nPINCachePeriod,
                (void *)p_pkcs11h_certificate
        );
 
@@ -2002,7 +2059,8 @@ pkcs11h_createCertificateSession (
        }
        
        if (rv == CKR_OK) {
-               pkcs11h_certificate->hKey = (CK_OBJECT_HANDLE)-1;
+               pkcs11h_certificate->hKey = PKCS11H_INVALID_OBJECT_HANDLE;
+               pkcs11h_certificate->fCertPrivate = fCertPrivate;
        }
 
        if (rv == CKR_OK) {
@@ -2032,19 +2090,16 @@ pkcs11h_createCertificateSession (
                        }
                }
 
-               if (rv == CKR_OK) {
-                       rv = _pkcs11h_setCertificateSession_Key (
-                               pkcs11h_certificate
-                       );
-               }
-       
                if (rv == CKR_OK) {
                        fOpSuccess = true;
                }
                else {
                        if (!fLogonRetry) {
                                fLogonRetry = true;
-                               rv = _pkcs11h_login (pkcs11h_certificate->session);
+                               rv = _pkcs11h_login (
+                                       pkcs11h_certificate->session,
+                                       !pkcs11h_certificate->fCertPrivate
+                               );
                        }
                }
        }
@@ -2130,11 +2185,38 @@ pkcs11h_sign (
        }
 
        while (rv == CKR_OK && !fOpSuccess) {
-               rv = pkcs11h_certificate->session->provider->f->C_SignInit (
-                       pkcs11h_certificate->session->hSession,
-                       &mech,
-                       pkcs11h_certificate->hKey
-               );
+
+               /*
+                * Don't try invalid object
+                */
+               if (
+                       rv == CKR_OK &&
+                       pkcs11h_certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE
+               ) {
+                       rv = CKR_OBJECT_HANDLE_INVALID;
+               }
+
+               if (rv == CKR_OK) {
+                       rv = pkcs11h_certificate->session->provider->f->C_SignInit (
+                               pkcs11h_certificate->session->hSession,
+                               &mech,
+                               pkcs11h_certificate->hKey
+                       );
+               }
+
+               if (rv == CKR_OK) {
+                       CK_ULONG size = *target_size;
+                       rv = pkcs11h_certificate->session->provider->f->C_Sign (
+                               pkcs11h_certificate->session->hSession,
+                               (CK_BYTE_PTR)source,
+                               source_size,
+                               (CK_BYTE_PTR)target,
+                               &size
+                       );
+
+                       *target_size = (int)size;
+               }
+
 
                if (rv == CKR_OK) {
                        fOpSuccess = true;
@@ -2153,19 +2235,6 @@ pkcs11h_sign (
                }
        }
 
-       if (rv == CKR_OK) {
-               CK_ULONG size = *target_size;
-               rv = pkcs11h_certificate->session->provider->f->C_Sign (
-                       pkcs11h_certificate->session->hSession,
-                       (CK_BYTE_PTR)source,
-                       source_size,
-                       (CK_BYTE_PTR)target,
-                       &size
-               );
-
-               *target_size = (int)size;
-       }
-
        PKCS11DLOG (
                PKCS11_LOG_DEBUG2,
                "PKCS#11: pkcs11h_sign return rv=%ld-'%s'",
@@ -2214,11 +2283,38 @@ pkcs11h_signRecover (
        }
 
        while (rv == CKR_OK && !fOpSuccess) {
-               rv = pkcs11h_certificate->session->provider->f->C_SignRecoverInit (
-                       pkcs11h_certificate->session->hSession,
-                       &mech,
-                       pkcs11h_certificate->hKey
-               );
+
+               /*
+                * Don't try invalid object
+                */
+               if (
+                       rv == CKR_OK &&
+                       pkcs11h_certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE
+               ) {
+                       rv = CKR_OBJECT_HANDLE_INVALID;
+               }
+
+               if (rv == CKR_OK) {
+                       rv = pkcs11h_certificate->session->provider->f->C_SignRecoverInit (
+                               pkcs11h_certificate->session->hSession,
+                               &mech,
+                               pkcs11h_certificate->hKey
+                       );
+               }
+
+               if (rv == CKR_OK) {
+                       CK_ULONG size = *target_size;
+                       rv = pkcs11h_certificate->session->provider->f->C_SignRecover (
+                               pkcs11h_certificate->session->hSession,
+                               (CK_BYTE_PTR)source,
+                               source_size,
+                               (CK_BYTE_PTR)target,
+                               &size
+                       );
+
+                       *target_size = (int)size;
+               }
+
 
                if (rv == CKR_OK) {
                        fOpSuccess = true;
@@ -2237,19 +2333,6 @@ pkcs11h_signRecover (
                }
        }
 
-       if (rv == CKR_OK) {
-               CK_ULONG size = *target_size;
-               rv = pkcs11h_certificate->session->provider->f->C_SignRecover (
-                       pkcs11h_certificate->session->hSession,
-                       (CK_BYTE_PTR)source,
-                       source_size,
-                       (CK_BYTE_PTR)target,
-                       &size
-               );
-
-               *target_size = (int)size;
-       }
-
        PKCS11DLOG (
                PKCS11_LOG_DEBUG2,
                "PKCS#11: pkcs11h_signRecover return rv=%ld-'%s'",
@@ -2299,11 +2382,37 @@ pkcs11h_decrypt (
        }
 
        while (rv == CKR_OK && !fOpSuccess) {
-               rv = pkcs11h_certificate->session->provider->f->C_DecryptInit (
-                       pkcs11h_certificate->session->hSession,
-                       &mech,
-                       pkcs11h_certificate->hKey
-               );
+
+               /*
+                * Don't try invalid object
+                */
+               if (
+                       rv == CKR_OK &&
+                       pkcs11h_certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE
+               ) {
+                       rv = CKR_OBJECT_HANDLE_INVALID;
+               }
+
+               if (rv == CKR_OK) {
+                       rv = pkcs11h_certificate->session->provider->f->C_DecryptInit (
+                               pkcs11h_certificate->session->hSession,
+                               &mech,
+                               pkcs11h_certificate->hKey
+                       );
+               }
+
+               if (rv == CKR_OK) {
+                       size = *target_size;
+                       rv = pkcs11h_certificate->session->provider->f->C_Decrypt (
+                               pkcs11h_certificate->session->hSession,
+                               (CK_BYTE_PTR)source,
+                               source_size,
+                               (CK_BYTE_PTR)target,
+                               &size
+                       );
+
+                       *target_size = (int)size;
+               }
 
                if (rv == CKR_OK) {
                        fOpSuccess = true;
@@ -2322,19 +2431,6 @@ pkcs11h_decrypt (
                }
        }
 
-       if (rv == CKR_OK) {
-               size = *target_size;
-               rv = pkcs11h_certificate->session->provider->f->C_Decrypt (
-                       pkcs11h_certificate->session->hSession,
-                       (CK_BYTE_PTR)source,
-                       source_size,
-                       (CK_BYTE_PTR)target,
-                       &size
-               );
-
-               *target_size = (int)size;
-       }
-
        PKCS11DLOG (
                PKCS11_LOG_DEBUG2,
                "PKCS#11: pkcs11h_decrypt return rv=%ld-'%s'",
@@ -2524,9 +2620,11 @@ _pkcs11h_openssl_get_pkcs11h_certificate (
        pkcs11h_openssl_session_t session = _pkcs11h_openssl_get_pkcs11h_openssl_session (rsa);
        
        PKCS11ASSERT (session!=NULL);
-       PKCS11ASSERT (session->pkcs11h_certificate!=NULL);
+       PKCS11ASSERT (session->certificate!=NULL);
+       PKCS11ASSERT (session->certificate->session!=NULL);
+       PKCS11ASSERT (session->certificate->session->fValid);
 
-       return session->pkcs11h_certificate;
+       return session->certificate;
 }
 
 #if OPENSSL_VERSION_NUMBER < 0x00907000L
@@ -2696,46 +2794,61 @@ _pkcs11h_openssl_sign (
                rv = CKR_KEY_SIZE_RANGE;
        }
 
-       PKCS11DLOG (
-               PKCS11_LOG_DEBUG1,
-               "PKCS#11: Performing signature"
-       );
+       /*
+        * Get key attributes
+        * so signature mode will
+        * be available
+        */
+       if (rv == CKR_OK) {
+               rv = _pkcs11h_getCertificateKeyAttributes (pkcs11h_certificate);
+       }
 
-       *siglen = myrsa_size;
+       if (rv == CKR_OK) {
+               PKCS11DLOG (
+                       PKCS11_LOG_DEBUG1,
+                       "PKCS#11: Performing signature"
+               );
 
-       switch (pkcs11h_certificate->signmode) {
-               case pkcs11h_signmode_sign:
-                       if (
-                               (rv = pkcs11h_sign (
-                                       pkcs11h_certificate,
-                                       CKM_RSA_PKCS,
-                                       enc,
-                                       enc_len,
-                                       sigret,
-                                       siglen
-                               )) != CKR_OK
-                       ) {
-                               PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11h_getMessage (rv));
-                       }
-               break;
-               case pkcs11h_signmode_recover:
-                       if (
-                               (rv = pkcs11h_signRecover (
-                                       pkcs11h_certificate,
-                                       CKM_RSA_PKCS,
-                                       enc,
-                                       enc_len,
-                                       sigret,
-                                       siglen
-                               )) != CKR_OK
-                       ) {
-                               PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot perform signature-recover %ld:'%s'", rv, pkcs11h_getMessage (rv));
-                       }
-               break;
-               default:
-                       rv = CKR_FUNCTION_REJECTED;
-                       PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Invalid signature mode");
-               break;
+               *siglen = myrsa_size;
+
+               switch (pkcs11h_certificate->signmode) {
+                       case pkcs11h_signmode_sign:
+                               if (
+                                       (rv = pkcs11h_sign (
+                                               pkcs11h_certificate,
+                                               CKM_RSA_PKCS,
+                                               enc,
+                                               enc_len,
+                                               sigret,
+                                               siglen
+                                       )) != CKR_OK
+                               ) {
+                                       PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11h_getMessage (rv));
+                               }
+                       break;
+                       case pkcs11h_signmode_recover:
+                               if (
+                                       (rv = pkcs11h_signRecover (
+                                               pkcs11h_certificate,
+                                               CKM_RSA_PKCS,
+                                               enc,
+                                               enc_len,
+                                               sigret,
+                                               siglen
+                                       )) != CKR_OK
+                               ) {
+                                       PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot perform signature-recover %ld:'%s'", rv, pkcs11h_getMessage (rv));
+                               }
+                       break;
+                       default:
+                               rv = CKR_FUNCTION_REJECTED;
+                               PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Invalid signature mode");
+                       break;
+               }
+       }
+
+       if (enc_alloc != NULL) {
+               free (enc_alloc);
        }
        
        PKCS11DLOG (
@@ -2745,10 +2858,6 @@ _pkcs11h_openssl_sign (
                pkcs11h_getMessage (rv)
        );
 
-       if (enc_alloc != NULL) {
-               free (enc_alloc);
-       }
-       
        return rv == CKR_OK ? 1 : -1; 
 }
 
@@ -2858,9 +2967,9 @@ pkcs11h_openssl_freeSession (
                        X509_free (pkcs11h_openssl_session->x509);
                        pkcs11h_openssl_session->x509 = NULL;
                }
-               if (pkcs11h_openssl_session->pkcs11h_certificate != NULL) {
-                       pkcs11h_freeCertificateSession (pkcs11h_openssl_session->pkcs11h_certificate);
-                       pkcs11h_openssl_session->pkcs11h_certificate = NULL;
+               if (pkcs11h_openssl_session->certificate != NULL) {
+                       pkcs11h_freeCertificateSession (pkcs11h_openssl_session->certificate);
+                       pkcs11h_openssl_session->certificate = NULL;
                }
                
                free (pkcs11h_openssl_session);
@@ -2907,7 +3016,7 @@ pkcs11h_openssl_getRSA (
        if (
                fOK &&
                (rv = pkcs11h_getCertificate (
-                       pkcs11h_openssl_session->pkcs11h_certificate,
+                       pkcs11h_openssl_session->certificate,
                        certificate,
                        &certificate_size
                )) != CKR_OK
index dd820ad597e2e8c159e26ed20648d20152dcb225..df3db66603c723f6f3ae66abb443b34e96d0bf5c 100644 (file)
@@ -89,6 +89,7 @@ typedef struct pkcs11h_session_s {
        struct pkcs11h_session_s *next;
 
        int nReferenceCount;
+       bool fValid;
 
        pkcs11h_provider_t provider;
 
@@ -119,6 +120,8 @@ typedef struct pkcs11h_certificate_s {
        } signmode;
 
        CK_OBJECT_HANDLE hKey;
+
+       bool fCertPrivate;
 } *pkcs11h_certificate_t;
 
 typedef struct pkcs11h_data_s {
@@ -138,7 +141,7 @@ typedef struct pkcs11h_openssl_session_s {
        X509 *x509;
        RSA_METHOD smart_rsa;
        int (*orig_finish)(RSA *rsa);
-       pkcs11h_certificate_t pkcs11h_certificate;
+       pkcs11h_certificate_t certificate;
 } *pkcs11h_openssl_session_t;
 
 CK_RV
@@ -180,6 +183,7 @@ pkcs11h_createCertificateSession (
        IN const char * const szIdType,
        IN const char * const szId,
        IN const bool fProtectedAuthentication,
+       IN const bool fCertPrivate,
        IN const int nPINCachePeriod,
        OUT pkcs11h_certificate_t * const pkcs11h_certificate
 );
index c0c54edf2857c69630d3b003ce3604863f3744b0..240bad6d9ac34fa8ba135bca37cfcd6be8dcabfd 100644 (file)
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -220,11 +220,12 @@ pkcs11_addProvider (
 int
 SSL_CTX_use_pkcs11 (
        IN OUT SSL_CTX * const ssl_ctx,
-       IN const char * const pkcs11h_slot_type,
-       IN const char * const pkcs11h_slot,
-       IN const char * const pkcs11h_id_type,
-       IN const char * const pkcs11h_id,
-       IN const bool pkcs11h_protected_authentication
+       IN const char * const pkcs11_slot_type,
+       IN const char * const pkcs11_slot,
+       IN const char * const pkcs11_id_type,
+       IN const char * const pkcs11_id,
+       IN const bool pkcs11_protected_authentication,
+       IN const bool pkcs11_cert_private
 ) {
        X509 *x509 = NULL;
        RSA *rsa = NULL;
@@ -235,20 +236,20 @@ SSL_CTX_use_pkcs11 (
 
        PKCS11LOG (
                PKCS11_LOG_DEBUG2,
-               "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11h_slot_type='%s', pkcs11h_slot='%s', pkcs11h_id_type='%s', pkcs11h_id='%s', pkcs11h_protected_authentication=%d",
+               "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_slot_type='%s', pkcs11_slot='%s', pkcs11_id_type='%s', pkcs11_id='%s', pkcs11_protected_authentication=%d",
                (void *)ssl_ctx,
-               pkcs11h_slot_type,
-               pkcs11h_slot,
-               pkcs11h_id_type,
-               pkcs11h_id,
-               pkcs11h_protected_authentication ? 1 : 0
+               pkcs11_slot_type,
+               pkcs11_slot,
+               pkcs11_id_type,
+               pkcs11_id,
+               pkcs11_protected_authentication ? 1 : 0
        );
 
        PKCS11ASSERT (ssl_ctx!=NULL);
-       PKCS11ASSERT (pkcs11h_slot_type!=NULL);
-       PKCS11ASSERT (pkcs11h_slot!=NULL);
-       PKCS11ASSERT (pkcs11h_id_type!=NULL);
-       PKCS11ASSERT (pkcs11h_id!=NULL);
+       PKCS11ASSERT (pkcs11_slot_type!=NULL);
+       PKCS11ASSERT (pkcs11_slot!=NULL);
+       PKCS11ASSERT (pkcs11_id_type!=NULL);
+       PKCS11ASSERT (pkcs11_id!=NULL);
 
        if (
                fOK &&
@@ -261,13 +262,14 @@ SSL_CTX_use_pkcs11 (
        if (
                fOK &&
                (rv = pkcs11h_createCertificateSession (
-                       pkcs11h_slot_type,
-                       pkcs11h_slot,
-                       pkcs11h_id_type,
-                       pkcs11h_id,
-                       pkcs11h_protected_authentication,
+                       pkcs11_slot_type,
+                       pkcs11_slot,
+                       pkcs11_id_type,
+                       pkcs11_id,
+                       pkcs11_protected_authentication,
+                       pkcs11_cert_private,
                        PKCS11H_PIN_CACHE_INFINITE,
-                       &pkcs11h_openssl_session->pkcs11h_certificate
+                       &pkcs11h_openssl_session->certificate
                )) != CKR_OK
        ) {
                fOK = false;
index cb55e06d0dddbaf2a556322a4654e2abeeaa4b5a..652647fcad9571639c7742774ed34dbd95586c32 100644 (file)
--- a/pkcs11.h
+++ b/pkcs11.h
@@ -53,7 +53,8 @@ SSL_CTX_use_pkcs11 (
        const char * const pkcs11_slot,
        const char * const pkcs11_id_type,
        const char * const pkcs11_id,
-       const bool pkcs11_protected_authentication
+       const bool pkcs11_protected_authentication,
+       const bool pkcs11_cert_private
 );
 
 void
diff --git a/ssl.c b/ssl.c
index 878a24e970a7c140207704c4e920752d2ea751d0..945edd0c390238815782434b5793c25364979601 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -853,7 +853,7 @@ init_ssl (const struct options *options)
       if (options->pkcs11_providers[0])
        {
         /* Load Certificate and Private Key */
-       if (!SSL_CTX_use_pkcs11 (ctx, options->pkcs11_slot_type, options->pkcs11_slot, options->pkcs11_id_type, options->pkcs11_id, options->pkcs11_protected_authentication))
+       if (!SSL_CTX_use_pkcs11 (ctx, options->pkcs11_slot_type, options->pkcs11_slot, options->pkcs11_id_type, options->pkcs11_id, options->pkcs11_protected_authentication, options->pkcs11_cert_private))
          msg (M_SSLERR, "Cannot load certificate \"%s:%s\" from slot \"%s:%s\" using PKCS#11 interface",
                options->pkcs11_id_type, options->pkcs11_id, options->pkcs11_slot_type, options->pkcs11_slot);
        }