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.
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.
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]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright 2010 Nexenta Systems, Inc. All rights resrved.
28 #include <cryptoutil.h>
38 #include <sys/types.h>
40 #include <security/cryptoki.h>
41 #include "cryptoadm.h"
44 #define HDR2 " S V K a U D\n"
45 #define HDR3 " i e e i n e\n"
46 #define HDR4 " S g V r y r W w r\n"
47 #define HDR5 " E D D i n e i G G r r i\n"
48 #define HDR6 " H n e i g + r + e e a a v E\n"
49 #define HDR7 "min max W c c g n R i R n n p p e C\n"
52 static int err
; /* To store errno which may be overwritten by gettext() */
53 static boolean_t
is_in_policylist(midstr_t
, umechlist_t
*);
54 static char *uent2str(uentry_t
*);
55 static boolean_t
check_random(CK_SLOT_ID
, CK_FUNCTION_LIST_PTR
);
57 static void display_slot_flags(CK_FLAGS flags
)
59 (void) printf(gettext("Slot Flags: "));
60 if (flags
& CKF_TOKEN_PRESENT
)
61 (void) printf("CKF_TOKEN_PRESENT ");
62 if (flags
& CKF_REMOVABLE_DEVICE
)
63 (void) printf("CKF_REMOVABLE_DEVICE ");
64 if (flags
& CKF_HW_SLOT
)
65 (void) printf("CKF_HW_SLOT ");
70 display_token_flags(CK_FLAGS flags
)
72 (void) printf(gettext("Flags: "));
74 (void) printf("CKF_RNG ");
75 if (flags
& CKF_WRITE_PROTECTED
)
76 (void) printf("CKF_WRITE_PROTECTED ");
77 if (flags
& CKF_LOGIN_REQUIRED
)
78 (void) printf("CKF_LOGIN_REQUIRED ");
79 if (flags
& CKF_USER_PIN_INITIALIZED
)
80 (void) printf("CKF_USER_PIN_INITIALIZED ");
81 if (flags
& CKF_RESTORE_KEY_NOT_NEEDED
)
82 (void) printf("CKF_RESTORE_KEY_NOT_NEEDED ");
83 if (flags
& CKF_CLOCK_ON_TOKEN
)
84 (void) printf("CKF_CLOCK_ON_TOKEN ");
85 if (flags
& CKF_PROTECTED_AUTHENTICATION_PATH
)
86 (void) printf("CKF_PROTECTED_AUTHENTICATION_PATH ");
87 if (flags
& CKF_DUAL_CRYPTO_OPERATIONS
)
88 (void) printf("CKF_DUAL_CRYPTO_OPERATIONS ");
89 if (flags
& CKF_TOKEN_INITIALIZED
)
90 (void) printf("CKF_TOKEN_INITIALIZED ");
91 if (flags
& CKF_SECONDARY_AUTHENTICATION
)
92 (void) printf("CKF_SECONDARY_AUTHENTICATION ");
93 if (flags
& CKF_USER_PIN_COUNT_LOW
)
94 (void) printf("CKF_USER_PIN_COUNT_LOW ");
95 if (flags
& CKF_USER_PIN_FINAL_TRY
)
96 (void) printf("CKF_USER_PIN_FINAL_TRY ");
97 if (flags
& CKF_USER_PIN_LOCKED
)
98 (void) printf("CKF_USER_PIN_LOCKED ");
99 if (flags
& CKF_USER_PIN_TO_BE_CHANGED
)
100 (void) printf("CKF_USER_PIN_TO_BE_CHANGED ");
101 if (flags
& CKF_SO_PIN_COUNT_LOW
)
102 (void) printf("CKF_SO_PIN_COUNT_LOW ");
103 if (flags
& CKF_SO_PIN_FINAL_TRY
)
104 (void) printf("CKF_SO_PIN_FINAL_TRY ");
105 if (flags
& CKF_SO_PIN_LOCKED
)
106 (void) printf("CKF_SO_PIN_LOCKED ");
107 if (flags
& CKF_SO_PIN_TO_BE_CHANGED
)
108 (void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
109 if (flags
& CKF_SO_PIN_TO_BE_CHANGED
)
110 (void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
115 display_mech_info(CK_MECHANISM_INFO
*mechInfo
)
117 CK_FLAGS ec_flags
= CKF_EC_F_P
| CKF_EC_F_2M
| CKF_EC_ECPARAMETERS
|
118 CKF_EC_NAMEDCURVE
| CKF_EC_UNCOMPRESS
| CKF_EC_COMPRESS
;
120 (void) printf("%-4ld %-4ld ", mechInfo
->ulMinKeySize
,
121 mechInfo
->ulMaxKeySize
);
122 (void) printf("%s %s %s %s %s %s %s %s %s %s %s %s "
124 (mechInfo
->flags
& CKF_HW
) ? "X" : ".",
125 (mechInfo
->flags
& CKF_ENCRYPT
) ? "X" : ".",
126 (mechInfo
->flags
& CKF_DECRYPT
) ? "X" : ".",
127 (mechInfo
->flags
& CKF_DIGEST
) ? "X" : ".",
128 (mechInfo
->flags
& CKF_SIGN
) ? "X" : ".",
129 (mechInfo
->flags
& CKF_SIGN_RECOVER
) ? "X" : ".",
130 (mechInfo
->flags
& CKF_VERIFY
) ? "X" : ".",
131 (mechInfo
->flags
& CKF_VERIFY_RECOVER
) ? "X" : ".",
132 (mechInfo
->flags
& CKF_GENERATE
) ? "X" : ".",
133 (mechInfo
->flags
& CKF_GENERATE_KEY_PAIR
) ? "X" : ".",
134 (mechInfo
->flags
& CKF_WRAP
) ? "X" : ".",
135 (mechInfo
->flags
& CKF_UNWRAP
) ? "X" : ".",
136 (mechInfo
->flags
& CKF_DERIVE
) ? "X" : ".",
137 (mechInfo
->flags
& ec_flags
) ? "X" : ".");
141 * Converts the provided list of mechanism names in their string format to
142 * their corresponding PKCS#11 mechanism IDs.
144 * The list of mechanism names to be converted is provided in the
145 * "mlist" argument. The list of converted mechanism IDs is returned
146 * in the "pmech_list" argument.
148 * This function is called by list_metaslot_info() and
149 * list_mechlist_for_lib() functions.
152 convert_mechlist(CK_MECHANISM_TYPE
**pmech_list
, CK_ULONG
*mech_count
,
156 mechlist_t
*p
= mlist
;
163 *pmech_list
= malloc(n
* sizeof (CK_MECHANISM_TYPE
));
164 if (pmech_list
== NULL
) {
165 cryptodebug("out of memory");
169 for (i
= 0; i
< n
; i
++) {
170 if (pkcs11_str2mech(p
->name
, &(*pmech_list
[i
])) != CKR_OK
) {
181 * Display the mechanism list for a user-level library
184 list_mechlist_for_lib(char *libname
, mechlist_t
*mlist
,
185 flag_val_t
*rng_flag
, boolean_t no_warn
,
186 boolean_t verbose
, boolean_t show_mechs
)
189 CK_RV (*Tmp_C_GetFunctionList
)(CK_FUNCTION_LIST_PTR_PTR
);
190 CK_FUNCTION_LIST_PTR prov_funcs
; /* Provider's function list */
191 CK_SLOT_ID_PTR prov_slots
= NULL
; /* Provider's slot list */
192 CK_MECHANISM_TYPE_PTR pmech_list
= NULL
; /* mech list for a slot */
193 CK_SLOT_INFO slotinfo
;
196 uentry_t
*puent
= NULL
;
197 boolean_t lib_initialized
= B_FALSE
;
200 const char *mech_name
;
202 char libpath
[MAXPATHLEN
];
203 char buf
[MAXPATHLEN
];
207 if (libname
== NULL
) {
208 /* should not happen */
209 cryptoerror(LOG_STDERR
, gettext("internal error."));
210 cryptodebug("list_mechlist_for_lib() - libname is NULL.");
214 /* Check if the library is in the pkcs11.conf file */
215 if ((puent
= getent_uef(libname
)) == NULL
) {
216 cryptoerror(LOG_STDERR
,
217 gettext("%s does not exist."), libname
);
222 /* Remove $ISA from the library name */
223 if (strlcpy(buf
, libname
, sizeof (buf
)) >= sizeof (buf
)) {
224 (void) printf(gettext("%s: the provider name is too long."),
229 if ((isa
= strstr(buf
, PKCS11_ISA
)) != NULL
) {
231 isa
+= strlen(PKCS11_ISA
);
232 (void) snprintf(libpath
, MAXPATHLEN
, "%s%s%s", buf
, "/", isa
);
234 (void) strlcpy(libpath
, libname
, sizeof (libpath
));
238 * Open the provider. Use RTLD_NOW here, as a way to
239 * catch any providers with incomplete symbols that
240 * might otherwise cause problems during libpkcs11's
243 dldesc
= dlopen(libpath
, RTLD_NOW
);
244 if (dldesc
== NULL
) {
245 dl_error
= dlerror();
246 cryptodebug("Cannot load PKCS#11 library %s. dlerror: %s",
247 libname
, dl_error
!= NULL
? dl_error
: "Unknown");
252 /* Get the pointer to provider's C_GetFunctionList() */
253 Tmp_C_GetFunctionList
= (CK_RV(*)())dlsym(dldesc
, "C_GetFunctionList");
254 if (Tmp_C_GetFunctionList
== NULL
) {
255 cryptodebug("Cannot get the address of the C_GetFunctionList "
261 /* Get the provider's function list */
262 rv
= Tmp_C_GetFunctionList(&prov_funcs
);
264 cryptodebug("failed to call C_GetFunctionList from %s",
270 /* Initialize this provider */
271 rv
= prov_funcs
->C_Initialize(NULL_PTR
);
273 cryptodebug("failed to call C_Initialize from %s, "
274 "return code = %d", libname
, rv
);
278 lib_initialized
= B_TRUE
;
282 * Find out how many slots this provider has, call with tokenPresent
283 * set to FALSE so all potential slots are returned.
285 rv
= prov_funcs
->C_GetSlotList(FALSE
, NULL_PTR
, &slot_count
);
287 cryptodebug("failed to get the slotlist from %s.", libname
);
290 } else if (slot_count
== 0) {
292 (void) printf(gettext("%s: no slots presented.\n"),
298 /* Allocate memory for the slot list */
299 prov_slots
= malloc(slot_count
* sizeof (CK_SLOT_ID
));
300 if (prov_slots
== NULL
) {
301 cryptodebug("out of memory.");
306 /* Get the slot list from provider */
307 rv
= prov_funcs
->C_GetSlotList(FALSE
, prov_slots
, &slot_count
);
309 cryptodebug("failed to call C_GetSlotList() from %s.",
316 (void) printf(gettext("Number of slots: %d\n"), slot_count
);
319 /* Get the mechanism list for each slot */
320 for (i
= 0; i
< slot_count
; i
++) {
324 * In some languages, the # symbol should be
325 * converted to "no", an "n" followed by a
328 (void) printf(gettext("\nSlot #%d\n"), i
+1);
330 if ((rng_flag
!= NULL
) && (*rng_flag
== NO_RNG
)) {
331 if (check_random(prov_slots
[i
], prov_funcs
)) {
339 rv
= prov_funcs
->C_GetSlotInfo(prov_slots
[i
], &slotinfo
);
341 cryptodebug("failed to get slotinfo from %s", libname
);
346 CK_TOKEN_INFO tokeninfo
;
348 (void) printf(gettext("Description: %.64s\n"
349 "Manufacturer: %.32s\n"
350 "PKCS#11 Version: %d.%d\n"),
351 slotinfo
.slotDescription
,
352 slotinfo
.manufacturerID
,
353 prov_funcs
->version
.major
,
354 prov_funcs
->version
.minor
);
356 (void) printf(gettext("Hardware Version: %d.%d\n"
357 "Firmware Version: %d.%d\n"),
358 slotinfo
.hardwareVersion
.major
,
359 slotinfo
.hardwareVersion
.minor
,
360 slotinfo
.firmwareVersion
.major
,
361 slotinfo
.firmwareVersion
.minor
);
363 (void) printf(gettext("Token Present: %s\n"),
364 (slotinfo
.flags
& CKF_TOKEN_PRESENT
?
365 gettext("True") : gettext("False")));
367 display_slot_flags(slotinfo
.flags
);
369 rv
= prov_funcs
->C_GetTokenInfo(prov_slots
[i
],
372 cryptodebug("Failed to get "
373 "token info from %s", libname
);
378 (void) printf(gettext("Token Label: %.32s\n"
379 "Manufacturer ID: %.32s\n"
381 "Serial Number: %.16s\n"
382 "Hardware Version: %d.%d\n"
383 "Firmware Version: %d.%d\n"
385 "PIN Min Length: %d\n"
386 "PIN Max Length: %d\n"),
388 tokeninfo
.manufacturerID
,
390 tokeninfo
.serialNumber
,
391 tokeninfo
.hardwareVersion
.major
,
392 tokeninfo
.hardwareVersion
.minor
,
393 tokeninfo
.firmwareVersion
.major
,
394 tokeninfo
.firmwareVersion
.minor
,
396 tokeninfo
.ulMinPinLen
,
397 tokeninfo
.ulMaxPinLen
);
399 display_token_flags(tokeninfo
.flags
);
403 rv
= prov_funcs
->C_GetMechanismList(prov_slots
[i
],
404 NULL_PTR
, &mech_count
);
407 "failed to call C_GetMechanismList() "
408 "from %s.", libname
);
413 if (mech_count
== 0) {
414 /* no mechanisms in this slot */
418 pmech_list
= malloc(mech_count
*
419 sizeof (CK_MECHANISM_TYPE
));
420 if (pmech_list
== NULL
) {
421 cryptodebug("out of memory");
426 /* Get the actual mechanism list */
427 rv
= prov_funcs
->C_GetMechanismList(prov_slots
[i
],
428 pmech_list
, &mech_count
);
431 "failed to call C_GetMechanismList() "
432 "from %s.", libname
);
438 /* use the mechanism list passed in */
439 rc
= convert_mechlist(&pmech_list
, &mech_count
, mlist
);
445 (void) printf(gettext("Mechanisms:\n"));
447 if (verbose
&& show_mechs
) {
448 display_verbose_mech_header();
451 * Merge the current mechanism list into the returning
454 for (j
= 0; show_mechs
&& j
< mech_count
; j
++) {
455 CK_MECHANISM_TYPE mech
= pmech_list
[j
];
456 CK_MECHANISM_INFO mech_info
;
458 rv
= prov_funcs
->C_GetMechanismInfo(
459 prov_slots
[i
], mech
, &mech_info
);
463 "C_GetMechanismInfo() from %s.",
470 if (mech
>= CKM_VENDOR_DEFINED
) {
471 (void) printf("%#lx", mech
);
473 mech_name
= pkcs11_mech2str(mech
);
474 (void) printf("%-29s", mech_name
);
478 display_mech_info(&mech_info
);
489 if (rng_flag
!= NULL
|| rc
== FAILURE
) {
496 (void) printf(gettext(
497 "%s: failed to retrieve the mechanism list.\n"), libname
);
500 if (lib_initialized
) {
501 (void) prov_funcs
->C_Finalize(NULL_PTR
);
504 if (dldesc
!= NULL
) {
505 (void) dlclose(dldesc
);
508 if (prov_slots
!= NULL
) {
517 * Display the mechanism policy for a user-level library
520 list_policy_for_lib(char *libname
)
522 uentry_t
*puent
= NULL
;
525 if (libname
== NULL
) {
526 /* should not happen */
527 cryptoerror(LOG_STDERR
, gettext("internal error."));
528 cryptodebug("list_policy_for_lib() - libname is NULL.");
532 /* Get the library entry from the pkcs11.conf file */
533 if ((puent
= getent_uef(libname
)) == NULL
) {
534 cryptoerror(LOG_STDERR
,
535 gettext("%s does not exist."), libname
);
539 /* Print the policy for this library */
540 rc
= print_uef_policy(puent
);
548 * Disable mechanisms for a user-level library
551 disable_uef_lib(char *libname
, boolean_t rndflag
, boolean_t allflag
,
552 mechlist_t
*marglist
)
557 if (libname
== NULL
) {
558 /* should not happen */
559 cryptoerror(LOG_STDERR
, gettext("internal error."));
560 cryptodebug("disable_uef_lib() - libname is NULL.");
564 /* Get the provider entry from the pkcs11.conf file */
565 if ((puent
= getent_uef(libname
)) == NULL
) {
566 cryptoerror(LOG_STDERR
,
567 gettext("%s does not exist."), libname
);
572 * Update the mechanism policy of this library entry, based on
573 * the current policy mode of the library and the mechanisms specified
578 * If disabling all, just need to clean up the policylist and
579 * set the flag_enabledlist flag to be B_TRUE.
581 free_umechlist(puent
->policylist
);
582 puent
->policylist
= NULL
;
584 puent
->flag_enabledlist
= B_TRUE
;
586 } else if (marglist
!= NULL
) {
587 if (puent
->flag_enabledlist
== B_TRUE
) {
589 * The current default policy mode of this library
590 * is "all are disabled, except ...", so if a
591 * specified mechanism is in the exception list
592 * (the policylist), delete it from the policylist.
594 rc
= update_policylist(puent
, marglist
, DELETE_MODE
);
597 * The current default policy mode of this library
598 * is "all are enabled", so if a specified mechanism
599 * is not in the exception list (policylist), add
600 * it into the policylist.
602 rc
= update_policylist(puent
, marglist
, ADD_MODE
);
604 } else if (!rndflag
) {
605 /* should not happen */
606 cryptoerror(LOG_STDERR
, gettext("internal error."));
607 cryptodebug("disable_uef_lib() - wrong arguments.");
612 puent
->flag_norandom
= B_TRUE
;
619 /* Update the pkcs11.conf file with the updated entry */
620 rc
= update_pkcs11conf(puent
);
627 * Enable disabled mechanisms for a user-level library.
630 enable_uef_lib(char *libname
, boolean_t rndflag
, boolean_t allflag
,
631 mechlist_t
*marglist
)
636 if (libname
== NULL
) {
637 /* should not happen */
638 cryptoerror(LOG_STDERR
, gettext("internal error."));
639 cryptodebug("enable_uef_lib() - libname is NULL.");
643 /* Get the provider entry from the pkcs11.conf file */
644 if ((puent
= getent_uef(libname
)) == NULL
) {
645 cryptoerror(LOG_STDERR
,
646 gettext("%s does not exist."), libname
);
651 * Update the mechanism policy of this library entry, based on
652 * the current policy mode of the library and the mechanisms
657 * If enabling all, what needs to be done are cleaning up the
658 * policylist and setting the "flag_enabledlist" flag to
661 free_umechlist(puent
->policylist
);
662 puent
->policylist
= NULL
;
664 puent
->flag_enabledlist
= B_FALSE
;
666 } else if (marglist
!= NULL
) {
667 if (puent
->flag_enabledlist
== B_TRUE
) {
669 * The current default policy mode of this library
670 * is "all are disabled, except ...", so if a
671 * specified mechanism is not in the exception list
672 * (policylist), add it.
674 rc
= update_policylist(puent
, marglist
, ADD_MODE
);
677 * The current default policy mode of this library
678 * is "all are enabled, except", so if a specified
679 * mechanism is in the exception list (policylist),
682 rc
= update_policylist(puent
, marglist
, DELETE_MODE
);
684 } else if (!rndflag
) {
685 /* should not come here */
686 cryptoerror(LOG_STDERR
, gettext("internal error."));
687 cryptodebug("enable_uef_lib() - wrong arguments.");
692 puent
->flag_norandom
= B_FALSE
;
699 /* Update the pkcs11.conf file with the updated entry */
700 rc
= update_pkcs11conf(puent
);
707 * Install a user-level library.
710 install_uef_lib(char *libname
)
714 char libpath
[MAXPATHLEN
];
715 char libbuf
[MAXPATHLEN
];
718 if (libname
== NULL
) {
719 /* should not happen */
720 cryptoerror(LOG_STDERR
, gettext("internal error."));
721 cryptodebug("install_uef_lib() - libname is NULL.");
725 /* Check if the provider already exists in the framework */
726 if ((puent
= getent_uef(libname
)) != NULL
) {
727 cryptoerror(LOG_STDERR
, gettext("%s exists already."),
734 * Check if the library exists in the system. if $ISA is in the
735 * path, only check the 32bit version.
737 if (strlcpy(libbuf
, libname
, MAXPATHLEN
) >= MAXPATHLEN
) {
738 cryptoerror(LOG_STDERR
,
739 gettext("the provider name is too long - %s"), libname
);
743 if ((isa
= strstr(libbuf
, PKCS11_ISA
)) != NULL
) {
745 isa
+= strlen(PKCS11_ISA
);
746 (void) snprintf(libpath
, sizeof (libpath
), "%s%s%s", libbuf
,
749 (void) strlcpy(libpath
, libname
, sizeof (libpath
));
752 /* Check if it is same as the framework library */
753 if (strcmp(libpath
, UEF_FRAME_LIB
) == 0) {
754 cryptoerror(LOG_STDERR
, gettext(
755 "The framework library %s can not be installed."),
760 if (stat(libpath
, &statbuf
) != 0) {
761 cryptoerror(LOG_STDERR
, gettext("%s not found"), libname
);
765 /* Need to add "\n" to libname for adding into the config file */
766 if (strlcat(libname
, "\n", MAXPATHLEN
) >= MAXPATHLEN
) {
767 cryptoerror(LOG_STDERR
, gettext(
768 "can not install %s; the name is too long."), libname
);
772 return (update_conf(_PATH_PKCS11_CONF
, libname
));
778 * Uninstall a user-level library.
781 uninstall_uef_lib(char *libname
)
787 char buffer2
[BUFSIZ
];
788 char tmpfile_name
[MAXPATHLEN
];
791 boolean_t in_package
;
795 if (libname
== NULL
) {
796 /* should not happen */
797 cryptoerror(LOG_STDERR
, gettext("internal error."));
798 cryptodebug("uninstall_uef_lib() - libname is NULL.");
802 /* Check if the provider exists */
803 if ((puent
= getent_uef(libname
)) == NULL
) {
804 cryptoerror(LOG_STDERR
,
805 gettext("%s does not exist."), libname
);
810 /* Open the pkcs11.conf file and lock it */
811 if ((pfile
= fopen(_PATH_PKCS11_CONF
, "r+")) == NULL
) {
813 cryptoerror(LOG_STDERR
,
814 gettext("failed to update the configuration - %s"),
816 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF
);
820 if (lockf(fileno(pfile
), F_TLOCK
, 0) == -1) {
822 cryptoerror(LOG_STDERR
,
823 gettext("failed to lock the configuration - %s"),
825 (void) fclose(pfile
);
830 * Create a temporary file in the /etc/crypto directory to save
831 * the new configuration file first.
833 (void) strlcpy(tmpfile_name
, TMPFILE_TEMPLATE
, sizeof (tmpfile_name
));
834 if (mkstemp(tmpfile_name
) == -1) {
836 cryptoerror(LOG_STDERR
,
837 gettext("failed to create a temporary file - %s"),
839 (void) fclose(pfile
);
843 if ((pfile_tmp
= fopen(tmpfile_name
, "w")) == NULL
) {
845 cryptoerror(LOG_STDERR
, gettext("failed to open %s - %s"),
846 tmpfile_name
, strerror(err
));
847 if (unlink(tmpfile_name
) != 0) {
849 cryptoerror(LOG_STDERR
, gettext(
850 "(Warning) failed to remove %s: %s"),
851 tmpfile_name
, strerror(err
));
853 (void) fclose(pfile
);
859 * Loop thru the config file. If the library to be uninstalled
860 * is in a package, just comment it off.
862 in_package
= B_FALSE
;
863 while (fgets(buffer
, BUFSIZ
, pfile
) != NULL
) {
865 if (!(buffer
[0] == ' ' || buffer
[0] == '\n' ||
866 buffer
[0] == '\t')) {
867 if (strstr(buffer
, " Start ") != NULL
) {
869 } else if (strstr(buffer
, " End ") != NULL
) {
870 in_package
= B_FALSE
;
871 } else if (buffer
[0] != '#') {
872 (void) strlcpy(buffer2
, buffer
, BUFSIZ
);
874 /* get rid of trailing '\n' */
875 len
= strlen(buffer2
);
876 if (buffer2
[len
-1] == '\n') {
881 if ((name
= strtok(buffer2
, SEP_COLON
))
885 } else if (strcmp(libname
, name
) == 0) {
893 (void) snprintf(buffer2
, sizeof (buffer2
),
894 "%s%s%s", "#", libname
, "\n");
895 if (fputs(buffer2
, pfile_tmp
) == EOF
) {
900 if (fputs(buffer
, pfile_tmp
) == EOF
) {
911 cryptoerror(LOG_STDERR
, gettext("write error."));
912 (void) fclose(pfile
);
913 (void) fclose(pfile_tmp
);
914 if (unlink(tmpfile_name
) != 0) {
916 cryptoerror(LOG_STDERR
, gettext(
917 "(Warning) failed to remove %s: %s"),
918 tmpfile_name
, strerror(err
));
923 (void) fclose(pfile
);
924 if (fclose(pfile_tmp
) != 0) {
926 cryptoerror(LOG_STDERR
,
927 gettext("failed to close a temporary file - %s"),
932 /* Now update the real config file */
933 if (rename(tmpfile_name
, _PATH_PKCS11_CONF
) == -1) {
935 cryptoerror(LOG_STDERR
,
936 gettext("failed to update the configuration - %s"),
938 cryptodebug("failed to rename %s to %s: %s", tmpfile
,
939 _PATH_PKCS11_CONF
, strerror(err
));
941 } else if (chmod(_PATH_PKCS11_CONF
,
942 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
) == -1) {
944 cryptoerror(LOG_STDERR
,
945 gettext("failed to update the configuration - %s"),
947 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF
,
954 if ((rc
== FAILURE
) && (unlink(tmpfile_name
) != 0)) {
956 cryptoerror(LOG_STDERR
, gettext(
957 "(Warning) failed to remove %s: %s"),
958 tmpfile_name
, strerror(err
));
966 display_policy(uentry_t
*puent
)
968 CK_MECHANISM_TYPE mech_id
;
969 const char *mech_name
;
976 if (puent
->flag_enabledlist
== B_FALSE
) {
977 (void) printf(gettext("%s: all mechanisms are enabled"),
979 ptr
= puent
->policylist
;
983 (void) printf(gettext(", except "));
984 while (ptr
!= NULL
) {
985 mech_id
= strtoul(ptr
->name
, NULL
, 0);
986 if (mech_id
& CKO_VENDOR_DEFINED
) {
987 /* vendor defined mechanism */
988 (void) printf("%s", ptr
->name
);
990 if (mech_id
>= CKM_VENDOR_DEFINED
) {
991 (void) printf("%#lx", mech_id
);
993 mech_name
= pkcs11_mech2str(
995 if (mech_name
== NULL
) {
998 (void) printf("%s", mech_name
);
1010 } else { /* puent->flag_enabledlist == B_TRUE */
1011 (void) printf(gettext("%s: all mechanisms are disabled"),
1013 ptr
= puent
->policylist
;
1017 (void) printf(gettext(", except "));
1018 while (ptr
!= NULL
) {
1019 mech_id
= strtoul(ptr
->name
, NULL
, 0);
1020 if (mech_id
& CKO_VENDOR_DEFINED
) {
1021 /* vendor defined mechanism */
1022 (void) printf("%s", ptr
->name
);
1024 mech_name
= pkcs11_mech2str(mech_id
);
1025 if (mech_name
== NULL
) {
1028 (void) printf("%s", mech_name
);
1045 * Print out the mechanism policy for a user-level provider pointed by puent.
1048 print_uef_policy(uentry_t
*puent
)
1050 flag_val_t rng_flag
;
1052 if (puent
== NULL
) {
1057 if (list_mechlist_for_lib(puent
->name
, NULL
, &rng_flag
, B_TRUE
,
1058 B_FALSE
, B_FALSE
) != SUCCESS
) {
1059 cryptoerror(LOG_STDERR
,
1060 gettext("%s internal error."), puent
->name
);
1064 if (display_policy(puent
) != SUCCESS
) {
1069 if (puent
->flag_norandom
== B_TRUE
)
1072 * "random" is a keyword and not to be translated.
1074 (void) printf(gettext(" %s is disabled."), "random");
1076 if (rng_flag
== HAS_RNG
)
1079 * "random" is a keyword and not to be translated.
1081 (void) printf(gettext(" %s is enabled."), "random");
1083 (void) printf("\n");
1089 (void) printf(gettext("\nout of memory.\n"));
1095 * Check if the mechanism is in the mechanism list.
1098 is_in_policylist(midstr_t mechname
, umechlist_t
*plist
)
1100 boolean_t found
= B_FALSE
;
1102 if (mechname
== NULL
) {
1106 while (plist
!= NULL
) {
1107 if (strcmp(plist
->name
, mechname
) == 0) {
1111 plist
= plist
->next
;
1119 * Update the pkcs11.conf file with the updated entry.
1122 update_pkcs11conf(uentry_t
*puent
)
1126 char buffer
[BUFSIZ
];
1127 char buffer2
[BUFSIZ
];
1128 char tmpfile_name
[MAXPATHLEN
];
1135 if (puent
== NULL
) {
1136 cryptoerror(LOG_STDERR
, gettext("internal error."));
1140 /* Open the pkcs11.conf file */
1141 if ((pfile
= fopen(_PATH_PKCS11_CONF
, "r+")) == NULL
) {
1143 cryptoerror(LOG_STDERR
,
1144 gettext("failed to update the configuration - %s"),
1146 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF
);
1150 /* Lock the pkcs11.conf file */
1151 if (lockf(fileno(pfile
), F_TLOCK
, 0) == -1) {
1153 cryptoerror(LOG_STDERR
,
1154 gettext("failed to update the configuration - %s"),
1156 (void) fclose(pfile
);
1161 * Create a temporary file in the /etc/crypto directory to save
1162 * updated configuration file first.
1164 (void) strlcpy(tmpfile_name
, TMPFILE_TEMPLATE
, sizeof (tmpfile_name
));
1165 if (mkstemp(tmpfile_name
) == -1) {
1167 cryptoerror(LOG_STDERR
,
1168 gettext("failed to create a temporary file - %s"),
1170 (void) fclose(pfile
);
1174 if ((pfile_tmp
= fopen(tmpfile_name
, "w")) == NULL
) {
1176 cryptoerror(LOG_STDERR
, gettext("failed to open %s - %s"),
1177 tmpfile_name
, strerror(err
));
1178 if (unlink(tmpfile_name
) != 0) {
1180 cryptoerror(LOG_STDERR
, gettext(
1181 "(Warning) failed to remove %s: %s"),
1182 tmpfile_name
, strerror(err
));
1184 (void) fclose(pfile
);
1190 * Loop thru entire pkcs11.conf file, update the entry to be
1191 * updated and save the updated file to the temporary file first.
1193 while (fgets(buffer
, BUFSIZ
, pfile
) != NULL
) {
1195 if (!(buffer
[0] == '#' || buffer
[0] == ' ' ||
1196 buffer
[0] == '\n'|| buffer
[0] == '\t')) {
1198 * Get the provider name from this line and check if
1199 * this is the entry to be updated. Note: can not use
1200 * "buffer" directly because strtok will change its
1203 (void) strlcpy(buffer2
, buffer
, BUFSIZ
);
1205 /* get rid of trailing '\n' */
1206 len
= strlen(buffer2
);
1207 if (buffer2
[len
-1] == '\n') {
1210 buffer2
[len
] = '\0';
1212 if ((name
= strtok(buffer2
, SEP_COLON
)) == NULL
) {
1215 } else if (strcmp(puent
->name
, name
) == 0) {
1222 * This is the entry to be modified, get the updated
1225 if ((str
= uent2str(puent
)) == NULL
) {
1229 (void) strlcpy(buffer
, str
, BUFSIZ
);
1234 if (fputs(buffer
, pfile_tmp
) == EOF
) {
1236 cryptoerror(LOG_STDERR
, gettext(
1237 "failed to write to a temp file: %s."),
1244 if (rc
== FAILURE
) {
1245 (void) fclose(pfile
);
1246 (void) fclose(pfile_tmp
);
1247 if (unlink(tmpfile_name
) != 0) {
1249 cryptoerror(LOG_STDERR
, gettext(
1250 "(Warning) failed to remove %s: %s"),
1251 tmpfile_name
, strerror(err
));
1256 (void) fclose(pfile
);
1257 if (fclose(pfile_tmp
) != 0) {
1259 cryptoerror(LOG_STDERR
,
1260 gettext("failed to close %s: %s"), tmpfile_name
,
1265 /* Copy the temporary file to the pkcs11.conf file */
1266 if (rename(tmpfile_name
, _PATH_PKCS11_CONF
) == -1) {
1268 cryptoerror(LOG_STDERR
,
1269 gettext("failed to update the configuration - %s"),
1271 cryptodebug("failed to rename %s to %s: %s", tmpfile_name
,
1272 _PATH_PKCS11_CONF
, strerror(err
));
1274 } else if (chmod(_PATH_PKCS11_CONF
,
1275 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
) == -1) {
1277 cryptoerror(LOG_STDERR
,
1278 gettext("failed to update the configuration - %s"),
1280 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF
,
1287 if ((rc
== FAILURE
) && (unlink(tmpfile_name
) != 0)) {
1289 cryptoerror(LOG_STDERR
, gettext(
1290 "(Warning) failed to remove %s: %s"),
1291 tmpfile_name
, strerror(err
));
1299 * Convert an uentry to a character string
1302 uent2str(uentry_t
*puent
)
1305 boolean_t tok1_present
= B_FALSE
;
1307 char blank_buf
[128];
1309 if (puent
== NULL
) {
1310 cryptoerror(LOG_STDERR
, gettext("internal error."));
1314 buf
= malloc(BUFSIZ
);
1316 cryptoerror(LOG_STDERR
, gettext("out of memory."));
1320 /* convert the library name */
1321 if (strlcpy(buf
, puent
->name
, BUFSIZ
) >= BUFSIZ
) {
1327 /* convert the enabledlist or the disabledlist */
1328 if (puent
->flag_enabledlist
== B_TRUE
) {
1329 if (strlcat(buf
, SEP_COLON
, BUFSIZ
) >= BUFSIZ
) {
1334 if (strlcat(buf
, EF_ENABLED
, BUFSIZ
) >= BUFSIZ
) {
1339 phead
= puent
->policylist
;
1340 while (phead
!= NULL
) {
1341 if (strlcat(buf
, phead
->name
, BUFSIZ
) >= BUFSIZ
) {
1346 phead
= phead
->next
;
1347 if (phead
!= NULL
) {
1348 if (strlcat(buf
, SEP_COMMA
, BUFSIZ
)
1355 tok1_present
= B_TRUE
;
1356 } else if (puent
->policylist
!= NULL
) {
1357 if (strlcat(buf
, SEP_COLON
, BUFSIZ
) >= BUFSIZ
) {
1362 if (strlcat(buf
, EF_DISABLED
, BUFSIZ
) >= BUFSIZ
) {
1366 phead
= puent
->policylist
;
1367 while (phead
!= NULL
) {
1368 if (strlcat(buf
, phead
->name
, BUFSIZ
) >= BUFSIZ
) {
1373 phead
= phead
->next
;
1374 if (phead
!= NULL
) {
1375 if (strlcat(buf
, SEP_COMMA
, BUFSIZ
)
1382 tok1_present
= B_TRUE
;
1385 if (puent
->flag_norandom
== B_TRUE
) {
1386 if (strlcat(buf
, (tok1_present
? SEP_SEMICOLON
: SEP_COLON
),
1387 BUFSIZ
) >= BUFSIZ
) {
1392 if (strlcat(buf
, EF_NORANDOM
, BUFSIZ
) >= BUFSIZ
) {
1398 if (strcmp(puent
->name
, METASLOT_KEYWORD
) == 0) {
1400 /* write the metaslot_status= value */
1401 if (strlcat(buf
, (tok1_present
? SEP_SEMICOLON
: SEP_COLON
),
1402 BUFSIZ
) >= BUFSIZ
) {
1407 if (strlcat(buf
, METASLOT_STATUS
, BUFSIZ
) >= BUFSIZ
) {
1412 if (puent
->flag_metaslot_enabled
) {
1413 if (strlcat(buf
, ENABLED_KEYWORD
, BUFSIZ
) >= BUFSIZ
) {
1418 if (strlcat(buf
, DISABLED_KEYWORD
, BUFSIZ
)
1425 if (!tok1_present
) {
1426 tok1_present
= B_TRUE
;
1429 if (strlcat(buf
, SEP_SEMICOLON
, BUFSIZ
) >= BUFSIZ
) {
1434 if (strlcat(buf
, METASLOT_AUTO_KEY_MIGRATE
, BUFSIZ
) >= BUFSIZ
) {
1439 if (puent
->flag_metaslot_auto_key_migrate
) {
1440 if (strlcat(buf
, ENABLED_KEYWORD
, BUFSIZ
) >= BUFSIZ
) {
1445 if (strlcat(buf
, DISABLED_KEYWORD
, BUFSIZ
) >= BUFSIZ
) {
1451 bzero(blank_buf
, sizeof (blank_buf
));
1453 /* write metaslot_token= if specified */
1454 if (memcmp(puent
->metaslot_ks_token
, blank_buf
,
1455 TOKEN_LABEL_SIZE
) != 0) {
1456 /* write the metaslot_status= value */
1457 if (strlcat(buf
, (tok1_present
?
1458 SEP_SEMICOLON
: SEP_COLON
), BUFSIZ
) >= BUFSIZ
) {
1463 if (strlcat(buf
, METASLOT_TOKEN
, BUFSIZ
) >= BUFSIZ
) {
1469 (const char *)puent
->metaslot_ks_token
, BUFSIZ
)
1476 /* write metaslot_slot= if specified */
1477 if (memcmp(puent
->metaslot_ks_slot
, blank_buf
,
1478 SLOT_DESCRIPTION_SIZE
) != 0) {
1479 /* write the metaslot_status= value */
1480 if (strlcat(buf
, (tok1_present
?
1481 SEP_SEMICOLON
: SEP_COLON
), BUFSIZ
) >= BUFSIZ
) {
1486 if (strlcat(buf
, METASLOT_SLOT
, BUFSIZ
) >= BUFSIZ
) {
1492 (const char *)puent
->metaslot_ks_slot
, BUFSIZ
)
1500 if (strlcat(buf
, "\n", BUFSIZ
) >= BUFSIZ
) {
1510 * This function updates the default policy mode and the policy exception list
1511 * for a user-level provider based on the mechanism specified in the disable
1512 * or enable subcommand and the update mode. This function is called by the
1513 * enable_uef_lib() or disable_uef_lib().
1516 update_policylist(uentry_t
*puent
, mechlist_t
*marglist
, int update_mode
)
1518 CK_MECHANISM_TYPE mech_type
;
1522 umechlist_t
*pumech
;
1526 if ((puent
== NULL
) || (marglist
== NULL
)) {
1527 /* should not happen */
1528 cryptoerror(LOG_STDERR
, gettext("internal error."));
1529 cryptodebug("update_policylist()- puent or marglist is NULL.");
1533 if ((update_mode
!= ADD_MODE
) && (update_mode
!= DELETE_MODE
)) {
1534 /* should not happen */
1535 cryptoerror(LOG_STDERR
, gettext("internal error."));
1536 cryptodebug("update_policylist() - update_mode is incorrect.");
1541 * For each mechanism operand, get its mechanism type first.
1542 * If fails to get the mechanism type, the mechanism operand must be
1543 * invalid, gives an warning and ignore it. Otherwise,
1544 * - convert the mechanism type to the internal representation (hex)
1545 * in the pkcs11.conf file
1546 * - If update_mode == DELETE_MODE,
1547 * If the mechanism is in the policy list, delete it.
1548 * If the mechanism is not in the policy list, do nothing.
1549 * - If update_mode == ADD_MODE,
1550 * If the mechanism is not in the policy list, add it.
1551 * If the mechanism is in the policy list already, do nothing.
1554 if (pkcs11_str2mech(marglist
->name
, &mech_type
) != CKR_OK
) {
1556 * This mechanism is not a valid PKCS11 mechanism,
1557 * give warning and ignore it.
1559 cryptoerror(LOG_STDERR
, gettext(
1560 "(Warning) %s is not a valid PKCS#11 mechanism."),
1564 (void) snprintf(midname
, sizeof (midname
), "%#010x",
1566 if (update_mode
== DELETE_MODE
) {
1568 phead
= pcur
= puent
->policylist
;
1569 while (!found
&& pcur
) {
1570 if (strcmp(pcur
->name
, midname
) == 0) {
1579 if (phead
== pcur
) {
1581 puent
->policylist
->next
;
1584 phead
->next
= pcur
->next
;
1588 if (puent
->count
== 0) {
1589 puent
->policylist
= NULL
;
1592 } else if (update_mode
== ADD_MODE
) {
1593 if (!is_in_policylist(midname
,
1594 puent
->policylist
)) {
1595 pumech
= create_umech(midname
);
1596 if (pumech
== NULL
) {
1600 phead
= puent
->policylist
;
1601 puent
->policylist
= pumech
;
1602 pumech
->next
= phead
;
1607 marglist
= marglist
->next
;
1614 * Open a session to the given slot and check if we can do
1615 * random numbers by asking for one byte.
1618 check_random(CK_SLOT_ID slot_id
, CK_FUNCTION_LIST_PTR prov_funcs
)
1621 CK_SESSION_HANDLE hSession
;
1623 CK_BYTE_PTR test_byte_ptr
= &test_byte
;
1625 rv
= prov_funcs
->C_OpenSession(slot_id
, CKF_SERIAL_SESSION
,
1626 NULL_PTR
, NULL
, &hSession
);
1630 /* We care only about the return value */
1631 rv
= prov_funcs
->C_GenerateRandom(hSession
, test_byte_ptr
,
1632 sizeof (test_byte
));
1633 (void) prov_funcs
->C_CloseSession(hSession
);
1636 * These checks are purely to determine whether the slot can do
1637 * random numbers. So, we don't check whether the routine
1638 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that
1639 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED.
1641 if (rv
!= CKR_FUNCTION_NOT_SUPPORTED
&& rv
!= CKR_RANDOM_NO_RNG
)
1648 display_verbose_mech_header()
1650 (void) printf("%28s %s", " ", HDR1
);
1651 (void) printf("%28s %s", " ", HDR2
);
1652 (void) printf("%28s %s", " ", HDR3
);
1653 (void) printf("%28s %s", " ", HDR4
);
1654 (void) printf("%28s %s", " ", HDR5
);
1655 (void) printf("%28s %s", " ", HDR6
);
1656 (void) printf("%-28.28s %s", gettext("mechanism name"), HDR7
);
1659 * Strictly for appearance's sake, the first header line should be
1660 * as long as the length of the translated text above. The format
1661 * lengths should all match too.
1663 (void) printf("%28s ---- ---- "
1664 "- - - - - - - - - - - - - -\n",
1665 gettext("----------------------------"));