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