From b585364aed8ef6fd7641cbc8f0f79217df4057d5 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 1 Nov 2005 22:42:58 +0000 Subject: More PKCS#11 changes. 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 | 5 + options.c | 10 + options.h | 1 + pkcs11-helper.c | 673 ++++++++++++++++++++++++++++++++------------------------ pkcs11-helper.h | 6 +- pkcs11.c | 44 ++-- pkcs11.h | 3 +- ssl.c | 2 +- 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) { @@ -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 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); } -- cgit v1.2.3