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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Administration for metaslot
28 *
29 * All the "list" operations will call functions in libpkcs11.so
30 * Normally, it doesn't make sense to call functions in libpkcs11.so directly
31 * because libpkcs11.so depends on the configuration file (pkcs11.conf) the
32 * cryptoadm command is trying to administer. However, since metaslot
33 * is part of the framework, it is not possible to get information about
34 * it without actually calling functions in libpkcs11.so.
35 *
36 * So, for the listing operation, which won't modify the value of pkcs11.conf
37 * it is safe to call libpkcs11.so.
38 *
39 * For other operations that modifies the pkcs11.conf file, libpkcs11.so
40 * will not be called.
41 *
42 */
43
44 #include <cryptoutil.h>
45 #include <stdio.h>
46 #include <libintl.h>
47 #include <dlfcn.h>
48 #include <link.h>
49 #include <strings.h>
50 #include <security/cryptoki.h>
51 #include <cryptoutil.h>
52 #include "cryptoadm.h"
53
54 #define METASLOT_ID 0
55
56 int
list_metaslot_info(boolean_t show_mechs,boolean_t verbose,mechlist_t * mechlist)57 list_metaslot_info(boolean_t show_mechs, boolean_t verbose,
58 mechlist_t *mechlist)
59 {
60 int rc = SUCCESS;
61 CK_RV rv;
62 CK_SLOT_INFO slot_info;
63 CK_TOKEN_INFO token_info;
64 CK_MECHANISM_TYPE_PTR pmech_list = NULL;
65 CK_ULONG mech_count;
66 int i;
67 CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
68 CK_FUNCTION_LIST_PTR funcs;
69 void *dldesc = NULL;
70 boolean_t lib_initialized = B_FALSE;
71 uentry_t *puent;
72 char buf[128];
73
74
75 /*
76 * Display the system-wide metaslot settings as specified
77 * in pkcs11.conf file.
78 */
79 if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
80 cryptoerror(LOG_STDERR,
81 gettext("metaslot entry doesn't exist."));
82 return (FAILURE);
83 }
84
85 (void) printf(gettext("System-wide Meta Slot Configuration:\n"));
86 /*
87 * TRANSLATION_NOTE
88 * Strictly for appearance's sake, this line should be as long as
89 * the length of the translated text above.
90 */
91 (void) printf(gettext("------------------------------------\n"));
92 (void) printf(gettext("Status: %s\n"), puent->flag_metaslot_enabled ?
93 gettext("enabled") : gettext("disabled"));
94 (void) printf(gettext("Sensitive Token Object Automatic Migrate: %s\n"),
95 puent->flag_metaslot_auto_key_migrate ? gettext("enabled") :
96 gettext("disabled"));
97
98 bzero(buf, sizeof (buf));
99 if (memcmp(puent->metaslot_ks_slot, buf, SLOT_DESCRIPTION_SIZE) != 0) {
100 (void) printf(gettext("Persistent object store slot: %s\n"),
101 puent->metaslot_ks_slot);
102 }
103
104 if (memcmp(puent->metaslot_ks_token, buf, TOKEN_LABEL_SIZE) != 0) {
105 (void) printf(gettext("Persistent object store token: %s\n"),
106 puent->metaslot_ks_token);
107 }
108
109 if ((!verbose) && (!show_mechs)) {
110 return (SUCCESS);
111 }
112
113 if (verbose) {
114 (void) printf(gettext("\nDetailed Meta Slot Information:\n"));
115 /*
116 * TRANSLATION_NOTE
117 * Strictly for appearance's sake, this line should be as
118 * long as the length of the translated text above.
119 */
120 (void) printf(gettext("-------------------------------\n"));
121 }
122
123 /*
124 * Need to actually make calls to libpkcs11.so to get
125 * information about metaslot.
126 */
127
128 dldesc = dlopen(UEF_FRAME_LIB, RTLD_NOW);
129 if (dldesc == NULL) {
130 char *dl_error;
131 dl_error = dlerror();
132 cryptodebug("Cannot load PKCS#11 framework library. "
133 "dlerror:%s", dl_error);
134 return (FAILURE);
135 }
136
137 /* Get the pointer to library's C_GetFunctionList() */
138 Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");
139 if (Tmp_C_GetFunctionList == NULL) {
140 cryptodebug("Cannot get the address of the C_GetFunctionList "
141 "from framework");
142 rc = FAILURE;
143 goto finish;
144 }
145
146
147 /* Get the provider's function list */
148 rv = Tmp_C_GetFunctionList(&funcs);
149 if (rv != CKR_OK) {
150 cryptodebug("failed to call C_GetFunctionList in "
151 "framework library");
152 rc = FAILURE;
153 goto finish;
154 }
155
156 /* Initialize this provider */
157 rv = funcs->C_Initialize(NULL_PTR);
158 if (rv != CKR_OK) {
159 cryptodebug("C_Initialize failed with error code 0x%x\n", rv);
160 rc = FAILURE;
161 goto finish;
162 } else {
163 lib_initialized = B_TRUE;
164 }
165
166 /*
167 * We know for sure that metaslot is slot 0 in the framework,
168 * so, we will do a C_GetSlotInfo() trying to see if it works.
169 * If it fails with CKR_SLOT_ID_INVALID, we know that metaslot
170 * is not really enabled.
171 */
172 rv = funcs->C_GetSlotInfo(METASLOT_ID, &slot_info);
173 if (rv == CKR_SLOT_ID_INVALID) {
174 (void) printf(gettext("actual status: disabled.\n"));
175 /*
176 * Even if the -m and -v flag is supplied, there's nothing
177 * interesting to display about metaslot since it is disabled,
178 * so, just stop right here.
179 */
180 goto finish;
181 }
182
183 if (rv != CKR_OK) {
184 cryptodebug("C_GetSlotInfo failed with error "
185 "code 0x%x\n", rv);
186 rc = FAILURE;
187 goto finish;
188 }
189
190 if (!verbose) {
191 goto display_mechs;
192 }
193
194 (void) printf(gettext("actual status: enabled.\n"));
195
196 (void) printf(gettext("Description: %.64s\n"),
197 slot_info.slotDescription);
198
199 (void) printf(gettext("Token Present: %s\n"),
200 (slot_info.flags & CKF_TOKEN_PRESENT ?
201 gettext("True") : gettext("False")));
202
203 rv = funcs->C_GetTokenInfo(METASLOT_ID, &token_info);
204 if (rv != CKR_OK) {
205 cryptodebug("C_GetTokenInfo failed with error "
206 "code 0x%x\n", rv);
207 rc = FAILURE;
208 goto finish;
209 }
210
211 (void) printf(gettext("Token Label: %.32s\n"
212 "Manufacturer ID: %.32s\n"
213 "Model: %.16s\n"
214 "Serial Number: %.16s\n"
215 "Hardware Version: %d.%d\n"
216 "Firmware Version: %d.%d\n"
217 "UTC Time: %.16s\n"
218 "PIN Min Length: %d\n"
219 "PIN Max Length: %d\n"),
220 token_info.label,
221 token_info.manufacturerID,
222 token_info.model,
223 token_info.serialNumber,
224 token_info.hardwareVersion.major,
225 token_info.hardwareVersion.minor,
226 token_info.firmwareVersion.major,
227 token_info.firmwareVersion.minor,
228 token_info.utcTime,
229 token_info.ulMinPinLen,
230 token_info.ulMaxPinLen);
231
232 display_token_flags(token_info.flags);
233
234 if (!show_mechs) {
235 goto finish;
236 }
237
238 display_mechs:
239
240 if (mechlist == NULL) {
241 rv = funcs->C_GetMechanismList(METASLOT_ID, NULL_PTR,
242 &mech_count);
243 if (rv != CKR_OK) {
244 cryptodebug("C_GetMechanismList failed with error "
245 "code 0x%x\n", rv);
246 rc = FAILURE;
247 goto finish;
248 }
249
250 if (mech_count > 0) {
251 pmech_list = malloc(mech_count *
252 sizeof (CK_MECHANISM_TYPE));
253 if (pmech_list == NULL) {
254 cryptodebug("out of memory");
255 rc = FAILURE;
256 goto finish;
257 }
258 rv = funcs->C_GetMechanismList(METASLOT_ID, pmech_list,
259 &mech_count);
260 if (rv != CKR_OK) {
261 cryptodebug("C_GetMechanismList failed with "
262 "error code 0x%x\n", rv);
263 rc = FAILURE;
264 goto finish;
265 }
266 }
267 } else {
268 rc = convert_mechlist(&pmech_list, &mech_count, mechlist);
269 if (rc != SUCCESS) {
270 goto finish;
271 }
272 }
273
274 (void) printf(gettext("Mechanisms:\n"));
275 if (mech_count == 0) {
276 /* should never be this case */
277 (void) printf(gettext("No mechanisms\n"));
278 goto finish;
279 }
280 if (verbose) {
281 display_verbose_mech_header();
282 }
283
284 for (i = 0; i < mech_count; i++) {
285 CK_MECHANISM_TYPE mech = pmech_list[i];
286
287 if (mech >= CKM_VENDOR_DEFINED) {
288 (void) printf("%#lx", mech);
289 } else {
290 (void) printf("%-29s", pkcs11_mech2str(mech));
291 }
292
293 if (verbose) {
294 CK_MECHANISM_INFO mech_info;
295 rv = funcs->C_GetMechanismInfo(METASLOT_ID,
296 mech, &mech_info);
297 if (rv != CKR_OK) {
298 cryptodebug("C_GetMechanismInfo failed with "
299 "error code 0x%x\n", rv);
300 rc = FAILURE;
301 goto finish;
302 }
303 display_mech_info(&mech_info);
304 }
305 (void) printf("\n");
306 }
307
308 finish:
309
310 if ((rc == FAILURE) && (show_mechs)) {
311 (void) printf(gettext(
312 "metaslot: failed to retrieve the mechanism list.\n"));
313 }
314
315 if (lib_initialized) {
316 (void) funcs->C_Finalize(NULL_PTR);
317 }
318
319 if (dldesc != NULL) {
320 (void) dlclose(dldesc);
321 }
322
323 if (pmech_list != NULL) {
324 (void) free(pmech_list);
325 }
326
327 return (rc);
328 }
329
330 int
list_metaslot_policy()331 list_metaslot_policy()
332 {
333
334 uentry_t *puent;
335 int rc;
336
337 if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
338 cryptoerror(LOG_STDERR,
339 gettext("metaslot entry doesn't exist."));
340 return (FAILURE);
341 }
342
343 rc = display_policy(puent);
344 (void) printf("\n");
345 free_uentry(puent);
346 return (rc);
347 }
348
349 /*
350 * disable metaslot and some of its configuration options
351 *
352 * If mechlist==NULL, and the other 2 flags are false, just disabled
353 * the metaslot feature.
354 *
355 * mechlist: list of mechanisms to disable
356 * allflag: if true, indicates all mechanisms should be disabled.
357 * auto_key_migrate_flag: if true, indicates auto key migrate should be disabled
358 */
359 int
disable_metaslot(mechlist_t * mechlist,boolean_t allflag,boolean_t auto_key_migrate_flag)360 disable_metaslot(mechlist_t *mechlist, boolean_t allflag,
361 boolean_t auto_key_migrate_flag)
362 {
363 uentry_t *puent;
364 int rc = SUCCESS;
365
366 if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
367 cryptoerror(LOG_STDERR,
368 gettext("metaslot entry doesn't exist."));
369 return (FAILURE);
370 }
371
372
373 if ((mechlist == NULL) && (!auto_key_migrate_flag) && (!allflag)) {
374 /* disable metaslot */
375 puent->flag_metaslot_enabled = B_FALSE;
376 goto write_to_file;
377 }
378
379 if (auto_key_migrate_flag) {
380 /* need to disable auto_key_migrate */
381 puent->flag_metaslot_auto_key_migrate = B_FALSE;
382 }
383
384 if ((mechlist == NULL) && (!allflag)) {
385 goto write_to_file;
386 }
387
388 /* disable specified mechanisms */
389 if (allflag) {
390 free_umechlist(puent->policylist);
391 puent->policylist = NULL;
392 puent->count = 0;
393 puent->flag_enabledlist = B_TRUE;
394 rc = SUCCESS;
395 } else {
396 if (puent->flag_enabledlist == B_TRUE) {
397 /*
398 * The current default policy mode
399 * is "all are disabled, except ...", so if a
400 * specified mechanism is in the exception list
401 * (the policylist), delete it from the policylist.
402 */
403 rc = update_policylist(puent, mechlist, DELETE_MODE);
404 } else {
405 /*
406 * The current default policy mode of this library
407 * is "all are enabled", so if a specified mechanism
408 * is not in the exception list (policylist), add
409 * it into the policylist.
410 */
411 rc = update_policylist(puent, mechlist, ADD_MODE);
412 }
413 }
414
415 if (rc != SUCCESS) {
416 goto finish;
417 }
418
419 /* If all mechanisms are disabled, metaslot will be disabled as well */
420 if ((puent->flag_enabledlist) && (puent->count == 0)) {
421 puent->flag_metaslot_enabled = B_FALSE;
422 }
423
424 write_to_file:
425
426 rc = update_pkcs11conf(puent);
427
428 finish:
429 free_uentry(puent);
430 return (rc);
431 }
432
433 /*
434 * enable metaslot and some of its configuration options
435 *
436 * If mechlist==NULL, and the other flags are false, or not specified,
437 * just enable the metaslot feature.
438 *
439 * token: if specified, indicate label of token to be used as keystore.
440 * slot: if specified, indicate slot to be used as keystore.
441 * use_default: if true, indicate to use the default keystore. It should
442 * not be specified if either token or slot is specified.
443 * mechlist: list of mechanisms to enable
444 * allflag: if true, indicates all mechanisms should be enabled.
445 * auto_key_migrate_flag: if true, indicates auto key migrate should be enabled
446 */
447 int
enable_metaslot(char * token,char * slot,boolean_t use_default,mechlist_t * mechlist,boolean_t allflag,boolean_t auto_key_migrate_flag)448 enable_metaslot(char *token, char *slot, boolean_t use_default,
449 mechlist_t *mechlist, boolean_t allflag, boolean_t auto_key_migrate_flag)
450 {
451 uentry_t *puent;
452 int rc = SUCCESS;
453
454 if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
455 cryptoerror(LOG_STDERR,
456 gettext("metaslot entry doesn't exist."));
457 return (FAILURE);
458 }
459
460 puent->flag_metaslot_enabled = B_TRUE;
461
462 if (auto_key_migrate_flag) {
463 /* need to enable auto_key_migrate */
464 puent->flag_metaslot_auto_key_migrate = B_TRUE;
465 }
466
467 if (allflag) {
468 /*
469 * If enabling all, what needs to be done are cleaning up the
470 * policylist and setting the "flag_enabledlist" flag to
471 * B_FALSE.
472 */
473 free_umechlist(puent->policylist);
474 puent->policylist = NULL;
475 puent->count = 0;
476 puent->flag_enabledlist = B_FALSE;
477 rc = SUCCESS;
478 } else {
479 if (mechlist) {
480 if (puent->flag_enabledlist == B_TRUE) {
481 /*
482 * The current default policy mode of this
483 * library is "all are disabled, except ...",
484 * so if a specified mechanism is not in the
485 * exception list (policylist), add it.
486 */
487 rc = update_policylist(puent, mechlist,
488 ADD_MODE);
489 } else {
490 /*
491 * The current default policy mode of this
492 * library is "all are enabled, except", so if
493 * a specified mechanism is in the exception
494 * list (policylist), delete it.
495 */
496 rc = update_policylist(puent, mechlist,
497 DELETE_MODE);
498 }
499 }
500 }
501
502 if (rc != SUCCESS) {
503 goto finish;
504 }
505
506 if (!use_default && !token && !slot) {
507 /* no need to change metaslot keystore */
508 goto write_to_file;
509 }
510
511 (void) bzero((char *)puent->metaslot_ks_token, TOKEN_LABEL_SIZE);
512 (void) bzero((char *)puent->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE);
513
514 if (use_default) {
515 (void) strlcpy((char *)puent->metaslot_ks_token,
516 SOFT_TOKEN_LABEL, TOKEN_LABEL_SIZE);
517 (void) strlcpy((char *)puent->metaslot_ks_slot,
518 SOFT_SLOT_DESCRIPTION, SLOT_DESCRIPTION_SIZE);
519 } else {
520
521 if (token) {
522 (void) strlcpy((char *)puent->metaslot_ks_token, token,
523 TOKEN_LABEL_SIZE);
524 }
525
526 if (slot) {
527 (void) strlcpy((char *)puent->metaslot_ks_slot, slot,
528 SLOT_DESCRIPTION_SIZE);
529 }
530 }
531
532
533 write_to_file:
534
535 rc = update_pkcs11conf(puent);
536
537 finish:
538 free_uentry(puent);
539 return (rc);
540 }
541