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