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(1M). 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(1M) 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(1M) 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