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 free(session
->init
.pMech
->pParameter
);
69 session
->init
.pMech
->pParameter
=
70 malloc(pMechanism
->ulParameterLen
);
71 if (session
->init
.pMech
->pParameter
== NULL
) {
72 free(session
->init
.pMech
);
73 session
->init
.pMech
= NULL
;
74 return (CKR_HOST_MEMORY
);
76 } /* otherwise reuse it */
77 (void) memcpy(session
->init
.pMech
->pParameter
,
78 pMechanism
->pParameter
, pMechanism
->ulParameterLen
);
81 * free the previous pParameter if not yet freed
82 * because we don't need it now.
84 if (session
->init
.pMech
->pParameter
!= NULL
) {
85 free(session
->init
.pMech
->pParameter
);
86 session
->init
.pMech
->pParameter
= NULL
;
89 /* copy the rest of data */
90 session
->init
.pMech
->mechanism
=
91 pMechanism
->mechanism
;
92 session
->init
.pMech
->ulParameterLen
=
93 pMechanism
->ulParameterLen
;
96 session
->init
.session
= session
;
97 session
->init
.optype
= optype
;
98 session
->init
.key
= key
;
99 session
->init
.done
= B_FALSE
;
100 session
->init
.app
= B_TRUE
;
105 * meta_operation_init
109 meta_operation_init(CK_FLAGS optype
, meta_session_t
*session
,
110 CK_MECHANISM
*pMechanism
, meta_object_t
*key
)
113 mechinfo_t
**supporting_slots
;
115 unsigned long i
, slotCount
= 0;
116 slot_session_t
*init_session
= NULL
;
117 CK_MECHANISM_INFO mech_info
;
120 * If an operation is already active, cleanup existing operation
121 * and start a new one.
123 if (session
->op1
.type
!= 0) {
125 if ((optype
== CKF_ENCRYPT
) || (optype
== CKF_DECRYPT
) ||
126 (optype
== CKF_DIGEST
)) {
129 if ((pMechanism
->ulParameterLen
> 0) &&
130 (pMechanism
->pParameter
!= NULL
)) {
132 malloc(pMechanism
->ulParameterLen
);
133 if (mech
.pParameter
== NULL
) {
134 return (CKR_HOST_MEMORY
);
136 (void) memcpy(mech
.pParameter
,
137 pMechanism
->pParameter
,
138 pMechanism
->ulParameterLen
);
140 mech
.pParameter
= NULL
;
141 mech
.ulParameterLen
= 0;
144 meta_operation_cleanup(session
, session
->op1
.type
,
146 rv
= meta_operation_init_defer(optype
, session
,
148 if (mech
.pParameter
!= NULL
) {
149 free(mech
.pParameter
);
154 meta_operation_cleanup(session
, session
->op1
.type
,
160 mech_info
.flags
= optype
;
163 * Get a list of capable slots.
165 * If the specified mechanism is used in this session last time,
166 * the list of capable slots is already retrieved. We can save
167 * some processing, and just use that list of slots.
169 if (((session
->mech_support_info
).mech
!= pMechanism
->mechanism
) ||
170 ((session
->mech_support_info
).num_supporting_slots
== 0)) {
171 (session
->mech_support_info
).mech
= pMechanism
->mechanism
;
172 rv
= meta_mechManager_get_slots(&(session
->mech_support_info
),
173 B_FALSE
, &mech_info
);
179 rv
= CKR_FUNCTION_FAILED
;
181 /* The following 2 assignment is just to make the code more readable */
182 slotCount
= (session
->mech_support_info
).num_supporting_slots
;
183 supporting_slots
= (session
->mech_support_info
).supporting_slots
;
185 /* Attempt to initialize operation on slots until one succeeds. */
186 for (i
= 0; i
< slotCount
; i
++) {
187 slot_object_t
*init_key
;
192 slotnum
= supporting_slots
[i
]->slotnum
;
195 * An actual session with the underlying slot is required
196 * for the operation. When the operation is successfully
197 * completed, the underlying session with the slot
198 * is not released back to the list of available sessions
199 * pool. This will help if the next operation can
200 * also be done on the same slot, because it avoids
201 * one extra trip to the session pool to get an idle session.
202 * If the operation can't be done on that slot,
203 * we release the session back to the session pool then.
205 if (session
->op1
.session
!= NULL
) {
207 if ((session
->op1
.session
)->slotnum
== slotnum
) {
208 init_session
= session
->op1
.session
;
210 * set it to NULL for now, assign it to
211 * init_session again if it is successful
213 session
->op1
.session
= NULL
;
221 rv
= meta_get_slot_session(slotnum
, &init_session
,
222 session
->session_flags
);
228 /* if necessary, ensure a clone of the obj exists in slot */
229 if (optype
!= CKF_DIGEST
) {
230 rv
= meta_object_get_clone(key
, slotnum
, init_session
,
238 fw_st_id
= init_session
->fw_st_id
;
241 rv
= FUNCLIST(fw_st_id
)->C_EncryptInit(
242 init_session
->hSession
, pMechanism
,
246 rv
= FUNCLIST(fw_st_id
)->C_DecryptInit(
247 init_session
->hSession
, pMechanism
,
251 rv
= FUNCLIST(fw_st_id
)->C_DigestInit(
252 init_session
->hSession
, pMechanism
);
255 rv
= FUNCLIST(fw_st_id
)->C_SignInit(
256 init_session
->hSession
, pMechanism
,
260 rv
= FUNCLIST(fw_st_id
)->C_VerifyInit(
261 init_session
->hSession
, pMechanism
,
264 case CKF_SIGN_RECOVER
:
265 rv
= FUNCLIST(fw_st_id
)->C_SignRecoverInit(
266 init_session
->hSession
, pMechanism
,
269 case CKF_VERIFY_RECOVER
:
270 rv
= FUNCLIST(fw_st_id
)->C_VerifyRecoverInit(
271 init_session
->hSession
, pMechanism
,
277 rv
= CKR_FUNCTION_FAILED
;
290 meta_release_slot_session(init_session
);
299 * If currently stored session is not the one being in use now,
300 * release the previous one and store the current one
302 if ((session
->op1
.session
) &&
303 (session
->op1
.session
!= init_session
)) {
304 meta_release_slot_session(session
->op1
.session
);
307 /* Save the session */
308 session
->op1
.session
= init_session
;
309 session
->op1
.type
= optype
;
311 session
->init
.slotnum
= slotnum
;
312 session
->init
.done
= B_TRUE
;
322 * meta_operation_init_softtoken()
323 * It will always do the crypto init operation on softtoken slot.
326 meta_operation_init_softtoken(CK_FLAGS optype
, meta_session_t
*session
,
327 CK_MECHANISM
*pMechanism
, meta_object_t
*key
)
329 CK_RV rv
= CKR_FUNCTION_FAILED
;
330 slot_session_t
*init_session
= NULL
;
331 slot_object_t
*init_key
;
333 CK_ULONG softtoken_slot_num
;
335 softtoken_slot_num
= get_softtoken_slotnum();
337 * If an operation is already active, cleanup existing operation
338 * and start a new one.
340 if (session
->op1
.type
!= 0) {
344 if ((pMechanism
->ulParameterLen
> 0) &&
345 (pMechanism
->pParameter
!= NULL
)) {
347 malloc(pMechanism
->ulParameterLen
);
348 if (mech
.pParameter
== NULL
) {
349 return (CKR_HOST_MEMORY
);
351 (void) memcpy(mech
.pParameter
,
352 pMechanism
->pParameter
, pMechanism
->ulParameterLen
);
354 mech
.pParameter
= NULL
;
355 mech
.ulParameterLen
= 0;
358 meta_operation_cleanup(session
, session
->op1
.type
, B_FALSE
);
359 rv
= meta_operation_init_defer(optype
, session
, &mech
,
361 if (mech
.pParameter
!= NULL
) {
362 free(mech
.pParameter
);
369 * An actual session with the underlying slot is required
370 * for the operation. When the operation is successfully
371 * completed, the underlying session with the slot
372 * is not released back to the list of available sessions
373 * pool. This will help if the next operation can
374 * also be done on the same slot, because it avoids
375 * one extra trip to the session pool to get an idle session.
376 * If the operation can't be done on that slot,
377 * we release the session back to the session pool.
379 if (session
->op1
.session
!= NULL
) {
380 if ((session
->op1
.session
)->slotnum
==
381 softtoken_slot_num
) {
382 init_session
= session
->op1
.session
;
384 * set it to NULL for now, assign it to
385 * init_session again if it is successful
387 session
->op1
.session
= NULL
;
393 if (init_session
== NULL
) {
394 /* get the active session from softtoken slot */
395 rv
= meta_get_slot_session(softtoken_slot_num
,
396 &init_session
, session
->session_flags
);
402 /* if necessary, ensure a clone of the obj exists in softtoken slot */
403 if (optype
!= CKF_DIGEST
) {
404 rv
= meta_object_get_clone(key
, softtoken_slot_num
,
405 init_session
, &init_key
);
408 if (init_session
!= NULL
) {
409 meta_release_slot_session(init_session
);
416 fw_st_id
= init_session
->fw_st_id
;
419 * Currently, we only support offloading encrypt, decrypt
420 * and digest operations to softtoken based on kernel
421 * threshold for the supported mechanisms.
425 rv
= FUNCLIST(fw_st_id
)->C_EncryptInit(
426 init_session
->hSession
, pMechanism
,
430 rv
= FUNCLIST(fw_st_id
)->C_DecryptInit(
431 init_session
->hSession
, pMechanism
,
435 rv
= FUNCLIST(fw_st_id
)->C_DigestInit(
436 init_session
->hSession
, pMechanism
);
441 rv
= CKR_FUNCTION_FAILED
;
448 * If currently stored session is not the one being in use now,
449 * release the previous one and store the current one
451 if ((session
->op1
.session
) &&
452 (session
->op1
.session
!= init_session
)) {
453 meta_release_slot_session(session
->op1
.session
);
456 /* Save the session */
457 session
->op1
.session
= init_session
;
458 session
->op1
.type
= optype
;
460 * The init.done flag will be checked by the meta_do_operation()
461 * to indicate whether the C_xxxInit has been done against
464 session
->init
.done
= B_TRUE
;
465 session
->init
.slotnum
= softtoken_slot_num
;
473 meta_GetThreshold(CK_MECHANISM_TYPE mechanism
)
478 for (i
= 0; i
< MAX_NUM_THRESHOLD
; i
++) {
479 if (mechanism
== meta_mechs_threshold
[i
].mech_type
)
480 return (meta_mechs_threshold
[i
].mech_threshold
);
483 /* no matching mechanism */
492 * 1) The spec says you cannot do a C_Encrypt after a C_EncUpdate,
493 * but we don't explicitly enforce it here (ie, disallow doing MODE_SINGLE
494 * after a MODE_UPDATE). Instead, we just assume the underlying provider
495 * will catch the problem and return an appropriate error.
497 * 2) Note that the Verify operations are a little unusual, due to the
498 * PKCS#11 API. For C_Verify, the last two arguments are used as inputs,
499 * unlike the other single pass operations (where they are outputs). For
500 * C_VerifyFinal, in/inLen are passed instead of out/outLen like the other
503 * 3) C_DigestKey is the only crypto operation that uses an object after
504 * the operation has been initialized. No other callers should provide
505 * this argument (use NULL).
508 meta_do_operation(CK_FLAGS optype
, int mode
,
509 meta_session_t
*session
, meta_object_t
*object
,
510 CK_BYTE
*in
, CK_ULONG inLen
, CK_BYTE
*out
, CK_ULONG
*outLen
)
513 CK_SESSION_HANDLE hSession
;
515 slot_session_t
*slot_session
= NULL
;
516 slot_object_t
*slot_object
= NULL
;
519 boolean_t shutdown
, finished_normally
;
522 * We've deferred the init for encrypt, decrypt and digest
523 * operations. As we know the size of the input data now, we
524 * can decide where to perform the real init operation based
525 * on the kernel cipher-specific thresholds for certain
526 * supported mechanisms.
528 if ((optype
== CKF_ENCRYPT
) || (optype
== CKF_DECRYPT
) ||
529 (optype
== CKF_DIGEST
)) {
530 if (Tmp_GetThreshold
!= NULL
) {
531 if (!session
->init
.app
) {
532 return (CKR_OPERATION_NOT_INITIALIZED
);
534 threshold
= meta_GetThreshold(
535 session
->init
.pMech
->mechanism
);
538 if ((threshold_chk_enabled
== B_FALSE
) || (inLen
> threshold
)) {
539 if ((session
->init
.app
) && (!session
->init
.done
)) {
541 * Call real init operation only if the
542 * application has called C_xxxInit
543 * but the real init operation has not
546 rv
= meta_operation_init(optype
,
547 session
->init
.session
,
552 } else if (!session
->init
.app
) {
554 * This checking detects the case that
555 * application calls C_En(De)Crypt/Digest
556 * directly without calling C_xxxInit.
558 return (CKR_OPERATION_NOT_INITIALIZED
);
562 * The size of the input data is smaller than the
563 * threshold so we'll use softoken to perform the
564 * crypto operation for better performance reason.
566 if ((session
->init
.app
) && (!session
->init
.done
)) {
568 * Call real init operation only if the
569 * application has called C_xxxInit
570 * but the real init operation has not
573 rv
= meta_operation_init_softtoken(optype
,
574 session
->init
.session
,
579 * In case the operation fails in
580 * softtoken, go back to use the
581 * original slot again.
583 rv
= meta_operation_init(optype
,
584 session
->init
.session
,
590 } else if (!session
->init
.app
) {
592 * This checking detects the case that
593 * application calls C_En(De)Crypt/Digest
594 * directly without calling C_xxxInit.
596 return (CKR_OPERATION_NOT_INITIALIZED
);
599 } else if (optype
!= session
->op1
.type
) {
600 return (CKR_OPERATION_NOT_INITIALIZED
);
603 slot_session
= session
->op1
.session
;
606 hSession
= slot_session
->hSession
;
607 fw_st_id
= slot_session
->fw_st_id
;
609 /* should never be here */
610 rv
= CKR_FUNCTION_FAILED
;
614 /* Do the operation... */
615 if (optype
== CKF_ENCRYPT
&& mode
== MODE_SINGLE
) {
616 rv
= FUNCLIST(fw_st_id
)->C_Encrypt(hSession
, in
,
618 } else if (optype
== CKF_ENCRYPT
&& mode
== MODE_UPDATE
) {
619 rv
= FUNCLIST(fw_st_id
)->C_EncryptUpdate(hSession
, in
,
621 } else if (optype
== CKF_ENCRYPT
&& mode
== MODE_FINAL
) {
622 rv
= FUNCLIST(fw_st_id
)->C_EncryptFinal(hSession
, out
,
625 } else if (optype
== CKF_DECRYPT
&& mode
== MODE_SINGLE
) {
626 rv
= FUNCLIST(fw_st_id
)->C_Decrypt(hSession
, in
,
628 } else if (optype
== CKF_DECRYPT
&& mode
== MODE_UPDATE
) {
629 rv
= FUNCLIST(fw_st_id
)->C_DecryptUpdate(hSession
, in
,
631 } else if (optype
== CKF_DECRYPT
&& mode
== MODE_FINAL
) {
632 rv
= FUNCLIST(fw_st_id
)->C_DecryptFinal(hSession
, out
,
635 } else if (optype
== CKF_DIGEST
&& mode
== MODE_SINGLE
) {
636 rv
= FUNCLIST(fw_st_id
)->C_Digest(hSession
, in
, inLen
,
638 } else if (optype
== CKF_DIGEST
&& mode
== MODE_UPDATE
) {
639 /* noOutputForOp = TRUE; */
640 rv
= FUNCLIST(fw_st_id
)->C_DigestUpdate(hSession
, in
,
642 } else if (optype
== CKF_DIGEST
&& mode
== MODE_UPDATE_WITHKEY
) {
643 /* noOutputForOp = TRUE; */
645 * For C_DigestKey, a key is provided and
648 rv
= meta_object_get_clone(object
,
649 slot_session
->slotnum
, slot_session
, &slot_object
);
651 rv
= FUNCLIST(fw_st_id
)->C_DigestKey(hSession
,
652 slot_object
->hObject
);
653 } else if (optype
== CKF_DIGEST
&& mode
== MODE_FINAL
) {
654 rv
= FUNCLIST(fw_st_id
)->C_DigestFinal(hSession
, out
,
657 } else if (optype
== CKF_SIGN
&& mode
== MODE_SINGLE
) {
658 rv
= FUNCLIST(fw_st_id
)->C_Sign(hSession
, in
, inLen
,
660 } else if (optype
== CKF_SIGN
&& mode
== MODE_UPDATE
) {
661 /* noOutputForOp = TRUE; */
662 rv
= FUNCLIST(fw_st_id
)->C_SignUpdate(hSession
, in
,
664 } else if (optype
== CKF_SIGN
&& mode
== MODE_FINAL
) {
665 rv
= FUNCLIST(fw_st_id
)->C_SignFinal(hSession
, out
,
668 } else if (optype
== CKF_VERIFY
&& mode
== MODE_SINGLE
) {
669 /* noOutputForOp = TRUE; */
670 /* Yes, use *outLen not outLen (think in2/in2Len) */
671 rv
= FUNCLIST(fw_st_id
)->C_Verify(hSession
, in
,
672 inLen
, out
, *outLen
);
673 } else if (optype
== CKF_VERIFY
&& mode
== MODE_UPDATE
) {
674 /* noOutputForOp = TRUE; */
675 rv
= FUNCLIST(fw_st_id
)->C_VerifyUpdate(hSession
, in
,
677 } else if (optype
== CKF_VERIFY
&& mode
== MODE_FINAL
) {
678 /* noOutputForOp = TRUE; */
679 /* Yes, use in/inLen instead of out/outLen */
680 rv
= FUNCLIST(fw_st_id
)->C_VerifyFinal(hSession
, in
,
683 } else if (optype
== CKF_SIGN_RECOVER
&& mode
== MODE_SINGLE
) {
684 rv
= FUNCLIST(fw_st_id
)->C_SignRecover(hSession
, in
,
686 } else if (optype
== CKF_VERIFY_RECOVER
&& mode
== MODE_SINGLE
) {
687 rv
= FUNCLIST(fw_st_id
)->C_VerifyRecover(hSession
, in
,
691 rv
= CKR_FUNCTION_FAILED
;
696 * Mark the operation type as inactive if an abnormal error
697 * happens, or if the operation normally results in an inactive
700 * NOTE: The spec isn't very explicit about what happens when you
701 * call C_FooFinal (or C_Foo) with a NULL output buffer (to get the
702 * output size), but there is no output. Technically this should be
703 * no different than the normal case (ie, when there is output), and
704 * the operation should remain active until the second call actually
705 * terminates it. However, one could make the case that there is no
706 * need for a second call, since no data is available. This presents
707 * dilemma for metaslot, because we don't know if the operation is
708 * going to remain active or not. We will assume a strict reading of
709 * the spec, the operation will remain active.
712 if (rv
== CKR_BUFFER_TOO_SMALL
||
713 (rv
== CKR_OK
&& out
== NULL
&& optype
!= CKF_VERIFY
)) {
714 /* Leave op active for retry (with larger buffer). */
716 } else if (rv
!= CKR_OK
) {
718 finished_normally
= B_FALSE
;
719 } else { /* CKR_OK */
720 if (mode
== MODE_SINGLE
|| mode
== MODE_FINAL
) {
722 finished_normally
= B_TRUE
;
723 } else { /* mode == MODE_UPDATE */
729 if (mode
== MODE_SINGLE
|| mode
== MODE_FINAL
) {
730 session
->init
.app
= B_FALSE
;
733 meta_operation_cleanup(session
, optype
, finished_normally
);
740 free_session_mechanism(meta_session_t
*session
)
742 if (session
->init
.pMech
!= NULL
) {
743 if (session
->init
.pMech
->pParameter
!= NULL
) {
744 free(session
->init
.pMech
->pParameter
);
745 session
->init
.pMech
->pParameter
= NULL
;
746 session
->init
.pMech
->ulParameterLen
= 0;
748 free(session
->init
.pMech
);
749 session
->init
.pMech
= NULL
;
754 * meta_operation_cleanup
756 * Cleans up an operation in the specified session.
757 * If the operation did not finish normally, it will force
758 * the operation to terminate.
761 meta_operation_cleanup(meta_session_t
*session
, CK_FLAGS optype
,
762 boolean_t finished_normally
)
764 operation_info_t
*op
;
765 CK_SESSION_HANDLE hSession
;
768 if (!finished_normally
) {
769 CK_BYTE dummy_buf
[8];
771 if (session
->op1
.type
== optype
) {
774 if ((optype
== CKF_ENCRYPT
) ||
775 (optype
== CKF_DECRYPT
) ||
776 (optype
== CKF_DIGEST
)) {
777 session
->op1
.type
= 0;
778 session
->init
.app
= B_FALSE
;
779 session
->init
.done
= B_FALSE
;
780 free_session_mechanism(session
);
785 hSession
= op
->session
->hSession
;
786 fw_st_id
= op
->session
->fw_st_id
;
789 * There's no simple, reliable way to abort an
790 * operation. So, we'll force the operation to finish.
792 * We are here either because we need to abort either after
793 * C_xxxxxInit() or C_xxxxxUpdate().
795 * We will call C_xxxxxUpdate() with invalid argument to
796 * force the operation to abort. According to the PKCS#11
797 * spec, any call to C_xxxxxUpdate() returns in an error
798 * will terminate the current operation.
803 (void) FUNCLIST(fw_st_id
)->C_EncryptUpdate(hSession
,
804 NULL
, 8, dummy_buf
, NULL
);
807 (void) FUNCLIST(fw_st_id
)->C_DecryptUpdate(hSession
,
808 NULL
, 8, dummy_buf
, NULL
);
811 (void) FUNCLIST(fw_st_id
)->C_DigestUpdate(hSession
,
815 (void) FUNCLIST(fw_st_id
)->C_SignUpdate(hSession
,
818 case CKF_SIGN_RECOVER
:
819 (void) FUNCLIST(fw_st_id
)->C_SignRecover(hSession
,
820 NULL
, 8, dummy_buf
, NULL
);
823 (void) FUNCLIST(fw_st_id
)->C_VerifyUpdate(hSession
,
826 case CKF_VERIFY_RECOVER
:
827 (void) FUNCLIST(fw_st_id
)->C_VerifyRecover(hSession
,
828 NULL
, 8, dummy_buf
, NULL
);
834 meta_release_slot_session(session
->op1
.session
);
835 session
->op1
.session
= NULL
;
838 if ((optype
== CKF_ENCRYPT
) || (optype
== CKF_DECRYPT
) ||
839 (optype
== CKF_DIGEST
)) {
840 session
->init
.done
= B_FALSE
;
841 free_session_mechanism(session
);
843 session
->op1
.type
= 0;
847 * Gets the list of slots that supports the specified mechanism.
849 * If "token_only", check if the keystore slot supports the specified mech,
850 * if so, return that slot only
852 * Otherwise, get list of all slots that support the mech.
856 get_slotlist_for_mech(CK_MECHANISM_TYPE mech_type
,
857 mech_support_info_t
*mech_support_info
,
858 mechinfo_t
***slots
, unsigned long *slot_count
, boolean_t token_only
,
859 CK_MECHANISM_INFO
*mech_info
)
861 boolean_t mech_supported
= B_FALSE
;
865 rv
= meta_mechManager_slot_supports_mech(mech_type
,
866 get_keystore_slotnum(), &mech_supported
,
867 &((mech_support_info
->supporting_slots
)[0]), B_FALSE
,
874 if (mech_supported
) {
875 mech_support_info
->mech
= mech_type
;
877 * Want to leave this at 0, that way, when
878 * other operation needs to
879 * use this mechanism, but not just for the
880 * keystore slot, we will look at other slots
882 mech_support_info
->num_supporting_slots
= 0;
883 *slots
= mech_support_info
->supporting_slots
;
886 rv
= CKR_FUNCTION_FAILED
;
890 * Get a list of slots that support this mech .
892 * If the specified mechanism is used last time,
893 * the list of capable slots is already retrieved.
894 * We can save some processing, and just use that list of slots.
896 if ((mech_support_info
->mech
!= mech_type
) ||
897 (mech_support_info
->num_supporting_slots
== 0)) {
898 mech_support_info
->mech
= mech_type
;
899 rv
= meta_mechManager_get_slots(mech_support_info
,
902 return (CKR_FUNCTION_FAILED
);
905 *slots
= mech_support_info
->supporting_slots
;
906 *slot_count
= mech_support_info
->num_supporting_slots
;
914 * Generates symmetric (k1=key, k2=null) or asymmetric (k1=pub, k2=priv) keys.
918 meta_generate_keys(meta_session_t
*session
, CK_MECHANISM
*pMechanism
,
919 CK_ATTRIBUTE
*k1Template
, CK_ULONG k1AttrCount
, meta_object_t
*key1
,
920 CK_ATTRIBUTE
*k2Template
, CK_ULONG k2AttrCount
, meta_object_t
*key2
)
923 slot_session_t
*gen_session
= NULL
;
924 slot_object_t
*slot_key1
= NULL
, *slot_key2
= NULL
;
925 mechinfo_t
**slots
= NULL
;
926 unsigned long i
, slotCount
= 0;
927 boolean_t doKeyPair
= B_FALSE
, token_only
= B_FALSE
;
929 CK_MECHANISM_INFO mech_info
;
931 * Since the keygen call is in a loop, it is performance-wise useful
932 * to keep track of the token value
934 CK_BBOOL current_token1_value
= FALSE
, current_token2_value
= FALSE
;
936 (void) get_template_boolean(CKA_TOKEN
, k1Template
, k1AttrCount
,
938 (void) get_template_boolean(CKA_SENSITIVE
, k1Template
, k1AttrCount
,
939 &(key1
->isSensitive
));
940 (void) get_template_boolean(CKA_PRIVATE
, k1Template
, k1AttrCount
,
943 if (!get_template_boolean(CKA_EXTRACTABLE
, k1Template
, k1AttrCount
,
944 &(key1
->isExtractable
)))
945 key1
->isExtractable
= B_TRUE
;
948 current_token1_value
= TRUE
;
950 mech_info
.flags
= CKF_GENERATE
;
953 (void) get_template_boolean(CKA_TOKEN
, k2Template
, k2AttrCount
,
955 (void) get_template_boolean(CKA_SENSITIVE
, k2Template
,
956 k2AttrCount
, &(key2
->isSensitive
));
957 (void) get_template_boolean(CKA_PRIVATE
, k2Template
,
958 k2AttrCount
, &(key2
->isPrivate
));
960 if (!get_template_boolean(CKA_EXTRACTABLE
, k2Template
,
961 k2AttrCount
, &(key2
->isExtractable
)))
962 key2
->isExtractable
= B_TRUE
;
965 current_token2_value
= TRUE
;
968 mech_info
.flags
= CKF_GENERATE_KEY_PAIR
;
972 /* Can't create token objects in a read-only session. */
973 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
974 ((key1
->isToken
) || ((key2
) && (key2
->isToken
)))) {
975 return (CKR_SESSION_READ_ONLY
);
978 if (meta_freeobject_check(session
, key1
, pMechanism
, k1Template
,
981 if ((key1
->isPrivate
|| (doKeyPair
&& key2
->isPrivate
)) &&
982 !metaslot_logged_in())
983 return (CKR_USER_NOT_LOGGED_IN
);
985 if (!meta_freeobject_set(key1
, k1Template
, k1AttrCount
,
987 return (CKR_FUNCTION_FAILED
);
990 key2
->isFreeObject
= FREE_ALLOWED_KEY
;
991 if (!meta_freeobject_set(key2
, k2Template
, k2AttrCount
,
993 return (CKR_FUNCTION_FAILED
);
996 } else if (doKeyPair
) {
998 * If this is a keypair operation, the second key cannot be
999 * a FreeObject if the first is not. Both keys will have the
1000 * same fate when it comes to provider choices
1002 key2
->isFreeObject
= FREE_DISABLED
;
1003 key2
->isFreeToken
= FREE_DISABLED
;
1006 if ((key1
->isToken
) || ((doKeyPair
) && (key2
->isToken
))) {
1008 * Token objects can only be generated in the token object
1009 * slot. If token object slot doesn't support generating
1010 * the key, it will just not be done.
1012 token_only
= B_TRUE
;
1015 rv
= get_slotlist_for_mech(pMechanism
->mechanism
,
1016 &(session
->mech_support_info
), &slots
, &slotCount
, token_only
,
1023 rv
= meta_slot_object_alloc(&slot_key1
);
1024 if (doKeyPair
&& rv
== CKR_OK
)
1025 rv
= meta_slot_object_alloc(&slot_key2
);
1029 /* Attempt to generate key on slots until one succeeds. */
1030 for (i
= 0; i
< slotCount
; i
++) {
1031 CK_SESSION_HANDLE hSession
;
1032 CK_SLOT_ID fw_st_id
;
1036 slotnum
= slots
[i
]->slotnum
;
1038 if (session
->op1
.session
!= NULL
) {
1039 if ((session
->op1
.session
)->slotnum
== slotnum
) {
1040 gen_session
= session
->op1
.session
;
1042 * set it to NULL for now, assign it to
1043 * gen_session again if it is successful
1045 session
->op1
.session
= NULL
;
1051 if (gen_session
== NULL
) {
1052 rv
= meta_get_slot_session(slotnum
, &gen_session
,
1053 session
->session_flags
);
1060 * If this is a freetoken, make sure the templates are
1061 * approriate for the slot being used.
1063 if (key1
->isFreeToken
== FREE_ENABLED
) {
1064 rv
= meta_freetoken_set(slotnum
,
1065 ¤t_token1_value
, k1Template
, k1AttrCount
);
1070 if (doKeyPair
&& key2
->isFreeToken
== FREE_ENABLED
) {
1071 rv
= meta_freetoken_set(slotnum
,
1072 ¤t_token2_value
, k2Template
, k2AttrCount
);
1077 fw_st_id
= gen_session
->fw_st_id
;
1078 hSession
= gen_session
->hSession
;
1081 rv
= FUNCLIST(fw_st_id
)->C_GenerateKeyPair(hSession
,
1082 pMechanism
, k1Template
, k1AttrCount
,
1083 k2Template
, k2AttrCount
,
1084 &slot_key1
->hObject
, &slot_key2
->hObject
);
1086 rv
= FUNCLIST(fw_st_id
)->C_GenerateKey(hSession
,
1087 pMechanism
, k1Template
, k1AttrCount
,
1088 &slot_key1
->hObject
);
1100 meta_release_slot_session(gen_session
);
1109 rv
= meta_object_get_attr(gen_session
, slot_key1
->hObject
, key1
);
1115 rv
= meta_object_get_attr(gen_session
, slot_key2
->hObject
,
1122 /* Allow FreeToken to activate onto token obj list */
1123 if (key1
->isFreeToken
== FREE_ENABLED
)
1124 key1
->isToken
= B_TRUE
;
1126 meta_slot_object_activate(slot_key1
, gen_session
, key1
->isToken
);
1127 key1
->clones
[slotnum
] = slot_key1
;
1128 key1
->master_clone_slotnum
= slotnum
;
1130 if (key1
->isFreeObject
== FREE_ENABLED
) {
1131 rv
= meta_freeobject_clone(session
, key1
);
1137 /* Allow FreeToken to activate onto token obj list */
1138 if (key2
->isFreeToken
== FREE_ENABLED
)
1139 key2
->isToken
= B_TRUE
;
1141 meta_slot_object_activate(slot_key2
, gen_session
,
1143 key2
->clones
[slotnum
] = slot_key2
;
1144 key2
->master_clone_slotnum
= slotnum
;
1146 if (key2
->isFreeObject
== FREE_ENABLED
) {
1147 rv
= meta_freeobject_clone(session
, key2
);
1155 meta_slot_object_dealloc(slot_key1
);
1159 meta_slot_object_dealloc(slot_key2
);
1162 /* Save the session in case it can be used later */
1165 * If currently stored session is not the one being in use now,
1166 * release the previous one and store the current one
1168 if ((session
->op1
.session
) &&
1169 (session
->op1
.session
!= gen_session
)) {
1170 meta_release_slot_session(session
->op1
.session
);
1173 /* Save the session */
1174 session
->op1
.session
= gen_session
;
1186 meta_wrap_key(meta_session_t
*session
, CK_MECHANISM
*pMechanism
,
1187 meta_object_t
*wrappingkey
, meta_object_t
*inputkey
, CK_BYTE
*wrapped_key
,
1188 CK_ULONG
*wrapped_key_len
)
1191 slot_session_t
*wrap_session
= NULL
;
1192 slot_object_t
*slot_wrappingkey
, *slot_inputkey
;
1193 mechinfo_t
**slots
= NULL
;
1194 unsigned long i
, slotCount
= 0;
1196 CK_MECHANISM_INFO mech_info
;
1199 * If the key to be wrapped is a token object,
1200 * the operation can only be done in the token object slot.
1202 mech_info
.flags
= CKF_WRAP
;
1203 rv
= get_slotlist_for_mech(pMechanism
->mechanism
,
1204 &(session
->mech_support_info
), &slots
, &slotCount
,
1205 inputkey
->isToken
, &mech_info
);
1211 /* Attempt to wrap key on slots until one succeeds. */
1212 for (i
= 0; i
< slotCount
; i
++) {
1214 slotnum
= slots
[i
]->slotnum
;
1215 wrap_session
= NULL
;
1217 if (session
->op1
.session
!= NULL
) {
1218 if ((session
->op1
.session
)->slotnum
== slotnum
) {
1219 wrap_session
= session
->op1
.session
;
1221 * set it to NULL for now, assign it to
1222 * wrap_session again if it is successful
1224 session
->op1
.session
= NULL
;
1226 wrap_session
= NULL
;
1230 if (wrap_session
== NULL
) {
1231 rv
= meta_get_slot_session(slotnum
, &wrap_session
,
1232 session
->session_flags
);
1238 rv
= meta_object_get_clone(wrappingkey
, slotnum
,
1239 wrap_session
, &slot_wrappingkey
);
1243 rv
= meta_object_get_clone(inputkey
, slotnum
,
1244 wrap_session
, &slot_inputkey
);
1248 rv
= FUNCLIST(wrap_session
->fw_st_id
)->C_WrapKey(
1249 wrap_session
->hSession
, pMechanism
,
1250 slot_wrappingkey
->hObject
, slot_inputkey
->hObject
,
1251 wrapped_key
, wrapped_key_len
);
1253 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
1262 meta_release_slot_session(wrap_session
);
1263 wrap_session
= NULL
;
1267 if (rv
!= CKR_BUFFER_TOO_SMALL
) {
1268 if (i
== slotCount
) {
1275 /* Save the session in case it can be used later */
1278 * If currently stored session is not the one being in use now,
1279 * release the previous one and store the current one
1281 if ((session
->op1
.session
) &&
1282 (session
->op1
.session
!= wrap_session
)) {
1283 meta_release_slot_session(session
->op1
.session
);
1286 /* Save the session */
1287 session
->op1
.session
= wrap_session
;
1299 meta_unwrap_key(meta_session_t
*session
,
1300 CK_MECHANISM
*pMechanism
, meta_object_t
*unwrapping_key
,
1301 CK_BYTE
*wrapped_key
, CK_ULONG wrapped_key_len
,
1302 CK_ATTRIBUTE
*template, CK_ULONG template_size
,
1303 meta_object_t
*unwrapped_key
)
1306 CK_OBJECT_HANDLE hUnwrappedKey
;
1307 slot_session_t
*unwrap_session
= NULL
;
1308 slot_object_t
*slot_unwrappingkey
, *slot_unwrapped_key
;
1309 mechinfo_t
**slots
= NULL
;
1310 unsigned long i
, slotCount
= 0;
1312 CK_MECHANISM_INFO mech_info
;
1314 /* Can't create token objects in a read-only session. */
1315 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
1316 unwrapped_key
->isToken
) {
1317 return (CKR_SESSION_READ_ONLY
);
1321 * If the the resulting unwrapped key
1322 * needs to be a token object, the operation can only
1323 * be performed in the token slot, if it is supported.
1325 mech_info
.flags
= CKF_UNWRAP
;
1326 rv
= get_slotlist_for_mech(pMechanism
->mechanism
,
1327 &(session
->mech_support_info
), &slots
, &slotCount
,
1328 unwrapped_key
->isToken
, &mech_info
);
1334 rv
= meta_slot_object_alloc(&slot_unwrapped_key
);
1339 /* Attempt to unwrap key on slots until one succeeds. */
1340 for (i
= 0; i
< slotCount
; i
++) {
1342 slotnum
= slots
[i
]->slotnum
;
1343 unwrap_session
= NULL
;
1345 if (session
->op1
.session
!= NULL
) {
1346 if ((session
->op1
.session
)->slotnum
== slotnum
) {
1347 unwrap_session
= session
->op1
.session
;
1349 * set it to NULL for now, assign it to
1350 * unwrap_session again if it is successful
1352 session
->op1
.session
= NULL
;
1354 unwrap_session
= NULL
;
1358 if (unwrap_session
== NULL
) {
1359 rv
= meta_get_slot_session(slotnum
, &unwrap_session
,
1360 session
->session_flags
);
1366 rv
= meta_object_get_clone(unwrapping_key
, slotnum
,
1367 unwrap_session
, &slot_unwrappingkey
);
1371 rv
= FUNCLIST(unwrap_session
->fw_st_id
)->C_UnwrapKey(
1372 unwrap_session
->hSession
, pMechanism
,
1373 slot_unwrappingkey
->hObject
, wrapped_key
, wrapped_key_len
,
1374 template, template_size
, &hUnwrappedKey
);
1376 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
1383 if (unwrap_session
) {
1384 meta_release_slot_session(unwrap_session
);
1385 unwrap_session
= NULL
;
1391 if (rv
!= CKR_BUFFER_TOO_SMALL
) {
1398 slot_unwrapped_key
->hObject
= hUnwrappedKey
;
1399 unwrapped_key
->clones
[slotnum
] = slot_unwrapped_key
;
1400 unwrapped_key
->master_clone_slotnum
= slotnum
;
1401 rv
= meta_object_get_attr(unwrap_session
,
1402 slot_unwrapped_key
->hObject
, unwrapped_key
);
1406 meta_slot_object_activate(slot_unwrapped_key
, unwrap_session
,
1407 unwrapped_key
->isToken
);
1408 slot_unwrapped_key
= NULL
;
1411 if (slot_unwrapped_key
) {
1412 meta_slot_object_dealloc(slot_unwrapped_key
);
1415 /* Save the session in case it can be used later */
1418 * If currently stored session is not the one being in use now,
1419 * release the previous one and store the current one
1421 if ((session
->op1
.session
) &&
1422 (session
->op1
.session
!= unwrap_session
)) {
1423 meta_release_slot_session(session
->op1
.session
);
1426 /* Save the session */
1427 session
->op1
.session
= unwrap_session
;
1437 * Core implementation for C_DeriveKey. This function is a bit gross because
1438 * of PKCS#11 kludges that pass extra object handles in the mechanism
1439 * parameters. Normally C_DeriveKey takes a single existing key as input,
1440 * and creates a single new key as output. But a few mechanisms take 2 keys
1441 * as input, and the two SSL/TLS mechanisms create 4 keys as output.
1443 * When an extra input key (basekey2) is set, we set *phBaseKey2 to the clone's
1444 * object handle. phBaseKey2 is provided by the caller so we don't have to
1445 * trudge down into different mechanism parameters to set it when issuing the
1448 * For the SSL/TLS mechanisms, newKey2/newKey3/newKey4 will be set. We pull
1449 * the new handles from pMech->pParameter in order to fill in the appropriate
1450 * meta_object fields.
1453 meta_derive_key(meta_session_t
*session
, CK_MECHANISM
*pMechanism
,
1454 meta_object_t
*basekey1
, meta_object_t
*basekey2
,
1455 CK_OBJECT_HANDLE
*phBaseKey2
,
1456 CK_ATTRIBUTE
*pTemplate
, CK_ULONG ulAttributeCount
,
1457 meta_object_t
*newKey1
, meta_object_t
*newKey2
,
1458 meta_object_t
*newKey3
, meta_object_t
*newKey4
)
1461 CK_OBJECT_HANDLE hDerivedKey
;
1464 boolean_t isSSL
= B_FALSE
;
1465 boolean_t isTLSPRF
= B_FALSE
;
1466 mechinfo_t
**slots
= NULL
;
1467 unsigned long i
, slot_count
= 0;
1468 slot_session_t
*derive_session
= NULL
;
1469 slot_object_t
*slot_basekey1
= NULL
, *slot_basekey2
= NULL
;
1470 slot_object_t
*slotkey1
= NULL
, *slotkey2
= NULL
, *slotkey3
= NULL
,
1472 CK_MECHANISM_INFO mech_info
;
1473 CK_BBOOL current_token_value
= FALSE
;
1476 * if the derived key needs to be a token object, can only
1477 * perform the derive operation in the token slot
1479 (void) get_template_boolean(CKA_TOKEN
, pTemplate
, ulAttributeCount
,
1480 &(newKey1
->isToken
));
1481 (void) get_template_boolean(CKA_PRIVATE
, pTemplate
, ulAttributeCount
,
1482 &(newKey1
->isPrivate
));
1483 (void) get_template_boolean(CKA_SENSITIVE
, pTemplate
, ulAttributeCount
,
1484 &(newKey1
->isSensitive
));
1486 if (newKey1
->isToken
)
1487 current_token_value
= TRUE
;
1489 /* Can't create token objects in a read-only session. */
1490 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
1492 rv
= CKR_SESSION_READ_ONLY
;
1496 if (meta_freeobject_check(session
, newKey1
, pMechanism
, pTemplate
,
1497 ulAttributeCount
, 0)) {
1499 if (newKey1
->isPrivate
&& !metaslot_logged_in())
1500 return (CKR_USER_NOT_LOGGED_IN
);
1502 if (!meta_freeobject_set(newKey1
, pTemplate
, ulAttributeCount
,
1504 return (CKR_FUNCTION_FAILED
);
1507 mech_info
.flags
= CKF_DERIVE
;
1508 rv
= get_slotlist_for_mech(pMechanism
->mechanism
,
1509 &(session
->mech_support_info
), &slots
, &slot_count
,
1510 newKey1
->isToken
, &mech_info
);
1516 if (pMechanism
->mechanism
== CKM_SSL3_KEY_AND_MAC_DERIVE
||
1517 pMechanism
->mechanism
== CKM_TLS_KEY_AND_MAC_DERIVE
)
1520 else if (pMechanism
->mechanism
== CKM_TLS_PRF
)
1523 rv
= meta_slot_object_alloc(&slotkey1
);
1526 rv
= meta_slot_object_alloc(&slotkey2
);
1528 rv
= meta_slot_object_alloc(&slotkey3
);
1530 rv
= meta_slot_object_alloc(&slotkey4
);
1536 for (i
= 0; i
< slot_count
; i
++) {
1537 slotnum
= slots
[i
]->slotnum
;
1539 derive_session
= NULL
;
1541 if (session
->op1
.session
!= NULL
) {
1542 if ((session
->op1
.session
)->slotnum
== slotnum
) {
1543 derive_session
= session
->op1
.session
;
1545 * set it to NULL for now, assign it to
1546 * derive_session again if it is successful
1548 session
->op1
.session
= NULL
;
1550 derive_session
= NULL
;
1554 if (derive_session
== NULL
) {
1555 rv
= meta_get_slot_session(slotnum
, &derive_session
,
1556 session
->session_flags
);
1562 rv
= meta_object_get_clone(basekey1
, slotnum
,
1563 derive_session
, &slot_basekey1
);
1568 rv
= meta_object_get_clone(basekey2
, slotnum
,
1569 derive_session
, &slot_basekey2
);
1573 /* Pass the handle somewhere in the mech params. */
1574 *phBaseKey2
= slot_basekey2
->hObject
;
1577 if (newKey1
->isFreeToken
== FREE_ENABLED
) {
1578 rv
= meta_freetoken_set(slotnum
, ¤t_token_value
,
1579 pTemplate
, ulAttributeCount
);
1584 rv
= FUNCLIST(derive_session
->fw_st_id
)->C_DeriveKey(
1585 derive_session
->hSession
, pMechanism
,
1586 slot_basekey1
->hObject
, pTemplate
, ulAttributeCount
,
1587 (isSSL
|| isTLSPRF
) ? NULL
: &hDerivedKey
);
1596 if (derive_session
) {
1597 meta_release_slot_session(derive_session
);
1598 derive_session
= NULL
;
1600 /* No need to cleanup clones, so we can reuse them later. */
1612 * These SSL/TLS are unique in that the parameter in the API for
1613 * the new key is unused (NULL). Instead, there are 4 keys which
1614 * are derived, and are passed back through the mechanism params.
1615 * Both mechs use the same mechanism parameter type.
1618 CK_SSL3_KEY_MAT_PARAMS
*keyparams
;
1619 CK_SSL3_KEY_MAT_OUT
*keys
;
1621 /* NULL checks already done by caller */
1622 keyparams
= (CK_SSL3_KEY_MAT_PARAMS
*)pMechanism
->pParameter
;
1623 keys
= keyparams
->pReturnedKeyMaterial
;
1625 slotkey1
->hObject
= keys
->hClientMacSecret
;
1626 slotkey2
->hObject
= keys
->hServerMacSecret
;
1627 slotkey3
->hObject
= keys
->hClientKey
;
1628 slotkey4
->hObject
= keys
->hServerKey
;
1630 rv
= meta_object_get_attr(derive_session
,
1631 slotkey1
->hObject
, newKey1
);
1636 rv
= meta_object_get_attr(derive_session
,
1637 slotkey2
->hObject
, newKey2
);
1642 rv
= meta_object_get_attr(derive_session
,
1643 slotkey3
->hObject
, newKey3
);
1648 rv
= meta_object_get_attr(derive_session
,
1649 slotkey4
->hObject
, newKey4
);
1654 newKey1
->clones
[slotnum
] = slotkey1
;
1655 newKey2
->clones
[slotnum
] = slotkey2
;
1656 newKey3
->clones
[slotnum
] = slotkey3
;
1657 newKey4
->clones
[slotnum
] = slotkey4
;
1659 newKey1
->master_clone_slotnum
= slotnum
;
1660 newKey2
->master_clone_slotnum
= slotnum
;
1661 newKey3
->master_clone_slotnum
= slotnum
;
1662 newKey4
->master_clone_slotnum
= slotnum
;
1664 meta_slot_object_activate(slotkey1
, derive_session
,
1667 meta_slot_object_activate(slotkey2
, derive_session
,
1670 meta_slot_object_activate(slotkey3
, derive_session
,
1673 meta_slot_object_activate(slotkey4
, derive_session
,
1678 slotkey1
->hObject
= hDerivedKey
;
1679 newKey1
->clones
[slotnum
] = slotkey1
;
1680 newKey1
->master_clone_slotnum
= slotnum
;
1682 rv
= meta_object_get_attr(derive_session
,
1683 slotkey1
->hObject
, newKey1
);
1688 /* Allow FreeToken to activate onto token obj list */
1689 if (newKey1
->isFreeToken
== FREE_ENABLED
)
1690 newKey1
->isToken
= B_TRUE
;
1692 meta_slot_object_activate(slotkey1
, derive_session
,
1697 if (newKey1
->isFreeObject
== FREE_ENABLED
)
1698 (void) meta_freeobject_clone(session
, newKey1
);
1703 meta_slot_object_dealloc(slotkey1
);
1706 meta_slot_object_dealloc(slotkey2
);
1709 meta_slot_object_dealloc(slotkey3
);
1712 meta_slot_object_dealloc(slotkey4
);
1715 /* Save the session in case it can be used later */
1718 * If currently stored session is not the one being in use now,
1719 * release the previous one and store the current one
1721 if ((session
->op1
.session
) &&
1722 (session
->op1
.session
!= derive_session
)) {
1723 meta_release_slot_session(session
->op1
.session
);
1726 /* Save the session */
1727 session
->op1
.session
= derive_session
;
1735 * Check the following 4 environment variables for user/application's
1736 * configuration for metaslot. User's configuration takes precedence
1737 * over the system wide configuration for metaslot
1739 * ${METASLOT_ENABLED}
1740 * ${METASLOT_OBJECTSTORE_SLOT}
1741 * ${METASLOT_OBJECTSTORE_TOKEN}
1742 * ${METASLOT_AUTO_KEY_MIGRATE}
1744 * ${_METASLOT_ENABLE_THRESHOLD} - private environmental variable to
1745 * enable the treshold checking which is disabled by default.
1747 * values defined in these environment variables will be stored in the
1748 * global variable "metaslot_config". Variable threshold_chk_disabled is an
1752 get_user_metaslot_config()
1754 char *env_val
= NULL
;
1757 * Check to see if any environment variable is defined
1758 * by the user for configuring metaslot.
1760 bzero(&metaslot_config
, sizeof (metaslot_config
));
1762 /* METASLOT_ENABLED */
1763 env_val
= getenv("METASLOT_ENABLED");
1765 metaslot_config
.enabled_specified
= B_TRUE
;
1766 if (strcasecmp(env_val
, TRUE_STRING
) == 0) {
1767 metaslot_config
.enabled
= B_TRUE
;
1768 } else if (strcasecmp(env_val
, FALSE_STRING
) == 0) {
1769 metaslot_config
.enabled
= B_FALSE
;
1771 /* value is neither 1 or 0, ignore this value */
1772 metaslot_config
.enabled_specified
= B_FALSE
;
1776 /* METASLOT_AUTO_KEY_MIGRATE */
1777 env_val
= getenv("METASLOT_AUTO_KEY_MIGRATE");
1779 metaslot_config
.auto_key_migrate_specified
= B_TRUE
;
1780 if (strcasecmp(env_val
, TRUE_STRING
) == 0) {
1781 metaslot_config
.auto_key_migrate
= B_TRUE
;
1782 } else if (strcasecmp(env_val
, FALSE_STRING
) == 0) {
1783 metaslot_config
.auto_key_migrate
= B_FALSE
;
1785 /* value is neither 1 or 0, ignore this value */
1786 metaslot_config
.auto_key_migrate_specified
= B_FALSE
;
1790 /* METASLOT_OBJECTSTORE_SLOT */
1791 env_val
= getenv("METASLOT_OBJECTSTORE_SLOT");
1793 metaslot_config
.keystore_slot_specified
= B_TRUE
;
1794 (void) strlcpy((char *)metaslot_config
.keystore_slot
, env_val
,
1795 SLOT_DESCRIPTION_SIZE
);
1798 /* METASLOT_OBJECTSTORE_TOKEN */
1799 env_val
= getenv("METASLOT_OBJECTSTORE_TOKEN");
1801 metaslot_config
.keystore_token_specified
= B_TRUE
;
1802 (void) strlcpy((char *)metaslot_config
.keystore_token
, env_val
,
1806 /* _METASLOT_ENABLE_THRESHOLD */
1807 env_val
= getenv("_METASLOT_ENABLE_THRESHOLD");
1809 threshold_chk_enabled
= B_TRUE
;