/* * Load a module - this will load the shared object, call * C_Initialize, and get the list of function pointers */ void * C_LoadModule(const char *mspec, CK_FUNCTION_LIST_PTR_PTR funcs) { sc_pkcs11_module_t *mod; CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR); int rv; lt_dlinit(); mod = (sc_pkcs11_module_t *) calloc(1, sizeof(*mod)); mod->_magic = MAGIC; if (mspec == NULL) mspec = PKCS11_DEFAULT_MODULE_NAME; mod->handle = lt_dlopen(mspec); if (mod->handle == NULL) { #if 0 fprintf(stderr, "lt_dlopen failed: %s\n", lt_dlerror()); #endif goto failed; } /* Get the list of function pointers */ c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) lt_dlsym(mod->handle, "C_GetFunctionList"); if (!c_get_function_list) goto failed; rv = c_get_function_list(funcs); if (rv == CKR_OK) return (void *) mod; failed: C_UnloadModule((void *) mod); return NULL; }
CK_FUNCTION_LIST *pkcs11_get_function_list(const char *param) { CK_FUNCTION_LIST *funcs; CK_RV (*get_fun)(); void *d; const char *e = param ? param : getenv("PKCS11_LIBRARY"); e = e ? e : DEFAULT_PKCSLIB; d = dlopen(e, RTLD_LAZY); if (d == NULL) { fprintf(stdout, "dlopen('%s') failed\n", e); return NULL; } *(void **) (&get_fun) = dlsym(d, "C_GetFunctionList"); if (get_fun == NULL) { fprintf(stdout, "Symbol lookup failed\n"); return NULL; } CK_RV rc = get_fun(&funcs); if (rc != CKR_OK) { show_error(stdout, "C_GetFunctionList", rc); funcs = NULL; } else if(funcs == NULL) { fprintf(stdout, "C_GetFunctionList returned empty value\n"); } return funcs; }
Pkcs11* Pkcs11::open(const char_type *path) { // __CHECK_CONTEXT_RV(m_pContext, false); Dl* module; CK_RV rv; CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR); CK_FUNCTION_LIST_PTR api = NULL; module = new Dl(); JQ_ASSERT(module); do { if( !module->open(path) ) { jq_emitError(String().sprintf(E_SC_PKCS11_LoadModule)(path)()); break; } c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) module->symbol("C_GetFunctionList"); if( !c_get_function_list ) { jq_emitError(E_SC_PKCS11_GetFuncList); break; } rv = c_get_function_list( &api ); if ( rv != CKR_OK ) { jq_emitError(E_SC_PKCS11_ApiLoad); break; } rv = ((CK_FUNCTION_LIST_PTR)api)->C_Initialize(NULL); if(rv != CKR_OK) { jq_emitError(E_SC_PKCS11_Initialize); break; } return new Pkcs11(module, api); } while(0); if( module ) { module->close(); delete module; } return NULL; }
CK_FUNCTION_LIST * p11_init(void) { CK_RV rv; CK_RV (*pfoo)(); char *loc1_lib = "/usr/lib/pkcs11/PKCS11_API.so64"; char *loc2_lib = "libopencryptoki.so"; CK_FUNCTION_LIST *funcs = NULL; p11_lib = dlopen(loc1_lib, RTLD_NOW); if (p11_lib != NULL) goto get_list; p11_lib = dlopen(loc2_lib, RTLD_NOW); if (p11_lib == NULL) { print_error("Couldn't get a handle to the PKCS#11 library."); return NULL; } get_list: pfoo = (CK_RV (*)())dlsym(p11_lib,"C_GetFunctionList"); if (pfoo == NULL) { print_error("Couldn't get the address of the C_GetFunctionList routine."); dlclose(p11_lib); return NULL; } rv = pfoo(&funcs); if (rv != CKR_OK) { p11_error("C_GetFunctionList", rv); dlclose(p11_lib); return NULL; } rv = funcs->C_Initialize(NULL_PTR); if (rv != CKR_OK) { p11_error("C_Initialize", rv); dlclose(p11_lib); return NULL; } if (v_flag > 1) printf("PKCS#11 library initialized\n"); return funcs; }
CK_FUNCTION_LIST *pkcs11_get_function_list(const char *param) { CK_FUNCTION_LIST *funcs; void *d; const char *e = param ? param : getenv("PKCS11_LIBRARY"); e = e ? e : DEFAULT_PKCSLIB; d = LoadLibrary(e); if (d == NULL) { fprintf(stdout, "LoadLibrary Failed (%s)\n", e); return NULL; } #ifndef USE_GET_FUNCTION_LIST /* Look-up all symbols from dll */ funcs = (CK_FUNCTION_LIST_PTR) malloc(sizeof(CK_FUNCTION_LIST)); if(funcs) { #undef CK_NEED_ARG_LIST #undef CK_PKCS11_FUNCTION_INFO #define CK_PKCS11_FUNCTION_INFO(name) \ if((funcs->name = (CK_RV (*)())GetProcAddress(d, #name)) == NULL) { \ fprintf(stdout, "Error looking up %s\n", #name); \ free(funcs); \ return NULL; \ } #include "pkcs11f.h" } #else /* Look-up C_GetFunctionList and use it to get all functions */ CK_RV (*get_fun)(); get_fun = (CK_RV (*)())GetProcAddress(d, "C_GetFunctionList"); if (get_fun == NULL) { fprintf(stdout, "Symbol lookup failed\n"); return NULL; } CK_RV rc = get_fun(&funcs); if (rc != CKR_OK) { show_error(stdout, "C_GetFunctionList", rc); funcs = NULL; } else if(funcs == NULL) { fprintf(stdout, "C_GetFunctionList returned empty value\n"); } #endif return funcs; }
CK_RV load_library(char *library, CK_FUNCTION_LIST_PTR *p11p) { CK_RV rv; LpHandleType p11lib_handle = NULL; CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR); if (!library) { *p11p = NULL; return(-1); } #ifdef _WIN32 p11lib_handle = LoadLibrary(library); #else p11lib_handle = dlopen(library, RTLD_NOW); #endif if (p11lib_handle == NULL) { #ifdef _WIN32 printf("Error loading PKCS11 library: %s\n", (char *)GetLastError); #else printf("Error loading PKCS11 library: %s\n", dlerror()); #endif return(EXIT_FAILURE); } getflist = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) GetFuncFromMod(p11lib_handle, "C_GetFunctionList"); if (getflist == NULL) { #ifdef _WIN32 printf("Error finding \"C_GetFunctionList\" symbol: %s\n", (char *)GetLastError); #else printf("Error finding \"C_GetFunctionList\" symbol: %s\n", dlerror()); #endif return(EXIT_FAILURE); } rv = (*getflist)(p11p); if (rv != CKR_OK) { printf("Error calling \"C_GetFunctionList\" (rv = %d)\n", rv); return(rv); } return(CKR_OK); }
/********************************************************************** Function: sc_get_function_list() Description: Get the name of the PKCS11 dll to use from the registry, load it, get the entry for the C_GetFunctionList call it to set the pFunctionList. Parameters: Returns: the pFunctionList or NULL **********************************************************************/ CK_FUNCTION_LIST_PTR sc_get_function_list() { CK_RV status; #if defined(USE_PKCS11_DL) || defined(WIN32) CK_RV (*gfl)(CK_FUNCTION_LIST_PTR_PTR); #endif if (pFunctionList) { return pFunctionList; } #if defined(USE_PKCS11_DL) || defined(WIN32) if (!h_m_pkcs11) { char * dllname = NULL; #ifdef WIN32 HKEY hkDir = NULL; char val_dllname[512] = {"NONE"}; LONG lval; DWORD type; if (!h_m_pkcs11) { RegOpenKey(HKEY_CURRENT_USER,GSI_REGISTRY_DIR,&hkDir); lval = sizeof(val_dllname) -1; if (hkDir && (RegQueryValueEx(hkDir, "PKCS11.DLL", 0, &type, val_dllname,&lval) == ERROR_SUCCESS)) { h_m_pkcs11 = LoadLibrary(val_dllname); } if (hkDir) { RegCloseKey(hkDir); } if (!h_m_pkcs11) { SCerr(SCERR_F_SCINIT,SCERR_R_NO_PKCS11_DLL); ERR_add_error_data(2,"Name of DLL=", dllname? dllname:"NONE"); return NULL; } } gfl = (CK_RV (*)(CK_FUNCTION_LIST_PTR *)) GetProcAddress(h_m_pkcs11,"C_GetFunctionList"); #else if (!h_m_pkcs11) { dllname = getenv("PKCS11_LIB"); if (!dllname) { dllname = "libDSPKCS.so"; } h_m_pkcs11 = dlopen("libDSPKCS.so",RTLD_LAZY); } if (!h_m_pkcs11) { SCerr(SCERR_F_SCINIT,SCERR_R_NO_PKCS11_DLL); ERR_add_error_data(2,"Name of shared library=", dllname); return NULL; } gfl = (CK_RV(*)(CK_FUNCTION_LIST_PTR_PTR)) dlsym(h_m_pkcs11,"C_GetFunctionList"); #endif if (!gfl) { SCerr(SCERR_F_LOAD_DLL,SCERR_R_NO_PKCS11_DLL); ERR_add_error_data(1,"Cant find C_GetFunctionList"); return NULL; } } status = (*gfl)(&pFunctionList); #else status = C_GetFunctionList(&pFunctionList); #endif /* PKCS11_DYNLOAD */ if (status != CKR_OK) { SCerr(SCERR_F_LOAD_DLL,SCERR_R_UNSUPPORTED); ERR_add_error_data(1,sc_ERR_code(status)); return NULL; } return pFunctionList; }
/* * For each provider found in pkcs11.conf: expand $ISA if necessary, * verify the module is signed, load the provider, find all of its * slots, and store the function list and disabled policy. * * This function requires that the uentrylist_t and pkcs11_slottable_t * already have memory allocated, and that the uentrylist_t is already * populated with provider and policy information. * * pInitArgs can be set to NULL, but is normally the same value * the framework's C_Initialize() was called with. * * Unless metaslot is explicitly disabled, it is setup when all other * providers are loaded. */ CK_RV pkcs11_slot_mapping(uentrylist_t *pplist, CK_VOID_PTR pInitArgs) { CK_RV rv = CKR_OK; CK_RV prov_rv; /* Provider's return code */ CK_INFO prov_info; CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR); CK_FUNCTION_LIST_PTR prov_funcs = NULL; /* Provider's function list */ CK_ULONG prov_slot_count; /* Number of slots */ CK_SLOT_ID slot_id; /* slotID assigned for framework */ CK_SLOT_ID_PTR prov_slots = NULL; /* Provider's slot list */ /* Enabled or Disabled policy */ CK_MECHANISM_TYPE_PTR prov_pol_mechs = NULL; void *dldesc = NULL; char *isa, *fullpath = NULL, *dl_error; uentrylist_t *phead; uint_t prov_count = 0; pkcs11_slot_t *cur_slot; CK_ULONG i; size_t len; uentry_t *metaslot_entry = NULL; /* number of slots in the framework, not including metaslot */ uint_t slot_count = 0; ELFsign_status_t estatus = ELFSIGN_UNKNOWN; char *estatus_str = NULL; int kcfdfd = -1; door_arg_t darg; kcf_door_arg_t *kda = NULL; kcf_door_arg_t *rkda = NULL; int r; phead = pplist; /* Loop through all of the provider listed in pkcs11.conf */ while (phead != NULL) { if (!strcasecmp(phead->puent->name, "metaslot")) { /* * Skip standard processing for metaslot * entry since it is not an actual library * that can be dlopened. * It will be initialized later. */ if (metaslot_entry != NULL) { cryptoerror(LOG_ERR, "libpkcs11: multiple entries for metaslot " "detected. All but the first entry will " "be ignored"); } else { metaslot_entry = phead->puent; } goto contparse; } /* Check for Instruction Set Architecture indicator */ if ((isa = strstr(phead->puent->name, PKCS11_ISA)) != NULL) { /* Substitute the architecture dependent path */ len = strlen(phead->puent->name) - strlen(PKCS11_ISA) + strlen(PKCS11_ISA_DIR) + 1; if ((fullpath = (char *)malloc(len)) == NULL) { cryptoerror(LOG_ERR, "libpksc11: parsing %s, out of memory. " "Cannot continue parsing.", _PATH_PKCS11_CONF); rv = CKR_HOST_MEMORY; goto conferror; } *isa = '\000'; isa += strlen(PKCS11_ISA); (void) snprintf(fullpath, len, "%s%s%s", phead->puent->name, PKCS11_ISA_DIR, isa); } else if ((fullpath = strdup(phead->puent->name)) == 0) { cryptoerror(LOG_ERR, "libpkcs11: parsing %s, out of memory. " "Cannot continue parsing.", _PATH_PKCS11_CONF); rv = CKR_HOST_MEMORY; goto conferror; } /* * Open the provider. Use RTLD_NOW to make sure we * will not encounter symbol referencing errors later. * Use RTLD_GROUP to limit the provider to it's own * symbols, which prevents it from mistakenly accessing * the framework's C_* functions. */ dldesc = dlopen(fullpath, RTLD_NOW|RTLD_GROUP); /* * If we failed to load it, we will just skip this * provider and move on to the next one. */ if (dldesc == NULL) { dl_error = dlerror(); cryptoerror(LOG_ERR, "libpkcs11: Cannot load PKCS#11 library %s. " "dlerror: %s. %s", fullpath, dl_error != NULL ? dl_error : "Unknown", conf_err); goto contparse; } /* Get the pointer to provider's C_GetFunctionList() */ Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList"); /* * If we failed to get the pointer to C_GetFunctionList(), * skip this provider and continue to the next one. */ if (Tmp_C_GetFunctionList == NULL) { cryptoerror(LOG_ERR, "libpkcs11: Could not dlsym() C_GetFunctionList() " "for %s. May not be a PKCS#11 library. %s", fullpath, conf_err); (void) dlclose(dldesc); goto contparse; } /* Get the provider's function list */ prov_rv = Tmp_C_GetFunctionList(&prov_funcs); /* * If we failed to get the provider's function list, * skip this provider and continue to the next one. */ if (prov_rv != CKR_OK) { cryptoerror(LOG_ERR, "libpkcs11: Could not get function list for %s. " "%s Error: %s.", fullpath, conf_err, pkcs11_strerror(prov_rv)); (void) dlclose(dldesc); goto contparse; } /* Initialize this provider */ prov_rv = prov_funcs->C_Initialize(pInitArgs); /* * If we failed to initialize this provider, * skip this provider and continue to the next one. */ if ((prov_rv != CKR_OK) && (prov_rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { cryptoerror(LOG_ERR, "libpkcs11: Could not initialize %s. " "%s Error: %s.", fullpath, conf_err, pkcs11_strerror(prov_rv)); (void) dlclose(dldesc); goto contparse; } /* * Make sure this provider is implementing the same * major version, and at least the same minor version * that we are. */ prov_rv = prov_funcs->C_GetInfo(&prov_info); /* * If we can't verify that we are implementing the * same major version, or if it is definitely not the same * version, we need to skip this provider. */ if ((prov_rv != CKR_OK) || (prov_info.cryptokiVersion.major != CRYPTOKI_VERSION_MAJOR)) { if (prov_rv != CKR_OK) { cryptoerror(LOG_ERR, "libpkcs11: Could not verify version of " "%s. %s Error: %s.", fullpath, conf_err, pkcs11_strerror(prov_rv)); } else { cryptoerror(LOG_ERR, "libpkcs11: Only CRYPTOKI major version " "%d is supported. %s is major " "version %d. %s", CRYPTOKI_VERSION_MAJOR, fullpath, prov_info.cryptokiVersion.major, conf_err); } (void) prov_funcs->C_Finalize(NULL); (void) dlclose(dldesc); goto contparse; } /* * Warn the administrator (at debug) that a provider with * a significantly older or newer version of * CRYPTOKI is being used. It should not cause * problems, but logging a warning makes it easier * to debug later. */ if ((prov_info.cryptokiVersion.minor < CRYPTOKI_VERSION_WARN_MINOR) || (prov_info.cryptokiVersion.minor > CRYPTOKI_VERSION_MINOR)) { cryptoerror(LOG_DEBUG, "libpkcs11: %s CRYPTOKI minor version, %d, may " "not be compatible with minor version %d.", fullpath, prov_info.cryptokiVersion.minor, CRYPTOKI_VERSION_MINOR); } /* * Find out how many slots this provider has, * call with tokenPresent set to FALSE so all * potential slots are returned. */ prov_rv = prov_funcs->C_GetSlotList(FALSE, NULL, &prov_slot_count); /* * If the call failed, or if no slots are returned, * then skip this provider and continue to next one. */ if (prov_rv != CKR_OK) { cryptoerror(LOG_ERR, "libpksc11: Could not get slot list from %s. " "%s Error: %s.", fullpath, conf_err, pkcs11_strerror(prov_rv)); (void) prov_funcs->C_Finalize(NULL); (void) dlclose(dldesc); goto contparse; } if (prov_slot_count == 0) { cryptodebug("libpkcs11: No slots presented from %s. " "Skipping this plug-in at this time.\n", fullpath); (void) prov_funcs->C_Finalize(NULL); (void) dlclose(dldesc); goto contparse; } /* * Verify that the module is signed correctly. * * NOTE: there is a potential race condition here, * since the module is verified well after we have * opened the provider via dlopen(). This could be * resolved by a variant of dlopen() that would take a * file descriptor as an argument and by changing the * kcfd libelfsign door protocol to use and fd instead * of a path - but that wouldn't work in the kernel case. */ while ((kcfdfd = open(_PATH_KCFD_DOOR, O_RDONLY)) == -1) { if (!(errno == EINTR || errno == EAGAIN)) break; } if (kcfdfd == -1) { cryptoerror(LOG_ERR, "libpkcs11: open %s: %s", _PATH_KCFD_DOOR, strerror(errno)); goto verifycleanup; } /* Mark the door "close on exec" */ (void) fcntl(kcfdfd, F_SETFD, FD_CLOEXEC); if ((kda = malloc(sizeof (kcf_door_arg_t))) == NULL) { cryptoerror(LOG_ERR, "libpkcs11: malloc of kda " "failed: %s", strerror(errno)); goto verifycleanup; } kda->da_version = KCF_KCFD_VERSION1; kda->da_iskernel = B_FALSE; (void) strlcpy(kda->da_u.filename, fullpath, strlen(fullpath) + 1); darg.data_ptr = (char *)kda; darg.data_size = sizeof (kcf_door_arg_t); darg.desc_ptr = NULL; darg.desc_num = 0; darg.rbuf = (char *)kda; darg.rsize = sizeof (kcf_door_arg_t); while ((r = door_call(kcfdfd, &darg)) != 0) { if (!(errno == EINTR || errno == EAGAIN)) break; } if (r != 0) { cryptoerror(LOG_ERR, "libpkcs11: Unable to contact kcfd: %s", strerror(errno)); goto verifycleanup; } /*LINTED*/ rkda = (kcf_door_arg_t *)darg.rbuf; if (rkda->da_version != KCF_KCFD_VERSION1) { cryptoerror(LOG_ERR, "libpkcs11: kcfd and libelfsign versions " "don't match: got %d expected %d", rkda->da_version, KCF_KCFD_VERSION1); goto verifycleanup; } estatus = rkda->da_u.result.status; verifycleanup: if (kcfdfd != -1) { (void) close(kcfdfd); } if (rkda != NULL && rkda != kda) (void) munmap((char *)rkda, darg.rsize); if (kda != NULL) { bzero(kda, sizeof (kda)); free(kda); kda = NULL; rkda = NULL; /* rkda is an alias of kda */ } switch (estatus) { case ELFSIGN_SUCCESS: case ELFSIGN_RESTRICTED: break; case ELFSIGN_NOTSIGNED: estatus_str = strdup("not a signed provider."); break; case ELFSIGN_FAILED: estatus_str = strdup("signature verification failed."); break; default: estatus_str = strdup("unexpected failure in ELF " "signature verification. " "System may have been tampered with."); } if (estatus_str != NULL) { cryptoerror(LOG_ERR, "libpkcs11: %s %s %s", fullpath, estatus_str ? estatus_str : "", estatus == ELFSIGN_UNKNOWN ? "Cannot continue parsing " _PATH_PKCS11_CONF: conf_err); (void) prov_funcs->C_Finalize(NULL); (void) dlclose(dldesc); free(estatus_str); estatus_str = NULL; if (estatus == ELFSIGN_UNKNOWN) { prov_funcs = NULL; dldesc = NULL; rv = CKR_GENERAL_ERROR; goto conferror; } goto contparse; } /* Allocate memory for the slot list */ prov_slots = calloc(prov_slot_count, sizeof (CK_SLOT_ID)); if (prov_slots == NULL) { cryptoerror(LOG_ERR, "libpkcs11: Could not allocate memory for " "plug-in slots. Cannot continue parsing %s\n", _PATH_PKCS11_CONF); rv = CKR_HOST_MEMORY; goto conferror; } /* Get slot list from provider */ prov_rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &prov_slot_count); /* if second call fails, drop this provider */ if (prov_rv != CKR_OK) { cryptoerror(LOG_ERR, "libpkcs11: Second call to C_GetSlotList() for %s " "failed. %s Error: %s.", fullpath, conf_err, pkcs11_strerror(prov_rv)); (void) prov_funcs->C_Finalize(NULL); (void) dlclose(dldesc); goto contparse; } /* * Parse the list of disabled or enabled mechanisms, will * apply to each of the provider's slots. */ if (phead->puent->count > 0) { rv = pkcs11_mech_parse(phead->puent->policylist, &prov_pol_mechs, phead->puent->count); if (rv == CKR_HOST_MEMORY) { cryptoerror(LOG_ERR, "libpkcs11: Could not parse configuration," "out of memory. Cannot continue parsing " "%s.", _PATH_PKCS11_CONF); goto conferror; } else if (rv == CKR_MECHANISM_INVALID) { /* * Configuration file is corrupted for this * provider. */ cryptoerror(LOG_ERR, "libpkcs11: Policy invalid or corrupted " "for %s. Use cryptoadm(1M) to fix " "this. Skipping this plug-in.", fullpath); (void) prov_funcs->C_Finalize(NULL); (void) dlclose(dldesc); goto contparse; } } /* Allocate memory in our slottable for these slots */ rv = pkcs11_slottable_increase(prov_slot_count); /* * If any error is returned, it will be memory related, * so we need to abort the attempt at filling the * slottable. */ if (rv != CKR_OK) { cryptoerror(LOG_ERR, "libpkcs11: slottable could not increase. " "Cannot continue parsing %s.", _PATH_PKCS11_CONF); goto conferror; } /* Configure information for each new slot */ for (i = 0; i < prov_slot_count; i++) { /* allocate slot in framework */ rv = pkcs11_slot_allocate(&slot_id); if (rv != CKR_OK) { cryptoerror(LOG_ERR, "libpkcs11: Could not allocate " "new slot. Cannot continue parsing %s.", _PATH_PKCS11_CONF); goto conferror; } slot_count++; cur_slot = slottable->st_slots[slot_id]; (void) pthread_mutex_lock(&cur_slot->sl_mutex); cur_slot->sl_id = prov_slots[i]; cur_slot->sl_func_list = prov_funcs; cur_slot->sl_enabledpol = phead->puent->flag_enabledlist; cur_slot->sl_pol_mechs = prov_pol_mechs; cur_slot->sl_pol_count = phead->puent->count; cur_slot->sl_norandom = phead->puent->flag_norandom; cur_slot->sl_dldesc = dldesc; cur_slot->sl_prov_id = prov_count + 1; (void) pthread_mutex_unlock(&cur_slot->sl_mutex); } /* Set and reset values to process next provider */ prov_count++; contparse: prov_slot_count = 0; Tmp_C_GetFunctionList = NULL; prov_funcs = NULL; dldesc = NULL; if (fullpath != NULL) { free(fullpath); fullpath = NULL; } if (prov_slots != NULL) { free(prov_slots); prov_slots = NULL; } phead = phead->next; } if (slot_count == 0) { /* * there's no other slot in the framework, * there is nothing to do */ goto config_complete; } /* determine if metaslot should be enabled */ /* * Check to see if any environment variable is defined * by the user for configuring metaslot. Users' * setting always take precedence over the system wide * setting. So, we will first check for any user's * defined env variables before looking at the system-wide * configuration. */ get_user_metaslot_config(); /* no metaslot entry in /etc/crypto/pkcs11.conf */ if (!metaslot_entry) { /* * If user env variable indicates metaslot should be enabled, * but there's no entry in /etc/crypto/pkcs11.conf for * metaslot at all, will respect the user's defined value */ if ((metaslot_config.enabled_specified) && (metaslot_config.enabled)) { metaslot_enabled = B_TRUE; } } else { if (!metaslot_config.enabled_specified) { /* * take system wide value if * it is not specified by user */ metaslot_enabled = metaslot_entry->flag_metaslot_enabled; } else { metaslot_enabled = metaslot_config.enabled; } } /* * * As long as the user or system configuration file does not * disable metaslot, it will be enabled regardless of the * number of slots plugged into the framework. Therefore, * metaslot is enabled even when there's only one slot * plugged into the framework. This is necessary for * presenting a consistent token label view to applications. * * However, for the case where there is only 1 slot plugged into * the framework, we can use "fastpath". * * "fastpath" will pass all of the application's requests * directly to the underlying provider. Only when policy is in * effect will we need to keep slotID around. * * When metaslot is enabled, and fastpath is enabled, * all the metaslot processing will be skipped. * When there is only 1 slot, there's * really not much metaslot can do in terms of combining functionality * of different slots, and object migration. * */ /* check to see if fastpath can be used */ if (slottable->st_last == slottable->st_first) { cur_slot = slottable->st_slots[slottable->st_first]; (void) pthread_mutex_lock(&cur_slot->sl_mutex); if ((cur_slot->sl_pol_count == 0) && (!cur_slot->sl_enabledpol) && (!cur_slot->sl_norandom)) { /* No policy is in effect, don't need slotid */ fast_funcs = cur_slot->sl_func_list; purefastpath = B_TRUE; } else { fast_funcs = cur_slot->sl_func_list; fast_slot = slottable->st_first; policyfastpath = B_TRUE; } (void) pthread_mutex_unlock(&cur_slot->sl_mutex); } if ((purefastpath || policyfastpath) && (!metaslot_enabled)) { goto config_complete; } /* * If we get here, there are more than 2 slots in the framework, * we need to set up metaslot if it is enabled */ if (metaslot_enabled) { rv = setup_metaslot(metaslot_entry); if (rv != CKR_OK) { goto conferror; } } config_complete: return (CKR_OK); conferror: /* * This cleanup code is only exercised when a major, * unrecoverable error like "out of memory" occurs. */ if (prov_funcs != NULL) { (void) prov_funcs->C_Finalize(NULL); } if (dldesc != NULL) { (void) dlclose(dldesc); } if (fullpath != NULL) { free(fullpath); fullpath = NULL; } if (prov_slots != NULL) { free(prov_slots); prov_slots = NULL; } return (rv); }
int list_metaslot_info(boolean_t show_mechs, boolean_t verbose, mechlist_t *mechlist) { int rc = SUCCESS; CK_RV rv; CK_SLOT_INFO slot_info; CK_TOKEN_INFO token_info; CK_MECHANISM_TYPE_PTR pmech_list = NULL; CK_ULONG mech_count; int i; CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR); CK_FUNCTION_LIST_PTR funcs; void *dldesc = NULL; boolean_t lib_initialized = B_FALSE; uentry_t *puent; char buf[128]; /* * Display the system-wide metaslot settings as specified * in pkcs11.conf file. */ if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) { cryptoerror(LOG_STDERR, gettext("metaslot entry doesn't exist.")); return (FAILURE); } (void) printf(gettext("System-wide Meta Slot Configuration:\n")); /* * TRANSLATION_NOTE * Strictly for appearance's sake, this line should be as long as * the length of the translated text above. */ (void) printf(gettext("------------------------------------\n")); (void) printf(gettext("Status: %s\n"), puent->flag_metaslot_enabled ? gettext("enabled") : gettext("disabled")); (void) printf(gettext("Sensitive Token Object Automatic Migrate: %s\n"), puent->flag_metaslot_auto_key_migrate ? gettext("enabled") : gettext("disabled")); bzero(buf, sizeof (buf)); if (memcmp(puent->metaslot_ks_slot, buf, SLOT_DESCRIPTION_SIZE) != 0) { (void) printf(gettext("Persistent object store slot: %s\n"), puent->metaslot_ks_slot); } if (memcmp(puent->metaslot_ks_token, buf, TOKEN_LABEL_SIZE) != 0) { (void) printf(gettext("Persistent object store token: %s\n"), puent->metaslot_ks_token); } if ((!verbose) && (!show_mechs)) { return (SUCCESS); } if (verbose) { (void) printf(gettext("\nDetailed Meta Slot Information:\n")); /* * TRANSLATION_NOTE * Strictly for appearance's sake, this line should be as * long as the length of the translated text above. */ (void) printf(gettext("-------------------------------\n")); } /* * Need to actually make calls to libpkcs11.so to get * information about metaslot. */ dldesc = dlopen(UEF_FRAME_LIB, RTLD_NOW); if (dldesc == NULL) { char *dl_error; dl_error = dlerror(); cryptodebug("Cannot load PKCS#11 framework library. " "dlerror:%s", dl_error); return (FAILURE); } /* Get the pointer to library's C_GetFunctionList() */ Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList"); if (Tmp_C_GetFunctionList == NULL) { cryptodebug("Cannot get the address of the C_GetFunctionList " "from framework"); rc = FAILURE; goto finish; } /* Get the provider's function list */ rv = Tmp_C_GetFunctionList(&funcs); if (rv != CKR_OK) { cryptodebug("failed to call C_GetFunctionList in " "framework library"); rc = FAILURE; goto finish; } /* Initialize this provider */ rv = funcs->C_Initialize(NULL_PTR); if (rv != CKR_OK) { cryptodebug("C_Initialize failed with error code 0x%x\n", rv); rc = FAILURE; goto finish; } else { lib_initialized = B_TRUE; } /* * We know for sure that metaslot is slot 0 in the framework, * so, we will do a C_GetSlotInfo() trying to see if it works. * If it fails with CKR_SLOT_ID_INVALID, we know that metaslot * is not really enabled. */ rv = funcs->C_GetSlotInfo(METASLOT_ID, &slot_info); if (rv == CKR_SLOT_ID_INVALID) { (void) printf(gettext("actual status: disabled.\n")); /* * Even if the -m and -v flag is supplied, there's nothing * interesting to display about metaslot since it is disabled, * so, just stop right here. */ goto finish; } if (rv != CKR_OK) { cryptodebug("C_GetSlotInfo failed with error " "code 0x%x\n", rv); rc = FAILURE; goto finish; } if (!verbose) { goto display_mechs; } (void) printf(gettext("actual status: enabled.\n")); (void) printf(gettext("Description: %.64s\n"), slot_info.slotDescription); (void) printf(gettext("Token Present: %s\n"), (slot_info.flags & CKF_TOKEN_PRESENT ? gettext("True") : gettext("False"))); rv = funcs->C_GetTokenInfo(METASLOT_ID, &token_info); if (rv != CKR_OK) { cryptodebug("C_GetTokenInfo failed with error " "code 0x%x\n", rv); rc = FAILURE; goto finish; } (void) printf(gettext("Token Label: %.32s\n" "Manufacturer ID: %.32s\n" "Model: %.16s\n" "Serial Number: %.16s\n" "Hardware Version: %d.%d\n" "Firmware Version: %d.%d\n" "UTC Time: %.16s\n" "PIN Min Length: %d\n" "PIN Max Length: %d\n"), token_info.label, token_info.manufacturerID, token_info.model, token_info.serialNumber, token_info.hardwareVersion.major, token_info.hardwareVersion.minor, token_info.firmwareVersion.major, token_info.firmwareVersion.minor, token_info.utcTime, token_info.ulMinPinLen, token_info.ulMaxPinLen); display_token_flags(token_info.flags); if (!show_mechs) { goto finish; } display_mechs: if (mechlist == NULL) { rv = funcs->C_GetMechanismList(METASLOT_ID, NULL_PTR, &mech_count); if (rv != CKR_OK) { cryptodebug("C_GetMechanismList failed with error " "code 0x%x\n", rv); rc = FAILURE; goto finish; } if (mech_count > 0) { pmech_list = malloc(mech_count * sizeof (CK_MECHANISM_TYPE)); if (pmech_list == NULL) { cryptodebug("out of memory"); rc = FAILURE; goto finish; } rv = funcs->C_GetMechanismList(METASLOT_ID, pmech_list, &mech_count); if (rv != CKR_OK) { cryptodebug("C_GetMechanismList failed with " "error code 0x%x\n", rv); rc = FAILURE; goto finish; } } } else { rc = convert_mechlist(&pmech_list, &mech_count, mechlist); if (rc != SUCCESS) { goto finish; } } (void) printf(gettext("Mechanisms:\n")); if (mech_count == 0) { /* should never be this case */ (void) printf(gettext("No mechanisms\n")); goto finish; } if (verbose) { display_verbose_mech_header(); } for (i = 0; i < mech_count; i++) { CK_MECHANISM_TYPE mech = pmech_list[i]; if (mech >= CKM_VENDOR_DEFINED) { (void) printf("%#lx", mech); } else { (void) printf("%-29s", pkcs11_mech2str(mech)); } if (verbose) { CK_MECHANISM_INFO mech_info; rv = funcs->C_GetMechanismInfo(METASLOT_ID, mech, &mech_info); if (rv != CKR_OK) { cryptodebug("C_GetMechanismInfo failed with " "error code 0x%x\n", rv); rc = FAILURE; goto finish; } display_mech_info(&mech_info); } (void) printf("\n"); } finish: if ((rc == FAILURE) && (show_mechs)) { (void) printf(gettext( "metaslot: failed to retrieve the mechanism list.\n")); } if (lib_initialized) { (void) funcs->C_Finalize(NULL_PTR); } if (dldesc != NULL) { (void) dlclose(dldesc); } if (pmech_list != NULL) { (void) free(pmech_list); } return (rc); }
int main (int argc, char **argv) { CK_RV rv = CKR_OK; CK_FUNCTION_LIST_PTR pkcs11; CK_RV (*C_GetFunctionList) (CK_FUNCTION_LIST_PTR_PTR) = 0; char *lib_path, *string_to_search; unsigned int string_to_search_len; CK_INFO info; CK_SLOT_INFO slot_info; CK_ULONG slot_list_size = 8; CK_SLOT_ID slot_list[slot_list_size]; CK_TOKEN_INFO token_info; CK_ULONG i; CK_SESSION_HANDLE session_handle; CK_OBJECT_HANDLE object_list[16]; CK_ULONG object_list_size = 16, objects_found; if (argc >= 2) lib_path = argv[1]; if (argc >= 3) string_to_search = argv[2]; string_to_search_len = strlen(string_to_search); void *pkcs11_so; pkcs11_so = dlopen (lib_path, RTLD_NOW); if (pkcs11_so == NULL) { fprintf (stderr, "Could not load library: %s\n", dlerror()); return CKR_GENERAL_ERROR; } C_GetFunctionList = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) dlsym(pkcs11_so, "C_GetFunctionList"); rv = C_GetFunctionList (&pkcs11); g_assert (rv == CKR_OK); /**/ rv = pkcs11->C_Initialize (NULL); g_assert (rv == CKR_OK); rv = pkcs11->C_GetInfo (&info); g_assert (rv == CKR_OK); printf ("CK_INFO\n"); printf ("PKCS#11 version: %u.%u\n", info.cryptokiVersion.major, info.cryptokiVersion.minor); printf ("Manufacturer ID: %s\n", info.manufacturerID); printf ("Flags: %lx\n", (CK_ULONG) info.flags); printf ("Library Description: "); print_info (info.libraryDescription, 32); printf ("library version: %u.%u\n", info.libraryVersion.major, info.libraryVersion.minor); rv = pkcs11->C_GetSlotList (CK_TRUE, slot_list, &slot_list_size); g_assert (rv == CKR_OK); printf ("Number of slots: %lu\n", slot_list_size); printf ("Slot number: "); for (i = 0; i < slot_list_size; i++) { printf ("%lu ", (CK_ULONG) slot_list[i]); } printf ("\n"); /**/ rv = pkcs11->C_GetSlotInfo (slot_list[0], &slot_info); g_assert (rv == CKR_OK); printf ("CK_SLOT_INFO\n"); printf ("Slot description: "); print_info (slot_info.slotDescription, 64); printf ("Manufacturer ID: "); print_info (slot_info.manufacturerID, 32); printf ("Flags: %lx\n", slot_info.flags); printf ("Hardware version: %u.%u\n", slot_info.hardwareVersion.major, slot_info.hardwareVersion.minor); printf ("Firmware version: %u.%u\n", slot_info.firmwareVersion.major, slot_info.firmwareVersion.minor); rv = pkcs11->C_GetTokenInfo (slot_list[0], &token_info); g_assert (rv == CKR_OK); test_session (pkcs11, slot_list[0]); rv = pkcs11->C_OpenSession (slot_list[0], CKF_SERIAL_SESSION, NULL, NULL, &session_handle); g_assert (rv == CKR_OK); test_search (pkcs11, slot_list[0], session_handle, string_to_search, string_to_search_len, object_list, object_list_size, &objects_found); test_attribute_value (pkcs11, slot_list[0], session_handle, object_list[0]); rv = pkcs11->C_CloseSession(session_handle); g_assert (rv == CKR_OK); rv = pkcs11->C_Finalize (NULL); g_assert (rv == CKR_OK); rv = dlclose(pkcs11_so); if (rv != 0) { fprintf (stderr, "Could not dlclose\n"); } return 0; }
// Load the device module bool Win32LoadSecModule(SECURE *sec) { SEC_DATA_WIN32 *w; HINSTANCE hInst; CK_FUNCTION_LIST_PTR api = NULL; CK_RV (*get_function_list)(CK_FUNCTION_LIST_PTR_PTR); // Validate arguments if (sec == NULL) { return false; } if (sec->Dev->Id == 9) { char username[MAX_SIZE]; DWORD size; // Because the device driver of Juki-Net needs the contents // of the Software\JPKI registry key on HKLU of SYSTEM, // if there is no key, copy the key from the value of other user // if (MsRegIsValue(REG_CURRENT_USER, "Software\\JPKI", "Name") == false || // MsRegIsValue(REG_CURRENT_USER, "Software\\JPKI", "RWType") == false) size = sizeof(username); GetUserName(username, &size); if (StrCmpi(username, "System") == 0) { TOKEN_LIST *t = MsRegEnumKey(REG_USERS, NULL); if (t != NULL) { UINT i; for (i = 0;i < t->NumTokens;i++) { char tmp[MAX_PATH]; if (StrCmpi(t->Token[i], ".DEFAULT") != 0 && StrCmpi(t->Token[i], "S-1-5-18") != 0) { Format(tmp, sizeof(tmp), "%s\\Software\\JPKI", t->Token[i]); if (MsRegIsValue(REG_USERS, tmp, "Name") && MsRegIsValue(REG_USERS, tmp, "RWType")) { char *name = MsRegReadStr(REG_USERS, tmp, "Name"); char *port = MsRegReadStr(REG_USERS, tmp, "Port"); UINT type = MsRegReadInt(REG_USERS, tmp, "RWType"); MsRegWriteStr(REG_CURRENT_USER, "Software\\JPKI", "Name", name); MsRegWriteStr(REG_CURRENT_USER, "Software\\JPKI", "Port", port); MsRegWriteInt(REG_CURRENT_USER, "Software\\JPKI", "RWType", type); Free(name); Free(port); break; } } } FreeToken(t); } } } // Load the Library hInst = Win32SecureLoadLibraryEx(sec->Dev->ModuleName, 0); if (hInst == NULL) { // Failure return false; } // Get the API get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) GetProcAddress(hInst, "C_GetFunctionList"); if (get_function_list == NULL) { // Failure FreeLibrary(hInst); return false; } get_function_list(&api); if (api == NULL) { // Failure FreeLibrary(hInst); return false; } sec->Data = ZeroMalloc(sizeof(SEC_DATA_WIN32)); w = sec->Data; w->hInst = hInst; sec->Api = api; return true; }