/*
 * 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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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);
}
Example #7
0
/**********************************************************************
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;
}
Example #8
0
/*
 * 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);
}
Example #9
0
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);
}
Example #10
0
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;
}
Example #11
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;
}