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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <cryptoutil.h>
31 #include "metaGlobal.h"
33 extern cipher_mechs_threshold_t meta_mechs_threshold
[];
34 static boolean_t threshold_chk_enabled
= B_FALSE
;
37 meta_operation_init_defer(CK_FLAGS optype
, meta_session_t
*session
,
38 CK_MECHANISM
*pMechanism
, meta_object_t
*key
)
41 if (session
->init
.pMech
== NULL
) {
42 session
->init
.pMech
= malloc(sizeof (CK_MECHANISM
));
43 if (session
->init
.pMech
== NULL
)
44 return (CKR_HOST_MEMORY
);
46 (void) memcpy(session
->init
.pMech
, pMechanism
,
47 sizeof (CK_MECHANISM
));
49 if ((pMechanism
->ulParameterLen
> 0) &&
50 (pMechanism
->pParameter
!= NULL
)) {
51 session
->init
.pMech
->pParameter
=
52 malloc(pMechanism
->ulParameterLen
);
53 if (session
->init
.pMech
->pParameter
== NULL
) {
54 free(session
->init
.pMech
);
55 session
->init
.pMech
= NULL
;
56 return (CKR_HOST_MEMORY
);
58 (void) memcpy(session
->init
.pMech
->pParameter
,
59 pMechanism
->pParameter
, pMechanism
->ulParameterLen
);
61 session
->init
.pMech
->pParameter
= NULL
;
63 } else { /* reuse it */
64 if ((pMechanism
->ulParameterLen
> 0) &&
65 (pMechanism
->pParameter
!= NULL
)) {
66 if (pMechanism
->ulParameterLen
!=
67 session
->init
.pMech
->ulParameterLen
) {
68 if (session
->init
.pMech
->pParameter
!= NULL
)
69 free(session
->init
.pMech
->pParameter
);
70 session
->init
.pMech
->pParameter
=
71 malloc(pMechanism
->ulParameterLen
);
72 if (session
->init
.pMech
->pParameter
== NULL
) {
73 free(session
->init
.pMech
);
74 session
->init
.pMech
= NULL
;
75 return (CKR_HOST_MEMORY
);
77 } /* otherwise reuse it */
78 (void) memcpy(session
->init
.pMech
->pParameter
,
79 pMechanism
->pParameter
, pMechanism
->ulParameterLen
);
82 * free the previous pParameter if not yet freed
83 * because we don't need it now.
85 if (session
->init
.pMech
->pParameter
!= NULL
) {
86 free(session
->init
.pMech
->pParameter
);
87 session
->init
.pMech
->pParameter
= NULL
;
90 /* copy the rest of data */
91 session
->init
.pMech
->mechanism
=
92 pMechanism
->mechanism
;
93 session
->init
.pMech
->ulParameterLen
=
94 pMechanism
->ulParameterLen
;
97 session
->init
.session
= session
;
98 session
->init
.optype
= optype
;
99 session
->init
.key
= key
;
100 session
->init
.done
= B_FALSE
;
101 session
->init
.app
= B_TRUE
;
106 * meta_operation_init
110 meta_operation_init(CK_FLAGS optype
, meta_session_t
*session
,
111 CK_MECHANISM
*pMechanism
, meta_object_t
*key
)
114 mechinfo_t
**supporting_slots
;
116 unsigned long i
, slotCount
= 0;
117 slot_session_t
*init_session
= NULL
;
118 CK_MECHANISM_INFO mech_info
;
121 * If an operation is already active, cleanup existing operation
122 * and start a new one.
124 if (session
->op1
.type
!= 0) {
126 if ((optype
== CKF_ENCRYPT
) || (optype
== CKF_DECRYPT
) ||
127 (optype
== CKF_DIGEST
)) {
130 if ((pMechanism
->ulParameterLen
> 0) &&
131 (pMechanism
->pParameter
!= NULL
)) {
133 malloc(pMechanism
->ulParameterLen
);
134 if (mech
.pParameter
== NULL
) {
135 return (CKR_HOST_MEMORY
);
137 (void) memcpy(mech
.pParameter
,
138 pMechanism
->pParameter
,
139 pMechanism
->ulParameterLen
);
141 mech
.pParameter
= NULL
;
142 mech
.ulParameterLen
= 0;
145 meta_operation_cleanup(session
, session
->op1
.type
,
147 rv
= meta_operation_init_defer(optype
, session
,
149 if (mech
.pParameter
!= NULL
) {
150 free(mech
.pParameter
);
155 meta_operation_cleanup(session
, session
->op1
.type
,
161 mech_info
.flags
= optype
;
164 * Get a list of capable slots.
166 * If the specified mechanism is used in this session last time,
167 * the list of capable slots is already retrieved. We can save
168 * some processing, and just use that list of slots.
170 if (((session
->mech_support_info
).mech
!= pMechanism
->mechanism
) ||
171 ((session
->mech_support_info
).num_supporting_slots
== 0)) {
172 (session
->mech_support_info
).mech
= pMechanism
->mechanism
;
173 rv
= meta_mechManager_get_slots(&(session
->mech_support_info
),
174 B_FALSE
, &mech_info
);
180 rv
= CKR_FUNCTION_FAILED
;
182 /* The following 2 assignment is just to make the code more readable */
183 slotCount
= (session
->mech_support_info
).num_supporting_slots
;
184 supporting_slots
= (session
->mech_support_info
).supporting_slots
;
186 /* Attempt to initialize operation on slots until one succeeds. */
187 for (i
= 0; i
< slotCount
; i
++) {
188 slot_object_t
*init_key
;
193 slotnum
= supporting_slots
[i
]->slotnum
;
196 * An actual session with the underlying slot is required
197 * for the operation. When the operation is successfully
198 * completed, the underlying session with the slot
199 * is not released back to the list of available sessions
200 * pool. This will help if the next operation can
201 * also be done on the same slot, because it avoids
202 * one extra trip to the session pool to get an idle session.
203 * If the operation can't be done on that slot,
204 * we release the session back to the session pool then.
206 if (session
->op1
.session
!= NULL
) {
208 if ((session
->op1
.session
)->slotnum
== slotnum
) {
209 init_session
= session
->op1
.session
;
211 * set it to NULL for now, assign it to
212 * init_session again if it is successful
214 session
->op1
.session
= NULL
;
222 rv
= meta_get_slot_session(slotnum
, &init_session
,
223 session
->session_flags
);
229 /* if necessary, ensure a clone of the obj exists in slot */
230 if (optype
!= CKF_DIGEST
) {
231 rv
= meta_object_get_clone(key
, slotnum
, init_session
,
239 fw_st_id
= init_session
->fw_st_id
;
242 rv
= FUNCLIST(fw_st_id
)->C_EncryptInit(
243 init_session
->hSession
, pMechanism
,
247 rv
= FUNCLIST(fw_st_id
)->C_DecryptInit(
248 init_session
->hSession
, pMechanism
,
252 rv
= FUNCLIST(fw_st_id
)->C_DigestInit(
253 init_session
->hSession
, pMechanism
);
256 rv
= FUNCLIST(fw_st_id
)->C_SignInit(
257 init_session
->hSession
, pMechanism
,
261 rv
= FUNCLIST(fw_st_id
)->C_VerifyInit(
262 init_session
->hSession
, pMechanism
,
265 case CKF_SIGN_RECOVER
:
266 rv
= FUNCLIST(fw_st_id
)->C_SignRecoverInit(
267 init_session
->hSession
, pMechanism
,
270 case CKF_VERIFY_RECOVER
:
271 rv
= FUNCLIST(fw_st_id
)->C_VerifyRecoverInit(
272 init_session
->hSession
, pMechanism
,
278 rv
= CKR_FUNCTION_FAILED
;
291 meta_release_slot_session(init_session
);
300 * If currently stored session is not the one being in use now,
301 * release the previous one and store the current one
303 if ((session
->op1
.session
) &&
304 (session
->op1
.session
!= init_session
)) {
305 meta_release_slot_session(session
->op1
.session
);
308 /* Save the session */
309 session
->op1
.session
= init_session
;
310 session
->op1
.type
= optype
;
312 session
->init
.slotnum
= slotnum
;
313 session
->init
.done
= B_TRUE
;
323 * meta_operation_init_softtoken()
324 * It will always do the crypto init operation on softtoken slot.
327 meta_operation_init_softtoken(CK_FLAGS optype
, meta_session_t
*session
,
328 CK_MECHANISM
*pMechanism
, meta_object_t
*key
)
330 CK_RV rv
= CKR_FUNCTION_FAILED
;
331 slot_session_t
*init_session
= NULL
;
332 slot_object_t
*init_key
;
334 CK_ULONG softtoken_slot_num
;
336 softtoken_slot_num
= get_softtoken_slotnum();
338 * If an operation is already active, cleanup existing operation
339 * and start a new one.
341 if (session
->op1
.type
!= 0) {
345 if ((pMechanism
->ulParameterLen
> 0) &&
346 (pMechanism
->pParameter
!= NULL
)) {
348 malloc(pMechanism
->ulParameterLen
);
349 if (mech
.pParameter
== NULL
) {
350 return (CKR_HOST_MEMORY
);
352 (void) memcpy(mech
.pParameter
,
353 pMechanism
->pParameter
, pMechanism
->ulParameterLen
);
355 mech
.pParameter
= NULL
;
356 mech
.ulParameterLen
= 0;
359 meta_operation_cleanup(session
, session
->op1
.type
, B_FALSE
);
360 rv
= meta_operation_init_defer(optype
, session
, &mech
,
362 if (mech
.pParameter
!= NULL
) {
363 free(mech
.pParameter
);
370 * An actual session with the underlying slot is required
371 * for the operation. When the operation is successfully
372 * completed, the underlying session with the slot
373 * is not released back to the list of available sessions
374 * pool. This will help if the next operation can
375 * also be done on the same slot, because it avoids
376 * one extra trip to the session pool to get an idle session.
377 * If the operation can't be done on that slot,
378 * we release the session back to the session pool.
380 if (session
->op1
.session
!= NULL
) {
381 if ((session
->op1
.session
)->slotnum
==
382 softtoken_slot_num
) {
383 init_session
= session
->op1
.session
;
385 * set it to NULL for now, assign it to
386 * init_session again if it is successful
388 session
->op1
.session
= NULL
;
394 if (init_session
== NULL
) {
395 /* get the active session from softtoken slot */
396 rv
= meta_get_slot_session(softtoken_slot_num
,
397 &init_session
, session
->session_flags
);
403 /* if necessary, ensure a clone of the obj exists in softtoken slot */
404 if (optype
!= CKF_DIGEST
) {
405 rv
= meta_object_get_clone(key
, softtoken_slot_num
,
406 init_session
, &init_key
);
409 if (init_session
!= NULL
) {
410 meta_release_slot_session(init_session
);
417 fw_st_id
= init_session
->fw_st_id
;
420 * Currently, we only support offloading encrypt, decrypt
421 * and digest operations to softtoken based on kernel
422 * threshold for the supported mechanisms.
426 rv
= FUNCLIST(fw_st_id
)->C_EncryptInit(
427 init_session
->hSession
, pMechanism
,
431 rv
= FUNCLIST(fw_st_id
)->C_DecryptInit(
432 init_session
->hSession
, pMechanism
,
436 rv
= FUNCLIST(fw_st_id
)->C_DigestInit(
437 init_session
->hSession
, pMechanism
);
442 rv
= CKR_FUNCTION_FAILED
;
449 * If currently stored session is not the one being in use now,
450 * release the previous one and store the current one
452 if ((session
->op1
.session
) &&
453 (session
->op1
.session
!= init_session
)) {
454 meta_release_slot_session(session
->op1
.session
);
457 /* Save the session */
458 session
->op1
.session
= init_session
;
459 session
->op1
.type
= optype
;
461 * The init.done flag will be checked by the meta_do_operation()
462 * to indicate whether the C_xxxInit has been done against
465 session
->init
.done
= B_TRUE
;
466 session
->init
.slotnum
= softtoken_slot_num
;
474 meta_GetThreshold(CK_MECHANISM_TYPE mechanism
)
479 for (i
= 0; i
< MAX_NUM_THRESHOLD
; i
++) {
480 if (mechanism
== meta_mechs_threshold
[i
].mech_type
)
481 return (meta_mechs_threshold
[i
].mech_threshold
);
484 /* no matching mechanism */
493 * 1) The spec says you cannot do a C_Encrypt after a C_EncUpdate,
494 * but we don't explicitly enforce it here (ie, disallow doing MODE_SINGLE
495 * after a MODE_UPDATE). Instead, we just assume the underlying provider
496 * will catch the problem and return an appropriate error.
498 * 2) Note that the Verify operations are a little unusual, due to the
499 * PKCS#11 API. For C_Verify, the last two arguments are used as inputs,
500 * unlike the other single pass operations (where they are outputs). For
501 * C_VerifyFinal, in/inLen are passed instead of out/outLen like the other
504 * 3) C_DigestKey is the only crypto operation that uses an object after
505 * the operation has been initialized. No other callers should provide
506 * this argument (use NULL).
509 meta_do_operation(CK_FLAGS optype
, int mode
,
510 meta_session_t
*session
, meta_object_t
*object
,
511 CK_BYTE
*in
, CK_ULONG inLen
, CK_BYTE
*out
, CK_ULONG
*outLen
)
514 CK_SESSION_HANDLE hSession
;
516 slot_session_t
*slot_session
= NULL
;
517 slot_object_t
*slot_object
= NULL
;
520 boolean_t shutdown
, finished_normally
;
523 * We've deferred the init for encrypt, decrypt and digest
524 * operations. As we know the size of the input data now, we
525 * can decide where to perform the real init operation based
526 * on the kernel cipher-specific thresholds for certain
527 * supported mechanisms.
529 if ((optype
== CKF_ENCRYPT
) || (optype
== CKF_DECRYPT
) ||
530 (optype
== CKF_DIGEST
)) {
531 if (Tmp_GetThreshold
!= NULL
) {
532 if (!session
->init
.app
) {
533 return (CKR_OPERATION_NOT_INITIALIZED
);
535 threshold
= meta_GetThreshold(
536 session
->init
.pMech
->mechanism
);
539 if ((threshold_chk_enabled
== B_FALSE
) || (inLen
> threshold
)) {
540 if ((session
->init
.app
) && (!session
->init
.done
)) {
542 * Call real init operation only if the
543 * application has called C_xxxInit
544 * but the real init operation has not
547 rv
= meta_operation_init(optype
,
548 session
->init
.session
,
553 } else if (!session
->init
.app
) {
555 * This checking detects the case that
556 * application calls C_En(De)Crypt/Digest
557 * directly without calling C_xxxInit.
559 return (CKR_OPERATION_NOT_INITIALIZED
);
563 * The size of the input data is smaller than the
564 * threshold so we'll use softoken to perform the
565 * crypto operation for better performance reason.
567 if ((session
->init
.app
) && (!session
->init
.done
)) {
569 * Call real init operation only if the
570 * application has called C_xxxInit
571 * but the real init operation has not
574 rv
= meta_operation_init_softtoken(optype
,
575 session
->init
.session
,
580 * In case the operation fails in
581 * softtoken, go back to use the
582 * original slot again.
584 rv
= meta_operation_init(optype
,
585 session
->init
.session
,
591 } else if (!session
->init
.app
) {
593 * This checking detects the case that
594 * application calls C_En(De)Crypt/Digest
595 * directly without calling C_xxxInit.
597 return (CKR_OPERATION_NOT_INITIALIZED
);
600 } else if (optype
!= session
->op1
.type
) {
601 return (CKR_OPERATION_NOT_INITIALIZED
);
604 slot_session
= session
->op1
.session
;
607 hSession
= slot_session
->hSession
;
608 fw_st_id
= slot_session
->fw_st_id
;
610 /* should never be here */
611 rv
= CKR_FUNCTION_FAILED
;
615 /* Do the operation... */
616 if (optype
== CKF_ENCRYPT
&& mode
== MODE_SINGLE
) {
617 rv
= FUNCLIST(fw_st_id
)->C_Encrypt(hSession
, in
,
619 } else if (optype
== CKF_ENCRYPT
&& mode
== MODE_UPDATE
) {
620 rv
= FUNCLIST(fw_st_id
)->C_EncryptUpdate(hSession
, in
,
622 } else if (optype
== CKF_ENCRYPT
&& mode
== MODE_FINAL
) {
623 rv
= FUNCLIST(fw_st_id
)->C_EncryptFinal(hSession
, out
,
626 } else if (optype
== CKF_DECRYPT
&& mode
== MODE_SINGLE
) {
627 rv
= FUNCLIST(fw_st_id
)->C_Decrypt(hSession
, in
,
629 } else if (optype
== CKF_DECRYPT
&& mode
== MODE_UPDATE
) {
630 rv
= FUNCLIST(fw_st_id
)->C_DecryptUpdate(hSession
, in
,
632 } else if (optype
== CKF_DECRYPT
&& mode
== MODE_FINAL
) {
633 rv
= FUNCLIST(fw_st_id
)->C_DecryptFinal(hSession
, out
,
636 } else if (optype
== CKF_DIGEST
&& mode
== MODE_SINGLE
) {
637 rv
= FUNCLIST(fw_st_id
)->C_Digest(hSession
, in
, inLen
,
639 } else if (optype
== CKF_DIGEST
&& mode
== MODE_UPDATE
) {
640 /* noOutputForOp = TRUE; */
641 rv
= FUNCLIST(fw_st_id
)->C_DigestUpdate(hSession
, in
,
643 } else if (optype
== CKF_DIGEST
&& mode
== MODE_UPDATE_WITHKEY
) {
644 /* noOutputForOp = TRUE; */
646 * For C_DigestKey, a key is provided and
649 rv
= meta_object_get_clone(object
,
650 slot_session
->slotnum
, slot_session
, &slot_object
);
652 rv
= FUNCLIST(fw_st_id
)->C_DigestKey(hSession
,
653 slot_object
->hObject
);
654 } else if (optype
== CKF_DIGEST
&& mode
== MODE_FINAL
) {
655 rv
= FUNCLIST(fw_st_id
)->C_DigestFinal(hSession
, out
,
658 } else if (optype
== CKF_SIGN
&& mode
== MODE_SINGLE
) {
659 rv
= FUNCLIST(fw_st_id
)->C_Sign(hSession
, in
, inLen
,
661 } else if (optype
== CKF_SIGN
&& mode
== MODE_UPDATE
) {
662 /* noOutputForOp = TRUE; */
663 rv
= FUNCLIST(fw_st_id
)->C_SignUpdate(hSession
, in
,
665 } else if (optype
== CKF_SIGN
&& mode
== MODE_FINAL
) {
666 rv
= FUNCLIST(fw_st_id
)->C_SignFinal(hSession
, out
,
669 } else if (optype
== CKF_VERIFY
&& mode
== MODE_SINGLE
) {
670 /* noOutputForOp = TRUE; */
671 /* Yes, use *outLen not outLen (think in2/in2Len) */
672 rv
= FUNCLIST(fw_st_id
)->C_Verify(hSession
, in
,
673 inLen
, out
, *outLen
);
674 } else if (optype
== CKF_VERIFY
&& mode
== MODE_UPDATE
) {
675 /* noOutputForOp = TRUE; */
676 rv
= FUNCLIST(fw_st_id
)->C_VerifyUpdate(hSession
, in
,
678 } else if (optype
== CKF_VERIFY
&& mode
== MODE_FINAL
) {
679 /* noOutputForOp = TRUE; */
680 /* Yes, use in/inLen instead of out/outLen */
681 rv
= FUNCLIST(fw_st_id
)->C_VerifyFinal(hSession
, in
,
684 } else if (optype
== CKF_SIGN_RECOVER
&& mode
== MODE_SINGLE
) {
685 rv
= FUNCLIST(fw_st_id
)->C_SignRecover(hSession
, in
,
687 } else if (optype
== CKF_VERIFY_RECOVER
&& mode
== MODE_SINGLE
) {
688 rv
= FUNCLIST(fw_st_id
)->C_VerifyRecover(hSession
, in
,
692 rv
= CKR_FUNCTION_FAILED
;
697 * Mark the operation type as inactive if an abnormal error
698 * happens, or if the operation normally results in an inactive
701 * NOTE: The spec isn't very explicit about what happens when you
702 * call C_FooFinal (or C_Foo) with a NULL output buffer (to get the
703 * output size), but there is no output. Technically this should be
704 * no different than the normal case (ie, when there is output), and
705 * the operation should remain active until the second call actually
706 * terminates it. However, one could make the case that there is no
707 * need for a second call, since no data is available. This presents
708 * dilemma for metaslot, because we don't know if the operation is
709 * going to remain active or not. We will assume a strict reading of
710 * the spec, the operation will remain active.
713 if (rv
== CKR_BUFFER_TOO_SMALL
||
714 (rv
== CKR_OK
&& out
== NULL
&& optype
!= CKF_VERIFY
)) {
715 /* Leave op active for retry (with larger buffer). */
717 } else if (rv
!= CKR_OK
) {
719 finished_normally
= B_FALSE
;
720 } else { /* CKR_OK */
721 if (mode
== MODE_SINGLE
|| mode
== MODE_FINAL
) {
723 finished_normally
= B_TRUE
;
724 } else { /* mode == MODE_UPDATE */
730 if (mode
== MODE_SINGLE
|| mode
== MODE_FINAL
) {
731 session
->init
.app
= B_FALSE
;
734 meta_operation_cleanup(session
, optype
, finished_normally
);
741 free_session_mechanism(meta_session_t
*session
)
743 if (session
->init
.pMech
!= NULL
) {
744 if (session
->init
.pMech
->pParameter
!= NULL
) {
745 free(session
->init
.pMech
->pParameter
);
746 session
->init
.pMech
->pParameter
= NULL
;
747 session
->init
.pMech
->ulParameterLen
= 0;
749 free(session
->init
.pMech
);
750 session
->init
.pMech
= NULL
;
755 * meta_operation_cleanup
757 * Cleans up an operation in the specified session.
758 * If the operation did not finish normally, it will force
759 * the operation to terminate.
762 meta_operation_cleanup(meta_session_t
*session
, CK_FLAGS optype
,
763 boolean_t finished_normally
)
765 operation_info_t
*op
;
766 CK_SESSION_HANDLE hSession
;
769 if (!finished_normally
) {
770 CK_BYTE dummy_buf
[8];
772 if (session
->op1
.type
== optype
) {
775 if ((optype
== CKF_ENCRYPT
) ||
776 (optype
== CKF_DECRYPT
) ||
777 (optype
== CKF_DIGEST
)) {
778 session
->op1
.type
= 0;
779 session
->init
.app
= B_FALSE
;
780 session
->init
.done
= B_FALSE
;
781 free_session_mechanism(session
);
786 hSession
= op
->session
->hSession
;
787 fw_st_id
= op
->session
->fw_st_id
;
790 * There's no simple, reliable way to abort an
791 * operation. So, we'll force the operation to finish.
793 * We are here either because we need to abort either after
794 * C_xxxxxInit() or C_xxxxxUpdate().
796 * We will call C_xxxxxUpdate() with invalid argument to
797 * force the operation to abort. According to the PKCS#11
798 * spec, any call to C_xxxxxUpdate() returns in an error
799 * will terminate the current operation.
804 (void) FUNCLIST(fw_st_id
)->C_EncryptUpdate(hSession
,
805 NULL
, 8, dummy_buf
, NULL
);
808 (void) FUNCLIST(fw_st_id
)->C_DecryptUpdate(hSession
,
809 NULL
, 8, dummy_buf
, NULL
);
812 (void) FUNCLIST(fw_st_id
)->C_DigestUpdate(hSession
,
816 (void) FUNCLIST(fw_st_id
)->C_SignUpdate(hSession
,
819 case CKF_SIGN_RECOVER
:
820 (void) FUNCLIST(fw_st_id
)->C_SignRecover(hSession
,
821 NULL
, 8, dummy_buf
, NULL
);
824 (void) FUNCLIST(fw_st_id
)->C_VerifyUpdate(hSession
,
827 case CKF_VERIFY_RECOVER
:
828 (void) FUNCLIST(fw_st_id
)->C_VerifyRecover(hSession
,
829 NULL
, 8, dummy_buf
, NULL
);
835 meta_release_slot_session(session
->op1
.session
);
836 session
->op1
.session
= NULL
;
839 if ((optype
== CKF_ENCRYPT
) || (optype
== CKF_DECRYPT
) ||
840 (optype
== CKF_DIGEST
)) {
841 session
->init
.done
= B_FALSE
;
842 free_session_mechanism(session
);
844 session
->op1
.type
= 0;
848 * Gets the list of slots that supports the specified mechanism.
850 * If "token_only", check if the keystore slot supports the specified mech,
851 * if so, return that slot only
853 * Otherwise, get list of all slots that support the mech.
857 get_slotlist_for_mech(CK_MECHANISM_TYPE mech_type
,
858 mech_support_info_t
*mech_support_info
,
859 mechinfo_t
***slots
, unsigned long *slot_count
, boolean_t token_only
,
860 CK_MECHANISM_INFO
*mech_info
)
862 boolean_t mech_supported
= B_FALSE
;
866 rv
= meta_mechManager_slot_supports_mech(mech_type
,
867 get_keystore_slotnum(), &mech_supported
,
868 &((mech_support_info
->supporting_slots
)[0]), B_FALSE
,
875 if (mech_supported
) {
876 mech_support_info
->mech
= mech_type
;
878 * Want to leave this at 0, that way, when
879 * other operation needs to
880 * use this mechanism, but not just for the
881 * keystore slot, we will look at other slots
883 mech_support_info
->num_supporting_slots
= 0;
884 *slots
= mech_support_info
->supporting_slots
;
887 rv
= CKR_FUNCTION_FAILED
;
891 * Get a list of slots that support this mech .
893 * If the specified mechanism is used last time,
894 * the list of capable slots is already retrieved.
895 * We can save some processing, and just use that list of slots.
897 if ((mech_support_info
->mech
!= mech_type
) ||
898 (mech_support_info
->num_supporting_slots
== 0)) {
899 mech_support_info
->mech
= mech_type
;
900 rv
= meta_mechManager_get_slots(mech_support_info
,
903 return (CKR_FUNCTION_FAILED
);
906 *slots
= mech_support_info
->supporting_slots
;
907 *slot_count
= mech_support_info
->num_supporting_slots
;
915 * Generates symmetric (k1=key, k2=null) or asymmetric (k1=pub, k2=priv) keys.
919 meta_generate_keys(meta_session_t
*session
, CK_MECHANISM
*pMechanism
,
920 CK_ATTRIBUTE
*k1Template
, CK_ULONG k1AttrCount
, meta_object_t
*key1
,
921 CK_ATTRIBUTE
*k2Template
, CK_ULONG k2AttrCount
, meta_object_t
*key2
)
924 slot_session_t
*gen_session
= NULL
;
925 slot_object_t
*slot_key1
= NULL
, *slot_key2
= NULL
;
926 mechinfo_t
**slots
= NULL
;
927 unsigned long i
, slotCount
= 0;
928 boolean_t doKeyPair
= B_FALSE
, token_only
= B_FALSE
;
930 CK_MECHANISM_INFO mech_info
;
932 * Since the keygen call is in a loop, it is performance-wise useful
933 * to keep track of the token value
935 CK_BBOOL current_token1_value
= FALSE
, current_token2_value
= FALSE
;
937 (void) get_template_boolean(CKA_TOKEN
, k1Template
, k1AttrCount
,
939 (void) get_template_boolean(CKA_SENSITIVE
, k1Template
, k1AttrCount
,
940 &(key1
->isSensitive
));
941 (void) get_template_boolean(CKA_PRIVATE
, k1Template
, k1AttrCount
,
944 if (!get_template_boolean(CKA_EXTRACTABLE
, k1Template
, k1AttrCount
,
945 &(key1
->isExtractable
)))
946 key1
->isExtractable
= B_TRUE
;
949 current_token1_value
= TRUE
;
951 mech_info
.flags
= CKF_GENERATE
;
954 (void) get_template_boolean(CKA_TOKEN
, k2Template
, k2AttrCount
,
956 (void) get_template_boolean(CKA_SENSITIVE
, k2Template
,
957 k2AttrCount
, &(key2
->isSensitive
));
958 (void) get_template_boolean(CKA_PRIVATE
, k2Template
,
959 k2AttrCount
, &(key2
->isPrivate
));
961 if (!get_template_boolean(CKA_EXTRACTABLE
, k2Template
,
962 k2AttrCount
, &(key2
->isExtractable
)))
963 key2
->isExtractable
= B_TRUE
;
966 current_token2_value
= TRUE
;
969 mech_info
.flags
= CKF_GENERATE_KEY_PAIR
;
973 /* Can't create token objects in a read-only session. */
974 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
975 ((key1
->isToken
) || ((key2
) && (key2
->isToken
)))) {
976 return (CKR_SESSION_READ_ONLY
);
979 if (meta_freeobject_check(session
, key1
, pMechanism
, k1Template
,
980 k1AttrCount
, NULL
)) {
982 if ((key1
->isPrivate
|| (doKeyPair
&& key2
->isPrivate
)) &&
983 !metaslot_logged_in())
984 return (CKR_USER_NOT_LOGGED_IN
);
986 if (!meta_freeobject_set(key1
, k1Template
, k1AttrCount
,
988 return (CKR_FUNCTION_FAILED
);
991 key2
->isFreeObject
= FREE_ALLOWED_KEY
;
992 if (!meta_freeobject_set(key2
, k2Template
, k2AttrCount
,
994 return (CKR_FUNCTION_FAILED
);
997 } else if (doKeyPair
) {
999 * If this is a keypair operation, the second key cannot be
1000 * a FreeObject if the first is not. Both keys will have the
1001 * same fate when it comes to provider choices
1003 key2
->isFreeObject
= FREE_DISABLED
;
1004 key2
->isFreeToken
= FREE_DISABLED
;
1007 if ((key1
->isToken
) || ((doKeyPair
) && (key2
->isToken
))) {
1009 * Token objects can only be generated in the token object
1010 * slot. If token object slot doesn't support generating
1011 * the key, it will just not be done.
1013 token_only
= B_TRUE
;
1016 rv
= get_slotlist_for_mech(pMechanism
->mechanism
,
1017 &(session
->mech_support_info
), &slots
, &slotCount
, token_only
,
1024 rv
= meta_slot_object_alloc(&slot_key1
);
1025 if (doKeyPair
&& rv
== CKR_OK
)
1026 rv
= meta_slot_object_alloc(&slot_key2
);
1030 /* Attempt to generate key on slots until one succeeds. */
1031 for (i
= 0; i
< slotCount
; i
++) {
1032 CK_SESSION_HANDLE hSession
;
1033 CK_SLOT_ID fw_st_id
;
1037 slotnum
= slots
[i
]->slotnum
;
1039 if (session
->op1
.session
!= NULL
) {
1040 if ((session
->op1
.session
)->slotnum
== slotnum
) {
1041 gen_session
= session
->op1
.session
;
1043 * set it to NULL for now, assign it to
1044 * gen_session again if it is successful
1046 session
->op1
.session
= NULL
;
1052 if (gen_session
== NULL
) {
1053 rv
= meta_get_slot_session(slotnum
, &gen_session
,
1054 session
->session_flags
);
1061 * If this is a freetoken, make sure the templates are
1062 * approriate for the slot being used.
1064 if (key1
->isFreeToken
== FREE_ENABLED
) {
1065 rv
= meta_freetoken_set(slotnum
,
1066 ¤t_token1_value
, k1Template
, k1AttrCount
);
1071 if (doKeyPair
&& key2
->isFreeToken
== FREE_ENABLED
) {
1072 rv
= meta_freetoken_set(slotnum
,
1073 ¤t_token2_value
, k2Template
, k2AttrCount
);
1078 fw_st_id
= gen_session
->fw_st_id
;
1079 hSession
= gen_session
->hSession
;
1082 rv
= FUNCLIST(fw_st_id
)->C_GenerateKeyPair(hSession
,
1083 pMechanism
, k1Template
, k1AttrCount
,
1084 k2Template
, k2AttrCount
,
1085 &slot_key1
->hObject
, &slot_key2
->hObject
);
1087 rv
= FUNCLIST(fw_st_id
)->C_GenerateKey(hSession
,
1088 pMechanism
, k1Template
, k1AttrCount
,
1089 &slot_key1
->hObject
);
1101 meta_release_slot_session(gen_session
);
1110 rv
= meta_object_get_attr(gen_session
, slot_key1
->hObject
, key1
);
1116 rv
= meta_object_get_attr(gen_session
, slot_key2
->hObject
,
1123 /* Allow FreeToken to activate onto token obj list */
1124 if (key1
->isFreeToken
== FREE_ENABLED
)
1125 key1
->isToken
= B_TRUE
;
1127 meta_slot_object_activate(slot_key1
, gen_session
, key1
->isToken
);
1128 key1
->clones
[slotnum
] = slot_key1
;
1129 key1
->master_clone_slotnum
= slotnum
;
1131 if (key1
->isFreeObject
== FREE_ENABLED
) {
1132 rv
= meta_freeobject_clone(session
, key1
);
1138 /* Allow FreeToken to activate onto token obj list */
1139 if (key2
->isFreeToken
== FREE_ENABLED
)
1140 key2
->isToken
= B_TRUE
;
1142 meta_slot_object_activate(slot_key2
, gen_session
,
1144 key2
->clones
[slotnum
] = slot_key2
;
1145 key2
->master_clone_slotnum
= slotnum
;
1147 if (key2
->isFreeObject
== FREE_ENABLED
) {
1148 rv
= meta_freeobject_clone(session
, key2
);
1156 meta_slot_object_dealloc(slot_key1
);
1160 meta_slot_object_dealloc(slot_key2
);
1163 /* Save the session in case it can be used later */
1166 * If currently stored session is not the one being in use now,
1167 * release the previous one and store the current one
1169 if ((session
->op1
.session
) &&
1170 (session
->op1
.session
!= gen_session
)) {
1171 meta_release_slot_session(session
->op1
.session
);
1174 /* Save the session */
1175 session
->op1
.session
= gen_session
;
1187 meta_wrap_key(meta_session_t
*session
, CK_MECHANISM
*pMechanism
,
1188 meta_object_t
*wrappingkey
, meta_object_t
*inputkey
, CK_BYTE
*wrapped_key
,
1189 CK_ULONG
*wrapped_key_len
)
1192 slot_session_t
*wrap_session
= NULL
;
1193 slot_object_t
*slot_wrappingkey
, *slot_inputkey
;
1194 mechinfo_t
**slots
= NULL
;
1195 unsigned long i
, slotCount
= 0;
1197 CK_MECHANISM_INFO mech_info
;
1200 * If the key to be wrapped is a token object,
1201 * the operation can only be done in the token object slot.
1203 mech_info
.flags
= CKF_WRAP
;
1204 rv
= get_slotlist_for_mech(pMechanism
->mechanism
,
1205 &(session
->mech_support_info
), &slots
, &slotCount
,
1206 inputkey
->isToken
, &mech_info
);
1212 /* Attempt to wrap key on slots until one succeeds. */
1213 for (i
= 0; i
< slotCount
; i
++) {
1215 slotnum
= slots
[i
]->slotnum
;
1216 wrap_session
= NULL
;
1218 if (session
->op1
.session
!= NULL
) {
1219 if ((session
->op1
.session
)->slotnum
== slotnum
) {
1220 wrap_session
= session
->op1
.session
;
1222 * set it to NULL for now, assign it to
1223 * wrap_session again if it is successful
1225 session
->op1
.session
= NULL
;
1227 wrap_session
= NULL
;
1231 if (wrap_session
== NULL
) {
1232 rv
= meta_get_slot_session(slotnum
, &wrap_session
,
1233 session
->session_flags
);
1239 rv
= meta_object_get_clone(wrappingkey
, slotnum
,
1240 wrap_session
, &slot_wrappingkey
);
1244 rv
= meta_object_get_clone(inputkey
, slotnum
,
1245 wrap_session
, &slot_inputkey
);
1249 rv
= FUNCLIST(wrap_session
->fw_st_id
)->C_WrapKey(
1250 wrap_session
->hSession
, pMechanism
,
1251 slot_wrappingkey
->hObject
, slot_inputkey
->hObject
,
1252 wrapped_key
, wrapped_key_len
);
1254 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
1263 meta_release_slot_session(wrap_session
);
1264 wrap_session
= NULL
;
1268 if (rv
!= CKR_BUFFER_TOO_SMALL
) {
1269 if (i
== slotCount
) {
1276 /* Save the session in case it can be used later */
1279 * If currently stored session is not the one being in use now,
1280 * release the previous one and store the current one
1282 if ((session
->op1
.session
) &&
1283 (session
->op1
.session
!= wrap_session
)) {
1284 meta_release_slot_session(session
->op1
.session
);
1287 /* Save the session */
1288 session
->op1
.session
= wrap_session
;
1300 meta_unwrap_key(meta_session_t
*session
,
1301 CK_MECHANISM
*pMechanism
, meta_object_t
*unwrapping_key
,
1302 CK_BYTE
*wrapped_key
, CK_ULONG wrapped_key_len
,
1303 CK_ATTRIBUTE
*template, CK_ULONG template_size
,
1304 meta_object_t
*unwrapped_key
)
1307 CK_OBJECT_HANDLE hUnwrappedKey
;
1308 slot_session_t
*unwrap_session
= NULL
;
1309 slot_object_t
*slot_unwrappingkey
, *slot_unwrapped_key
;
1310 mechinfo_t
**slots
= NULL
;
1311 unsigned long i
, slotCount
= 0;
1313 CK_MECHANISM_INFO mech_info
;
1315 /* Can't create token objects in a read-only session. */
1316 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
1317 unwrapped_key
->isToken
) {
1318 return (CKR_SESSION_READ_ONLY
);
1322 * If the the resulting unwrapped key
1323 * needs to be a token object, the operation can only
1324 * be performed in the token slot, if it is supported.
1326 mech_info
.flags
= CKF_UNWRAP
;
1327 rv
= get_slotlist_for_mech(pMechanism
->mechanism
,
1328 &(session
->mech_support_info
), &slots
, &slotCount
,
1329 unwrapped_key
->isToken
, &mech_info
);
1335 rv
= meta_slot_object_alloc(&slot_unwrapped_key
);
1340 /* Attempt to unwrap key on slots until one succeeds. */
1341 for (i
= 0; i
< slotCount
; i
++) {
1343 slotnum
= slots
[i
]->slotnum
;
1344 unwrap_session
= NULL
;
1346 if (session
->op1
.session
!= NULL
) {
1347 if ((session
->op1
.session
)->slotnum
== slotnum
) {
1348 unwrap_session
= session
->op1
.session
;
1350 * set it to NULL for now, assign it to
1351 * unwrap_session again if it is successful
1353 session
->op1
.session
= NULL
;
1355 unwrap_session
= NULL
;
1359 if (unwrap_session
== NULL
) {
1360 rv
= meta_get_slot_session(slotnum
, &unwrap_session
,
1361 session
->session_flags
);
1367 rv
= meta_object_get_clone(unwrapping_key
, slotnum
,
1368 unwrap_session
, &slot_unwrappingkey
);
1372 rv
= FUNCLIST(unwrap_session
->fw_st_id
)->C_UnwrapKey(
1373 unwrap_session
->hSession
, pMechanism
,
1374 slot_unwrappingkey
->hObject
, wrapped_key
, wrapped_key_len
,
1375 template, template_size
, &hUnwrappedKey
);
1377 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
1384 if (unwrap_session
) {
1385 meta_release_slot_session(unwrap_session
);
1386 unwrap_session
= NULL
;
1392 if (rv
!= CKR_BUFFER_TOO_SMALL
) {
1399 slot_unwrapped_key
->hObject
= hUnwrappedKey
;
1400 unwrapped_key
->clones
[slotnum
] = slot_unwrapped_key
;
1401 unwrapped_key
->master_clone_slotnum
= slotnum
;
1402 rv
= meta_object_get_attr(unwrap_session
,
1403 slot_unwrapped_key
->hObject
, unwrapped_key
);
1407 meta_slot_object_activate(slot_unwrapped_key
, unwrap_session
,
1408 unwrapped_key
->isToken
);
1409 slot_unwrapped_key
= NULL
;
1412 if (slot_unwrapped_key
) {
1413 meta_slot_object_dealloc(slot_unwrapped_key
);
1416 /* Save the session in case it can be used later */
1419 * If currently stored session is not the one being in use now,
1420 * release the previous one and store the current one
1422 if ((session
->op1
.session
) &&
1423 (session
->op1
.session
!= unwrap_session
)) {
1424 meta_release_slot_session(session
->op1
.session
);
1427 /* Save the session */
1428 session
->op1
.session
= unwrap_session
;
1438 * Core implementation for C_DeriveKey. This function is a bit gross because
1439 * of PKCS#11 kludges that pass extra object handles in the mechanism
1440 * parameters. Normally C_DeriveKey takes a single existing key as input,
1441 * and creates a single new key as output. But a few mechanisms take 2 keys
1442 * as input, and the two SSL/TLS mechanisms create 4 keys as output.
1444 * When an extra input key (basekey2) is set, we set *phBaseKey2 to the clone's
1445 * object handle. phBaseKey2 is provided by the caller so we don't have to
1446 * trudge down into different mechanism parameters to set it when issuing the
1449 * For the SSL/TLS mechanisms, newKey2/newKey3/newKey4 will be set. We pull
1450 * the new handles from pMech->pParameter in order to fill in the appropriate
1451 * meta_object fields.
1454 meta_derive_key(meta_session_t
*session
, CK_MECHANISM
*pMechanism
,
1455 meta_object_t
*basekey1
, meta_object_t
*basekey2
,
1456 CK_OBJECT_HANDLE
*phBaseKey2
,
1457 CK_ATTRIBUTE
*pTemplate
, CK_ULONG ulAttributeCount
,
1458 meta_object_t
*newKey1
, meta_object_t
*newKey2
,
1459 meta_object_t
*newKey3
, meta_object_t
*newKey4
)
1462 CK_OBJECT_HANDLE hDerivedKey
;
1465 boolean_t isSSL
= B_FALSE
;
1466 boolean_t isTLSPRF
= B_FALSE
;
1467 mechinfo_t
**slots
= NULL
;
1468 unsigned long i
, slot_count
= 0;
1469 slot_session_t
*derive_session
= NULL
;
1470 slot_object_t
*slot_basekey1
= NULL
, *slot_basekey2
= NULL
;
1471 slot_object_t
*slotkey1
= NULL
, *slotkey2
= NULL
, *slotkey3
= NULL
,
1473 CK_MECHANISM_INFO mech_info
;
1474 CK_BBOOL current_token_value
= FALSE
;
1477 * if the derived key needs to be a token object, can only
1478 * perform the derive operation in the token slot
1480 (void) get_template_boolean(CKA_TOKEN
, pTemplate
, ulAttributeCount
,
1481 &(newKey1
->isToken
));
1482 (void) get_template_boolean(CKA_PRIVATE
, pTemplate
, ulAttributeCount
,
1483 &(newKey1
->isPrivate
));
1484 (void) get_template_boolean(CKA_SENSITIVE
, pTemplate
, ulAttributeCount
,
1485 &(newKey1
->isSensitive
));
1487 if (newKey1
->isToken
)
1488 current_token_value
= TRUE
;
1490 /* Can't create token objects in a read-only session. */
1491 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
1493 rv
= CKR_SESSION_READ_ONLY
;
1497 if (meta_freeobject_check(session
, newKey1
, pMechanism
, pTemplate
,
1498 ulAttributeCount
, NULL
)) {
1500 if (newKey1
->isPrivate
&& !metaslot_logged_in())
1501 return (CKR_USER_NOT_LOGGED_IN
);
1503 if (!meta_freeobject_set(newKey1
, pTemplate
, ulAttributeCount
,
1505 return (CKR_FUNCTION_FAILED
);
1508 mech_info
.flags
= CKF_DERIVE
;
1509 rv
= get_slotlist_for_mech(pMechanism
->mechanism
,
1510 &(session
->mech_support_info
), &slots
, &slot_count
,
1511 newKey1
->isToken
, &mech_info
);
1517 if (pMechanism
->mechanism
== CKM_SSL3_KEY_AND_MAC_DERIVE
||
1518 pMechanism
->mechanism
== CKM_TLS_KEY_AND_MAC_DERIVE
)
1521 else if (pMechanism
->mechanism
== CKM_TLS_PRF
)
1524 rv
= meta_slot_object_alloc(&slotkey1
);
1527 rv
= meta_slot_object_alloc(&slotkey2
);
1529 rv
= meta_slot_object_alloc(&slotkey3
);
1531 rv
= meta_slot_object_alloc(&slotkey4
);
1537 for (i
= 0; i
< slot_count
; i
++) {
1538 slotnum
= slots
[i
]->slotnum
;
1540 derive_session
= NULL
;
1542 if (session
->op1
.session
!= NULL
) {
1543 if ((session
->op1
.session
)->slotnum
== slotnum
) {
1544 derive_session
= session
->op1
.session
;
1546 * set it to NULL for now, assign it to
1547 * derive_session again if it is successful
1549 session
->op1
.session
= NULL
;
1551 derive_session
= NULL
;
1555 if (derive_session
== NULL
) {
1556 rv
= meta_get_slot_session(slotnum
, &derive_session
,
1557 session
->session_flags
);
1563 rv
= meta_object_get_clone(basekey1
, slotnum
,
1564 derive_session
, &slot_basekey1
);
1569 rv
= meta_object_get_clone(basekey2
, slotnum
,
1570 derive_session
, &slot_basekey2
);
1574 /* Pass the handle somewhere in the mech params. */
1575 *phBaseKey2
= slot_basekey2
->hObject
;
1578 if (newKey1
->isFreeToken
== FREE_ENABLED
) {
1579 rv
= meta_freetoken_set(slotnum
, ¤t_token_value
,
1580 pTemplate
, ulAttributeCount
);
1585 rv
= FUNCLIST(derive_session
->fw_st_id
)->C_DeriveKey(
1586 derive_session
->hSession
, pMechanism
,
1587 slot_basekey1
->hObject
, pTemplate
, ulAttributeCount
,
1588 (isSSL
|| isTLSPRF
) ? NULL
: &hDerivedKey
);
1597 if (derive_session
) {
1598 meta_release_slot_session(derive_session
);
1599 derive_session
= NULL
;
1601 /* No need to cleanup clones, so we can reuse them later. */
1613 * These SSL/TLS are unique in that the parameter in the API for
1614 * the new key is unused (NULL). Instead, there are 4 keys which
1615 * are derived, and are passed back through the mechanism params.
1616 * Both mechs use the same mechanism parameter type.
1619 CK_SSL3_KEY_MAT_PARAMS
*keyparams
;
1620 CK_SSL3_KEY_MAT_OUT
*keys
;
1622 /* NULL checks already done by caller */
1623 keyparams
= (CK_SSL3_KEY_MAT_PARAMS
*)pMechanism
->pParameter
;
1624 keys
= keyparams
->pReturnedKeyMaterial
;
1626 slotkey1
->hObject
= keys
->hClientMacSecret
;
1627 slotkey2
->hObject
= keys
->hServerMacSecret
;
1628 slotkey3
->hObject
= keys
->hClientKey
;
1629 slotkey4
->hObject
= keys
->hServerKey
;
1631 rv
= meta_object_get_attr(derive_session
,
1632 slotkey1
->hObject
, newKey1
);
1637 rv
= meta_object_get_attr(derive_session
,
1638 slotkey2
->hObject
, newKey2
);
1643 rv
= meta_object_get_attr(derive_session
,
1644 slotkey3
->hObject
, newKey3
);
1649 rv
= meta_object_get_attr(derive_session
,
1650 slotkey4
->hObject
, newKey4
);
1655 newKey1
->clones
[slotnum
] = slotkey1
;
1656 newKey2
->clones
[slotnum
] = slotkey2
;
1657 newKey3
->clones
[slotnum
] = slotkey3
;
1658 newKey4
->clones
[slotnum
] = slotkey4
;
1660 newKey1
->master_clone_slotnum
= slotnum
;
1661 newKey2
->master_clone_slotnum
= slotnum
;
1662 newKey3
->master_clone_slotnum
= slotnum
;
1663 newKey4
->master_clone_slotnum
= slotnum
;
1665 meta_slot_object_activate(slotkey1
, derive_session
,
1668 meta_slot_object_activate(slotkey2
, derive_session
,
1671 meta_slot_object_activate(slotkey3
, derive_session
,
1674 meta_slot_object_activate(slotkey4
, derive_session
,
1679 slotkey1
->hObject
= hDerivedKey
;
1680 newKey1
->clones
[slotnum
] = slotkey1
;
1681 newKey1
->master_clone_slotnum
= slotnum
;
1683 rv
= meta_object_get_attr(derive_session
,
1684 slotkey1
->hObject
, newKey1
);
1689 /* Allow FreeToken to activate onto token obj list */
1690 if (newKey1
->isFreeToken
== FREE_ENABLED
)
1691 newKey1
->isToken
= B_TRUE
;
1693 meta_slot_object_activate(slotkey1
, derive_session
,
1698 if (newKey1
->isFreeObject
== FREE_ENABLED
)
1699 (void) meta_freeobject_clone(session
, newKey1
);
1704 meta_slot_object_dealloc(slotkey1
);
1707 meta_slot_object_dealloc(slotkey2
);
1710 meta_slot_object_dealloc(slotkey3
);
1713 meta_slot_object_dealloc(slotkey4
);
1716 /* Save the session in case it can be used later */
1719 * If currently stored session is not the one being in use now,
1720 * release the previous one and store the current one
1722 if ((session
->op1
.session
) &&
1723 (session
->op1
.session
!= derive_session
)) {
1724 meta_release_slot_session(session
->op1
.session
);
1727 /* Save the session */
1728 session
->op1
.session
= derive_session
;
1736 * Check the following 4 environment variables for user/application's
1737 * configuration for metaslot. User's configuration takes precedence
1738 * over the system wide configuration for metaslot
1740 * ${METASLOT_ENABLED}
1741 * ${METASLOT_OBJECTSTORE_SLOT}
1742 * ${METASLOT_OBJECTSTORE_TOKEN}
1743 * ${METASLOT_AUTO_KEY_MIGRATE}
1745 * ${_METASLOT_ENABLE_THRESHOLD} - private environmental variable to
1746 * enable the treshold checking which is disabled by default.
1748 * values defined in these environment variables will be stored in the
1749 * global variable "metaslot_config". Variable threshold_chk_disabled is an
1753 get_user_metaslot_config()
1755 char *env_val
= NULL
;
1758 * Check to see if any environment variable is defined
1759 * by the user for configuring metaslot.
1761 bzero(&metaslot_config
, sizeof (metaslot_config
));
1763 /* METASLOT_ENABLED */
1764 env_val
= getenv("METASLOT_ENABLED");
1766 metaslot_config
.enabled_specified
= B_TRUE
;
1767 if (strcasecmp(env_val
, TRUE_STRING
) == 0) {
1768 metaslot_config
.enabled
= B_TRUE
;
1769 } else if (strcasecmp(env_val
, FALSE_STRING
) == 0) {
1770 metaslot_config
.enabled
= B_FALSE
;
1772 /* value is neither 1 or 0, ignore this value */
1773 metaslot_config
.enabled_specified
= B_FALSE
;
1777 /* METASLOT_AUTO_KEY_MIGRATE */
1778 env_val
= getenv("METASLOT_AUTO_KEY_MIGRATE");
1780 metaslot_config
.auto_key_migrate_specified
= B_TRUE
;
1781 if (strcasecmp(env_val
, TRUE_STRING
) == 0) {
1782 metaslot_config
.auto_key_migrate
= B_TRUE
;
1783 } else if (strcasecmp(env_val
, FALSE_STRING
) == 0) {
1784 metaslot_config
.auto_key_migrate
= B_FALSE
;
1786 /* value is neither 1 or 0, ignore this value */
1787 metaslot_config
.auto_key_migrate_specified
= B_FALSE
;
1791 /* METASLOT_OBJECTSTORE_SLOT */
1792 env_val
= getenv("METASLOT_OBJECTSTORE_SLOT");
1794 metaslot_config
.keystore_slot_specified
= B_TRUE
;
1795 (void) strlcpy((char *)metaslot_config
.keystore_slot
, env_val
,
1796 SLOT_DESCRIPTION_SIZE
);
1799 /* METASLOT_OBJECTSTORE_TOKEN */
1800 env_val
= getenv("METASLOT_OBJECTSTORE_TOKEN");
1802 metaslot_config
.keystore_token_specified
= B_TRUE
;
1803 (void) strlcpy((char *)metaslot_config
.keystore_token
, env_val
,
1807 /* _METASLOT_ENABLE_THRESHOLD */
1808 env_val
= getenv("_METASLOT_ENABLE_THRESHOLD");
1810 threshold_chk_enabled
= B_TRUE
;