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