@@ -432,7 +432,7 @@ static void pkcs11_val(const char* op, CK_ULONG val)
432432 */
433433int wc_Pkcs11_Initialize (Pkcs11Dev * dev , const char * library , void * heap )
434434{
435- return wc_Pkcs11_Initialize_ex (dev , library , heap , NULL );
435+ return wc_Pkcs11_Initialize_v3 (dev , library , heap , NULL , NULL , NULL );
436436}
437437
438438/**
@@ -451,52 +451,249 @@ int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, void* heap)
451451 */
452452int wc_Pkcs11_Initialize_ex (Pkcs11Dev * dev , const char * library , void * heap ,
453453 CK_RV * rvp )
454+ {
455+ return wc_Pkcs11_Initialize_v3 (dev , library , heap , NULL , NULL , rvp );
456+ }
457+
458+ /**
459+ * Load library, get function list and initialize PKCS#11.
460+ *
461+ * @param [in] dev Device object.
462+ * @param [in] library Library name including path.
463+ * @param [in] heap Heap hint.
464+ * @param [in,out] version On in, desired version of interface.
465+ * On out, actual obtained version of interface.
466+ * @param [in] interfaceName Name of the interface to use.
467+ * @param [out] rvp PKCS#11 return value. Last return value seen.
468+ * May be NULL.
469+ * @return BAD_FUNC_ARG when dev or library are NULL pointers.
470+ * @return BAD_PATH_ERROR when dynamic library cannot be opened.
471+ * @return WC_INIT_E when the initialization PKCS#11 fails.
472+ * @return WC_HW_E when unable to get PKCS#11 function list.
473+ * @return 0 on success.
474+ */
475+ int wc_Pkcs11_Initialize_v3 (Pkcs11Dev * dev , const char * library ,
476+ void * heap , int * version , const char * interfaceName , CK_RV * rvp )
454477{
455478 int ret = 0 ;
456479 CK_RV rv = CKR_OK ;
457- #ifndef HAVE_PKCS11_STATIC
480+ #if !defined( HAVE_PKCS11_STATIC ) && !defined( HAVE_PKCS11_V3_STATIC )
458481 void * func ;
459482#endif
460483 CK_C_INITIALIZE_ARGS args ;
484+ CK_VERSION_PTR version_ptr = NULL ;
461485
462486 if (dev == NULL || library == NULL )
463487 ret = BAD_FUNC_ARG ;
464488
465489 if (ret == 0 ) {
466490 dev -> heap = heap ;
467- #ifndef HAVE_PKCS11_STATIC
491+ #if defined(HAVE_PKCS11_V3_STATIC )
492+ CK_INTERFACE_PTR interface = NULL ;
493+ CK_VERSION pkcs11_version = {0 , 0 };
494+
495+ if (version != NULL ) {
496+ if (* version == WC_PCKS11VERSION_2_20 ) {
497+ pkcs11_version .major = 2 ;
498+ pkcs11_version .minor = 20 ;
499+ }
500+ else if (* version == WC_PCKS11VERSION_2_20 ) {
501+ pkcs11_version .major = 2 ;
502+ pkcs11_version .minor = 40 ;
503+ }
504+ else if (* version == WC_PCKS11VERSION_3_0 ) {
505+ pkcs11_version .major = 3 ;
506+ pkcs11_version .minor = 0 ;
507+ }
508+ else if (* version == WC_PCKS11VERSION_3_1 ) {
509+ pkcs11_version .major = 3 ;
510+ pkcs11_version .minor = 1 ;
511+ }
512+ version_ptr = & pkcs11_version ;
513+ }
514+ else {
515+ version_ptr = NULL ;
516+ }
517+
518+ rv = C_GetInterface ((CK_UTF8CHAR_PTR ) interfaceName , version_ptr ,
519+ & interface , 0 );
520+
521+ if (rv == CKR_OK ) {
522+ dev -> func = interface -> pFunctionList ;
523+ version_ptr = (CK_VERSION_PTR ) interface -> pFunctionList ;
524+ if (version_ptr -> major == 2 && version_ptr -> minor == 20 ) {
525+ dev -> version = WC_PCKS11VERSION_2_20 ;
526+ }
527+ else if (version_ptr -> major == 2 &&
528+ version_ptr -> minor == 40 ) {
529+ dev -> version = WC_PCKS11VERSION_2_40 ;
530+ }
531+ else if (version_ptr -> major == 3 &&
532+ version_ptr -> minor == 0 ) {
533+ dev -> version = WC_PCKS11VERSION_3_0 ;
534+ }
535+ else if (version_ptr -> major == 3 &&
536+ version_ptr -> minor == 1 ) {
537+ dev -> version = WC_PCKS11VERSION_3_1 ;
538+ }
539+ else {
540+ WOLFSSL_MSG_EX ("Unsupported PKCS#11 version: %d.%d" ,
541+ version_ptr -> major , version_ptr -> minor );
542+ ret = WC_HW_E ;
543+ }
544+ }
545+ else {
546+ PKCS11_RV ("CK_C_GetInterface" , rv );
547+ ret = WC_HW_E ;
548+ }
549+ #elif defined(HAVE_PKCS11_STATIC )
550+ rv = C_GetFunctionList (& dev -> func );
551+ if (rv == CKR_OK ) {
552+ version_ptr = (CK_VERSION_PTR ) dev -> func ;
553+ if (version_ptr -> major == 2 &&
554+ version_ptr -> minor == 20 ) {
555+ dev -> version = WC_PCKS11VERSION_2_20 ;
556+ }
557+ else if (version_ptr -> major == 2 &&
558+ version_ptr -> minor == 40 ) {
559+ dev -> version = WC_PCKS11VERSION_2_40 ;
560+ }
561+ else {
562+ WOLFSSL_MSG_EX ("Unsupported PKCS#11 version: %d.%d" ,
563+ version_ptr -> major ,
564+ version_ptr -> minor );
565+ ret = WC_HW_E ;
566+ }
567+ }
568+ else {
569+ PKCS11_RV ("CK_C_GetFunctionList" , rv );
570+ ret = WC_HW_E ;
571+ }
572+ #else
573+ /* Load dynamic library */
468574 dev -> dlHandle = dlopen (library , RTLD_NOW | RTLD_LOCAL );
469575 if (dev -> dlHandle == NULL ) {
470576 WOLFSSL_MSG (dlerror ());
471577 ret = BAD_PATH_ERROR ;
472578 }
473- }
474579
475- if (ret == 0 ) {
476- dev -> func = NULL ;
477- func = dlsym (dev -> dlHandle , "C_GetFunctionList" );
478- if (func == NULL ) {
479- WOLFSSL_MSG (dlerror ());
480- ret = WC_HW_E ;
580+ if (ret == 0 ) {
581+ /* Check if the library supports PKCS#11 version 3.0 (or above) by
582+ * looking for the C_GetInterface method (only present for >= V3.0).
583+ */
584+ func = dlsym (dev -> dlHandle , "C_GetInterface" );
585+ if (func != NULL ) {
586+ /* Function is present, use it */
587+ CK_INTERFACE_PTR interface = NULL ;
588+ CK_VERSION pkcs11_version = {0 , 0 };
589+ if (version != NULL ) {
590+ if (* version == WC_PCKS11VERSION_2_20 ) {
591+ pkcs11_version .major = 2 ;
592+ pkcs11_version .minor = 20 ;
593+ }
594+ else if (* version == WC_PCKS11VERSION_2_40 ) {
595+ pkcs11_version .major = 2 ;
596+ pkcs11_version .minor = 40 ;
597+ }
598+ else if (* version == WC_PCKS11VERSION_3_0 ) {
599+ pkcs11_version .major = 3 ;
600+ pkcs11_version .minor = 0 ;
601+ }
602+ else if (* version == WC_PCKS11VERSION_3_1 ) {
603+ pkcs11_version .major = 3 ;
604+ pkcs11_version .minor = 1 ;
605+ }
606+ version_ptr = & pkcs11_version ;
607+ }
608+ else {
609+ version_ptr = NULL ;
610+ }
611+
612+ rv = ((CK_C_GetInterface )func )((CK_UTF8CHAR_PTR ) interfaceName ,
613+ version_ptr , & interface , 0 );
614+ if (rv == CKR_OK ) {
615+ dev -> func = interface -> pFunctionList ;
616+ version_ptr = (CK_VERSION_PTR ) interface -> pFunctionList ;
617+ if (version_ptr -> major == 2 && version_ptr -> minor == 20 ) {
618+ dev -> version = WC_PCKS11VERSION_2_20 ;
619+ }
620+ else if (version_ptr -> major == 2 &&
621+ version_ptr -> minor == 40 ) {
622+ dev -> version = WC_PCKS11VERSION_2_40 ;
623+ }
624+ else if (version_ptr -> major == 3 &&
625+ version_ptr -> minor == 0 ) {
626+ dev -> version = WC_PCKS11VERSION_3_0 ;
627+ }
628+ else if (version_ptr -> major == 3 &&
629+ version_ptr -> minor == 1 ) {
630+ dev -> version = WC_PCKS11VERSION_3_1 ;
631+ }
632+ else {
633+ WOLFSSL_MSG_EX ("Unsupported PKCS#11 version: %d.%d" ,
634+ version_ptr -> major , version_ptr -> minor );
635+ ret = WC_HW_E ;
636+ }
637+ }
638+ else {
639+ PKCS11_RV ("CK_C_GetInterface" , rv );
640+ ret = WC_HW_E ;
641+ }
642+ }
643+ else {
644+ /* Function not present, try a 2.x library by looking for
645+ * C_GetFunctionList. */
646+ func = dlsym (dev -> dlHandle , "C_GetFunctionList" );
647+ if (func == NULL ) {
648+ #if defined(_WIN32 )
649+ WOLFSSL_MSG_EX ("GetProcAddress(): %d" , GetLastError ());
650+ #else
651+ WOLFSSL_MSG (dlerror ());
652+ #endif
653+ ret = WC_HW_E ;
654+ }
655+ if (ret == 0 ) {
656+ rv = ((CK_C_GetFunctionList )func )(& dev -> func );
657+ if (rv == CKR_OK ) {
658+ version_ptr = (CK_VERSION_PTR ) dev -> func ;
659+ if (version_ptr -> major == 2 &&
660+ version_ptr -> minor == 20 ) {
661+ dev -> version = WC_PCKS11VERSION_2_20 ;
662+ }
663+ else if (version_ptr -> major == 2 &&
664+ version_ptr -> minor == 40 ) {
665+ dev -> version = WC_PCKS11VERSION_2_40 ;
666+ }
667+ else {
668+ WOLFSSL_MSG_EX ("Unsupported PKCS#11 version: %d.%d" ,
669+ version_ptr -> major ,
670+ version_ptr -> minor );
671+ ret = WC_HW_E ;
672+ }
673+ }
674+ else {
675+ PKCS11_RV ("CK_C_GetFunctionList" , rv );
676+ ret = WC_HW_E ;
677+ }
678+ }
679+ }
481680 }
482- }
483- if (ret == 0 ) {
484- rv = ((CK_C_GetFunctionList )func )(& dev -> func );
485- #else
486- rv = C_GetFunctionList (& dev -> func );
487681#endif
488- if (rv != CKR_OK ) {
489- PKCS11_RV ("CK_C_GetFunctionList" , ret );
490- ret = WC_HW_E ;
491- }
492682 }
493683
684+ if (ret == 0 && version != NULL )
685+ * version = dev -> version ;
686+
494687 if (ret == 0 ) {
495688 XMEMSET (& args , 0x00 , sizeof (args ));
496689 args .flags = CKF_OS_LOCKING_OK ;
497690 rv = dev -> func -> C_Initialize (& args );
498- if (rv != CKR_OK ) {
499- PKCS11_RV ("C_Initialize" , ret );
691+ if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED ) {
692+ WOLFSSL_MSG ("PKCS#11 already initialized" );
693+ rv = CKR_OK ;
694+ }
695+ else if (rv != CKR_OK ) {
696+ PKCS11_RV ("C_Initialize" , rv );
500697 ret = WC_INIT_E ;
501698 }
502699 }
@@ -520,15 +717,15 @@ int wc_Pkcs11_Initialize_ex(Pkcs11Dev* dev, const char* library, void* heap,
520717void wc_Pkcs11_Finalize (Pkcs11Dev * dev )
521718{
522719 if (dev != NULL
523- #ifndef HAVE_PKCS11_STATIC
720+ #if ! defined ( HAVE_PKCS11_STATIC ) && ! defined ( HAVE_PKCS11_V3_STATIC )
524721 && dev -> dlHandle != NULL
525722#endif
526723 ) {
527724 if (dev -> func != NULL ) {
528725 dev -> func -> C_Finalize (NULL );
529726 dev -> func = NULL ;
530727 }
531- #ifndef HAVE_PKCS11_STATIC
728+ #if !defined( HAVE_PKCS11_STATIC ) && !defined( HAVE_PKCS11_V3_STATIC )
532729 dlclose (dev -> dlHandle );
533730 dev -> dlHandle = NULL ;
534731#endif
@@ -633,6 +830,7 @@ static int Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, int slotId,
633830 token -> userPin = NULL_PTR ;
634831 token -> userPinSz = 0 ;
635832 token -> userPinLogin = 0 ;
833+ token -> version = dev -> version ;
636834 }
637835
638836 XFREE (slot , dev -> heap , DYNAMIC_TYPE_TMP_BUFFER );
@@ -809,6 +1007,7 @@ static int Pkcs11OpenSession(Pkcs11Token* token, Pkcs11Session* session,
8091007 if (ret == 0 ) {
8101008 session -> func = token -> func ;
8111009 session -> slotId = token -> slotId ;
1010+ session -> version = token -> version ;
8121011 }
8131012
8141013 return ret ;
0 commit comments