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 resrved.
26 */
27
28 #include <cryptoutil.h>
29 #include <fcntl.h>
30 #include <libintl.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <strings.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <dlfcn.h>
37 #include <link.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <security/cryptoki.h>
41 #include "cryptoadm.h"
42
43 #define HDR1 " P\n"
44 #define HDR2 " S V K a U D\n"
45 #define HDR3 " i e e i n e\n"
46 #define HDR4 " S g V r y r W w r\n"
47 #define HDR5 " E D D i n e i G G r r i\n"
48 #define HDR6 " H n e i g + r + e e a a v E\n"
49 #define HDR7 "min max W c c g n R i R n n p p e C\n"
50
51
52 static int err; /* To store errno which may be overwritten by gettext() */
53 static boolean_t is_in_policylist(midstr_t, umechlist_t *);
54 static char *uent2str(uentry_t *);
55 static boolean_t check_random(CK_SLOT_ID, CK_FUNCTION_LIST_PTR);
56
display_slot_flags(CK_FLAGS flags)57 static void display_slot_flags(CK_FLAGS flags)
58 {
59 (void) printf(gettext("Slot Flags: "));
60 if (flags & CKF_TOKEN_PRESENT)
61 (void) printf("CKF_TOKEN_PRESENT ");
62 if (flags & CKF_REMOVABLE_DEVICE)
63 (void) printf("CKF_REMOVABLE_DEVICE ");
64 if (flags & CKF_HW_SLOT)
65 (void) printf("CKF_HW_SLOT ");
66 (void) printf("\n");
67 }
68
69 void
display_token_flags(CK_FLAGS flags)70 display_token_flags(CK_FLAGS flags)
71 {
72 (void) printf(gettext("Flags: "));
73 if (flags & CKF_RNG)
74 (void) printf("CKF_RNG ");
75 if (flags & CKF_WRITE_PROTECTED)
76 (void) printf("CKF_WRITE_PROTECTED ");
77 if (flags & CKF_LOGIN_REQUIRED)
78 (void) printf("CKF_LOGIN_REQUIRED ");
79 if (flags & CKF_USER_PIN_INITIALIZED)
80 (void) printf("CKF_USER_PIN_INITIALIZED ");
81 if (flags & CKF_RESTORE_KEY_NOT_NEEDED)
82 (void) printf("CKF_RESTORE_KEY_NOT_NEEDED ");
83 if (flags & CKF_CLOCK_ON_TOKEN)
84 (void) printf("CKF_CLOCK_ON_TOKEN ");
85 if (flags & CKF_PROTECTED_AUTHENTICATION_PATH)
86 (void) printf("CKF_PROTECTED_AUTHENTICATION_PATH ");
87 if (flags & CKF_DUAL_CRYPTO_OPERATIONS)
88 (void) printf("CKF_DUAL_CRYPTO_OPERATIONS ");
89 if (flags & CKF_TOKEN_INITIALIZED)
90 (void) printf("CKF_TOKEN_INITIALIZED ");
91 if (flags & CKF_SECONDARY_AUTHENTICATION)
92 (void) printf("CKF_SECONDARY_AUTHENTICATION ");
93 if (flags & CKF_USER_PIN_COUNT_LOW)
94 (void) printf("CKF_USER_PIN_COUNT_LOW ");
95 if (flags & CKF_USER_PIN_FINAL_TRY)
96 (void) printf("CKF_USER_PIN_FINAL_TRY ");
97 if (flags & CKF_USER_PIN_LOCKED)
98 (void) printf("CKF_USER_PIN_LOCKED ");
99 if (flags & CKF_USER_PIN_TO_BE_CHANGED)
100 (void) printf("CKF_USER_PIN_TO_BE_CHANGED ");
101 if (flags & CKF_SO_PIN_COUNT_LOW)
102 (void) printf("CKF_SO_PIN_COUNT_LOW ");
103 if (flags & CKF_SO_PIN_FINAL_TRY)
104 (void) printf("CKF_SO_PIN_FINAL_TRY ");
105 if (flags & CKF_SO_PIN_LOCKED)
106 (void) printf("CKF_SO_PIN_LOCKED ");
107 if (flags & CKF_SO_PIN_TO_BE_CHANGED)
108 (void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
109 if (flags & CKF_SO_PIN_TO_BE_CHANGED)
110 (void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
111 (void) printf("\n");
112 }
113
114 void
display_mech_info(CK_MECHANISM_INFO * mechInfo)115 display_mech_info(CK_MECHANISM_INFO *mechInfo)
116 {
117 CK_FLAGS ec_flags = CKF_EC_F_P | CKF_EC_F_2M | CKF_EC_ECPARAMETERS |
118 CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS | CKF_EC_COMPRESS;
119
120 (void) printf("%-4ld %-4ld ", mechInfo->ulMinKeySize,
121 mechInfo->ulMaxKeySize);
122 (void) printf("%s %s %s %s %s %s %s %s %s %s %s %s "
123 "%s %s",
124 (mechInfo->flags & CKF_HW) ? "X" : ".",
125 (mechInfo->flags & CKF_ENCRYPT) ? "X" : ".",
126 (mechInfo->flags & CKF_DECRYPT) ? "X" : ".",
127 (mechInfo->flags & CKF_DIGEST) ? "X" : ".",
128 (mechInfo->flags & CKF_SIGN) ? "X" : ".",
129 (mechInfo->flags & CKF_SIGN_RECOVER) ? "X" : ".",
130 (mechInfo->flags & CKF_VERIFY) ? "X" : ".",
131 (mechInfo->flags & CKF_VERIFY_RECOVER) ? "X" : ".",
132 (mechInfo->flags & CKF_GENERATE) ? "X" : ".",
133 (mechInfo->flags & CKF_GENERATE_KEY_PAIR) ? "X" : ".",
134 (mechInfo->flags & CKF_WRAP) ? "X" : ".",
135 (mechInfo->flags & CKF_UNWRAP) ? "X" : ".",
136 (mechInfo->flags & CKF_DERIVE) ? "X" : ".",
137 (mechInfo->flags & ec_flags) ? "X" : ".");
138 }
139
140 /*
141 * Converts the provided list of mechanism names in their string format to
142 * their corresponding PKCS#11 mechanism IDs.
143 *
144 * The list of mechanism names to be converted is provided in the
145 * "mlist" argument. The list of converted mechanism IDs is returned
146 * in the "pmech_list" argument.
147 *
148 * This function is called by list_metaslot_info() and
149 * list_mechlist_for_lib() functions.
150 */
151 int
convert_mechlist(CK_MECHANISM_TYPE ** pmech_list,CK_ULONG * mech_count,mechlist_t * mlist)152 convert_mechlist(CK_MECHANISM_TYPE **pmech_list, CK_ULONG *mech_count,
153 mechlist_t *mlist)
154 {
155 int i, n = 0;
156 mechlist_t *p = mlist;
157
158 while (p != NULL) {
159 p = p->next;
160 n++;
161 }
162
163 *pmech_list = malloc(n * sizeof (CK_MECHANISM_TYPE));
164 if (pmech_list == NULL) {
165 cryptodebug("out of memory");
166 return (FAILURE);
167 }
168 p = mlist;
169 for (i = 0; i < n; i++) {
170 if (pkcs11_str2mech(p->name, &(*pmech_list[i])) != CKR_OK) {
171 free(*pmech_list);
172 return (FAILURE);
173 }
174 p = p->next;
175 }
176 *mech_count = n;
177 return (SUCCESS);
178 }
179
180 /*
181 * Display the mechanism list for a user-level library
182 */
183 int
list_mechlist_for_lib(char * libname,mechlist_t * mlist,flag_val_t * rng_flag,boolean_t no_warn,boolean_t verbose,boolean_t show_mechs)184 list_mechlist_for_lib(char *libname, mechlist_t *mlist,
185 flag_val_t *rng_flag, boolean_t no_warn,
186 boolean_t verbose, boolean_t show_mechs)
187 {
188 CK_RV rv = CKR_OK;
189 CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
190 CK_FUNCTION_LIST_PTR prov_funcs; /* Provider's function list */
191 CK_SLOT_ID_PTR prov_slots = NULL; /* Provider's slot list */
192 CK_MECHANISM_TYPE_PTR pmech_list = NULL; /* mech list for a slot */
193 CK_SLOT_INFO slotinfo;
194 CK_ULONG slot_count;
195 CK_ULONG mech_count;
196 uentry_t *puent = NULL;
197 boolean_t lib_initialized = B_FALSE;
198 void *dldesc = NULL;
199 char *dl_error;
200 const char *mech_name;
201 char *isa;
202 char libpath[MAXPATHLEN];
203 char buf[MAXPATHLEN];
204 int i, j;
205 int rc = SUCCESS;
206
207 if (libname == NULL) {
208 /* should not happen */
209 cryptoerror(LOG_STDERR, gettext("internal error."));
210 cryptodebug("list_mechlist_for_lib() - libname is NULL.");
211 return (FAILURE);
212 }
213
214 /* Check if the library is in the pkcs11.conf file */
215 if ((puent = getent_uef(libname)) == NULL) {
216 cryptoerror(LOG_STDERR,
217 gettext("%s does not exist."), libname);
218 return (FAILURE);
219 }
220 free_uentry(puent);
221
222 /* Remove $ISA from the library name */
223 if (strlcpy(buf, libname, sizeof (buf)) >= sizeof (buf)) {
224 (void) printf(gettext("%s: the provider name is too long."),
225 libname);
226 return (FAILURE);
227 }
228
229 if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
230 *isa = '\000';
231 isa += strlen(PKCS11_ISA);
232 (void) snprintf(libpath, MAXPATHLEN, "%s%s%s", buf, "/", isa);
233 } else {
234 (void) strlcpy(libpath, libname, sizeof (libpath));
235 }
236
237 /*
238 * Open the provider. Use RTLD_NOW here, as a way to
239 * catch any providers with incomplete symbols that
240 * might otherwise cause problems during libpkcs11's
241 * execution.
242 */
243 dldesc = dlopen(libpath, RTLD_NOW);
244 if (dldesc == NULL) {
245 dl_error = dlerror();
246 cryptodebug("Cannot load PKCS#11 library %s. dlerror: %s",
247 libname, dl_error != NULL ? dl_error : "Unknown");
248 rc = FAILURE;
249 goto clean_exit;
250 }
251
252 /* Get the pointer to provider's C_GetFunctionList() */
253 Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");
254 if (Tmp_C_GetFunctionList == NULL) {
255 cryptodebug("Cannot get the address of the C_GetFunctionList "
256 "from %s", libname);
257 rc = FAILURE;
258 goto clean_exit;
259 }
260
261 /* Get the provider's function list */
262 rv = Tmp_C_GetFunctionList(&prov_funcs);
263 if (rv != CKR_OK) {
264 cryptodebug("failed to call C_GetFunctionList from %s",
265 libname);
266 rc = FAILURE;
267 goto clean_exit;
268 }
269
270 /* Initialize this provider */
271 rv = prov_funcs->C_Initialize(NULL_PTR);
272 if (rv != CKR_OK) {
273 cryptodebug("failed to call C_Initialize from %s, "
274 "return code = %d", libname, rv);
275 rc = FAILURE;
276 goto clean_exit;
277 } else {
278 lib_initialized = B_TRUE;
279 }
280
281 /*
282 * Find out how many slots this provider has, call with tokenPresent
283 * set to FALSE so all potential slots are returned.
284 */
285 rv = prov_funcs->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
286 if (rv != CKR_OK) {
287 cryptodebug("failed to get the slotlist from %s.", libname);
288 rc = FAILURE;
289 goto clean_exit;
290 } else if (slot_count == 0) {
291 if (!no_warn)
292 (void) printf(gettext("%s: no slots presented.\n"),
293 libname);
294 rc = SUCCESS;
295 goto clean_exit;
296 }
297
298 /* Allocate memory for the slot list */
299 prov_slots = malloc(slot_count * sizeof (CK_SLOT_ID));
300 if (prov_slots == NULL) {
301 cryptodebug("out of memory.");
302 rc = FAILURE;
303 goto clean_exit;
304 }
305
306 /* Get the slot list from provider */
307 rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &slot_count);
308 if (rv != CKR_OK) {
309 cryptodebug("failed to call C_GetSlotList() from %s.",
310 libname);
311 rc = FAILURE;
312 goto clean_exit;
313 }
314
315 if (verbose) {
316 (void) printf(gettext("Number of slots: %d\n"), slot_count);
317 }
318
319 /* Get the mechanism list for each slot */
320 for (i = 0; i < slot_count; i++) {
321 if (verbose)
322 /*
323 * TRANSLATION_NOTE
324 * In some languages, the # symbol should be
325 * converted to "no", an "n" followed by a
326 * superscript "o"..
327 */
328 (void) printf(gettext("\nSlot #%d\n"), i+1);
329
330 if ((rng_flag != NULL) && (*rng_flag == NO_RNG)) {
331 if (check_random(prov_slots[i], prov_funcs)) {
332 *rng_flag = HAS_RNG;
333 rc = SUCCESS;
334 goto clean_exit;
335 } else
336 continue;
337 }
338
339 rv = prov_funcs->C_GetSlotInfo(prov_slots[i], &slotinfo);
340 if (rv != CKR_OK) {
341 cryptodebug("failed to get slotinfo from %s", libname);
342 rc = FAILURE;
343 break;
344 }
345 if (verbose) {
346 CK_TOKEN_INFO tokeninfo;
347
348 (void) printf(gettext("Description: %.64s\n"
349 "Manufacturer: %.32s\n"
350 "PKCS#11 Version: %d.%d\n"),
351 slotinfo.slotDescription,
352 slotinfo.manufacturerID,
353 prov_funcs->version.major,
354 prov_funcs->version.minor);
355
356 (void) printf(gettext("Hardware Version: %d.%d\n"
357 "Firmware Version: %d.%d\n"),
358 slotinfo.hardwareVersion.major,
359 slotinfo.hardwareVersion.minor,
360 slotinfo.firmwareVersion.major,
361 slotinfo.firmwareVersion.minor);
362
363 (void) printf(gettext("Token Present: %s\n"),
364 (slotinfo.flags & CKF_TOKEN_PRESENT ?
365 gettext("True") : gettext("False")));
366
367 display_slot_flags(slotinfo.flags);
368
369 rv = prov_funcs->C_GetTokenInfo(prov_slots[i],
370 &tokeninfo);
371 if (rv != CKR_OK) {
372 cryptodebug("Failed to get "
373 "token info from %s", libname);
374 rc = FAILURE;
375 break;
376 }
377
378 (void) printf(gettext("Token Label: %.32s\n"
379 "Manufacturer ID: %.32s\n"
380 "Model: %.16s\n"
381 "Serial Number: %.16s\n"
382 "Hardware Version: %d.%d\n"
383 "Firmware Version: %d.%d\n"
384 "UTC Time: %.16s\n"
385 "PIN Min Length: %d\n"
386 "PIN Max Length: %d\n"),
387 tokeninfo.label,
388 tokeninfo.manufacturerID,
389 tokeninfo.model,
390 tokeninfo.serialNumber,
391 tokeninfo.hardwareVersion.major,
392 tokeninfo.hardwareVersion.minor,
393 tokeninfo.firmwareVersion.major,
394 tokeninfo.firmwareVersion.minor,
395 tokeninfo.utcTime,
396 tokeninfo.ulMinPinLen,
397 tokeninfo.ulMaxPinLen);
398
399 display_token_flags(tokeninfo.flags);
400 }
401
402 if (mlist == NULL) {
403 rv = prov_funcs->C_GetMechanismList(prov_slots[i],
404 NULL_PTR, &mech_count);
405 if (rv != CKR_OK) {
406 cryptodebug(
407 "failed to call C_GetMechanismList() "
408 "from %s.", libname);
409 rc = FAILURE;
410 break;
411 }
412
413 if (mech_count == 0) {
414 /* no mechanisms in this slot */
415 continue;
416 }
417
418 pmech_list = malloc(mech_count *
419 sizeof (CK_MECHANISM_TYPE));
420 if (pmech_list == NULL) {
421 cryptodebug("out of memory");
422 rc = FAILURE;
423 break;
424 }
425
426 /* Get the actual mechanism list */
427 rv = prov_funcs->C_GetMechanismList(prov_slots[i],
428 pmech_list, &mech_count);
429 if (rv != CKR_OK) {
430 cryptodebug(
431 "failed to call C_GetMechanismList() "
432 "from %s.", libname);
433 free(pmech_list);
434 rc = FAILURE;
435 break;
436 }
437 } else {
438 /* use the mechanism list passed in */
439 rc = convert_mechlist(&pmech_list, &mech_count, mlist);
440 if (rc != SUCCESS) {
441 goto clean_exit;
442 }
443 }
444 if (show_mechs)
445 (void) printf(gettext("Mechanisms:\n"));
446
447 if (verbose && show_mechs) {
448 display_verbose_mech_header();
449 }
450 /*
451 * Merge the current mechanism list into the returning
452 * mechanism list.
453 */
454 for (j = 0; show_mechs && j < mech_count; j++) {
455 CK_MECHANISM_TYPE mech = pmech_list[j];
456 CK_MECHANISM_INFO mech_info;
457
458 rv = prov_funcs->C_GetMechanismInfo(
459 prov_slots[i], mech, &mech_info);
460 if (rv != CKR_OK) {
461 cryptodebug(
462 "failed to call "
463 "C_GetMechanismInfo() from %s.",
464 libname);
465 free(pmech_list);
466 pmech_list = NULL;
467 rc = FAILURE;
468 break;
469 }
470 if (mech >= CKM_VENDOR_DEFINED) {
471 (void) printf("%#lx", mech);
472 } else {
473 mech_name = pkcs11_mech2str(mech);
474 (void) printf("%-29s", mech_name);
475 }
476
477 if (verbose) {
478 display_mech_info(&mech_info);
479 }
480 (void) printf("\n");
481 }
482 if (pmech_list)
483 free(pmech_list);
484 if (rc == FAILURE) {
485 break;
486 }
487 }
488
489 if (rng_flag != NULL || rc == FAILURE) {
490 goto clean_exit;
491 }
492
493 clean_exit:
494
495 if (rc == FAILURE) {
496 (void) printf(gettext(
497 "%s: failed to retrieve the mechanism list.\n"), libname);
498 }
499
500 if (lib_initialized) {
501 (void) prov_funcs->C_Finalize(NULL_PTR);
502 }
503
504 if (dldesc != NULL) {
505 (void) dlclose(dldesc);
506 }
507
508 if (prov_slots != NULL) {
509 free(prov_slots);
510 }
511
512 return (rc);
513 }
514
515
516 /*
517 * Display the mechanism policy for a user-level library
518 */
519 int
list_policy_for_lib(char * libname)520 list_policy_for_lib(char *libname)
521 {
522 uentry_t *puent = NULL;
523 int rc;
524
525 if (libname == NULL) {
526 /* should not happen */
527 cryptoerror(LOG_STDERR, gettext("internal error."));
528 cryptodebug("list_policy_for_lib() - libname is NULL.");
529 return (FAILURE);
530 }
531
532 /* Get the library entry from the pkcs11.conf file */
533 if ((puent = getent_uef(libname)) == NULL) {
534 cryptoerror(LOG_STDERR,
535 gettext("%s does not exist."), libname);
536 return (FAILURE);
537 }
538
539 /* Print the policy for this library */
540 rc = print_uef_policy(puent);
541 free_uentry(puent);
542
543 return (rc);
544 }
545
546
547 /*
548 * Disable mechanisms for a user-level library
549 */
550 int
disable_uef_lib(char * libname,boolean_t rndflag,boolean_t allflag,mechlist_t * marglist)551 disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
552 mechlist_t *marglist)
553 {
554 uentry_t *puent;
555 int rc;
556
557 if (libname == NULL) {
558 /* should not happen */
559 cryptoerror(LOG_STDERR, gettext("internal error."));
560 cryptodebug("disable_uef_lib() - libname is NULL.");
561 return (FAILURE);
562 }
563
564 /* Get the provider entry from the pkcs11.conf file */
565 if ((puent = getent_uef(libname)) == NULL) {
566 cryptoerror(LOG_STDERR,
567 gettext("%s does not exist."), libname);
568 return (FAILURE);
569 }
570
571 /*
572 * Update the mechanism policy of this library entry, based on
573 * the current policy mode of the library and the mechanisms specified
574 * in CLI.
575 */
576 if (allflag) {
577 /*
578 * If disabling all, just need to clean up the policylist and
579 * set the flag_enabledlist flag to be B_TRUE.
580 */
581 free_umechlist(puent->policylist);
582 puent->policylist = NULL;
583 puent->count = 0;
584 puent->flag_enabledlist = B_TRUE;
585 rc = SUCCESS;
586 } else if (marglist != NULL) {
587 if (puent->flag_enabledlist == B_TRUE) {
588 /*
589 * The current default policy mode of this library
590 * is "all are disabled, except ...", so if a
591 * specified mechanism is in the exception list
592 * (the policylist), delete it from the policylist.
593 */
594 rc = update_policylist(puent, marglist, DELETE_MODE);
595 } else {
596 /*
597 * The current default policy mode of this library
598 * is "all are enabled", so if a specified mechanism
599 * is not in the exception list (policylist), add
600 * it into the policylist.
601 */
602 rc = update_policylist(puent, marglist, ADD_MODE);
603 }
604 } else if (!rndflag) {
605 /* should not happen */
606 cryptoerror(LOG_STDERR, gettext("internal error."));
607 cryptodebug("disable_uef_lib() - wrong arguments.");
608 return (FAILURE);
609 }
610
611 if (rndflag)
612 puent->flag_norandom = B_TRUE;
613
614 if (rc == FAILURE) {
615 free_uentry(puent);
616 return (FAILURE);
617 }
618
619 /* Update the pkcs11.conf file with the updated entry */
620 rc = update_pkcs11conf(puent);
621 free_uentry(puent);
622 return (rc);
623 }
624
625
626 /*
627 * Enable disabled mechanisms for a user-level library.
628 */
629 int
enable_uef_lib(char * libname,boolean_t rndflag,boolean_t allflag,mechlist_t * marglist)630 enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
631 mechlist_t *marglist)
632 {
633 uentry_t *puent;
634 int rc = SUCCESS;
635
636 if (libname == NULL) {
637 /* should not happen */
638 cryptoerror(LOG_STDERR, gettext("internal error."));
639 cryptodebug("enable_uef_lib() - libname is NULL.");
640 return (FAILURE);
641 }
642
643 /* Get the provider entry from the pkcs11.conf file */
644 if ((puent = getent_uef(libname)) == NULL) {
645 cryptoerror(LOG_STDERR,
646 gettext("%s does not exist."), libname);
647 return (FAILURE);
648 }
649
650 /*
651 * Update the mechanism policy of this library entry, based on
652 * the current policy mode of the library and the mechanisms
653 * specified in CLI.
654 */
655 if (allflag) {
656 /*
657 * If enabling all, what needs to be done are cleaning up the
658 * policylist and setting the "flag_enabledlist" flag to
659 * B_FALSE.
660 */
661 free_umechlist(puent->policylist);
662 puent->policylist = NULL;
663 puent->count = 0;
664 puent->flag_enabledlist = B_FALSE;
665 rc = SUCCESS;
666 } else if (marglist != NULL) {
667 if (puent->flag_enabledlist == B_TRUE) {
668 /*
669 * The current default policy mode of this library
670 * is "all are disabled, except ...", so if a
671 * specified mechanism is not in the exception list
672 * (policylist), add it.
673 */
674 rc = update_policylist(puent, marglist, ADD_MODE);
675 } else {
676 /*
677 * The current default policy mode of this library
678 * is "all are enabled, except", so if a specified
679 * mechanism is in the exception list (policylist),
680 * delete it.
681 */
682 rc = update_policylist(puent, marglist, DELETE_MODE);
683 }
684 } else if (!rndflag) {
685 /* should not come here */
686 cryptoerror(LOG_STDERR, gettext("internal error."));
687 cryptodebug("enable_uef_lib() - wrong arguments.");
688 return (FAILURE);
689 }
690
691 if (rndflag)
692 puent->flag_norandom = B_FALSE;
693
694 if (rc == FAILURE) {
695 free_uentry(puent);
696 return (FAILURE);
697 }
698
699 /* Update the pkcs11.conf file with the updated entry */
700 rc = update_pkcs11conf(puent);
701 free_uentry(puent);
702 return (rc);
703 }
704
705
706 /*
707 * Install a user-level library.
708 */
709 int
install_uef_lib(char * libname)710 install_uef_lib(char *libname)
711 {
712 uentry_t *puent;
713 struct stat statbuf;
714 char libpath[MAXPATHLEN];
715 char libbuf[MAXPATHLEN];
716 char *isa;
717
718 if (libname == NULL) {
719 /* should not happen */
720 cryptoerror(LOG_STDERR, gettext("internal error."));
721 cryptodebug("install_uef_lib() - libname is NULL.");
722 return (FAILURE);
723 }
724
725 /* Check if the provider already exists in the framework */
726 if ((puent = getent_uef(libname)) != NULL) {
727 cryptoerror(LOG_STDERR, gettext("%s exists already."),
728 libname);
729 free_uentry(puent);
730 return (FAILURE);
731 }
732
733 /*
734 * Check if the library exists in the system. if $ISA is in the
735 * path, only check the 32bit version.
736 */
737 if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) {
738 cryptoerror(LOG_STDERR,
739 gettext("the provider name is too long - %s"), libname);
740 return (FAILURE);
741 }
742
743 if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) {
744 *isa = '\000';
745 isa += strlen(PKCS11_ISA);
746 (void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf,
747 "/", isa);
748 } else {
749 (void) strlcpy(libpath, libname, sizeof (libpath));
750 }
751
752 /* Check if it is same as the framework library */
753 if (strcmp(libpath, UEF_FRAME_LIB) == 0) {
754 cryptoerror(LOG_STDERR, gettext(
755 "The framework library %s can not be installed."),
756 libname);
757 return (FAILURE);
758 }
759
760 if (stat(libpath, &statbuf) != 0) {
761 cryptoerror(LOG_STDERR, gettext("%s not found"), libname);
762 return (FAILURE);
763 }
764
765 /* Need to add "\n" to libname for adding into the config file */
766 if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) {
767 cryptoerror(LOG_STDERR, gettext(
768 "can not install %s; the name is too long."), libname);
769 return (FAILURE);
770 }
771
772 return (update_conf(_PATH_PKCS11_CONF, libname));
773
774 }
775
776
777 /*
778 * Uninstall a user-level library.
779 */
780 int
uninstall_uef_lib(char * libname)781 uninstall_uef_lib(char *libname)
782 {
783 uentry_t *puent;
784 FILE *pfile;
785 FILE *pfile_tmp;
786 char buffer[BUFSIZ];
787 char buffer2[BUFSIZ];
788 char tmpfile_name[MAXPATHLEN];
789 char *name;
790 boolean_t found;
791 boolean_t in_package;
792 int len;
793 int rc = SUCCESS;
794
795 if (libname == NULL) {
796 /* should not happen */
797 cryptoerror(LOG_STDERR, gettext("internal error."));
798 cryptodebug("uninstall_uef_lib() - libname is NULL.");
799 return (FAILURE);
800 }
801
802 /* Check if the provider exists */
803 if ((puent = getent_uef(libname)) == NULL) {
804 cryptoerror(LOG_STDERR,
805 gettext("%s does not exist."), libname);
806 return (FAILURE);
807 }
808 free_uentry(puent);
809
810 /* Open the pkcs11.conf file and lock it */
811 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
812 err = errno;
813 cryptoerror(LOG_STDERR,
814 gettext("failed to update the configuration - %s"),
815 strerror(err));
816 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
817 return (FAILURE);
818 }
819
820 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
821 err = errno;
822 cryptoerror(LOG_STDERR,
823 gettext("failed to lock the configuration - %s"),
824 strerror(err));
825 (void) fclose(pfile);
826 return (FAILURE);
827 }
828
829 /*
830 * Create a temporary file in the /etc/crypto directory to save
831 * the new configuration file first.
832 */
833 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
834 if (mkstemp(tmpfile_name) == -1) {
835 err = errno;
836 cryptoerror(LOG_STDERR,
837 gettext("failed to create a temporary file - %s"),
838 strerror(err));
839 (void) fclose(pfile);
840 return (FAILURE);
841 }
842
843 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
844 err = errno;
845 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
846 tmpfile_name, strerror(err));
847 if (unlink(tmpfile_name) != 0) {
848 err = errno;
849 cryptoerror(LOG_STDERR, gettext(
850 "(Warning) failed to remove %s: %s"),
851 tmpfile_name, strerror(err));
852 }
853 (void) fclose(pfile);
854 return (FAILURE);
855 }
856
857
858 /*
859 * Loop thru the config file. If the library to be uninstalled
860 * is in a package, just comment it off.
861 */
862 in_package = B_FALSE;
863 while (fgets(buffer, BUFSIZ, pfile) != NULL) {
864 found = B_FALSE;
865 if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
866 buffer[0] == '\t')) {
867 if (strstr(buffer, " Start ") != NULL) {
868 in_package = B_TRUE;
869 } else if (strstr(buffer, " End ") != NULL) {
870 in_package = B_FALSE;
871 } else if (buffer[0] != '#') {
872 (void) strlcpy(buffer2, buffer, BUFSIZ);
873
874 /* get rid of trailing '\n' */
875 len = strlen(buffer2);
876 if (buffer2[len-1] == '\n') {
877 len--;
878 }
879 buffer2[len] = '\0';
880
881 if ((name = strtok(buffer2, SEP_COLON))
882 == NULL) {
883 rc = FAILURE;
884 break;
885 } else if (strcmp(libname, name) == 0) {
886 found = B_TRUE;
887 }
888 }
889 }
890
891 if (found) {
892 if (in_package) {
893 (void) snprintf(buffer2, sizeof (buffer2),
894 "%s%s%s", "#", libname, "\n");
895 if (fputs(buffer2, pfile_tmp) == EOF) {
896 rc = FAILURE;
897 }
898 }
899 } else {
900 if (fputs(buffer, pfile_tmp) == EOF) {
901 rc = FAILURE;
902 }
903 }
904
905 if (rc == FAILURE) {
906 break;
907 }
908 }
909
910 if (rc == FAILURE) {
911 cryptoerror(LOG_STDERR, gettext("write error."));
912 (void) fclose(pfile);
913 (void) fclose(pfile_tmp);
914 if (unlink(tmpfile_name) != 0) {
915 err = errno;
916 cryptoerror(LOG_STDERR, gettext(
917 "(Warning) failed to remove %s: %s"),
918 tmpfile_name, strerror(err));
919 }
920 return (FAILURE);
921 }
922
923 (void) fclose(pfile);
924 if (fclose(pfile_tmp) != 0) {
925 err = errno;
926 cryptoerror(LOG_STDERR,
927 gettext("failed to close a temporary file - %s"),
928 strerror(err));
929 return (FAILURE);
930 }
931
932 /* Now update the real config file */
933 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
934 err = errno;
935 cryptoerror(LOG_STDERR,
936 gettext("failed to update the configuration - %s"),
937 strerror(err));
938 cryptodebug("failed to rename %s to %s: %s", tmpfile,
939 _PATH_PKCS11_CONF, strerror(err));
940 rc = FAILURE;
941 } else if (chmod(_PATH_PKCS11_CONF,
942 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
943 err = errno;
944 cryptoerror(LOG_STDERR,
945 gettext("failed to update the configuration - %s"),
946 strerror(err));
947 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
948 strerror(err));
949 rc = FAILURE;
950 } else {
951 rc = SUCCESS;
952 }
953
954 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
955 err = errno;
956 cryptoerror(LOG_STDERR, gettext(
957 "(Warning) failed to remove %s: %s"),
958 tmpfile_name, strerror(err));
959 }
960
961 return (rc);
962 }
963
964
965 int
display_policy(uentry_t * puent)966 display_policy(uentry_t *puent)
967 {
968 CK_MECHANISM_TYPE mech_id;
969 const char *mech_name;
970 umechlist_t *ptr;
971
972 if (puent == NULL) {
973 return (SUCCESS);
974 }
975
976 if (puent->flag_enabledlist == B_FALSE) {
977 (void) printf(gettext("%s: all mechanisms are enabled"),
978 puent->name);
979 ptr = puent->policylist;
980 if (ptr == NULL) {
981 (void) printf(".");
982 } else {
983 (void) printf(gettext(", except "));
984 while (ptr != NULL) {
985 mech_id = strtoul(ptr->name, NULL, 0);
986 if (mech_id & CKO_VENDOR_DEFINED) {
987 /* vendor defined mechanism */
988 (void) printf("%s", ptr->name);
989 } else {
990 if (mech_id >= CKM_VENDOR_DEFINED) {
991 (void) printf("%#lx", mech_id);
992 } else {
993 mech_name = pkcs11_mech2str(
994 mech_id);
995 if (mech_name == NULL) {
996 return (FAILURE);
997 }
998 (void) printf("%s", mech_name);
999 }
1000 }
1001
1002 ptr = ptr->next;
1003 if (ptr == NULL) {
1004 (void) printf(".");
1005 } else {
1006 (void) printf(",");
1007 }
1008 }
1009 }
1010 } else { /* puent->flag_enabledlist == B_TRUE */
1011 (void) printf(gettext("%s: all mechanisms are disabled"),
1012 puent->name);
1013 ptr = puent->policylist;
1014 if (ptr == NULL) {
1015 (void) printf(".");
1016 } else {
1017 (void) printf(gettext(", except "));
1018 while (ptr != NULL) {
1019 mech_id = strtoul(ptr->name, NULL, 0);
1020 if (mech_id & CKO_VENDOR_DEFINED) {
1021 /* vendor defined mechanism */
1022 (void) printf("%s", ptr->name);
1023 } else {
1024 mech_name = pkcs11_mech2str(mech_id);
1025 if (mech_name == NULL) {
1026 return (FAILURE);
1027 }
1028 (void) printf("%s", mech_name);
1029 }
1030 ptr = ptr->next;
1031 if (ptr == NULL) {
1032 (void) printf(".");
1033 } else {
1034 (void) printf(",");
1035 }
1036 }
1037 }
1038 }
1039 return (SUCCESS);
1040 }
1041
1042
1043
1044 /*
1045 * Print out the mechanism policy for a user-level provider pointed by puent.
1046 */
1047 int
print_uef_policy(uentry_t * puent)1048 print_uef_policy(uentry_t *puent)
1049 {
1050 flag_val_t rng_flag;
1051
1052 if (puent == NULL) {
1053 return (FAILURE);
1054 }
1055
1056 rng_flag = NO_RNG;
1057 if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE,
1058 B_FALSE, B_FALSE) != SUCCESS) {
1059 cryptoerror(LOG_STDERR,
1060 gettext("%s internal error."), puent->name);
1061 return (FAILURE);
1062 }
1063
1064 if (display_policy(puent) != SUCCESS) {
1065 goto failed_exit;
1066 }
1067
1068
1069 if (puent->flag_norandom == B_TRUE)
1070 /*
1071 * TRANSLATION_NOTE
1072 * "random" is a keyword and not to be translated.
1073 */
1074 (void) printf(gettext(" %s is disabled."), "random");
1075 else {
1076 if (rng_flag == HAS_RNG)
1077 /*
1078 * TRANSLATION_NOTE
1079 * "random" is a keyword and not to be translated.
1080 */
1081 (void) printf(gettext(" %s is enabled."), "random");
1082 }
1083 (void) printf("\n");
1084
1085 return (SUCCESS);
1086
1087 failed_exit:
1088
1089 (void) printf(gettext("\nout of memory.\n"));
1090 return (FAILURE);
1091 }
1092
1093
1094 /*
1095 * Check if the mechanism is in the mechanism list.
1096 */
1097 static boolean_t
is_in_policylist(midstr_t mechname,umechlist_t * plist)1098 is_in_policylist(midstr_t mechname, umechlist_t *plist)
1099 {
1100 boolean_t found = B_FALSE;
1101
1102 if (mechname == NULL) {
1103 return (B_FALSE);
1104 }
1105
1106 while (plist != NULL) {
1107 if (strcmp(plist->name, mechname) == 0) {
1108 found = B_TRUE;
1109 break;
1110 }
1111 plist = plist->next;
1112 }
1113
1114 return (found);
1115 }
1116
1117
1118 /*
1119 * Update the pkcs11.conf file with the updated entry.
1120 */
1121 int
update_pkcs11conf(uentry_t * puent)1122 update_pkcs11conf(uentry_t *puent)
1123 {
1124 FILE *pfile;
1125 FILE *pfile_tmp;
1126 char buffer[BUFSIZ];
1127 char buffer2[BUFSIZ];
1128 char tmpfile_name[MAXPATHLEN];
1129 char *name;
1130 char *str;
1131 int len;
1132 int rc = SUCCESS;
1133 boolean_t found;
1134
1135 if (puent == NULL) {
1136 cryptoerror(LOG_STDERR, gettext("internal error."));
1137 return (FAILURE);
1138 }
1139
1140 /* Open the pkcs11.conf file */
1141 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
1142 err = errno;
1143 cryptoerror(LOG_STDERR,
1144 gettext("failed to update the configuration - %s"),
1145 strerror(err));
1146 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
1147 return (FAILURE);
1148 }
1149
1150 /* Lock the pkcs11.conf file */
1151 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
1152 err = errno;
1153 cryptoerror(LOG_STDERR,
1154 gettext("failed to update the configuration - %s"),
1155 strerror(err));
1156 (void) fclose(pfile);
1157 return (FAILURE);
1158 }
1159
1160 /*
1161 * Create a temporary file in the /etc/crypto directory to save
1162 * updated configuration file first.
1163 */
1164 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
1165 if (mkstemp(tmpfile_name) == -1) {
1166 err = errno;
1167 cryptoerror(LOG_STDERR,
1168 gettext("failed to create a temporary file - %s"),
1169 strerror(err));
1170 (void) fclose(pfile);
1171 return (FAILURE);
1172 }
1173
1174 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
1175 err = errno;
1176 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
1177 tmpfile_name, strerror(err));
1178 if (unlink(tmpfile_name) != 0) {
1179 err = errno;
1180 cryptoerror(LOG_STDERR, gettext(
1181 "(Warning) failed to remove %s: %s"),
1182 tmpfile_name, strerror(err));
1183 }
1184 (void) fclose(pfile);
1185 return (FAILURE);
1186 }
1187
1188
1189 /*
1190 * Loop thru entire pkcs11.conf file, update the entry to be
1191 * updated and save the updated file to the temporary file first.
1192 */
1193 while (fgets(buffer, BUFSIZ, pfile) != NULL) {
1194 found = B_FALSE;
1195 if (!(buffer[0] == '#' || buffer[0] == ' ' ||
1196 buffer[0] == '\n'|| buffer[0] == '\t')) {
1197 /*
1198 * Get the provider name from this line and check if
1199 * this is the entry to be updated. Note: can not use
1200 * "buffer" directly because strtok will change its
1201 * value.
1202 */
1203 (void) strlcpy(buffer2, buffer, BUFSIZ);
1204
1205 /* get rid of trailing '\n' */
1206 len = strlen(buffer2);
1207 if (buffer2[len-1] == '\n') {
1208 len--;
1209 }
1210 buffer2[len] = '\0';
1211
1212 if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
1213 rc = FAILURE;
1214 break;
1215 } else if (strcmp(puent->name, name) == 0) {
1216 found = B_TRUE;
1217 }
1218 }
1219
1220 if (found) {
1221 /*
1222 * This is the entry to be modified, get the updated
1223 * string.
1224 */
1225 if ((str = uent2str(puent)) == NULL) {
1226 rc = FAILURE;
1227 break;
1228 } else {
1229 (void) strlcpy(buffer, str, BUFSIZ);
1230 free(str);
1231 }
1232 }
1233
1234 if (fputs(buffer, pfile_tmp) == EOF) {
1235 err = errno;
1236 cryptoerror(LOG_STDERR, gettext(
1237 "failed to write to a temp file: %s."),
1238 strerror(err));
1239 rc = FAILURE;
1240 break;
1241 }
1242 }
1243
1244 if (rc == FAILURE) {
1245 (void) fclose(pfile);
1246 (void) fclose(pfile_tmp);
1247 if (unlink(tmpfile_name) != 0) {
1248 err = errno;
1249 cryptoerror(LOG_STDERR, gettext(
1250 "(Warning) failed to remove %s: %s"),
1251 tmpfile_name, strerror(err));
1252 }
1253 return (FAILURE);
1254 }
1255
1256 (void) fclose(pfile);
1257 if (fclose(pfile_tmp) != 0) {
1258 err = errno;
1259 cryptoerror(LOG_STDERR,
1260 gettext("failed to close %s: %s"), tmpfile_name,
1261 strerror(err));
1262 return (FAILURE);
1263 }
1264
1265 /* Copy the temporary file to the pkcs11.conf file */
1266 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
1267 err = errno;
1268 cryptoerror(LOG_STDERR,
1269 gettext("failed to update the configuration - %s"),
1270 strerror(err));
1271 cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
1272 _PATH_PKCS11_CONF, strerror(err));
1273 rc = FAILURE;
1274 } else if (chmod(_PATH_PKCS11_CONF,
1275 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1276 err = errno;
1277 cryptoerror(LOG_STDERR,
1278 gettext("failed to update the configuration - %s"),
1279 strerror(err));
1280 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
1281 strerror(err));
1282 rc = FAILURE;
1283 } else {
1284 rc = SUCCESS;
1285 }
1286
1287 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
1288 err = errno;
1289 cryptoerror(LOG_STDERR, gettext(
1290 "(Warning) failed to remove %s: %s"),
1291 tmpfile_name, strerror(err));
1292 }
1293
1294 return (rc);
1295 }
1296
1297
1298 /*
1299 * Convert an uentry to a character string
1300 */
1301 static char *
uent2str(uentry_t * puent)1302 uent2str(uentry_t *puent)
1303 {
1304 umechlist_t *phead;
1305 boolean_t tok1_present = B_FALSE;
1306 char *buf;
1307 char blank_buf[128];
1308
1309 if (puent == NULL) {
1310 cryptoerror(LOG_STDERR, gettext("internal error."));
1311 return (NULL);
1312 }
1313
1314 buf = malloc(BUFSIZ);
1315 if (buf == NULL) {
1316 cryptoerror(LOG_STDERR, gettext("out of memory."));
1317 return (NULL);
1318 }
1319
1320 /* convert the library name */
1321 if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) {
1322 free(buf);
1323 return (NULL);
1324 }
1325
1326
1327 /* convert the enabledlist or the disabledlist */
1328 if (puent->flag_enabledlist == B_TRUE) {
1329 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
1330 free(buf);
1331 return (NULL);
1332 }
1333
1334 if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) {
1335 free(buf);
1336 return (NULL);
1337 }
1338
1339 phead = puent->policylist;
1340 while (phead != NULL) {
1341 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
1342 free(buf);
1343 return (NULL);
1344 }
1345
1346 phead = phead->next;
1347 if (phead != NULL) {
1348 if (strlcat(buf, SEP_COMMA, BUFSIZ)
1349 >= BUFSIZ) {
1350 free(buf);
1351 return (NULL);
1352 }
1353 }
1354 }
1355 tok1_present = B_TRUE;
1356 } else if (puent->policylist != NULL) {
1357 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
1358 free(buf);
1359 return (NULL);
1360 }
1361
1362 if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) {
1363 free(buf);
1364 return (NULL);
1365 }
1366 phead = puent->policylist;
1367 while (phead != NULL) {
1368 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
1369 free(buf);
1370 return (NULL);
1371 }
1372
1373 phead = phead->next;
1374 if (phead != NULL) {
1375 if (strlcat(buf, SEP_COMMA, BUFSIZ)
1376 >= BUFSIZ) {
1377 free(buf);
1378 return (NULL);
1379 }
1380 }
1381 }
1382 tok1_present = B_TRUE;
1383 }
1384
1385 if (puent->flag_norandom == B_TRUE) {
1386 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
1387 BUFSIZ) >= BUFSIZ) {
1388 free(buf);
1389 return (NULL);
1390 }
1391
1392 if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) {
1393 free(buf);
1394 return (NULL);
1395 }
1396 }
1397
1398 if (strcmp(puent->name, METASLOT_KEYWORD) == 0) {
1399
1400 /* write the metaslot_status= value */
1401 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
1402 BUFSIZ) >= BUFSIZ) {
1403 free(buf);
1404 return (NULL);
1405 }
1406
1407 if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) {
1408 free(buf);
1409 return (NULL);
1410 }
1411
1412 if (puent->flag_metaslot_enabled) {
1413 if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
1414 free(buf);
1415 return (NULL);
1416 }
1417 } else {
1418 if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ)
1419 >= BUFSIZ) {
1420 free(buf);
1421 return (NULL);
1422 }
1423 }
1424
1425 if (!tok1_present) {
1426 tok1_present = B_TRUE;
1427 }
1428
1429 if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) {
1430 free(buf);
1431 return (NULL);
1432 }
1433
1434 if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) {
1435 free(buf);
1436 return (NULL);
1437 }
1438
1439 if (puent->flag_metaslot_auto_key_migrate) {
1440 if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
1441 free(buf);
1442 return (NULL);
1443 }
1444 } else {
1445 if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
1446 free(buf);
1447 return (NULL);
1448 }
1449 }
1450
1451 bzero(blank_buf, sizeof (blank_buf));
1452
1453 /* write metaslot_token= if specified */
1454 if (memcmp(puent->metaslot_ks_token, blank_buf,
1455 TOKEN_LABEL_SIZE) != 0) {
1456 /* write the metaslot_status= value */
1457 if (strlcat(buf, (tok1_present ?
1458 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
1459 free(buf);
1460 return (NULL);
1461 }
1462
1463 if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) {
1464 free(buf);
1465 return (NULL);
1466 }
1467
1468 if (strlcat(buf,
1469 (const char *)puent->metaslot_ks_token, BUFSIZ)
1470 >= BUFSIZ) {
1471 free(buf);
1472 return (NULL);
1473 }
1474 }
1475
1476 /* write metaslot_slot= if specified */
1477 if (memcmp(puent->metaslot_ks_slot, blank_buf,
1478 SLOT_DESCRIPTION_SIZE) != 0) {
1479 /* write the metaslot_status= value */
1480 if (strlcat(buf, (tok1_present ?
1481 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
1482 free(buf);
1483 return (NULL);
1484 }
1485
1486 if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) {
1487 free(buf);
1488 return (NULL);
1489 }
1490
1491 if (strlcat(buf,
1492 (const char *)puent->metaslot_ks_slot, BUFSIZ)
1493 >= BUFSIZ) {
1494 free(buf);
1495 return (NULL);
1496 }
1497 }
1498 }
1499
1500 if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
1501 free(buf);
1502 return (NULL);
1503 }
1504
1505 return (buf);
1506 }
1507
1508
1509 /*
1510 * This function updates the default policy mode and the policy exception list
1511 * for a user-level provider based on the mechanism specified in the disable
1512 * or enable subcommand and the update mode. This function is called by the
1513 * enable_uef_lib() or disable_uef_lib().
1514 */
1515 int
update_policylist(uentry_t * puent,mechlist_t * marglist,int update_mode)1516 update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode)
1517 {
1518 CK_MECHANISM_TYPE mech_type;
1519 midstr_t midname;
1520 umechlist_t *phead;
1521 umechlist_t *pcur;
1522 umechlist_t *pumech;
1523 boolean_t found;
1524 int rc = SUCCESS;
1525
1526 if ((puent == NULL) || (marglist == NULL)) {
1527 /* should not happen */
1528 cryptoerror(LOG_STDERR, gettext("internal error."));
1529 cryptodebug("update_policylist()- puent or marglist is NULL.");
1530 return (FAILURE);
1531 }
1532
1533 if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) {
1534 /* should not happen */
1535 cryptoerror(LOG_STDERR, gettext("internal error."));
1536 cryptodebug("update_policylist() - update_mode is incorrect.");
1537 return (FAILURE);
1538 }
1539
1540 /*
1541 * For each mechanism operand, get its mechanism type first.
1542 * If fails to get the mechanism type, the mechanism operand must be
1543 * invalid, gives an warning and ignore it. Otherwise,
1544 * - convert the mechanism type to the internal representation (hex)
1545 * in the pkcs11.conf file
1546 * - If update_mode == DELETE_MODE,
1547 * If the mechanism is in the policy list, delete it.
1548 * If the mechanism is not in the policy list, do nothing.
1549 * - If update_mode == ADD_MODE,
1550 * If the mechanism is not in the policy list, add it.
1551 * If the mechanism is in the policy list already, do nothing.
1552 */
1553 while (marglist) {
1554 if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) {
1555 /*
1556 * This mechanism is not a valid PKCS11 mechanism,
1557 * give warning and ignore it.
1558 */
1559 cryptoerror(LOG_STDERR, gettext(
1560 "(Warning) %s is not a valid PKCS#11 mechanism."),
1561 marglist->name);
1562 rc = FAILURE;
1563 } else {
1564 (void) snprintf(midname, sizeof (midname), "%#010x",
1565 (int)mech_type);
1566 if (update_mode == DELETE_MODE) {
1567 found = B_FALSE;
1568 phead = pcur = puent->policylist;
1569 while (!found && pcur) {
1570 if (strcmp(pcur->name, midname) == 0) {
1571 found = B_TRUE;
1572 } else {
1573 phead = pcur;
1574 pcur = pcur->next;
1575 }
1576 }
1577
1578 if (found) {
1579 if (phead == pcur) {
1580 puent->policylist =
1581 puent->policylist->next;
1582 free(pcur);
1583 } else {
1584 phead->next = pcur->next;
1585 free(pcur);
1586 }
1587 puent->count--;
1588 if (puent->count == 0) {
1589 puent->policylist = NULL;
1590 }
1591 }
1592 } else if (update_mode == ADD_MODE) {
1593 if (!is_in_policylist(midname,
1594 puent->policylist)) {
1595 pumech = create_umech(midname);
1596 if (pumech == NULL) {
1597 rc = FAILURE;
1598 break;
1599 }
1600 phead = puent->policylist;
1601 puent->policylist = pumech;
1602 pumech->next = phead;
1603 puent->count++;
1604 }
1605 }
1606 }
1607 marglist = marglist->next;
1608 }
1609
1610 return (rc);
1611 }
1612
1613 /*
1614 * Open a session to the given slot and check if we can do
1615 * random numbers by asking for one byte.
1616 */
1617 static boolean_t
check_random(CK_SLOT_ID slot_id,CK_FUNCTION_LIST_PTR prov_funcs)1618 check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs)
1619 {
1620 CK_RV rv;
1621 CK_SESSION_HANDLE hSession;
1622 CK_BYTE test_byte;
1623 CK_BYTE_PTR test_byte_ptr = &test_byte;
1624
1625 rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION,
1626 NULL_PTR, NULL, &hSession);
1627 if (rv != CKR_OK)
1628 return (B_FALSE);
1629
1630 /* We care only about the return value */
1631 rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr,
1632 sizeof (test_byte));
1633 (void) prov_funcs->C_CloseSession(hSession);
1634
1635 /*
1636 * These checks are purely to determine whether the slot can do
1637 * random numbers. So, we don't check whether the routine
1638 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that
1639 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED.
1640 */
1641 if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG)
1642 return (B_TRUE);
1643 else
1644 return (B_FALSE);
1645 }
1646
1647 void
display_verbose_mech_header()1648 display_verbose_mech_header()
1649 {
1650 (void) printf("%28s %s", " ", HDR1);
1651 (void) printf("%28s %s", " ", HDR2);
1652 (void) printf("%28s %s", " ", HDR3);
1653 (void) printf("%28s %s", " ", HDR4);
1654 (void) printf("%28s %s", " ", HDR5);
1655 (void) printf("%28s %s", " ", HDR6);
1656 (void) printf("%-28.28s %s", gettext("mechanism name"), HDR7);
1657 /*
1658 * TRANSLATION_NOTE
1659 * Strictly for appearance's sake, the first header line should be
1660 * as long as the length of the translated text above. The format
1661 * lengths should all match too.
1662 */
1663 (void) printf("%28s ---- ---- "
1664 "- - - - - - - - - - - - - -\n",
1665 gettext("----------------------------"));
1666 }
1667