aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--openvpn.85
-rw-r--r--options.c10
-rw-r--r--options.h1
-rw-r--r--pkcs11-helper.c673
-rw-r--r--pkcs11-helper.h6
-rw-r--r--pkcs11.c44
-rw-r--r--pkcs11.h3
-rw-r--r--ssl.c2
8 files changed, 438 insertions, 306 deletions
diff --git a/openvpn.8 b/openvpn.8
index 9242ca1..29df0da 100644
--- 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).
diff --git a/options.c b/options.c
index fbaef42..9231110 100644
--- 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"))
diff --git a/options.h b/options.h
index b9f3f12..85f989d 100644
--- 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
diff --git a/pkcs11-helper.c b/pkcs11-helper.c
index 18fa627..9eb074e 100644
--- a/pkcs11-helper.c
+++ b/pkcs11-helper.c
@@ -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) {
@@ -2033,18 +2091,15 @@ 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
diff --git a/pkcs11-helper.h b/pkcs11-helper.h
index dd820ad..df3db66 100644
--- a/pkcs11-helper.h
+++ b/pkcs11-helper.h
@@ -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
);
diff --git a/pkcs11.c b/pkcs11.c
index c0c54ed..240bad6 100644
--- 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;
diff --git a/pkcs11.h b/pkcs11.h
index cb55e06..652647f 100644
--- 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 878a24e..945edd0 100644
--- 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);
}