1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 /*
25  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
26  */
27 
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <dlfcn.h>
31 #include <fcntl.h>
32 #include <link.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <strings.h>
36 #include <errno.h>
37 #include <pthread.h>
38 #include <sys/mman.h>
39 #include <libscf.h>
40 
41 #include <sys/crypto/elfsign.h>
42 #include <cryptoutil.h>
43 
44 #include <security/cryptoki.h>
45 #include "pkcs11Global.h"
46 #include "pkcs11Conf.h"
47 #include "pkcs11Slot.h"
48 #include "metaGlobal.h"
49 
50 /*
51  * Fastpath is used when there is only one slot available from a single provider
52  * plugged into the framework this is the common case.
53  * These globals are used to track the function pointers and policy when
54  * the fast-path is activated.
55  * This will need to be revisted if per-slot policy is ever
56  * implemented.
57  */
58 boolean_t purefastpath = B_FALSE;
59 boolean_t policyfastpath = B_FALSE;
60 CK_FUNCTION_LIST_PTR fast_funcs = NULL;
61 CK_SLOT_ID fast_slot = 0;
62 boolean_t metaslot_enabled = B_FALSE;
63 boolean_t metaslot_auto_key_migrate = B_FALSE;
64 metaslot_config_t metaslot_config;
65 void (*Tmp_GetThreshold)(void *) = NULL;
66 cipher_mechs_threshold_t meta_mechs_threshold[MAX_NUM_THRESHOLD];
67 
68 static const char *conf_err = "See cryptoadm(1M). Skipping this plug-in.";
69 
70 /*
71  * Set up metaslot for the framework using either user configuration
72  * or system wide configuration options
73  *
74  * Also sets up the global "slottable" to have the first slot be metaslot.
75  */
76 static CK_RV
77 setup_metaslot(uentry_t *metaslot_entry) {
78 	CK_RV rv;
79 	CK_MECHANISM_TYPE_PTR prov_pol_mechs = NULL;
80 	pkcs11_slot_t *cur_slot;
81 
82 	/* process policies for mechanisms */
83 	if ((metaslot_entry) && (metaslot_entry->count > 0)) {
84 		rv = pkcs11_mech_parse(metaslot_entry->policylist,
85 		    &prov_pol_mechs, metaslot_entry->count);
86 
87 		if (rv == CKR_HOST_MEMORY) {
88 			cryptoerror(LOG_ERR,
89 			    "libpkcs11: Could not parse configuration,"
90 			    "out of memory. Cannot continue parsing "
91 			    "%s.\n", _PATH_PKCS11_CONF);
92 			return (rv);
93 		} else if (rv == CKR_MECHANISM_INVALID) {
94 			/*
95 			 * Configuration file is corrupted for metaslot
96 			 */
97 			cryptoerror(LOG_ERR,
98 			    "libpkcs11: Policy invalid or corrupted "
99 			    "for metaslot. Use cryptoadm(1M) to fix "
100 			    "this. Disabling metaslot functionality.\n");
101 			metaslot_enabled = B_FALSE;
102 			return (rv);
103 		}
104 	}
105 
106 	/*
107 	 * Check for metaslot policy.  If all mechanisms are
108 	 * disabled, disable metaslot since there is nothing
109 	 * interesting for it to do
110 	 */
111 	if ((metaslot_entry) && (metaslot_entry->flag_enabledlist) &&
112 	    (prov_pol_mechs == NULL)) {
113 		metaslot_enabled = B_FALSE;
114 		return (rv);
115 	}
116 
117 	/*
118 	 * save system wide value for metaslot's keystore.
119 	 * If either slot description or token label is specified by
120 	 * the user, the system wide value for both is ignored.
121 	 */
122 	if ((metaslot_entry) &&
123 	    (!metaslot_config.keystore_token_specified) &&
124 	    (!metaslot_config.keystore_slot_specified)) {
125 		/*
126 		 * blank_str is used for comparing with token label,
127 		 * and slot description, make sure it is better than
128 		 * the larger of both
129 		 */
130 		char blank_str[TOKEN_LABEL_SIZE + SLOT_DESCRIPTION_SIZE];
131 
132 		bzero(blank_str, sizeof (blank_str));
133 
134 		if (memcmp(metaslot_entry->metaslot_ks_token,
135 		    blank_str, TOKEN_LABEL_SIZE) != 0) {
136 			metaslot_config.keystore_token_specified = B_TRUE;
137 			(void) strlcpy(
138 			    (char *)metaslot_config.keystore_token,
139 			    (const char *)metaslot_entry->metaslot_ks_token,
140 			    TOKEN_LABEL_SIZE);
141 		}
142 
143 		if (memcmp(metaslot_entry->metaslot_ks_slot,
144 		    blank_str, SLOT_DESCRIPTION_SIZE) != 0) {
145 			metaslot_config.keystore_slot_specified = B_TRUE;
146 			(void) strlcpy(
147 			    (char *)metaslot_config.keystore_slot,
148 			    (const char *)metaslot_entry->metaslot_ks_slot,
149 			    SLOT_DESCRIPTION_SIZE);
150 		}
151 	}
152 
153 	/* check system-wide value for auto_key_migrate */
154 	if (metaslot_config.auto_key_migrate_specified) {
155 		/* take user's specified value */
156 		metaslot_auto_key_migrate = metaslot_config.auto_key_migrate;
157 	} else {
158 		if (metaslot_entry) {
159 			/* use system-wide default */
160 			metaslot_auto_key_migrate =
161 			    metaslot_entry->flag_metaslot_auto_key_migrate;
162 		} else {
163 			/*
164 			 * there's no system wide metaslot entry,
165 			 * default auto_key_migrate to true
166 			 */
167 			metaslot_auto_key_migrate = B_TRUE;
168 		}
169 	}
170 
171 
172 	/* Make first slotID be 0, for metaslot. */
173 	slottable->st_first = 0;
174 
175 	/* Set up the slottable entry for metaslot */
176 	slottable->st_slots[0] = NULL;
177 	cur_slot = calloc(1, sizeof (pkcs11_slot_t));
178 	if (cur_slot == NULL) {
179 		rv = CKR_HOST_MEMORY;
180 		return (rv);
181 	}
182 	cur_slot->sl_wfse_state = WFSE_CLEAR;
183 	cur_slot->sl_enabledpol = B_FALSE;
184 	cur_slot->sl_no_wfse = B_FALSE;
185 	(void) pthread_mutex_init(&cur_slot->sl_mutex, NULL);
186 
187 	/*
188 	 * The metaslot entry was prealloc'd by
189 	 * pkcs11_slottable_increase()
190 	 */
191 	(void) pthread_mutex_lock(&slottable->st_mutex);
192 	slottable->st_slots[0] = cur_slot;
193 	(void) pthread_mutex_unlock(&slottable->st_mutex);
194 
195 	(void) pthread_mutex_lock(&cur_slot->sl_mutex);
196 	cur_slot->sl_id = METASLOT_SLOTID;
197 	cur_slot->sl_func_list = &metaslot_functionList;
198 	if (metaslot_entry) {
199 		cur_slot->sl_enabledpol = metaslot_entry->flag_enabledlist;
200 		cur_slot->sl_pol_count = metaslot_entry->count;
201 	} else {
202 		/* if no metaslot entry, assume all mechs are enabled */
203 		cur_slot->sl_enabledpol = B_FALSE;
204 		cur_slot->sl_pol_count = 0;
205 	}
206 	cur_slot->sl_pol_mechs = prov_pol_mechs;
207 	cur_slot->sl_dldesc = NULL; /* not applicable */
208 	cur_slot->sl_prov_id = 0;
209 	(void) pthread_mutex_unlock(&cur_slot->sl_mutex);
210 
211 	/* Call the meta_Initialize() to initialize metaslot */
212 	rv = meta_Initialize(NULL);
213 	if (rv != CKR_OK) {
214 		cryptoerror(LOG_ERR,
215 		    "libpkcs11: Can't initialize metaslot (%s)",
216 		    pkcs11_strerror(rv));
217 		goto cleanup;
218 	}
219 
220 	return (CKR_OK);
221 
222 cleanup:
223 	metaslot_enabled = B_FALSE;
224 	slottable->st_slots[0] = NULL;
225 
226 	if (cur_slot) {
227 		(void) pthread_mutex_destroy(&cur_slot->sl_mutex);
228 		free(cur_slot);
229 	}
230 	return (rv);
231 }
232 
233 /*
234  * For each provider found in pkcs11.conf: expand $ISA if necessary,
235  * verify the module is signed, load the provider, find all of its
236  * slots, and store the function list and disabled policy.
237  *
238  * This function requires that the uentrylist_t and pkcs11_slottable_t
239  * already have memory allocated, and that the uentrylist_t is already
240  * populated with provider and policy information.
241  *
242  * pInitArgs can be set to NULL, but is normally the same value
243  * the framework's C_Initialize() was called with.
244  *
245  * Unless metaslot is explicitly disabled, it is setup when all other
246  * providers are loaded.
247  */
248 CK_RV
249 pkcs11_slot_mapping(uentrylist_t *pplist, CK_VOID_PTR pInitArgs)
250 {
251 	CK_RV rv = CKR_OK;
252 	CK_RV prov_rv;			/* Provider's return code */
253 	CK_INFO prov_info;
254 	CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
255 	CK_FUNCTION_LIST_PTR prov_funcs = NULL; /* Provider's function list */
256 	CK_ULONG prov_slot_count; 		/* Number of slots */
257 	CK_SLOT_ID slot_id; 		/* slotID assigned for framework */
258 	CK_SLOT_ID_PTR prov_slots = NULL; 	/* Provider's slot list */
259 					/* Enabled or Disabled policy */
260 	CK_MECHANISM_TYPE_PTR prov_pol_mechs = NULL;
261 
262 	void *dldesc = NULL;
263 	char *isa, *fullpath = NULL, *dl_error;
264 	uentrylist_t *phead;
265 	uint_t prov_count = 0;
266 	pkcs11_slot_t *cur_slot;
267 	CK_ULONG i;
268 	size_t len;
269 	uentry_t *metaslot_entry = NULL;
270 	/* number of slots in the framework, not including metaslot */
271 	uint_t slot_count = 0;
272 
273 	phead = pplist;
274 
275 	/* Loop through all of the provider listed in pkcs11.conf */
276 	while (phead != NULL) {
277 		if (!strcasecmp(phead->puent->name, "metaslot")) {
278 			/*
279 			 * Skip standard processing for metaslot
280 			 * entry since it is not an actual library
281 			 * that can be dlopened.
282 			 * It will be initialized later.
283 			 */
284 			if (metaslot_entry != NULL) {
285 				cryptoerror(LOG_ERR,
286 				    "libpkcs11: multiple entries for metaslot "
287 				    "detected.  All but the first entry will "
288 				    "be ignored");
289 			} else {
290 				metaslot_entry = phead->puent;
291 			}
292 			goto contparse;
293 		}
294 
295 		if (!strcasecmp(phead->puent->name, FIPS_KEYWORD)) {
296 			/*
297 			 * Skip standard processing for fips-140
298 			 * entry since it is not an actual library
299 			 * that can be dlopened.
300 			 */
301 			goto contparse;
302 		}
303 
304 		/* Check for Instruction Set Architecture indicator */
305 		if ((isa = strstr(phead->puent->name, PKCS11_ISA)) != NULL) {
306 			/* Substitute the architecture dependent path */
307 			len = strlen(phead->puent->name) -
308 			    strlen(PKCS11_ISA) +
309 			    strlen(PKCS11_ISA_DIR) + 1;
310 			if ((fullpath = (char *)malloc(len)) == NULL) {
311 				cryptoerror(LOG_ERR,
312 				    "libpksc11: parsing %s, out of memory. "
313 				    "Cannot continue parsing.",
314 				    _PATH_PKCS11_CONF);
315 				rv = CKR_HOST_MEMORY;
316 				goto conferror;
317 			}
318 			*isa = '\000';
319 			isa += strlen(PKCS11_ISA);
320 			(void) snprintf(fullpath, len, "%s%s%s",
321 			    phead->puent->name, PKCS11_ISA_DIR, isa);
322 		} else if ((fullpath = strdup(phead->puent->name)) == 0) {
323 			cryptoerror(LOG_ERR,
324 			    "libpkcs11: parsing %s, out of memory. "
325 			    "Cannot continue parsing.",
326 			    _PATH_PKCS11_CONF);
327 			rv = CKR_HOST_MEMORY;
328 			goto conferror;
329 		}
330 
331 		/*
332 		 * Open the provider. We assume all of our plugins have
333 		 * their symbols properly defined, so the use of RTLD_NOW
334 		 * to flush out errors immediately is not necessary.
335 		 *
336 		 * Note that for proper operation, all plugins must be
337 		 * built with direct bindings enabled.
338 		 */
339 		dldesc = dlopen(fullpath, RTLD_LAZY);
340 
341 		/*
342 		 * If we failed to load it, we will just skip this
343 		 * provider and move on to the next one.
344 		 */
345 		if (dldesc == NULL) {
346 			dl_error = dlerror();
347 			cryptoerror(LOG_ERR,
348 			    "libpkcs11: Cannot load PKCS#11 library %s.  "
349 			    "dlerror: %s. %s",
350 			    fullpath, dl_error != NULL ? dl_error : "Unknown",
351 			    conf_err);
352 			goto contparse;
353 		}
354 
355 		/* Get the pointer to provider's C_GetFunctionList() */
356 		Tmp_C_GetFunctionList =
357 		    (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");
358 
359 		/*
360 		 * If we failed to get the pointer to C_GetFunctionList(),
361 		 * skip this provider and continue to the next one.
362 		 */
363 		if (Tmp_C_GetFunctionList == NULL) {
364 			cryptoerror(LOG_ERR,
365 			    "libpkcs11: Could not dlsym() C_GetFunctionList() "
366 			    "for %s. May not be a PKCS#11 library. %s",
367 			    fullpath, conf_err);
368 			(void) dlclose(dldesc);
369 			goto contparse;
370 		}
371 
372 
373 		/* Get the provider's function list */
374 		prov_rv = Tmp_C_GetFunctionList(&prov_funcs);
375 
376 		/*
377 		 * If we failed to get the provider's function list,
378 		 * skip this provider and continue to the next one.
379 		 */
380 		if (prov_rv != CKR_OK) {
381 			cryptoerror(LOG_ERR,
382 			    "libpkcs11: Could not get function list for %s. "
383 			    "%s Error: %s.",
384 			    fullpath, conf_err, pkcs11_strerror(prov_rv));
385 			(void) dlclose(dldesc);
386 			goto contparse;
387 		}
388 
389 		/* Initialize this provider */
390 		prov_rv = prov_funcs->C_Initialize(pInitArgs);
391 
392 		/*
393 		 * If we failed to initialize this provider,
394 		 * skip this provider and continue to the next one.
395 		 */
396 		if ((prov_rv != CKR_OK) &&
397 		    (prov_rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
398 			cryptoerror(LOG_ERR,
399 			    "libpkcs11: Could not initialize %s. "
400 			    "%s Error: %s.",
401 			    fullpath, conf_err, pkcs11_strerror(prov_rv));
402 			(void) dlclose(dldesc);
403 			goto contparse;
404 		}
405 
406 		/*
407 		 * Make sure this provider is implementing the same
408 		 * major version, and at least the same minor version
409 		 * that we are.
410 		 */
411 		prov_rv = prov_funcs->C_GetInfo(&prov_info);
412 
413 		/*
414 		 * If we can't verify that we are implementing the
415 		 * same major version, or if it is definitely not the same
416 		 * version, we need to skip this provider.
417 		 */
418 		if ((prov_rv != CKR_OK) ||
419 		    (prov_info.cryptokiVersion.major !=
420 		    CRYPTOKI_VERSION_MAJOR))  {
421 			if (prov_rv != CKR_OK) {
422 				cryptoerror(LOG_ERR,
423 				    "libpkcs11: Could not verify version of "
424 				    "%s. %s Error: %s.", fullpath,
425 				    conf_err, pkcs11_strerror(prov_rv));
426 			} else {
427 				cryptoerror(LOG_ERR,
428 				    "libpkcs11: Only CRYPTOKI major version "
429 				    "%d is supported.  %s is major "
430 				    "version %d. %s",
431 				    CRYPTOKI_VERSION_MAJOR, fullpath,
432 				    prov_info.cryptokiVersion.major, conf_err);
433 			}
434 			(void) prov_funcs->C_Finalize(NULL);
435 			(void) dlclose(dldesc);
436 			goto contparse;
437 		}
438 
439 		/*
440 		 * Warn the administrator (at debug) that a provider with
441 		 * a significantly older or newer version of
442 		 * CRYPTOKI is being used.  It should not cause
443 		 * problems, but logging a warning makes it easier
444 		 * to debug later.
445 		 */
446 		if ((prov_info.cryptokiVersion.minor <
447 		    CRYPTOKI_VERSION_WARN_MINOR) ||
448 		    (prov_info.cryptokiVersion.minor >
449 		    CRYPTOKI_VERSION_MINOR)) {
450 			cryptoerror(LOG_DEBUG,
451 			    "libpkcs11: %s CRYPTOKI minor version, %d, may "
452 			    "not be compatible with minor version %d.",
453 			    fullpath, prov_info.cryptokiVersion.minor,
454 			    CRYPTOKI_VERSION_MINOR);
455 		}
456 
457 		/*
458 		 * Find out how many slots this provider has,
459 		 * call with tokenPresent set to FALSE so all
460 		 * potential slots are returned.
461 		 */
462 		prov_rv = prov_funcs->C_GetSlotList(FALSE,
463 		    NULL, &prov_slot_count);
464 
465 		/*
466 		 * If the call failed, or if no slots are returned,
467 		 * then skip this provider and continue to next one.
468 		 */
469 		if (prov_rv != CKR_OK) {
470 			cryptoerror(LOG_ERR,
471 			    "libpksc11: Could not get slot list from %s. "
472 			    "%s Error: %s.",
473 			    fullpath, conf_err, pkcs11_strerror(prov_rv));
474 			(void) prov_funcs->C_Finalize(NULL);
475 			(void) dlclose(dldesc);
476 			goto contparse;
477 		}
478 
479 		if (prov_slot_count == 0) {
480 			cryptodebug("libpkcs11: No slots presented from %s. "
481 			    "Skipping this plug-in at this time.\n",
482 			    fullpath);
483 			(void) prov_funcs->C_Finalize(NULL);
484 			(void) dlclose(dldesc);
485 			goto contparse;
486 		}
487 
488 		/* Allocate memory for the slot list */
489 		prov_slots = calloc(prov_slot_count, sizeof (CK_SLOT_ID));
490 
491 		if (prov_slots == NULL) {
492 			cryptoerror(LOG_ERR,
493 			    "libpkcs11: Could not allocate memory for "
494 			    "plug-in slots. Cannot continue parsing %s\n",
495 			    _PATH_PKCS11_CONF);
496 			rv = CKR_HOST_MEMORY;
497 			goto conferror;
498 		}
499 
500 		/* Get slot list from provider */
501 		prov_rv = prov_funcs->C_GetSlotList(FALSE,
502 		    prov_slots, &prov_slot_count);
503 
504 		/* if second call fails, drop this provider */
505 		if (prov_rv != CKR_OK) {
506 			cryptoerror(LOG_ERR,
507 			    "libpkcs11: Second call to C_GetSlotList() for %s "
508 			    "failed. %s Error: %s.",
509 			    fullpath, conf_err, pkcs11_strerror(prov_rv));
510 			(void) prov_funcs->C_Finalize(NULL);
511 			(void) dlclose(dldesc);
512 			goto contparse;
513 		}
514 
515 		/*
516 		 * Parse the list of disabled or enabled mechanisms, will
517 		 * apply to each of the provider's slots.
518 		 */
519 		if (phead->puent->count > 0) {
520 			rv = pkcs11_mech_parse(phead->puent->policylist,
521 			    &prov_pol_mechs, phead->puent->count);
522 
523 			if (rv == CKR_HOST_MEMORY) {
524 				cryptoerror(LOG_ERR,
525 				    "libpkcs11: Could not parse configuration,"
526 				    "out of memory. Cannot continue parsing "
527 				    "%s.", _PATH_PKCS11_CONF);
528 				goto conferror;
529 			} else if (rv == CKR_MECHANISM_INVALID) {
530 				/*
531 				 * Configuration file is corrupted for this
532 				 * provider.
533 				 */
534 				cryptoerror(LOG_ERR,
535 				    "libpkcs11: Policy invalid or corrupted "
536 				    "for %s. Use cryptoadm(1M) to fix "
537 				    "this. Skipping this plug-in.",
538 				    fullpath);
539 				(void) prov_funcs->C_Finalize(NULL);
540 				(void) dlclose(dldesc);
541 				goto contparse;
542 			}
543 		}
544 
545 		/* Allocate memory in our slottable for these slots */
546 		rv = pkcs11_slottable_increase(prov_slot_count);
547 
548 		/*
549 		 * If any error is returned, it will be memory related,
550 		 * so we need to abort the attempt at filling the
551 		 * slottable.
552 		 */
553 		if (rv != CKR_OK) {
554 			cryptoerror(LOG_ERR,
555 			    "libpkcs11: slottable could not increase. "
556 			    "Cannot continue parsing %s.",
557 			    _PATH_PKCS11_CONF);
558 			goto conferror;
559 		}
560 
561 		/* Configure information for each new slot */
562 		for (i = 0; i < prov_slot_count; i++) {
563 			/* allocate slot in framework */
564 			rv = pkcs11_slot_allocate(&slot_id);
565 			if (rv != CKR_OK) {
566 				cryptoerror(LOG_ERR,
567 				    "libpkcs11: Could not allocate "
568 				    "new slot.  Cannot continue parsing %s.",
569 				    _PATH_PKCS11_CONF);
570 				goto conferror;
571 			}
572 			slot_count++;
573 			cur_slot = slottable->st_slots[slot_id];
574 			(void) pthread_mutex_lock(&cur_slot->sl_mutex);
575 			cur_slot->sl_id = prov_slots[i];
576 			cur_slot->sl_func_list = prov_funcs;
577 			cur_slot->sl_enabledpol =
578 			    phead->puent->flag_enabledlist;
579 			cur_slot->sl_pol_mechs = prov_pol_mechs;
580 			cur_slot->sl_pol_count = phead->puent->count;
581 			cur_slot->sl_norandom = phead->puent->flag_norandom;
582 			cur_slot->sl_dldesc = dldesc;
583 			cur_slot->sl_prov_id = prov_count + 1;
584 			(void) pthread_mutex_unlock(&cur_slot->sl_mutex);
585 		}
586 
587 		/*
588 		 * Get the pointer to private interface _SUNW_GetThreshold()
589 		 * in pkcs11_kernel.
590 		 */
591 
592 		if (Tmp_GetThreshold == NULL) {
593 			Tmp_GetThreshold =
594 			    (void(*)())dlsym(dldesc, "_SUNW_GetThreshold");
595 
596 			/* Get the threshold values for the supported mechs */
597 			if (Tmp_GetThreshold != NULL) {
598 				(void) memset(meta_mechs_threshold, 0,
599 				    sizeof (meta_mechs_threshold));
600 				Tmp_GetThreshold(meta_mechs_threshold);
601 			}
602 		}
603 
604 		/* Set and reset values to process next provider */
605 		prov_count++;
606 contparse:
607 		prov_slot_count = 0;
608 		Tmp_C_GetFunctionList = NULL;
609 		prov_funcs = NULL;
610 		dldesc = NULL;
611 		if (fullpath != NULL) {
612 			free(fullpath);
613 			fullpath = NULL;
614 		}
615 		if (prov_slots != NULL) {
616 			free(prov_slots);
617 			prov_slots = NULL;
618 		}
619 		phead = phead->next;
620 	}
621 
622 	if (slot_count == 0) {
623 		/*
624 		 * there's no other slot in the framework,
625 		 * there is nothing to do
626 		 */
627 		goto config_complete;
628 	}
629 
630 	/* determine if metaslot should be enabled */
631 
632 	/*
633 	 * Check to see if any environment variable is defined
634 	 * by the user for configuring metaslot.  Users'
635 	 * setting always take precedence over the system wide
636 	 * setting.  So, we will first check for any user's
637 	 * defined env variables before looking at the system-wide
638 	 * configuration.
639 	 */
640 	get_user_metaslot_config();
641 
642 	/* no metaslot entry in /etc/crypto/pkcs11.conf */
643 	if (!metaslot_entry) {
644 		/*
645 		 * If user env variable indicates metaslot should be enabled,
646 		 * but there's no entry in /etc/crypto/pkcs11.conf for
647 		 * metaslot at all, will respect the user's defined value
648 		 */
649 		if ((metaslot_config.enabled_specified) &&
650 		    (metaslot_config.enabled)) {
651 			metaslot_enabled = B_TRUE;
652 		}
653 	} else {
654 		if (!metaslot_config.enabled_specified) {
655 			/*
656 			 * take system wide value if
657 			 * it is not specified by user
658 			 */
659 			metaslot_enabled
660 			    = metaslot_entry->flag_metaslot_enabled;
661 		} else {
662 			metaslot_enabled = metaslot_config.enabled;
663 		}
664 	}
665 
666 	/*
667 	 *
668 	 * As long as the user or system configuration file does not
669 	 * disable metaslot, it will be enabled regardless of the
670 	 * number of slots plugged into the framework.  Therefore,
671 	 * metaslot is enabled even when there's only one slot
672 	 * plugged into the framework.  This is necessary for
673 	 * presenting a consistent token label view to applications.
674 	 *
675 	 * However, for the case where there is only 1 slot plugged into
676 	 * the framework, we can use "fastpath".
677 	 *
678 	 * "fastpath" will pass all of the application's requests
679 	 * directly to the underlying provider.  Only when policy is in
680 	 * effect will we need to keep slotID around.
681 	 *
682 	 * When metaslot is enabled, and fastpath is enabled,
683 	 * all the metaslot processing will be skipped.
684 	 * When there is only 1 slot, there's
685 	 * really not much metaslot can do in terms of combining functionality
686 	 * of different slots, and object migration.
687 	 *
688 	 */
689 
690 	/* check to see if fastpath can be used */
691 	if (slottable->st_last == slottable->st_first) {
692 
693 		cur_slot = slottable->st_slots[slottable->st_first];
694 
695 		(void) pthread_mutex_lock(&cur_slot->sl_mutex);
696 
697 		if ((cur_slot->sl_pol_count == 0) &&
698 		    (!cur_slot->sl_enabledpol) && (!cur_slot->sl_norandom)) {
699 			/* No policy is in effect, don't need slotid */
700 			fast_funcs = cur_slot->sl_func_list;
701 			purefastpath = B_TRUE;
702 		} else {
703 			fast_funcs = cur_slot->sl_func_list;
704 			fast_slot = slottable->st_first;
705 			policyfastpath = B_TRUE;
706 		}
707 
708 		(void) pthread_mutex_unlock(&cur_slot->sl_mutex);
709 	}
710 
711 	if ((purefastpath || policyfastpath) && (!metaslot_enabled)) {
712 		goto config_complete;
713 	}
714 
715 	/*
716 	 * If we get here, there are more than 2 slots in the framework,
717 	 * we need to set up metaslot if it is enabled
718 	 */
719 	if (metaslot_enabled) {
720 		rv = setup_metaslot(metaslot_entry);
721 		if (rv != CKR_OK) {
722 			goto conferror;
723 		}
724 	}
725 
726 
727 config_complete:
728 
729 	return (CKR_OK);
730 
731 conferror:
732 	/*
733 	 * This cleanup code is only exercised when a major,
734 	 * unrecoverable error like "out of memory".
735 	 */
736 	if (prov_funcs != NULL) {
737 		(void) prov_funcs->C_Finalize(NULL);
738 	}
739 	if (dldesc != NULL) {
740 		(void) dlclose(dldesc);
741 	}
742 	if (fullpath != NULL) {
743 		free(fullpath);
744 		fullpath = NULL;
745 	}
746 	if (prov_slots != NULL) {
747 		free(prov_slots);
748 		prov_slots = NULL;
749 	}
750 
751 	return (rv);
752 }
753 
754 /*
755  * pkcs11_mech_parse will take hex mechanism ids, as a list of
756  * strings, and convert them to CK_MECHANISM_TYPE_PTR.
757  */
758 CK_RV
759 pkcs11_mech_parse(umechlist_t *str_list, CK_MECHANISM_TYPE_PTR *mech_list,
760     int mech_count)
761 {
762 	CK_MECHANISM_TYPE_PTR tmp_list;
763 	umechlist_t *shead = str_list;
764 
765 	tmp_list = malloc(mech_count * sizeof (CK_MECHANISM_TYPE));
766 
767 	if (tmp_list == NULL) {
768 		cryptoerror(LOG_ERR, "libpkcs11: parsing %s, out of memory. "
769 		    "Cannot continue.",
770 		    _PATH_PKCS11_CONF);
771 		return (CKR_HOST_MEMORY);
772 	}
773 
774 	*mech_list = tmp_list;
775 
776 	/*
777 	 * The following will loop mech_count times, as there are
778 	 * exactly mech_count items in the str_list.
779 	 */
780 	while (shead != NULL) {
781 		CK_MECHANISM_TYPE cur_mech;
782 
783 		errno = 0;
784 
785 		/*
786 		 * "name" is a hexadecimal number, preceded by 0x.
787 		 */
788 		cur_mech = strtoul(shead->name, NULL, 16);
789 
790 		if ((cur_mech == 0) &&
791 		    ((errno == EINVAL) || (errno == ERANGE))) {
792 			free(mech_list);
793 			return (CKR_MECHANISM_INVALID);
794 		}
795 		*tmp_list = (CK_MECHANISM_TYPE)cur_mech;
796 		tmp_list++;
797 		shead = shead->next;
798 	}
799 
800 	return (CKR_OK);
801 }
802 
803 /*
804  * pkcs11_is_dismech is provided a slotid and a mechanism.
805  * If mech is not disabled, then return B_FALSE.
806  */
807 boolean_t
808 pkcs11_is_dismech(CK_SLOT_ID slotid, CK_MECHANISM_TYPE mech)
809 {
810 	ulong_t i;
811 	boolean_t enabled_pol;
812 	CK_MECHANISM_TYPE_PTR pol_mechs;
813 	ulong_t pol_count;
814 
815 	/* Find the associated slot and get the mech policy info */
816 	(void) pthread_mutex_lock(&slottable->st_slots[slotid]->sl_mutex);
817 	enabled_pol = slottable->st_slots[slotid]->sl_enabledpol;
818 	pol_mechs = slottable->st_slots[slotid]->sl_pol_mechs;
819 	pol_count = slottable->st_slots[slotid]->sl_pol_count;
820 	(void) pthread_mutex_unlock(&slottable->st_slots[slotid]->sl_mutex);
821 
822 	/* Check for policy */
823 	if ((!enabled_pol) && (pol_mechs == NULL)) {
824 		/* no policy */
825 		return (B_FALSE);
826 	} else if (pol_mechs == NULL) {
827 		/*
828 		 * We have an empty enabled list, which means no
829 		 * mechanisms are exempted from this policy: all
830 		 * are disabled.
831 		 */
832 		return (B_TRUE);
833 	}
834 
835 	for (i = 0; i < pol_count; i++) {
836 		/*
837 		 * If it matches, return status based on this
838 		 * being and enabled or a disabled list of mechs.
839 		 */
840 		if (pol_mechs[i] == mech) {
841 			return (enabled_pol ? B_FALSE : B_TRUE);
842 		}
843 	}
844 
845 	/* mech was not found in list */
846 	return (enabled_pol ? B_TRUE : B_FALSE);
847 }
848