From 6835555ef8ede3ac0997a0fe8365aa95391b32a3 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 17 Oct 2005 07:39:41 +0000 Subject: Brought up-to-date with Alon's PKCS11 patch at https://svn.openvpn.net/projects/openvpn/contrib/alon/BETA21/openvpn@645 Pre-2.1_beta5 git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@648 e7ae566f-a301-0410-adde-c780ea21d3b5 --- pkcs11.c | 1534 ++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 1049 insertions(+), 485 deletions(-) (limited to 'pkcs11.c') diff --git a/pkcs11.c b/pkcs11.c index cee178e..54dc532 100644 --- a/pkcs11.c +++ b/pkcs11.c @@ -57,6 +57,12 @@ #include "pkcs11.h" +/*=========================================== + * MACROS + */ + +#define snprintf openvpn_snprintf + /*=========================================== * Constants */ @@ -78,6 +84,25 @@ * Types */ +typedef bool (*pkcs11_hook_card_prompt_t)( + IN const void *pData, + IN const char * const szLabel +); + +typedef bool (*pkcs11_hook_pin_prompt_t)( + IN const void *pData, + IN const char * const szLabel, + OUT char * const szPIN, + IN const size_t nMaxPIN +); + +typedef struct pkcs11_hooks_s { + void *card_prompt_data; + void *pin_prompt_data; + pkcs11_hook_card_prompt_t card_prompt; + pkcs11_hook_pin_prompt_t pin_prompt; +} *pkcs11_hooks_t; + typedef struct pkcs11_provider_s { struct pkcs11_provider_s *next; @@ -91,27 +116,39 @@ typedef struct pkcs11_provider_s { CK_FUNCTION_LIST_PTR f; bool fShouldFinalize; char *szSignMode; + } *pkcs11_provider_t; typedef struct pkcs11_session_s { pkcs11_provider_t provider; + bool fProtectedAuthentication; + + char szLabel[sizeof (((CK_TOKEN_INFO *)NULL)->label)+1]; + CK_CHAR serialNumber[sizeof (((CK_TOKEN_INFO *)NULL)->serialNumber)]; + unsigned char *certificate; - int certificate_size; + size_t certificate_size; unsigned char *certificate_id; - int certificate_id_size; - - char *szPIN; - bool fLoginFailed; + size_t certificate_id_size; CK_SLOT_ID slot; bool fKeySignRecover; CK_SESSION_HANDLE session; CK_OBJECT_HANDLE key; + + time_t timePINExpire; } *pkcs11_session_t; +typedef struct pkcs11_data_s { + bool fInitialized; + int nPINCachePeriod; + pkcs11_provider_t providers; + pkcs11_hooks_t hooks; +} *pkcs11_data_t; + /*=========================================== * Low level prototypes */ @@ -121,14 +158,14 @@ void _fixupFixedString ( IN const char * const szSource, OUT char * const szTarget, /* MUST BE >= nLength+1 */ - IN const int nLength /* FIXED STRING LENGTH */ + IN const size_t nLength /* FIXED STRING LENGTH */ ); static void _hexToBinary ( IN const char * const szSource, OUT unsigned char * const target, - IN OUT int * const target_size + IN OUT size_t * const target_size ); static CK_RV @@ -154,11 +191,21 @@ _pkcs11_getObjectById ( IN const pkcs11_session_t pkcs11_session, IN const CK_OBJECT_CLASS class, IN const unsigned char * const id, - IN const int id_size, + IN const size_t id_size, OUT CK_OBJECT_HANDLE * const handle ); static CK_RV +_pkcs11_setSessionTokenInfo ( + IN const pkcs11_session_t pkcs11_session +); +static +CK_RV +_pkcs11_resetSlot ( + IN const pkcs11_session_t pkcs11_session +); +static +CK_RV _pkcs11_loadCertificate ( IN const pkcs11_session_t pkcs11_session, IN const char * const szIdType, @@ -173,15 +220,66 @@ static bool _isBetterCertificate ( IN const unsigned char * const pCurrent, - IN const int nCurrentSize, + IN const size_t nCurrentSize, IN const unsigned char * const pNew, - IN const int nNewSize + IN const size_t nNewSize +); +static +CK_RV +_pkcs11_validateSession ( + IN const pkcs11_session_t pkcs11_session +); +static +CK_RV +_pkcs11_login ( + IN const pkcs11_session_t pkcs11_session +); +static +CK_RV +_pkcs11_logout ( + IN const pkcs11_session_t pkcs11_session ); /*========================================= * Simplified functions prototypes */ - +static +bool +_pkcs11_hooks_card_prompt_default ( + IN const void *pData, + IN const char * const szLabel +); +static +bool +_pkcs11_hooks_pin_prompt_default ( + IN const void *pData, + IN const char * const szLabel, + OUT char * const szPIN, + IN const size_t nMaxPIN +); +static +CK_RV +pkcs11_initialize (); +static +CK_RV +pkcs11_terminate (); +static +CK_RV +pkcs11_setCardPromptHook ( + IN const pkcs11_hook_card_prompt_t hook, + IN void * const pData +); +static +CK_RV +pkcs11_setPINPromptHook ( + IN const pkcs11_hook_pin_prompt_t hook, + IN void * const pData +); +static +CK_RV +pkcs11_setPINCachePeriod ( + IN const int nPINCachePeriod +); static CK_RV pkcs11_addProvider ( @@ -190,7 +288,7 @@ pkcs11_addProvider ( ); static CK_RV -pkcs11_finalize (); +pkcs11_forkFixup (); static CK_RV pkcs11_createSession ( @@ -198,7 +296,6 @@ pkcs11_createSession ( IN const char * const szSlot, IN const char * const szIdType, IN const char * const szId, - IN const char * const szPIN, IN const bool fProtectedAuthentication, OUT pkcs11_session_t * const pkcs11_session ); @@ -209,23 +306,13 @@ pkcs11_freeSession ( ); static CK_RV -pkcs11_login ( - IN const pkcs11_session_t pkcs11_session -); -static -CK_RV -pkcs11_logout ( - IN const pkcs11_session_t pkcs11_session -); -static -CK_RV pkcs11_sign ( IN const pkcs11_session_t pkcs11_session, IN const CK_MECHANISM_TYPE mech_type, IN const unsigned char * const source, - IN const int source_size, + IN const size_t source_size, OUT unsigned char * const target, - IN OUT int * const target_size + IN OUT size_t * const target_size ); static CK_RV @@ -233,9 +320,9 @@ pkcs11_signRecover ( IN const pkcs11_session_t pkcs11_session, IN const CK_MECHANISM_TYPE mech_type, IN const unsigned char * const source, - IN const int source_size, + IN const size_t source_size, OUT unsigned char * const target, - IN OUT int * const target_size + IN OUT size_t * const target_size ); static CK_RV @@ -243,16 +330,16 @@ pkcs11_decrypt ( IN const pkcs11_session_t pkcs11_session, IN const CK_MECHANISM_TYPE mech_type, IN const unsigned char * const source, - IN const int source_size, + IN const size_t source_size, OUT unsigned char * const target, - IN OUT int * const target_size + IN OUT size_t * const target_size ); static CK_RV pkcs11_getCertificate ( IN const pkcs11_session_t pkcs11_session, - OUT char * const certificate, - IN OUT int * const certificate_size + OUT unsigned char * const certificate, + IN OUT size_t * const certificate_size ); static char * @@ -264,7 +351,7 @@ pkcs11_getMessage ( * Static data */ -static pkcs11_provider_t pkcs11_provider = NULL; +static pkcs11_data_t pkcs11_data = NULL; /*========================================== * Internal utility functions @@ -275,7 +362,7 @@ void _fixupFixedString ( IN const char * const szSource, OUT char * const szTarget, /* MUST BE >= nLength+1 */ - IN const int nLength /* FIXED STRING LENGTH */ + IN const size_t nLength /* FIXED STRING LENGTH */ ) { char *p; @@ -297,9 +384,9 @@ void _hexToBinary ( IN const char * const szSource, OUT unsigned char * const target, - IN OUT int * const target_size + IN OUT size_t * const target_size ) { - int target_max_size; + size_t target_max_size; const char *p; char buf[3] = {'\0', '\0', '\0'}; int i = 0; @@ -317,7 +404,7 @@ _hexToBinary ( buf[i%2] = *p; if ((i%2) == 1) { - int v; + unsigned v; sscanf (buf, "%x", &v); target[*target_size] = v & 0xff; (*target_size)++; @@ -333,9 +420,9 @@ static bool _isBetterCertificate ( IN const unsigned char * const pCurrent, - IN const int nCurrentSize, + IN const size_t nCurrentSize, IN const unsigned char * const pNew, - IN const int nNewSize + IN const size_t nNewSize ) { /* * This function compare the notBefore @@ -427,7 +514,7 @@ _pkcs11_getSlotById ( } for ( - i=0, provider=pkcs11_provider; + i=0, provider=pkcs11_data->providers; i < provider_number && provider != NULL; i++, provider = provider->next ); @@ -453,9 +540,6 @@ _pkcs11_getSlotByName ( IN const pkcs11_session_t pkcs11_session, IN const char * const szName ) { - CK_SLOT_ID slots[1024]; - CK_ULONG slotnum; - CK_SLOT_ID s; CK_RV rv; pkcs11_provider_t provider; @@ -465,13 +549,16 @@ _pkcs11_getSlotByName ( ASSERT (szName!=NULL); for ( - provider = pkcs11_provider; + provider = pkcs11_data->providers; ( provider != NULL && !fFound ); provider = provider->next ) { + CK_SLOT_ID slots[1024]; + CK_ULONG slotnum; + if (!provider->fEnabled) { continue; } @@ -484,6 +571,8 @@ _pkcs11_getSlotByName ( &slotnum )) == CKR_OK ) { + CK_SLOT_ID s; + for (s=0;!fFound && sproviders; ( provider != NULL && !fFound ); provider = provider->next ) { + CK_SLOT_ID slots[1024]; + CK_ULONG slotnum; + if (!provider->fEnabled) { continue; } @@ -551,6 +640,8 @@ _pkcs11_getSlotByLabel ( &slotnum )) == CKR_OK ) { + CK_SLOT_ID s; + for (s=0;!fFound && sprovider->f->C_GetTokenInfo ( + pkcs11_session->slot, + &info + )) == CKR_OK + ) { + _fixupFixedString ( + (char *)info.label, + pkcs11_session->szLabel, + sizeof (info.label) + ); + + memmove ( + pkcs11_session->serialNumber, + info.serialNumber, + sizeof (pkcs11_session->serialNumber) + ); + } + + return rv; +} + +static +CK_RV +_pkcs11_resetSlot ( + IN const pkcs11_session_t pkcs11_session +) { + CK_SLOT_ID slots[1024]; + CK_ULONG slotnum; + CK_RV rv; + bool fFound = false; + bool fCancel = false; + + ASSERT (pkcs11_session!=NULL); + + do { + slotnum = sizeof (slots) / sizeof (CK_SLOT_ID); + if ( + (rv = pkcs11_session->provider->f->C_GetSlotList ( + TRUE, + slots, + &slotnum + )) == CKR_OK + ) { + CK_SLOT_ID s; + + for (s=0;!fFound && sprovider->f->C_GetTokenInfo ( + slots[s], + &info + )) == CKR_OK + ) { + if ( + !memcmp ( + pkcs11_session->serialNumber, + info.serialNumber, + sizeof (pkcs11_session->serialNumber) + ) + ) { + pkcs11_session->slot = slots[s]; + fFound = true; + } + } + } + } + + if (!fFound) { + fCancel = !pkcs11_data->hooks->card_prompt ( + pkcs11_data->hooks->card_prompt_data, + pkcs11_session->szLabel + ); + } + } while (!fFound && !fCancel); + + return fFound ? CKR_OK : CKR_SLOT_ID_INVALID; +} + static CK_RV _pkcs11_getObjectById ( IN const pkcs11_session_t pkcs11_session, IN const CK_OBJECT_CLASS class, IN const unsigned char * const id, - IN const int id_size, + IN const size_t id_size, OUT CK_OBJECT_HANDLE * const handle ) { CK_ULONG count; - bool fFound = false; - CK_RV rv; + CK_RV rv = CKR_OK; CK_ATTRIBUTE filter[] = { {CKA_CLASS, (void *)&class, sizeof (class)}, @@ -603,34 +783,35 @@ _pkcs11_getObjectById ( ASSERT (id!=NULL); ASSERT (handle!=NULL); - if ( - (rv = pkcs11_session->provider->f->C_FindObjectsInit ( + if (rv == CKR_OK) { + rv = pkcs11_session->provider->f->C_FindObjectsInit ( pkcs11_session->session, filter, sizeof (filter) / sizeof (CK_ATTRIBUTE) - )) != CKR_OK - ) { - return rv; + ); } - if ( - (rv = pkcs11_session->provider->f->C_FindObjects ( + if (rv == CKR_OK) { + rv = pkcs11_session->provider->f->C_FindObjects ( pkcs11_session->session, handle, 1, &count - )) == CKR_OK + ); + } + + if ( + rv == CKR_OK && + count == 0 ) { - if (count > 0) { - fFound = true; - } + rv = CKR_FUNCTION_REJECTED; } pkcs11_session->provider->f->C_FindObjectsFinal ( pkcs11_session->session ); - return fFound ? CKR_OK : CKR_FUNCTION_REJECTED; + return rv; } static @@ -674,7 +855,7 @@ _pkcs11_loadCertificate ( ); } else if (!strcmp (szIdType, "id")) { - int s = sizeof (cert_filter_by); + size_t s = sizeof (cert_filter_by); cert_filter[1].type = CKA_ID; _hexToBinary ( @@ -876,155 +1057,432 @@ _pkcs11_loadKeyProperties ( return CKR_OK; } -/*======================================= - * Simplified PKCS#11 functions - */ +static +CK_RV +_pkcs11_validateSession ( + IN const pkcs11_session_t pkcs11_session +) { + if ( + pkcs11_session->timePINExpire != (time_t)0 && + pkcs11_session->timePINExpire < time (NULL) + ) { + _pkcs11_logout (pkcs11_session); + } + return CKR_OK; +} static CK_RV -pkcs11_addProvider ( - IN const char * const szProvider, - IN const char * const szSignMode +_pkcs11_login ( + IN const pkcs11_session_t pkcs11_session ) { - pkcs11_provider_t provider = NULL; - CK_C_GetFunctionList gfl = NULL; CK_RV rv = CKR_OK; - ASSERT (szProvider!=NULL); - if ( - rv == CKR_OK && - (provider = (pkcs11_provider_t)malloc (sizeof (struct pkcs11_provider_s))) == NULL - ) { - rv = CKR_HOST_MEMORY; - } + ASSERT (pkcs11_session!=NULL); + + _pkcs11_logout (pkcs11_session); if (rv == CKR_OK) { - memset (provider, 0, sizeof (struct pkcs11_provider_s)); - if (szSignMode == NULL) { - provider->szSignMode = strdup ("auto"); - } - else { - provider->szSignMode = strdup (szSignMode); - } - if (provider->szSignMode == NULL) { - rv = CKR_HOST_MEMORY; - } - } - - if (rv == CKR_OK) { -#if defined(WIN32) - provider->hLibrary = LoadLibrary (szProvider); -#else - provider->hLibrary = dlopen (szProvider, RTLD_NOW); -#endif - if (provider->hLibrary == NULL) { - rv = CKR_FUNCTION_FAILED; - } + rv = _pkcs11_resetSlot (pkcs11_session); } if (rv == CKR_OK) { -#if defined(WIN32) - gfl = (CK_C_GetFunctionList)GetProcAddress ( - provider->hLibrary, - "C_GetFunctionList" - ); -#else - gfl = (CK_C_GetFunctionList)dlsym ( - provider->hLibrary, - "C_GetFunctionList" + rv = pkcs11_session->provider->f->C_OpenSession ( + pkcs11_session->slot, + CKF_SERIAL_SESSION, + NULL_PTR, + NULL_PTR, + &pkcs11_session->session ); -#endif - if (gfl == NULL) { - rv = CKR_FUNCTION_FAILED; - } } if (rv == CKR_OK) { - rv = gfl (&provider->f); - } + 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) { - if ((rv = provider->f->C_Initialize (NULL)) != CKR_OK) { - if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) { - rv = CKR_OK; + if ( + rv == CKR_OK && + !pkcs11_session->fProtectedAuthentication + ) { + if ( + !pkcs11_data->hooks->pin_prompt ( + pkcs11_data->hooks->pin_prompt_data, + pkcs11_session->szLabel, + szPIN, + sizeof (szPIN) + ) + ) { + rv = CKR_FUNCTION_FAILED; + } + else { + utfPIN = (CK_UTF8CHAR_PTR)szPIN; + lPINLength = strlen (szPIN); + } } - } - else { - provider->fShouldFinalize = true; - } - } - - if (rv == CKR_OK) { - provider->fEnabled = true; - } - if (provider != NULL) { - if (pkcs11_provider == NULL) { - pkcs11_provider = provider; - } - else { - pkcs11_provider_t last = NULL; - - for ( - last = pkcs11_provider; - last->next != NULL; - last = last->next - ); - last->next = provider; - } + if (pkcs11_data->nPINCachePeriod == -1) { + pkcs11_session->timePINExpire = 0; + } + else { + pkcs11_session->timePINExpire = ( + time (NULL) + + (time_t)pkcs11_data->nPINCachePeriod + ); + } + if ( + rv == CKR_OK && + (rv = pkcs11_session->provider->f->C_Login ( + pkcs11_session->session, + 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 + ) + ); + } + + if ( + rv == CKR_OK && + pkcs11_session->certificate_id != NULL + ) { + rv = _pkcs11_getObjectById ( + pkcs11_session, + CKO_PRIVATE_KEY, + pkcs11_session->certificate_id, + pkcs11_session->certificate_id_size, + &pkcs11_session->key + ); } return rv; } - + static CK_RV -pkcs11_finalize () { +_pkcs11_logout ( + IN const pkcs11_session_t pkcs11_session +) { + ASSERT (pkcs11_session!=NULL); + + if (pkcs11_session->session != (CK_SESSION_HANDLE)-1) { + pkcs11_session->provider->f->C_Logout (pkcs11_session->session); + pkcs11_session->provider->f->C_CloseSession (pkcs11_session->session); + pkcs11_session->key = (CK_OBJECT_HANDLE)-1; + pkcs11_session->session = (CK_SESSION_HANDLE)-1; + } + + return CKR_OK; +} + + +/*======================================= + * Simplified PKCS#11 functions + */ + +static +bool +_pkcs11_hooks_card_prompt_default ( + IN const void * pData, + IN const char * const szLabel +) { + return false; +} + +static +bool +_pkcs11_hooks_pin_prompt_default ( + IN const void * pData, + IN const char * const szLabel, + OUT char * const szPIN, + IN const size_t nMaxPIN +) { + return false; +} + +static +CK_RV +pkcs11_initialize () { + + pkcs11_terminate (); + + pkcs11_data = (pkcs11_data_t)malloc (sizeof (struct pkcs11_data_s)); + if (pkcs11_data == NULL) { + return CKR_HOST_MEMORY; + } + + memset (pkcs11_data, 0, sizeof (struct pkcs11_data_s)); + + pkcs11_data->nPINCachePeriod = -1; + + pkcs11_data->hooks = (pkcs11_hooks_t)malloc (sizeof (struct pkcs11_hooks_s)); + if (pkcs11_data->hooks == NULL) { + return CKR_HOST_MEMORY; + } + + memset (pkcs11_data->hooks, 0, sizeof (struct pkcs11_hooks_s)); + + pkcs11_data->fInitialized = true; + + pkcs11_setCardPromptHook (_pkcs11_hooks_card_prompt_default, NULL); + pkcs11_setPINPromptHook (_pkcs11_hooks_pin_prompt_default, NULL); + + return CKR_OK; +} + +static +CK_RV +pkcs11_terminate () { + + if (pkcs11_data != NULL) { + pkcs11_provider_t last = NULL; + + for ( + ; + pkcs11_data->providers != NULL; + pkcs11_data->providers = pkcs11_data->providers->next + ) { + if (last != NULL) { + free (last); + } + last = pkcs11_data->providers; + + if (pkcs11_data->providers->szSignMode != NULL) { + free (pkcs11_data->providers->szSignMode); + pkcs11_data->providers->szSignMode = NULL; + } + + if (pkcs11_data->providers->fShouldFinalize) { + pkcs11_data->providers->f->C_Finalize (NULL); + pkcs11_data->providers->fShouldFinalize = false; + } + + if (pkcs11_data->providers->f != NULL) { + pkcs11_data->providers->f = NULL; + } - pkcs11_provider_t last = NULL; + if (pkcs11_data->providers->hLibrary != NULL) { +#if defined(WIN32) + FreeLibrary (pkcs11_data->providers->hLibrary); +#else + dlclose (pkcs11_data->providers->hLibrary); +#endif + pkcs11_data->providers->hLibrary = NULL; + } + } - for ( - ; - pkcs11_provider != NULL; - pkcs11_provider = pkcs11_provider->next - ) { if (last != NULL) { free (last); } - last = pkcs11_provider; - - if (pkcs11_provider->szSignMode != NULL) { - free (pkcs11_provider->szSignMode); - pkcs11_provider->szSignMode = NULL; - } - - if (pkcs11_provider->fShouldFinalize) { - pkcs11_provider->f->C_Finalize (NULL); - pkcs11_provider->fShouldFinalize = false; + + if (pkcs11_data->hooks != NULL) { + free (pkcs11_data->hooks); + pkcs11_data->hooks = NULL; } - if (pkcs11_provider->f != NULL) { - pkcs11_provider->f = NULL; + free (pkcs11_data); + pkcs11_data = NULL; + } + + return CKR_OK; +} + +static +CK_RV +pkcs11_setPINPromptHook ( + IN const pkcs11_hook_pin_prompt_t hook, + IN void * const pData +) { + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); + + pkcs11_data->hooks->pin_prompt = hook; + pkcs11_data->hooks->pin_prompt_data = pData; + + return CKR_OK; +} + +static +CK_RV +pkcs11_setCardPromptHook ( + IN const pkcs11_hook_card_prompt_t hook, + IN void * const pData +) { + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); + + pkcs11_data->hooks->card_prompt = hook; + pkcs11_data->hooks->card_prompt_data = pData; + + return CKR_OK; +} + +static +CK_RV +pkcs11_setPINCachePeriod ( + IN const int nPINCachePeriod +) { + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); + + pkcs11_data->nPINCachePeriod = nPINCachePeriod; + + return CKR_OK; +} + +static +CK_RV +pkcs11_addProvider ( + IN const char * const szProvider, + IN const char * const szSignMode +) { + pkcs11_provider_t provider = NULL; + CK_C_GetFunctionList gfl = NULL; + CK_RV rv = CKR_OK; + + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); + ASSERT (szProvider!=NULL); + + if ( + rv == CKR_OK && + (provider = (pkcs11_provider_t)malloc (sizeof (struct pkcs11_provider_s))) == NULL + ) { + rv = CKR_HOST_MEMORY; + } + + if (rv == CKR_OK) { + memset (provider, 0, sizeof (struct pkcs11_provider_s)); + if (szSignMode == NULL) { + provider->szSignMode = strdup ("auto"); } - - if (pkcs11_provider->hLibrary != NULL) { + else { + provider->szSignMode = strdup (szSignMode); + } + if (provider->szSignMode == NULL) { + rv = CKR_HOST_MEMORY; + } + } + + if (rv == CKR_OK) { #if defined(WIN32) - FreeLibrary (pkcs11_provider->hLibrary); + provider->hLibrary = LoadLibrary (szProvider); #else - dlclose (pkcs11_provider->hLibrary); + provider->hLibrary = dlopen (szProvider, RTLD_NOW); #endif - pkcs11_provider->hLibrary = NULL; + if (provider->hLibrary == NULL) { + rv = CKR_FUNCTION_FAILED; } } - if (last != NULL) { - free (last); + if (rv == CKR_OK) { +#if defined(WIN32) + gfl = (CK_C_GetFunctionList)GetProcAddress ( + provider->hLibrary, + "C_GetFunctionList" + ); +#else + /* + * Make compiler happy! + */ + void *p = dlsym ( + provider->hLibrary, + "C_GetFunctionList" + ); + memmove ( + &gfl, + &p, + sizeof (void *) + ); +#endif + if (gfl == NULL) { + rv = CKR_FUNCTION_FAILED; + } } - return CKR_OK; + if (rv == CKR_OK) { + rv = gfl (&provider->f); + } + + if (rv == CKR_OK) { + if ((rv = provider->f->C_Initialize (NULL)) != CKR_OK) { + if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) { + rv = CKR_OK; + } + } + else { + provider->fShouldFinalize = true; + } + } + + if (rv == CKR_OK) { + provider->fEnabled = true; + } + + if (provider != NULL) { + if (pkcs11_data->providers == NULL) { + pkcs11_data->providers = provider; + } + else { + pkcs11_provider_t last = NULL; + + for ( + last = pkcs11_data->providers; + last->next != NULL; + last = last->next + ); + last->next = provider; + } + } + + return rv; } +static +CK_RV +pkcs11_forkFixup () { + + pkcs11_provider_t current; + + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); + + for ( + current = pkcs11_data->providers; + current != NULL; + current = current->next + ) { + if (current->fEnabled) { + current->f->C_Initialize (NULL); + } + } + + return CKR_OK; +} + static CK_RV pkcs11_createSession ( @@ -1032,18 +1490,18 @@ pkcs11_createSession ( IN const char * const szSlot, IN const char * const szIdType, IN const char * const szId, - IN const char * const szPIN, IN const bool fProtectedAuthentication, OUT pkcs11_session_t * const p_pkcs11_session ) { pkcs11_session_t pkcs11_session; CK_RV rv = CKR_OK; + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); ASSERT (szSlotType!=NULL); ASSERT (szSlot!=NULL); ASSERT (szIdType!=NULL); ASSERT (szId!=NULL); - ASSERT (szPIN!=NULL); ASSERT (p_pkcs11_session!=NULL); if ( @@ -1058,36 +1516,46 @@ pkcs11_createSession ( memset (pkcs11_session, 0, sizeof (struct pkcs11_session_s)); } - if ( - rv == CKR_OK && - !fProtectedAuthentication - ) { - if ((pkcs11_session->szPIN = strdup (szPIN)) == NULL) { - rv = CKR_HOST_MEMORY; - } - } - if (rv == CKR_OK) { - pkcs11_session->fLoginFailed = false; pkcs11_session->key = (CK_OBJECT_HANDLE)-1; pkcs11_session->session = (CK_SESSION_HANDLE)-1; + pkcs11_session->fProtectedAuthentication = fProtectedAuthentication; + } - if (!strcmp (szSlotType, "id")) { - rv = _pkcs11_getSlotById (pkcs11_session, szSlot); - } - else if (!strcmp (szSlotType, "name")) { - rv = _pkcs11_getSlotByName (pkcs11_session, szSlot); - } - else if (!strcmp (szSlotType, "label")) { - rv = _pkcs11_getSlotByLabel (pkcs11_session, szSlot); - } - else { - rv = CKR_ARGUMENTS_BAD; - } + if (rv == CKR_OK) { + bool fCancel = false; + + do { + if (!strcmp (szSlotType, "id")) { + rv = _pkcs11_getSlotById (pkcs11_session, szSlot); + } + else if (!strcmp (szSlotType, "name")) { + rv = _pkcs11_getSlotByName (pkcs11_session, szSlot); + } + else if (!strcmp (szSlotType, "label")) { + rv = _pkcs11_getSlotByLabel (pkcs11_session, szSlot); + } + else { + rv = CKR_ARGUMENTS_BAD; + } + + if (rv == CKR_SLOT_ID_INVALID) { + char szLabel[1024]; + snprintf (szLabel, sizeof (szLabel), "SLOT(%s=%s)", szSlotType, szSlot); + fCancel = !pkcs11_data->hooks->card_prompt ( + pkcs11_data->hooks->card_prompt_data, + szLabel + ); + } + } while (rv == CKR_SLOT_ID_INVALID && !fCancel); } if (rv == CKR_OK) { - rv = pkcs11_login ( + rv = _pkcs11_setSessionTokenInfo (pkcs11_session); + } + + if (rv == CKR_OK) { + rv = _pkcs11_login ( pkcs11_session ); } @@ -1106,88 +1574,10 @@ pkcs11_createSession ( ); } - pkcs11_logout ( - pkcs11_session - ); - - return rv; -} - -CK_RV -pkcs11_freeSession ( - IN const pkcs11_session_t pkcs11_session -) { - if (pkcs11_session != NULL) { - pkcs11_logout (pkcs11_session); - - if (pkcs11_session->szPIN != NULL) { - free (pkcs11_session->szPIN); - } - if (pkcs11_session->certificate != NULL) { - free (pkcs11_session->certificate); - } - if (pkcs11_session->certificate_id != NULL) { - free (pkcs11_session->certificate_id); - } - - free (pkcs11_session); - } - - return CKR_OK; -} - -static -CK_RV -pkcs11_login ( - IN const pkcs11_session_t pkcs11_session -) { - CK_RV rv = CKR_OK; - - ASSERT (pkcs11_session!=NULL); - - pkcs11_logout (pkcs11_session); - - if (rv == CKR_OK) { - rv = pkcs11_session->provider->f->C_OpenSession ( - pkcs11_session->slot, - CKF_SERIAL_SESSION, - NULL_PTR, - NULL_PTR, - &pkcs11_session->session - ); - } - /* - * Do not lock the token + * Complete missing login process */ - if ( - rv == CKR_OK && - pkcs11_session->fLoginFailed - ) { - rv = CKR_PIN_INVALID; - } - - if ( - rv == CKR_OK && - (rv = pkcs11_session->provider->f->C_Login ( - pkcs11_session->session, - CKU_USER, - pkcs11_session->szPIN, - pkcs11_session->szPIN == NULL ? 0 : (CK_ULONG)strlen (pkcs11_session->szPIN) - )) != CKR_OK - ) { - if (rv == CKR_USER_ALREADY_LOGGED_IN) { - rv = CKR_OK; - } - else { - pkcs11_session->fLoginFailed = true; - } - } - - if ( - rv == CKR_OK && - pkcs11_session->certificate_id != NULL - ) { + if (rv == CKR_OK) { rv = _pkcs11_getObjectById ( pkcs11_session, CKO_PRIVATE_KEY, @@ -1197,25 +1587,27 @@ pkcs11_login ( ); } - if (rv != CKR_OK) { - pkcs11_logout (pkcs11_session); - } - return rv; } -static CK_RV -pkcs11_logout ( +pkcs11_freeSession ( IN const pkcs11_session_t pkcs11_session ) { - ASSERT (pkcs11_session!=NULL); + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); - if (pkcs11_session->session != (CK_SESSION_HANDLE)-1) { - pkcs11_session->provider->f->C_Logout (pkcs11_session->session); - pkcs11_session->provider->f->C_CloseSession (pkcs11_session->session); - pkcs11_session->key = (CK_OBJECT_HANDLE)-1; - pkcs11_session->session = (CK_SESSION_HANDLE)-1; + if (pkcs11_session != NULL) { + _pkcs11_logout (pkcs11_session); + + if (pkcs11_session->certificate != NULL) { + free (pkcs11_session->certificate); + } + if (pkcs11_session->certificate_id != NULL) { + free (pkcs11_session->certificate_id); + } + + free (pkcs11_session); } return CKR_OK; @@ -1227,40 +1619,55 @@ pkcs11_sign ( IN const pkcs11_session_t pkcs11_session, IN const CK_MECHANISM_TYPE mech_type, IN const unsigned char * const source, - IN const int source_size, + IN const size_t source_size, OUT unsigned char * const target, - IN OUT int * const target_size + IN OUT size_t * const target_size ) { CK_MECHANISM mech = { mech_type, NULL, 0 }; - CK_ULONG size; - CK_RV rv; + CK_RV rv = CKR_OK; + bool fLogonRetry = false; + bool fOpSuccess = false; + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); ASSERT (pkcs11_session!=NULL); ASSERT (source!=NULL); ASSERT (target_size!=NULL); - if ( - (rv = pkcs11_session->provider->f->C_SignInit ( + rv = _pkcs11_validateSession (pkcs11_session); + + while (rv == CKR_OK && !fOpSuccess) { + rv = pkcs11_session->provider->f->C_SignInit ( pkcs11_session->session, &mech, pkcs11_session->key - )) != CKR_OK - ) { - return rv; + ); + + if (rv == CKR_OK) { + fOpSuccess = true; + } + else { + if (!fLogonRetry) { + fLogonRetry = true; + rv = _pkcs11_login (pkcs11_session); + } + } } - size = *target_size; - rv = pkcs11_session->provider->f->C_Sign ( - pkcs11_session->session, - (CK_BYTE_PTR)source, - source_size, - (CK_BYTE_PTR)target, - &size - ); + if (rv == CKR_OK) { + CK_ULONG size = *target_size; + rv = pkcs11_session->provider->f->C_Sign ( + pkcs11_session->session, + (CK_BYTE_PTR)source, + source_size, + (CK_BYTE_PTR)target, + &size + ); - *target_size = (int)size; + *target_size = (int)size; + } return rv; } @@ -1271,40 +1678,55 @@ pkcs11_signRecover ( IN const pkcs11_session_t pkcs11_session, IN const CK_MECHANISM_TYPE mech_type, IN const unsigned char * const source, - IN const int source_size, + IN const size_t source_size, OUT unsigned char * const target, - IN OUT int * const target_size + IN OUT size_t * const target_size ) { CK_MECHANISM mech = { mech_type, NULL, 0 }; - CK_ULONG size; - CK_RV rv; + CK_RV rv = CKR_OK; + bool fLogonRetry = false; + bool fOpSuccess = false; + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); ASSERT (pkcs11_session!=NULL); ASSERT (source!=NULL); ASSERT (target_size!=NULL); - if ( - (rv = pkcs11_session->provider->f->C_SignRecoverInit ( + rv = _pkcs11_validateSession (pkcs11_session); + + while (rv == CKR_OK && !fOpSuccess) { + rv = pkcs11_session->provider->f->C_SignRecoverInit ( pkcs11_session->session, - &mech, - pkcs11_session->key - )) != CKR_OK - ) { - return rv; + &mech, + pkcs11_session->key + ); + + if (rv == CKR_OK) { + fOpSuccess = true; + } + else { + if (!fLogonRetry) { + fLogonRetry = true; + rv = _pkcs11_login (pkcs11_session); + } + } } - size = *target_size; - rv = pkcs11_session->provider->f->C_SignRecover ( - pkcs11_session->session, - (CK_BYTE_PTR)source, - source_size, - (CK_BYTE_PTR)target, - &size - ); + if (rv == CKR_OK) { + CK_ULONG size = *target_size; + rv = pkcs11_session->provider->f->C_SignRecover ( + pkcs11_session->session, + (CK_BYTE_PTR)source, + source_size, + (CK_BYTE_PTR)target, + &size + ); - *target_size = (int)size; + *target_size = (int)size; + } return rv; } @@ -1315,40 +1737,56 @@ pkcs11_decrypt ( IN const pkcs11_session_t pkcs11_session, IN const CK_MECHANISM_TYPE mech_type, IN const unsigned char * const source, - IN const int source_size, + IN const size_t source_size, OUT unsigned char * const target, - IN OUT int * const target_size + IN OUT size_t * const target_size ) { CK_MECHANISM mech = { mech_type, NULL, 0 }; CK_ULONG size; - CK_RV rv; + CK_RV rv = CKR_OK; + bool fLogonRetry = false; + bool fOpSuccess = false; + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); ASSERT (pkcs11_session!=NULL); ASSERT (source!=NULL); ASSERT (target_size!=NULL); - if ( - (rv = pkcs11_session->provider->f->C_DecryptInit ( + rv = _pkcs11_validateSession (pkcs11_session); + + while (rv == CKR_OK && !fOpSuccess) { + rv = pkcs11_session->provider->f->C_DecryptInit ( pkcs11_session->session, &mech, pkcs11_session->key - )) != CKR_OK - ) { - return rv; + ); + + if (rv == CKR_OK) { + fOpSuccess = true; + } + else { + if (!fLogonRetry) { + fLogonRetry = true; + rv = _pkcs11_login (pkcs11_session); + } + } } - size = *target_size; - rv = pkcs11_session->provider->f->C_Decrypt ( - pkcs11_session->session, - (CK_BYTE_PTR)source, - source_size, - (CK_BYTE_PTR)target, - &size - ); + if (rv == CKR_OK) { + size = *target_size; + rv = pkcs11_session->provider->f->C_Decrypt ( + pkcs11_session->session, + (CK_BYTE_PTR)source, + source_size, + (CK_BYTE_PTR)target, + &size + ); - *target_size = (int)size; + *target_size = (int)size; + } return rv; } @@ -1357,9 +1795,11 @@ static CK_RV pkcs11_getCertificate ( IN const pkcs11_session_t pkcs11_session, - OUT char * const certificate, - IN OUT int * const certificate_size + OUT unsigned char * const certificate, + IN OUT size_t * const certificate_size ) { + ASSERT (pkcs11_data!=NULL); + ASSERT (pkcs11_data->fInitialized); ASSERT (certificate_size!=NULL); *certificate_size = pkcs11_session->certificate_size; @@ -1474,10 +1914,11 @@ pkcs11_getMessage ( } /*========================================== - * openvpn interface + * openssl interface */ typedef struct openssl_session_s { + RSA_METHOD smart_rsa; int (*orig_finish)(RSA *rsa); pkcs11_session_t pkcs11_session; } *openssl_session_t; @@ -1525,7 +1966,7 @@ openssl_pkcs11_priv_dec ( flen, from, to, - rsa, + (void *)rsa, padding ); @@ -1541,13 +1982,6 @@ openssl_pkcs11_priv_dec ( rv = CKR_ARGUMENTS_BAD; } - if ( - rv == CKR_OK && - (rv = pkcs11_login (pkcs11_session)) != CKR_OK - ) { - msg (M_WARN, "PKCS#11: Cannot login to token %ld:'%s'", rv, pkcs11_getMessage (rv)); - } - if ( rv == CKR_OK && (rv = pkcs11_decrypt ( @@ -1556,14 +1990,12 @@ openssl_pkcs11_priv_dec ( from, flen, to, - &flen + (size_t *)&flen )) != CKR_OK ) { msg (M_WARN, "PKCS#11: Cannot decrypt using private key %ld:'%s'", rv, pkcs11_getMessage (rv)); } - pkcs11_logout (pkcs11_session); - msg ( D_PKCS11_DEBUG, "PKCS#11: openssl_pkcs11_priv_dec - return rv=%ld", @@ -1593,8 +2025,8 @@ openssl_pkcs11_sign ( m, m_len, sigret, - siglen, - rsa + (void *)siglen, + (void *)rsa ); ASSERT (m!=NULL); @@ -1607,46 +2039,35 @@ openssl_pkcs11_sign ( *siglen = RSA_size(rsa); - if ( - rv == CKR_OK && - (rv = pkcs11_login (pkcs11_session)) != CKR_OK - ) { - msg (M_WARN, "PKCS#11: Cannot login to token %ld:'%s'", rv, pkcs11_getMessage (rv)); - } - - if (rv == CKR_OK) { - if (pkcs11_session->fKeySignRecover) { - if ( - (rv = pkcs11_signRecover ( - pkcs11_session, - CKM_RSA_PKCS, - m, - m_len, - sigret, - siglen - )) != CKR_OK - ) { - msg (M_WARN, "PKCS#11: Cannot perform signature-recover %ld:'%s'", rv, pkcs11_getMessage (rv)); - } + if (pkcs11_session->fKeySignRecover) { + if ( + (rv = pkcs11_signRecover ( + pkcs11_session, + CKM_RSA_PKCS, + m, + m_len, + sigret, + siglen + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot perform signature-recover %ld:'%s'", rv, pkcs11_getMessage (rv)); } - else { - if ( - (rv = pkcs11_sign ( - pkcs11_session, - CKM_RSA_PKCS, - m, - m_len, - sigret, - siglen - )) != CKR_OK - ) { - msg (M_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11_getMessage (rv)); - } + } + else { + if ( + (rv = pkcs11_sign ( + pkcs11_session, + CKM_RSA_PKCS, + m, + m_len, + sigret, + siglen + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11_getMessage (rv)); } } - pkcs11_logout (pkcs11_session); - msg ( D_PKCS11_DEBUG, "PKCS#11: openssl_pkcs11_priv_sign - return rv=%ld", @@ -1664,8 +2085,8 @@ openssl_pkcs11_finish(RSA *rsa) { msg ( D_PKCS11_DEBUG, - "PKCS#11: openssl_pkcs11_finish - entered - rsa=%p", - rsa + "PKCS#11: openssl_pkcs11_finish - entered rsa=%p", + (void *)rsa ); openssl_session = (openssl_session_t)RSA_get_app_data (rsa); @@ -1703,27 +2124,37 @@ openssl_pkcs11_finish(RSA *rsa) { return 1; } -static RSA_METHOD * -openssl_pkcs11_get_rsa_method(RSA *rsa) +void +openssl_pkcs11_set_rsa(const openssl_session_t openssl_session, RSA *rsa) { - static RSA_METHOD smart_rsa; const RSA_METHOD *def = RSA_get_default_method(); - ASSERT (rsa); + ASSERT (openssl_session!=NULL); + ASSERT (rsa!=NULL); + + memmove (&openssl_session->smart_rsa, def, sizeof(RSA_METHOD)); + + openssl_session->orig_finish = def->finish; - /* use the OpenSSL version */ - memmove (&smart_rsa, def, sizeof(smart_rsa)); + openssl_session->smart_rsa.name = "pkcs11"; + openssl_session->smart_rsa.rsa_priv_enc = openssl_pkcs11_priv_enc; + openssl_session->smart_rsa.rsa_priv_dec = openssl_pkcs11_priv_dec; + openssl_session->smart_rsa.rsa_sign = openssl_pkcs11_sign; + openssl_session->smart_rsa.finish = openssl_pkcs11_finish; + openssl_session->smart_rsa.flags = RSA_METHOD_FLAG_NO_CHECK | RSA_FLAG_EXT_PKEY; - /* save original */ - ((openssl_session_t)RSA_get_app_data (rsa))->orig_finish = def->finish; + RSA_set_method (rsa, &openssl_session->smart_rsa); + RSA_set_app_data (rsa, openssl_session); + +#ifdef BROKEN_OPENSSL_ENGINE + if (fOK) { + if (!rsa->engine) + rsa->engine = ENGINE_get_default_RSA(); - smart_rsa.name = "pkcs11"; - smart_rsa.rsa_priv_enc = openssl_pkcs11_priv_enc; - smart_rsa.rsa_priv_dec = openssl_pkcs11_priv_dec; - smart_rsa.rsa_sign = openssl_pkcs11_sign; - smart_rsa.finish = openssl_pkcs11_finish; - smart_rsa.flags = RSA_METHOD_FLAG_NO_CHECK | RSA_FLAG_EXT_PKEY; - return &smart_rsa; + ENGINE_set_RSA(ENGINE_get_default_RSA(), openssl_session->smart_rsa); + msg(M_WARN, "PKCS#11: OpenSSL engine support is broken! Workaround enabled"); + } +#endif } @@ -1737,6 +2168,150 @@ static void broken_openssl_init() } #endif +/*========================================== + * openvpn interface + */ + +static +bool +_openvpn_pkcs11_card_prompt ( + IN const void *pData, + IN const char * const szLabel +) { + static struct user_pass token_pass; + char szPrompt[1024]; + char szTemp[1024]; + + ASSERT (szLabel!=NULL); + + openvpn_snprintf (szPrompt, sizeof (szPrompt), "INSERT"); + + token_pass.defined = false; + token_pass.nocache = true; + get_user_pass (&token_pass, NULL, true, szPrompt, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE); + strncpynt (szTemp, token_pass.password, sizeof (szTemp)); + purge_user_pass (&token_pass, true); + + if (strlen (szTemp) == 0) { + return false; + } + else { + return true; + } +} + +static +bool +_openvpn_pkcs11_pin_prompt ( + IN const void *pData, + IN const char * const szLabel, + OUT char * const szPIN, + IN const size_t nMaxPIN +) { + static struct user_pass token_pass; + char szPrompt[1024]; + + ASSERT (szLabel!=NULL); + + openvpn_snprintf (szPrompt, sizeof (szPrompt), "%s token", szLabel); + + token_pass.defined = false; + token_pass.nocache = true; + get_user_pass (&token_pass, NULL, true, szPrompt, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE); + strncpynt (szPIN, token_pass.password, nMaxPIN); + purge_user_pass (&token_pass, true); + + if (strlen (szPIN) == 0) { + return false; + } + else { + return true; + } +} + +void +init_pkcs11 ( + const int nPINCachePeriod +) { + CK_RV rv; + + msg ( + D_PKCS11_DEBUG, + "PKCS#11: init_pkcs11 - entered" + ); + + if ((rv = pkcs11_initialize ()) != CKR_OK) { + msg (M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11_getMessage (rv)); + } +/*Until REQUEST/REPLY interface. + if ((rv = pkcs11_setCardPromptHook (_openvpn_pkcs11_card_prompt, NULL)) != CKR_OK) { + msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11_getMessage (rv)); + } +*/ + if ((rv = pkcs11_setPINPromptHook (_openvpn_pkcs11_pin_prompt, NULL)) != CKR_OK) { + msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11_getMessage (rv)); + } + + if ((rv = pkcs11_setPINCachePeriod (nPINCachePeriod)) != CKR_OK) { + msg (M_FATAL, "PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11_getMessage (rv)); + } + + msg ( + D_PKCS11_DEBUG, + "PKCS#11: init_pkcs11 - return" + ); +} + +void +free_pkcs11 () { + msg ( + D_PKCS11_DEBUG, + "PKCS#11: free_pkcs11 - entered" + ); + + pkcs11_terminate (); + + msg ( + D_PKCS11_DEBUG, + "PKCS#11: free_pkcs11 - return" + ); +} + +void +fork_fix_pkcs11 () { + pkcs11_forkFixup (); +} + +void +add_pkcs11 ( + IN const char * const provider, + IN const char * const sign_mode +) { + CK_RV rv; + + msg ( + D_PKCS11_DEBUG, + "PKCS#11: add_pkcs11 - entered - provider='%s', sign_mode='%s'", + provider, + sign_mode == NULL ? "default" : sign_mode + ); + + msg ( + M_INFO, + "PKCS#11: Adding PKCS#11 provider '%s'", + provider + ); + + if ((rv = pkcs11_addProvider (provider, sign_mode)) != CKR_OK) { + msg (M_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11_getMessage (rv)); + } + + msg ( + D_PKCS11_DEBUG, + "PKCS#11: add_pkcs11 - return" + ); +} + int SSL_CTX_use_pkcs11 ( IN OUT SSL_CTX * const ssl_ctx, @@ -1744,7 +2319,6 @@ SSL_CTX_use_pkcs11 ( IN const char * const pkcs11_slot, IN const char * const pkcs11_id_type, IN const char * const pkcs11_id, - IN const char * const pin, IN const bool pkcs11_protected_authentication ) { X509 *x509 = NULL; @@ -1755,14 +2329,14 @@ SSL_CTX_use_pkcs11 ( CK_RV rv = CKR_OK; unsigned char certificate[10*1024]; - int certificate_size; + size_t certificate_size; unsigned char *p; bool fOK = true; msg ( D_PKCS11_DEBUG, "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", - ssl_ctx, + (void *)ssl_ctx, pkcs11_slot_type, pkcs11_slot, pkcs11_id_type, @@ -1775,9 +2349,6 @@ SSL_CTX_use_pkcs11 ( ASSERT (pkcs11_slot!=NULL); ASSERT (pkcs11_id_type!=NULL); ASSERT (pkcs11_id!=NULL); - if (!pkcs11_protected_authentication) { - ASSERT (pin!=NULL); - } if ( fOK && @@ -1798,7 +2369,6 @@ SSL_CTX_use_pkcs11 ( pkcs11_slot, pkcs11_id_type, pkcs11_id, - pin, pkcs11_protected_authentication, &openssl_session->pkcs11_session )) != CKR_OK @@ -1862,23 +2432,12 @@ SSL_CTX_use_pkcs11 ( } if (fOK) { - RSA_set_app_data (rsa, openssl_session); - RSA_set_method (rsa, openssl_pkcs11_get_rsa_method (rsa)); + openssl_pkcs11_set_rsa (openssl_session, rsa); rsa->flags |= RSA_FLAG_SIGN_VER; /* it will be freed when rsa usage count will be zero */ fShouldFreeOpenSSLSession = false; } - -#ifdef BROKEN_OPENSSL_ENGINE - if (fOK) { - if (!rsa->engine) - rsa->engine = ENGINE_get_default_RSA(); - - ENGINE_set_RSA(ENGINE_get_default_RSA(), openssl_pkcs11_get_rsa_method(rsa)); - msg(M_WARN, "PKCS#11: OpenSSL engine support is broken! Workaround enabled"); - } -#endif if ( fOK && @@ -1935,51 +2494,6 @@ SSL_CTX_use_pkcs11 ( return fOK; } -void -add_pkcs11 ( - IN const char * const provider, - IN const char * const sign_mode -) { - CK_RV rv; - - msg ( - D_PKCS11_DEBUG, - "PKCS#11: add_pkcs11 - entered - provider='%s', sign_mode='%s'", - provider, - sign_mode == NULL ? "default" : sign_mode - ); - - msg ( - M_INFO, - "PKCS#11: Adding PKCS#11 provider '%s'", - provider - ); - - if ((rv = pkcs11_addProvider (provider, sign_mode)) != CKR_OK) { - msg (M_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11_getMessage (rv)); - } - - msg ( - D_PKCS11_DEBUG, - "PKCS#11: add_pkcs11 - return" - ); -} - -void -free_pkcs11 () { - msg ( - D_PKCS11_DEBUG, - "PKCS#11: free_pkcs11 - entered" - ); - - pkcs11_finalize (); - - msg ( - D_PKCS11_DEBUG, - "PKCS#11: free_pkcs11 - return" - ); -} - void show_pkcs11_slots ( IN const int msglev, @@ -1992,14 +2506,30 @@ show_pkcs11_slots ( CK_SLOT_ID s; CK_RV rv; + pkcs11_provider_t pkcs11_provider; + ASSERT (provider!=NULL); + if ( + (rv = pkcs11_initialize ()) != CKR_OK + ) { + msg (M_FATAL, "PKCS#11: Cannot initialize interface %ld-'%s'", rv, pkcs11_getMessage (rv)); + } + if ( (rv = pkcs11_addProvider (provider, NULL)) != CKR_OK ) { msg (M_FATAL, "PKCS#11: Cannot initialize provider %ld-'%s'", rv, pkcs11_getMessage (rv)); } + /* + * our provider is head + */ + pkcs11_provider = pkcs11_data->providers; + if (pkcs11_provider == NULL || !pkcs11_provider->fEnabled) { + msg (M_FATAL, "PKCS#11: Cannot get provider %ld-'%s'", rv, pkcs11_getMessage (rv)); + } + if ( (rv = pkcs11_provider->f->C_GetInfo (&info)) != CKR_OK ) { @@ -2009,7 +2539,7 @@ show_pkcs11_slots ( char szManufacturerID[sizeof (info.manufacturerID)+1]; _fixupFixedString ( - info.manufacturerID, + (char *)info.manufacturerID, szManufacturerID, sizeof (info.manufacturerID) ); @@ -2062,7 +2592,7 @@ show_pkcs11_slots ( char szCurrentName[sizeof (info.slotDescription)+1]; _fixupFixedString ( - info.slotDescription, + (char *)info.slotDescription, szCurrentName, sizeof (info.slotDescription) ); @@ -2072,7 +2602,19 @@ show_pkcs11_slots ( } } - pkcs11_finalize (); + pkcs11_terminate (); +} + +static +bool +_show_pkcs11_objects_pin_prompt ( + IN const void *pData, + IN const char * const szLabel, + OUT char * const szPIN, + IN const size_t nMaxPIN +) { + strncpy (szPIN, (char *)pData, nMaxPIN); + return true; } void @@ -2090,18 +2632,40 @@ show_pkcs11_objects ( CK_SLOT_ID s; CK_RV rv; + pkcs11_provider_t pkcs11_provider; + ASSERT (provider!=NULL); ASSERT (slot!=NULL); ASSERT (pin!=NULL); s = atoi (slot); + if ( + (rv = pkcs11_initialize ()) != CKR_OK + ) { + msg (M_FATAL, "PKCS#11: Cannot initialize interface %ld-'%s'", rv, pkcs11_getMessage (rv)); + } + + if ( + (rv = pkcs11_setPINPromptHook (_show_pkcs11_objects_pin_prompt, (void *)pin)) != CKR_OK + ) { + msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11_getMessage (rv)); + } + if ( (rv = pkcs11_addProvider (provider, NULL)) != CKR_OK ) { msg (M_FATAL, "PKCS#11: Cannot initialize provider %ld-'%s'", rv, pkcs11_getMessage (rv)); } + /* + * our provider is head + */ + pkcs11_provider = pkcs11_data->providers; + if (pkcs11_provider == NULL || !pkcs11_provider->fEnabled) { + msg (M_FATAL, "PKCS#11: Cannot get provider %ld-'%s'", rv, pkcs11_getMessage (rv)); + } + if ( (rv = pkcs11_provider->f->C_GetTokenInfo ( s, @@ -2117,22 +2681,22 @@ show_pkcs11_objects ( char szSerialNumber[sizeof (info.serialNumber)+1]; _fixupFixedString ( - info.label, + (char *)info.label, szLabel, sizeof (info.label) ); _fixupFixedString ( - info.manufacturerID, + (char *)info.manufacturerID, szManufacturerID, sizeof (info.manufacturerID) ); _fixupFixedString ( - info.model, + (char *)info.model, szModel, sizeof (info.model) ); _fixupFixedString ( - info.serialNumber, + (char *)info.serialNumber, szSerialNumber, sizeof (info.serialNumber) ); @@ -2385,9 +2949,9 @@ show_pkcs11_objects ( pkcs11_provider->f->C_FindObjectsFinal (session); pkcs11_provider->f->C_Logout (session); pkcs11_provider->f->C_CloseSession (session); - pkcs11_finalize (); + pkcs11_terminate (); } #else static void dummy (void) {} -#endif /* USE_OPENSC && USE_SSL && USE_CRYPTO */ +#endif /* ENABLE_PKCS11 */ -- cgit