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.
29 #include <security/cryptoki.h>
30 #include <sys/crypto/ioctl.h>
31 #include "kernelGlobal.h"
32 #include "kernelSession.h"
33 #include "kernelObject.h"
36 attribute_in_template(CK_ATTRIBUTE_TYPE type
, CK_ATTRIBUTE_PTR t
, CK_ULONG cnt
)
40 for (i
= 0; i
< cnt
; i
++) {
41 if (t
[i
].type
== type
)
48 * This routine returns modulus bytes rounded up to the nearest 8 byte
49 * chunk. This is so we don't have to pass in max sized buffers for
50 * returned attributes. Every unnecessary byte that we pass in results
51 * in a kernel allocation.
54 get_modulus_bytes(CK_ATTRIBUTE_PTR t
, CK_ULONG cnt
)
59 for (i
= 0; i
< cnt
; i
++) {
60 if (t
[i
].type
== CKA_MODULUS_BITS
) {
61 get_ulong_attr_from_template(&modulus_len
, &t
[i
]);
62 /* convert from bit length to byte length */
63 modulus_len
= (modulus_len
- 1) / 64 + 1;
64 return (modulus_len
* 8);
71 * Remove specified attribute from array. Storage for the attribute's
72 * value is freed if 'free_attr' is TRUE. Attributes are shifted so they are
73 * contiguous within the array, i.e. the next attribute is shifted into
74 * the position of the removed attribute. Returns TRUE if specified
75 * attribute is removed.
78 remove_one_attribute(CK_ATTRIBUTE_PTR t
, CK_ULONG type
, uint_t count
,
83 for (i
= 0, j
= 0; i
< count
; i
++) {
84 if (t
[i
].type
== type
) {
91 t
[j
].type
= t
[i
].type
;
92 t
[j
].pValue
= t
[i
].pValue
;
93 t
[j
].ulValueLen
= t
[i
].ulValueLen
;
107 is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulAttributeCount
)
110 for (i
= 0; i
< ulAttributeCount
; i
++) {
111 if (pTemplate
[i
].type
== CKA_CLASS
&&
112 *(CK_OBJECT_CLASS
*)(pTemplate
[i
].pValue
) ==
120 * Allocate a template with space for new_count entries and copy the
121 * specified template into the new template.
123 static CK_ATTRIBUTE_PTR
124 grow_template(CK_ATTRIBUTE_PTR old_template
, CK_ULONG old_count
,
127 CK_ATTRIBUTE_PTR new_template
;
129 new_template
= malloc(new_count
* sizeof (CK_ATTRIBUTE
));
130 if (new_template
!= NULL
)
131 bcopy(old_template
, new_template
,
132 old_count
* sizeof (CK_ATTRIBUTE
));
133 return (new_template
);
137 * For fixed length keys such as DES, return the length based on
138 * the key type. For variable length keys such as AES, take the
139 * length from the CKA_VALUE_LEN attribute.
142 get_key_len_from_template(CK_MECHANISM_PTR pMechanism
,
143 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulAttributeCount
,
144 kernel_object_t
*basekey_p
, ulong_t
*key_len
)
146 boolean_t fixed_len_key
= B_FALSE
;
150 for (i
= 0; i
< ulAttributeCount
; i
++) {
151 if (pTemplate
[i
].type
== CKA_KEY_TYPE
) {
152 get_ulong_attr_from_template(&key_type
, &pTemplate
[i
]);
156 /* CKA_KEY_TYPE must be present */
157 if (i
== ulAttributeCount
)
158 return (CKR_TEMPLATE_INCOMPLETE
);
163 fixed_len_key
= B_TRUE
;
167 fixed_len_key
= B_TRUE
;
171 for (i
= 0; i
< ulAttributeCount
; i
++) {
172 if (pTemplate
[i
].type
== CKA_VALUE_LEN
) {
173 get_ulong_attr_from_template(key_len
,
178 /* CKA_VALUE_LEN must be present */
179 if (i
== ulAttributeCount
)
180 return (CKR_TEMPLATE_INCOMPLETE
);
182 case CKK_GENERIC_SECRET
:
184 * The key will not be truncated, so we need to
185 * get the max length for the mechanism.
187 if (pMechanism
->mechanism
== CKM_DH_PKCS_DERIVE
) {
190 tmp
.type
= CKA_PRIME
;
193 /* get size of attribute */
194 if (kernel_get_attribute(basekey_p
, &tmp
) != CKR_OK
) {
195 return (CKR_ARGUMENTS_BAD
);
197 *key_len
= tmp
.ulValueLen
;
198 } else if (pMechanism
->mechanism
== CKM_ECDH1_DERIVE
) {
199 *key_len
= EC_MAX_VALUE_LEN
;
201 return (CKR_ARGUMENTS_BAD
);
205 return (CKR_ATTRIBUTE_VALUE_INVALID
);
208 if (fixed_len_key
&& attribute_in_template(CKA_VALUE_LEN
,
209 pTemplate
, ulAttributeCount
))
210 return (CKR_TEMPLATE_INCONSISTENT
);
215 /* find specified attribute src template and copy to dest */
217 copy_attribute(CK_ULONG type
, CK_ATTRIBUTE_PTR src
, CK_ULONG src_cnt
,
218 CK_ATTRIBUTE_PTR dst
)
222 for (i
= 0; i
< src_cnt
; i
++) {
223 if (src
[i
].type
== type
) {
224 rv
= get_string_from_template(dst
, &src
[i
]);
229 * The public template didn't have attribute.
232 rv
= CKR_TEMPLATE_INCOMPLETE
;
238 free_attributes(caddr_t p
, uint_t
*countp
)
241 free_object_attributes(p
, *countp
);
247 key_gen_by_value(CK_MECHANISM_PTR pMechanism
, CK_ATTRIBUTE_PTR pTemplate
,
248 CK_ULONG ulCount
, kernel_session_t
*session_p
,
249 crypto_mech_type_t k_mech_type
, kernel_object_t
*new_objp
)
251 crypto_nostore_generate_key_t obj_ngk
;
252 char *key_buf
= NULL
;
253 CK_ATTRIBUTE_PTR newTemplate
= NULL
;
254 CK_BBOOL is_token_obj
= FALSE
;
260 obj_ngk
.ngk_in_count
= 0;
261 obj_ngk
.ngk_out_count
= 0;
263 rv
= get_key_len_from_template(pMechanism
, pTemplate
, ulCount
,
265 if (rv
!= CRYPTO_SUCCESS
)
268 if ((key_buf
= malloc(key_len
)) == NULL
) {
269 rv
= CKR_HOST_MEMORY
;
273 attr_count
= ulCount
+ 1;
274 newTemplate
= grow_template(pTemplate
, ulCount
, attr_count
);
275 if (newTemplate
== NULL
) {
276 rv
= CKR_HOST_MEMORY
;
280 /* Now add the CKA_VALUE attribute to template */
281 newTemplate
[ulCount
].type
= CKA_VALUE
;
282 newTemplate
[ulCount
].pValue
= (caddr_t
)key_buf
;
283 newTemplate
[ulCount
].ulValueLen
= key_len
;
285 rv
= process_object_attributes(newTemplate
, attr_count
- 1,
286 &obj_ngk
.ngk_in_attributes
, &is_token_obj
);
290 rv
= process_object_attributes(&newTemplate
[ulCount
],
291 1, &obj_ngk
.ngk_out_attributes
, &is_token_obj
);
296 /* Cannot create a token object with a READ-ONLY session. */
297 if (is_token_obj
&& session_p
->ses_RO
) {
298 rv
= CKR_SESSION_READ_ONLY
;
302 /* Call the CRYPTO_NOSTORE_GENERATE_KEY ioctl */
303 obj_ngk
.ngk_session
= session_p
->k_session
;
304 obj_ngk
.ngk_in_count
= attr_count
- 1;
305 obj_ngk
.ngk_out_count
= 1;
306 obj_ngk
.ngk_mechanism
.cm_type
= k_mech_type
;
307 obj_ngk
.ngk_mechanism
.cm_param
= pMechanism
->pParameter
;
308 obj_ngk
.ngk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
310 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_GENERATE_KEY
,
316 rv
= CKR_FUNCTION_FAILED
;
318 rv
= crypto2pkcs11_error_number(obj_ngk
.ngk_return_value
);
320 free_attributes(obj_ngk
.ngk_in_attributes
, &obj_ngk
.ngk_in_count
);
325 rv
= get_object_attributes(&newTemplate
[ulCount
], 1,
326 obj_ngk
.ngk_out_attributes
);
327 free_attributes(obj_ngk
.ngk_out_attributes
, &obj_ngk
.ngk_out_count
);
328 if (rv
!= CRYPTO_SUCCESS
) {
333 * CKA_VALUE_LEN is not stored with the secret key object,
334 * so we remove it by shifting attributes down one.
336 (void) remove_one_attribute(newTemplate
, CKA_VALUE_LEN
,
337 attr_count
, B_FALSE
);
339 rv
= kernel_build_object(newTemplate
, attr_count
- 1,
340 new_objp
, session_p
, KERNEL_GEN_KEY
);
341 if (rv
!= CRYPTO_SUCCESS
) {
344 new_objp
->is_lib_obj
= B_TRUE
;
345 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
346 (void) free(newTemplate
);
347 bzero(key_buf
, key_len
);
348 (void) free(key_buf
);
352 free_attributes(obj_ngk
.ngk_in_attributes
, &obj_ngk
.ngk_in_count
);
353 free_attributes(obj_ngk
.ngk_out_attributes
, &obj_ngk
.ngk_out_count
);
354 if (key_buf
!= NULL
) {
355 bzero(key_buf
, key_len
);
356 (void) free(key_buf
);
358 if (newTemplate
!= NULL
) {
359 (void) free(newTemplate
);
365 C_GenerateKey(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
366 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
, CK_OBJECT_HANDLE_PTR phKey
)
369 kernel_session_t
*session_p
;
370 kernel_object_t
*new_objp
= NULL
;
371 kernel_slot_t
*pslot
;
372 boolean_t ses_lock_held
= B_FALSE
;
374 CK_BBOOL is_token_obj
= FALSE
;
375 crypto_mech_type_t k_mech_type
;
378 if (!kernel_initialized
)
379 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
381 /* Obtain the session pointer */
382 rv
= handle2session(hSession
, &session_p
);
386 if ((pMechanism
== NULL
) || (phKey
== NULL
)) {
387 rv
= CKR_ARGUMENTS_BAD
;
391 if ((pTemplate
== NULL
) && (ulCount
!= 0)) {
392 rv
= CKR_ARGUMENTS_BAD
;
396 /* Get the kernel's internal mechanism number. */
397 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
402 /* Create an object wrapper in the library first */
403 new_objp
= calloc(1, sizeof (kernel_object_t
));
404 if (new_objp
== NULL
) {
405 rv
= CKR_HOST_MEMORY
;
410 * Special Case: if token does not support object creation,
411 * but does support key generation by value, then create a session
412 * object and initialize with value returned by token.
414 pslot
= slot_table
[session_p
->ses_slotid
];
415 if (!pslot
->sl_func_list
.fl_object_create
) {
416 rv
= key_gen_by_value(pMechanism
, pTemplate
, ulCount
, session_p
,
417 k_mech_type
, new_objp
);
421 crypto_object_generate_key_t obj_gk
;
423 /* Process the attributes */
424 rv
= process_object_attributes(pTemplate
, ulCount
,
425 &obj_gk
.gk_attributes
, &is_token_obj
);
429 /* Cannot create a token object with a READ-ONLY session. */
430 if (is_token_obj
&& session_p
->ses_RO
) {
431 free_object_attributes(obj_gk
.gk_attributes
, ulCount
);
432 rv
= CKR_SESSION_READ_ONLY
;
436 /* Call the CRYPTO_GENERATE_KEY ioctl */
437 obj_gk
.gk_session
= session_p
->k_session
;
438 obj_gk
.gk_count
= ulCount
;
439 obj_gk
.gk_mechanism
.cm_type
= k_mech_type
;
440 obj_gk
.gk_mechanism
.cm_param
= pMechanism
->pParameter
;
441 obj_gk
.gk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
443 while ((r
= ioctl(kernel_fd
, CRYPTO_GENERATE_KEY
,
449 rv
= CKR_FUNCTION_FAILED
;
451 rv
= crypto2pkcs11_error_number(obj_gk
.gk_return_value
);
454 free_object_attributes(obj_gk
.gk_attributes
, ulCount
);
460 /* Get the value of the CKA_PRIVATE attribute. */
461 rv
= get_cka_private_value(session_p
, obj_gk
.gk_handle
,
468 * Store the kernel object handle in the object wrapper and
469 * initialize the library object.
471 new_objp
->k_handle
= obj_gk
.gk_handle
;
472 new_objp
->is_lib_obj
= B_FALSE
;
473 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
474 new_objp
->extra_attrlistp
= NULL
;
477 new_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
479 new_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
482 new_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
484 new_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
487 (void) pthread_mutex_init(&new_objp
->object_mutex
, NULL
);
488 new_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
491 * Add the new object to the slot's token object list if it is a
492 * a token object. Otherwise, add it to the session's object list.
495 pslot
= slot_table
[session_p
->ses_slotid
];
496 kernel_add_token_object_to_slot(new_objp
, pslot
);
498 kernel_add_object_to_session(new_objp
, session_p
);
501 *phKey
= (CK_OBJECT_HANDLE
)new_objp
;
502 REFRELE(session_p
, ses_lock_held
);
506 if (new_objp
!= NULL
) {
507 (void) free(new_objp
);
510 REFRELE(session_p
, ses_lock_held
);
515 key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism
,
516 CK_ATTRIBUTE_PTR pPublicKeyTemplate
, CK_ULONG ulPublicKeyAttributeCount
,
517 CK_ATTRIBUTE_PTR pPrivateKeyTemplate
, CK_ULONG ulPrivateKeyAttributeCount
,
518 kernel_session_t
*session_p
, crypto_mech_type_t k_mech_type
,
519 kernel_object_t
*new_pub_objp
, kernel_object_t
*new_pri_objp
)
521 crypto_nostore_generate_key_pair_t obj_nkp
;
522 CK_ATTRIBUTE_PTR pubTemplate
= NULL
;
523 CK_ATTRIBUTE_PTR priTemplate
= NULL
;
525 CK_BBOOL is_token_obj1
= FALSE
;
526 CK_BBOOL is_token_obj2
= FALSE
;
527 uint_t pub_attr_count
, pri_attr_count
;
528 uint_t pub_out_attr_count
= 0, pri_out_attr_count
= 0;
529 char public_modulus
[512];
530 char public_exponent
[8];
531 char private_exponent
[512];
532 char private_modulus
[512];
535 char exponent_1
[512];
536 char exponent_2
[512];
537 char coefficient
[512];
538 CK_ULONG pub_class
= CKO_PUBLIC_KEY
;
539 CK_ULONG pri_class
= CKO_PRIVATE_KEY
;
541 CK_ULONG modulus_bytes
;
542 boolean_t has_class
, has_key_type
, has_pub_exponent
;
545 obj_nkp
.nkp_in_public_count
= 0;
546 obj_nkp
.nkp_out_public_count
= 0;
547 obj_nkp
.nkp_in_private_count
= 0;
548 obj_nkp
.nkp_out_private_count
= 0;
550 /* modulus bits must be present when generating a RSA key pair */
551 if (!attribute_in_template(CKA_MODULUS_BITS
, pPublicKeyTemplate
,
552 ulPublicKeyAttributeCount
)) {
553 rv
= CKR_TEMPLATE_INCOMPLETE
;
557 modulus_bytes
= get_modulus_bytes(pPublicKeyTemplate
,
558 ulPublicKeyAttributeCount
);
561 * Add CKA_MODULUS to the public template.
562 * This attribute must not be in the template.
564 if (attribute_in_template(CKA_MODULUS
, pPublicKeyTemplate
,
565 ulPublicKeyAttributeCount
)) {
566 rv
= CKR_TEMPLATE_INCONSISTENT
;
569 has_class
= attribute_in_template(CKA_CLASS
, pPublicKeyTemplate
,
570 ulPublicKeyAttributeCount
);
571 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPublicKeyTemplate
,
572 ulPublicKeyAttributeCount
);
573 has_pub_exponent
= attribute_in_template(CKA_PUBLIC_EXPONENT
,
574 pPublicKeyTemplate
, ulPublicKeyAttributeCount
);
576 pub_attr_count
= ulPublicKeyAttributeCount
+ 1;
581 if (!has_pub_exponent
)
583 pubTemplate
= grow_template(pPublicKeyTemplate
,
584 ulPublicKeyAttributeCount
, pub_attr_count
);
585 if (pubTemplate
== NULL
) {
586 rv
= CKR_HOST_MEMORY
;
590 n
= ulPublicKeyAttributeCount
;
592 pubTemplate
[n
].type
= CKA_CLASS
;
593 pubTemplate
[n
].pValue
= (caddr_t
)&pub_class
;
594 pubTemplate
[n
].ulValueLen
= sizeof (pub_class
);
598 pubTemplate
[n
].type
= CKA_KEY_TYPE
;
600 pubTemplate
[n
].pValue
= (caddr_t
)&key_type
;
601 pubTemplate
[n
].ulValueLen
= sizeof (key_type
);
604 if (!has_pub_exponent
) {
605 pubTemplate
[n
].type
= CKA_PUBLIC_EXPONENT
;
606 pubTemplate
[n
].pValue
= (caddr_t
)public_exponent
;
607 pubTemplate
[n
].ulValueLen
= modulus_bytes
;
609 pub_out_attr_count
++;
611 pubTemplate
[n
].type
= CKA_MODULUS
;
612 pubTemplate
[n
].pValue
= (caddr_t
)public_modulus
;
613 pubTemplate
[n
].ulValueLen
= modulus_bytes
;
614 pub_out_attr_count
++;
616 rv
= process_object_attributes(pubTemplate
,
617 pub_attr_count
- pub_out_attr_count
,
618 &obj_nkp
.nkp_in_public_attributes
, &is_token_obj1
);
622 obj_nkp
.nkp_in_public_count
= pub_attr_count
- pub_out_attr_count
;
624 rv
= process_object_attributes(
625 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
626 pub_out_attr_count
, &obj_nkp
.nkp_out_public_attributes
,
631 obj_nkp
.nkp_out_public_count
= pub_out_attr_count
;
634 * Cannot create a token object with a READ-ONLY
637 if (is_token_obj1
&& session_p
->ses_RO
) {
638 rv
= CKR_SESSION_READ_ONLY
;
643 * Add CKA_MODULUS and CKA_PRIVATE_EXPONENT
644 * to the private template. These attributes
645 * must not be in the template.
647 if (attribute_in_template(CKA_PRIVATE_EXPONENT
,
648 pPrivateKeyTemplate
, ulPrivateKeyAttributeCount
) ||
649 attribute_in_template(CKA_MODULUS
,
650 pPrivateKeyTemplate
, ulPrivateKeyAttributeCount
)) {
651 rv
= CKR_TEMPLATE_INCONSISTENT
;
654 has_class
= attribute_in_template(CKA_CLASS
, pPrivateKeyTemplate
,
655 ulPrivateKeyAttributeCount
);
656 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPrivateKeyTemplate
,
657 ulPrivateKeyAttributeCount
);
659 pri_attr_count
= ulPrivateKeyAttributeCount
+ 7;
665 /* allocate space for CKA_PUBLIC_EXPONENT */
666 priTemplate
= grow_template(pPrivateKeyTemplate
,
667 ulPrivateKeyAttributeCount
, pri_attr_count
+ 1);
668 if (priTemplate
== NULL
) {
669 rv
= CKR_HOST_MEMORY
;
672 n
= ulPrivateKeyAttributeCount
;
674 priTemplate
[n
].type
= CKA_CLASS
;
675 priTemplate
[n
].pValue
= (caddr_t
)&pri_class
;
676 priTemplate
[n
].ulValueLen
= sizeof (pri_class
);
680 priTemplate
[n
].type
= CKA_KEY_TYPE
;
682 priTemplate
[n
].pValue
= (caddr_t
)&key_type
;
683 priTemplate
[n
].ulValueLen
= sizeof (key_type
);
686 priTemplate
[n
].type
= CKA_MODULUS
;
687 priTemplate
[n
].pValue
= (caddr_t
)private_modulus
;
688 priTemplate
[n
].ulValueLen
= modulus_bytes
;
689 pri_out_attr_count
++;
692 priTemplate
[n
].type
= CKA_PRIVATE_EXPONENT
;
693 priTemplate
[n
].pValue
= (caddr_t
)private_exponent
;
694 priTemplate
[n
].ulValueLen
= modulus_bytes
;
695 pri_out_attr_count
++;
698 priTemplate
[n
].type
= CKA_PRIME_1
;
699 priTemplate
[n
].pValue
= (caddr_t
)prime_1
;
700 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
701 pri_out_attr_count
++;
704 priTemplate
[n
].type
= CKA_PRIME_2
;
705 priTemplate
[n
].pValue
= (caddr_t
)prime_2
;
706 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
707 pri_out_attr_count
++;
710 priTemplate
[n
].type
= CKA_EXPONENT_1
;
711 priTemplate
[n
].pValue
= (caddr_t
)exponent_1
;
712 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
713 pri_out_attr_count
++;
716 priTemplate
[n
].type
= CKA_EXPONENT_2
;
717 priTemplate
[n
].pValue
= (caddr_t
)exponent_2
;
718 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
719 pri_out_attr_count
++;
722 priTemplate
[n
].type
= CKA_COEFFICIENT
;
723 priTemplate
[n
].pValue
= (caddr_t
)coefficient
;
724 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
725 pri_out_attr_count
++;
727 rv
= process_object_attributes(priTemplate
,
728 pri_attr_count
- pri_out_attr_count
,
729 &obj_nkp
.nkp_in_private_attributes
, &is_token_obj2
);
733 obj_nkp
.nkp_in_private_count
= pri_attr_count
- pri_out_attr_count
;
735 rv
= process_object_attributes(
736 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
737 pri_out_attr_count
, &obj_nkp
.nkp_out_private_attributes
,
742 obj_nkp
.nkp_out_private_count
= pri_out_attr_count
;
745 * The public key and the private key need to contain the same
746 * attribute values for CKA_TOKEN.
748 if (is_token_obj1
!= is_token_obj2
) {
749 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
753 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
754 obj_nkp
.nkp_session
= session_p
-> k_session
;
755 obj_nkp
.nkp_mechanism
.cm_type
= k_mech_type
;
756 obj_nkp
.nkp_mechanism
.cm_param
= pMechanism
->pParameter
;
757 obj_nkp
.nkp_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
759 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_GENERATE_KEY_PAIR
,
765 rv
= CKR_FUNCTION_FAILED
;
767 rv
= crypto2pkcs11_error_number(obj_nkp
.nkp_return_value
);
769 free_attributes(obj_nkp
.nkp_in_public_attributes
,
770 &obj_nkp
.nkp_in_public_count
);
771 free_attributes(obj_nkp
.nkp_in_private_attributes
,
772 &obj_nkp
.nkp_in_private_count
);
778 rv
= get_object_attributes(
779 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
780 pub_out_attr_count
, obj_nkp
.nkp_out_public_attributes
);
781 if (rv
== CRYPTO_SUCCESS
) {
782 rv
= get_object_attributes(
783 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
784 pri_out_attr_count
, obj_nkp
.nkp_out_private_attributes
);
786 free_attributes(obj_nkp
.nkp_out_public_attributes
,
787 &obj_nkp
.nkp_out_public_count
);
788 free_attributes(obj_nkp
.nkp_out_private_attributes
,
789 &obj_nkp
.nkp_out_private_count
);
790 if (rv
!= CRYPTO_SUCCESS
) {
794 /* store generated modulus and public exponent */
795 rv
= kernel_build_object(pubTemplate
, pub_attr_count
, new_pub_objp
,
796 session_p
, KERNEL_GEN_KEY
);
797 if (rv
!= CRYPTO_SUCCESS
) {
802 * Copy CKA_PUBLIC_EXPONENT from the public template
803 * to the private template.
805 rv
= copy_attribute(CKA_PUBLIC_EXPONENT
, pubTemplate
,
806 pub_attr_count
, &priTemplate
[pri_attr_count
]);
807 if (rv
!= CRYPTO_SUCCESS
) {
811 rv
= kernel_build_object(priTemplate
, pri_attr_count
+ 1, new_pri_objp
,
812 session_p
, KERNEL_GEN_KEY
);
813 (void) free(priTemplate
[pri_attr_count
].pValue
);
814 if (rv
!= CRYPTO_SUCCESS
) {
817 (void) free(pubTemplate
);
818 (void) free(priTemplate
);
820 new_pub_objp
->is_lib_obj
= B_TRUE
;
821 new_pri_objp
->is_lib_obj
= B_TRUE
;
822 new_pub_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
823 new_pri_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
824 (void) pthread_mutex_init(&new_pub_objp
->object_mutex
, NULL
);
825 new_pub_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
826 (void) pthread_mutex_init(&new_pri_objp
->object_mutex
, NULL
);
827 new_pri_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
831 free_attributes(obj_nkp
.nkp_in_public_attributes
,
832 &obj_nkp
.nkp_in_public_count
);
833 free_attributes(obj_nkp
.nkp_out_public_attributes
,
834 &obj_nkp
.nkp_out_public_count
);
835 free_attributes(obj_nkp
.nkp_in_private_attributes
,
836 &obj_nkp
.nkp_in_private_count
);
837 free_attributes(obj_nkp
.nkp_out_private_attributes
,
838 &obj_nkp
.nkp_out_private_count
);
839 if (pubTemplate
!= NULL
) {
840 (void) free(pubTemplate
);
842 if (priTemplate
!= NULL
) {
843 (void) free(priTemplate
);
849 key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism
,
850 CK_ATTRIBUTE_PTR pPublicKeyTemplate
, CK_ULONG ulPublicKeyAttributeCount
,
851 CK_ATTRIBUTE_PTR pPrivateKeyTemplate
, CK_ULONG ulPrivateKeyAttributeCount
,
852 kernel_session_t
*session_p
, crypto_mech_type_t k_mech_type
,
853 kernel_object_t
*new_pub_objp
, kernel_object_t
*new_pri_objp
)
855 crypto_nostore_generate_key_pair_t obj_nkp
;
856 CK_ATTRIBUTE_PTR pubTemplate
= NULL
;
857 CK_ATTRIBUTE_PTR priTemplate
= NULL
;
859 CK_BBOOL is_token_obj1
= FALSE
;
860 CK_BBOOL is_token_obj2
= FALSE
;
861 uint_t pub_attr_count
, pri_attr_count
;
862 uint_t pub_out_attr_count
= 0, pri_out_attr_count
= 0;
863 char public_value
[256];
864 char private_value
[256];
865 CK_ULONG pub_class
= CKO_PUBLIC_KEY
;
866 CK_ULONG pri_class
= CKO_PRIVATE_KEY
;
868 boolean_t has_class
, has_key_type
;
871 obj_nkp
.nkp_in_public_count
= 0;
872 obj_nkp
.nkp_out_public_count
= 0;
873 obj_nkp
.nkp_in_private_count
= 0;
874 obj_nkp
.nkp_out_private_count
= 0;
877 * Add CKA_VALUE to the public template.
878 * This attribute must not be in the template.
880 if (attribute_in_template(CKA_VALUE
, pPublicKeyTemplate
,
881 ulPublicKeyAttributeCount
)) {
882 rv
= CKR_TEMPLATE_INCONSISTENT
;
885 has_class
= attribute_in_template(CKA_CLASS
, pPublicKeyTemplate
,
886 ulPublicKeyAttributeCount
);
887 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPublicKeyTemplate
,
888 ulPublicKeyAttributeCount
);
890 pub_attr_count
= ulPublicKeyAttributeCount
+ 1;
895 pubTemplate
= grow_template(pPublicKeyTemplate
,
896 ulPublicKeyAttributeCount
, pub_attr_count
);
897 if (pubTemplate
== NULL
) {
898 rv
= CKR_HOST_MEMORY
;
902 n
= ulPublicKeyAttributeCount
;
904 pubTemplate
[n
].type
= CKA_CLASS
;
905 pubTemplate
[n
].pValue
= (caddr_t
)&pub_class
;
906 pubTemplate
[n
].ulValueLen
= sizeof (pub_class
);
910 pubTemplate
[n
].type
= CKA_KEY_TYPE
;
912 pubTemplate
[n
].pValue
= (caddr_t
)&key_type
;
913 pubTemplate
[n
].ulValueLen
= sizeof (key_type
);
916 pubTemplate
[n
].type
= CKA_VALUE
;
917 pubTemplate
[n
].pValue
= (caddr_t
)public_value
;
918 pubTemplate
[n
].ulValueLen
= sizeof (public_value
);
919 pub_out_attr_count
++;
921 rv
= process_object_attributes(pubTemplate
,
922 pub_attr_count
- pub_out_attr_count
,
923 &obj_nkp
.nkp_in_public_attributes
, &is_token_obj1
);
927 obj_nkp
.nkp_in_public_count
= pub_attr_count
- pub_out_attr_count
;
929 rv
= process_object_attributes(
930 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
931 pub_out_attr_count
, &obj_nkp
.nkp_out_public_attributes
,
936 obj_nkp
.nkp_out_public_count
= pub_out_attr_count
;
939 * Cannot create a token object with a READ-ONLY
942 if (is_token_obj1
&& session_p
->ses_RO
) {
943 rv
= CKR_SESSION_READ_ONLY
;
948 * CKA_BASE, CKA_PRIME, and CKA_VALUE must not appear
949 * in private template.
951 if (attribute_in_template(CKA_BASE
, pPrivateKeyTemplate
,
952 ulPrivateKeyAttributeCount
) ||
953 attribute_in_template(CKA_PRIME
, pPrivateKeyTemplate
,
954 ulPrivateKeyAttributeCount
) ||
955 attribute_in_template(CKA_VALUE
, pPrivateKeyTemplate
,
956 ulPrivateKeyAttributeCount
)) {
957 rv
= CKR_TEMPLATE_INCONSISTENT
;
961 if (attribute_in_template(CKA_VALUE
, pPrivateKeyTemplate
,
962 ulPrivateKeyAttributeCount
)) {
963 rv
= CKR_TEMPLATE_INCONSISTENT
;
966 has_class
= attribute_in_template(CKA_CLASS
, pPrivateKeyTemplate
,
967 ulPrivateKeyAttributeCount
);
968 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPrivateKeyTemplate
,
969 ulPrivateKeyAttributeCount
);
971 pri_attr_count
= ulPrivateKeyAttributeCount
+ 1;
977 /* allocate space for CKA_BASE and CKA_PRIME */
978 priTemplate
= grow_template(pPrivateKeyTemplate
,
979 ulPrivateKeyAttributeCount
, pri_attr_count
+ 2);
980 if (priTemplate
== NULL
) {
981 rv
= CKR_HOST_MEMORY
;
984 n
= ulPrivateKeyAttributeCount
;
986 priTemplate
[n
].type
= CKA_CLASS
;
987 priTemplate
[n
].pValue
= (caddr_t
)&pri_class
;
988 priTemplate
[n
].ulValueLen
= sizeof (pri_class
);
992 priTemplate
[n
].type
= CKA_KEY_TYPE
;
994 priTemplate
[n
].pValue
= (caddr_t
)&key_type
;
995 priTemplate
[n
].ulValueLen
= sizeof (key_type
);
998 priTemplate
[n
].type
= CKA_VALUE
;
999 priTemplate
[n
].pValue
= (caddr_t
)private_value
;
1000 priTemplate
[n
].ulValueLen
= sizeof (private_value
);
1001 pri_out_attr_count
++;
1003 rv
= process_object_attributes(priTemplate
,
1004 pri_attr_count
- pri_out_attr_count
,
1005 &obj_nkp
.nkp_in_private_attributes
, &is_token_obj2
);
1009 obj_nkp
.nkp_in_private_count
= pri_attr_count
- pri_out_attr_count
;
1011 rv
= process_object_attributes(
1012 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
1013 pri_out_attr_count
, &obj_nkp
.nkp_out_private_attributes
,
1018 obj_nkp
.nkp_out_private_count
= pri_out_attr_count
;
1021 * The public key and the private key need to contain the same
1022 * attribute values for CKA_TOKEN.
1024 if (is_token_obj1
!= is_token_obj2
) {
1025 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
1029 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
1030 obj_nkp
.nkp_session
= session_p
-> k_session
;
1031 obj_nkp
.nkp_mechanism
.cm_type
= k_mech_type
;
1032 obj_nkp
.nkp_mechanism
.cm_param
= pMechanism
->pParameter
;
1033 obj_nkp
.nkp_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1035 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_GENERATE_KEY_PAIR
,
1041 rv
= CKR_FUNCTION_FAILED
;
1043 rv
= crypto2pkcs11_error_number(obj_nkp
.nkp_return_value
);
1045 free_attributes(obj_nkp
.nkp_in_public_attributes
,
1046 &obj_nkp
.nkp_in_public_count
);
1047 free_attributes(obj_nkp
.nkp_in_private_attributes
,
1048 &obj_nkp
.nkp_in_private_count
);
1054 rv
= get_object_attributes(
1055 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
1056 pub_out_attr_count
, obj_nkp
.nkp_out_public_attributes
);
1057 if (rv
== CRYPTO_SUCCESS
) {
1058 rv
= get_object_attributes(
1059 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
1060 pri_out_attr_count
, obj_nkp
.nkp_out_private_attributes
);
1062 free_attributes(obj_nkp
.nkp_out_public_attributes
,
1063 &obj_nkp
.nkp_out_public_count
);
1064 free_attributes(obj_nkp
.nkp_out_private_attributes
,
1065 &obj_nkp
.nkp_out_private_count
);
1067 if (rv
!= CRYPTO_SUCCESS
) {
1071 rv
= kernel_build_object(pubTemplate
, pub_attr_count
, new_pub_objp
,
1072 session_p
, KERNEL_GEN_KEY
);
1073 if (rv
!= CRYPTO_SUCCESS
) {
1078 * Copy CKA_BASE and CKA_PRIME from the public template
1079 * to the private template.
1081 rv
= copy_attribute(CKA_BASE
, pubTemplate
, pub_attr_count
,
1082 &priTemplate
[pri_attr_count
]);
1083 if (rv
!= CRYPTO_SUCCESS
) {
1086 rv
= copy_attribute(CKA_PRIME
, pubTemplate
, pub_attr_count
,
1087 &priTemplate
[pri_attr_count
+ 1]);
1088 if (rv
!= CRYPTO_SUCCESS
) {
1089 (void) free(priTemplate
[pri_attr_count
].pValue
);
1093 /* +2 to account for CKA_BASE and CKA_PRIME */
1094 rv
= kernel_build_object(priTemplate
, pri_attr_count
+ 2,
1095 new_pri_objp
, session_p
, KERNEL_GEN_KEY
);
1096 (void) free(priTemplate
[pri_attr_count
].pValue
);
1097 (void) free(priTemplate
[pri_attr_count
+ 1].pValue
);
1098 if (rv
!= CRYPTO_SUCCESS
) {
1101 (void) free(pubTemplate
);
1102 (void) free(priTemplate
);
1104 new_pub_objp
->is_lib_obj
= B_TRUE
;
1105 new_pri_objp
->is_lib_obj
= B_TRUE
;
1106 new_pub_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1107 new_pri_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1108 (void) pthread_mutex_init(&new_pub_objp
->object_mutex
, NULL
);
1109 new_pub_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1110 (void) pthread_mutex_init(&new_pri_objp
->object_mutex
, NULL
);
1111 new_pri_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1115 free_attributes(obj_nkp
.nkp_in_public_attributes
,
1116 &obj_nkp
.nkp_in_public_count
);
1117 free_attributes(obj_nkp
.nkp_out_public_attributes
,
1118 &obj_nkp
.nkp_out_public_count
);
1119 free_attributes(obj_nkp
.nkp_in_private_attributes
,
1120 &obj_nkp
.nkp_in_private_count
);
1121 free_attributes(obj_nkp
.nkp_out_private_attributes
,
1122 &obj_nkp
.nkp_out_private_count
);
1123 if (pubTemplate
!= NULL
) {
1124 (void) free(pubTemplate
);
1126 if (priTemplate
!= NULL
) {
1127 (void) free(priTemplate
);
1133 key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism
,
1134 CK_ATTRIBUTE_PTR pPublicKeyTemplate
, CK_ULONG ulPublicKeyAttributeCount
,
1135 CK_ATTRIBUTE_PTR pPrivateKeyTemplate
, CK_ULONG ulPrivateKeyAttributeCount
,
1136 kernel_session_t
*session_p
, crypto_mech_type_t k_mech_type
,
1137 kernel_object_t
*new_pub_objp
, kernel_object_t
*new_pri_objp
)
1139 crypto_nostore_generate_key_pair_t obj_nkp
;
1140 CK_ATTRIBUTE_PTR pubTemplate
= NULL
;
1141 CK_ATTRIBUTE_PTR priTemplate
= NULL
;
1143 CK_BBOOL is_token_obj1
= FALSE
;
1144 CK_BBOOL is_token_obj2
= FALSE
;
1145 uint_t pub_attr_count
, pri_attr_count
;
1146 uint_t pub_out_attr_count
= 0, pri_out_attr_count
= 0;
1147 char value
[EC_MAX_VALUE_LEN
];
1148 char point
[EC_MAX_POINT_LEN
];
1149 CK_ULONG pub_class
= CKO_PUBLIC_KEY
;
1150 CK_ULONG pri_class
= CKO_PRIVATE_KEY
;
1152 boolean_t has_class
, has_key_type
;
1155 obj_nkp
.nkp_in_public_count
= 0;
1156 obj_nkp
.nkp_out_public_count
= 0;
1157 obj_nkp
.nkp_in_private_count
= 0;
1158 obj_nkp
.nkp_out_private_count
= 0;
1161 * Add CKA_EC_POINT to the public template.
1162 * This is the generated value Q. This attribute
1163 * must not be in the template.
1165 if (attribute_in_template(CKA_EC_POINT
, pPublicKeyTemplate
,
1166 ulPublicKeyAttributeCount
)) {
1167 rv
= CKR_TEMPLATE_INCONSISTENT
;
1170 has_class
= attribute_in_template(CKA_CLASS
, pPublicKeyTemplate
,
1171 ulPublicKeyAttributeCount
);
1172 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPublicKeyTemplate
,
1173 ulPublicKeyAttributeCount
);
1175 pub_attr_count
= ulPublicKeyAttributeCount
+ 1;
1180 pubTemplate
= grow_template(pPublicKeyTemplate
,
1181 ulPublicKeyAttributeCount
, pub_attr_count
);
1182 if (pubTemplate
== NULL
) {
1183 rv
= CKR_HOST_MEMORY
;
1187 n
= ulPublicKeyAttributeCount
;
1189 pubTemplate
[n
].type
= CKA_CLASS
;
1190 pubTemplate
[n
].pValue
= (caddr_t
)&pub_class
;
1191 pubTemplate
[n
].ulValueLen
= sizeof (pub_class
);
1194 if (!has_key_type
) {
1195 pubTemplate
[n
].type
= CKA_KEY_TYPE
;
1197 pubTemplate
[n
].pValue
= (caddr_t
)&key_type
;
1198 pubTemplate
[n
].ulValueLen
= sizeof (key_type
);
1201 pubTemplate
[n
].type
= CKA_EC_POINT
;
1202 pubTemplate
[n
].pValue
= (caddr_t
)point
;
1203 pubTemplate
[n
].ulValueLen
= sizeof (point
);
1204 pub_out_attr_count
++;
1206 rv
= process_object_attributes(pubTemplate
,
1207 pub_attr_count
- pub_out_attr_count
,
1208 &obj_nkp
.nkp_in_public_attributes
, &is_token_obj1
);
1212 obj_nkp
.nkp_in_public_count
= pub_attr_count
- pub_out_attr_count
;
1214 rv
= process_object_attributes(
1215 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
1216 pub_out_attr_count
, &obj_nkp
.nkp_out_public_attributes
,
1221 obj_nkp
.nkp_out_public_count
= pub_out_attr_count
;
1224 * Cannot create a token object with a READ-ONLY
1227 if (is_token_obj1
&& session_p
->ses_RO
) {
1228 rv
= CKR_SESSION_READ_ONLY
;
1233 * CKA_EC_PARAMS and CKA_VALUE must not appear in
1236 if (attribute_in_template(CKA_EC_PARAMS
, pPrivateKeyTemplate
,
1237 ulPrivateKeyAttributeCount
) ||
1238 attribute_in_template(CKA_VALUE
, pPrivateKeyTemplate
,
1239 ulPrivateKeyAttributeCount
)) {
1240 rv
= CKR_TEMPLATE_INCONSISTENT
;
1243 has_class
= attribute_in_template(CKA_CLASS
, pPrivateKeyTemplate
,
1244 ulPrivateKeyAttributeCount
);
1245 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPrivateKeyTemplate
,
1246 ulPrivateKeyAttributeCount
);
1248 pri_attr_count
= ulPrivateKeyAttributeCount
+ 1;
1254 /* allocate space for CKA_EC_PARAMS */
1255 priTemplate
= grow_template(pPrivateKeyTemplate
,
1256 ulPrivateKeyAttributeCount
, pri_attr_count
+ 1);
1257 if (priTemplate
== NULL
) {
1258 rv
= CKR_HOST_MEMORY
;
1261 n
= ulPrivateKeyAttributeCount
;
1263 priTemplate
[n
].type
= CKA_CLASS
;
1264 priTemplate
[n
].pValue
= (caddr_t
)&pri_class
;
1265 priTemplate
[n
].ulValueLen
= sizeof (pri_class
);
1268 if (!has_key_type
) {
1269 priTemplate
[n
].type
= CKA_KEY_TYPE
;
1271 priTemplate
[n
].pValue
= (caddr_t
)&key_type
;
1272 priTemplate
[n
].ulValueLen
= sizeof (key_type
);
1275 priTemplate
[n
].type
= CKA_VALUE
;
1276 priTemplate
[n
].pValue
= (caddr_t
)value
;
1277 priTemplate
[n
].ulValueLen
= sizeof (value
);
1278 pri_out_attr_count
++;
1280 rv
= process_object_attributes(priTemplate
,
1281 pri_attr_count
- pri_out_attr_count
,
1282 &obj_nkp
.nkp_in_private_attributes
, &is_token_obj2
);
1286 obj_nkp
.nkp_in_private_count
= pri_attr_count
- pri_out_attr_count
;
1288 rv
= process_object_attributes(
1289 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
1290 pri_out_attr_count
, &obj_nkp
.nkp_out_private_attributes
,
1295 obj_nkp
.nkp_out_private_count
= pri_out_attr_count
;
1298 * The public key and the private key need to contain the same
1299 * attribute values for CKA_TOKEN.
1301 if (is_token_obj1
!= is_token_obj2
) {
1302 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
1306 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
1307 obj_nkp
.nkp_session
= session_p
-> k_session
;
1308 obj_nkp
.nkp_mechanism
.cm_type
= k_mech_type
;
1309 obj_nkp
.nkp_mechanism
.cm_param
= pMechanism
->pParameter
;
1310 obj_nkp
.nkp_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1312 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_GENERATE_KEY_PAIR
,
1318 rv
= CKR_FUNCTION_FAILED
;
1320 rv
= crypto2pkcs11_error_number(obj_nkp
.nkp_return_value
);
1322 free_attributes(obj_nkp
.nkp_in_public_attributes
,
1323 &obj_nkp
.nkp_in_public_count
);
1324 free_attributes(obj_nkp
.nkp_in_private_attributes
,
1325 &obj_nkp
.nkp_in_private_count
);
1331 rv
= get_object_attributes(
1332 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
1333 pub_out_attr_count
, obj_nkp
.nkp_out_public_attributes
);
1334 if (rv
== CRYPTO_SUCCESS
) {
1335 rv
= get_object_attributes(
1336 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
1337 pri_out_attr_count
, obj_nkp
.nkp_out_private_attributes
);
1339 free_attributes(obj_nkp
.nkp_out_public_attributes
,
1340 &obj_nkp
.nkp_out_public_count
);
1341 free_attributes(obj_nkp
.nkp_out_private_attributes
,
1342 &obj_nkp
.nkp_out_private_count
);
1343 if (rv
!= CRYPTO_SUCCESS
) {
1347 rv
= kernel_build_object(pubTemplate
, pub_attr_count
, new_pub_objp
,
1348 session_p
, KERNEL_GEN_KEY
);
1349 if (rv
!= CRYPTO_SUCCESS
) {
1354 * Copy CKA_EC_PARAMS from the public template to the
1357 rv
= copy_attribute(CKA_EC_PARAMS
, pubTemplate
, pub_attr_count
,
1358 &priTemplate
[pri_attr_count
]);
1359 if (rv
!= CRYPTO_SUCCESS
) {
1363 /* +1 to account for CKA_EC_PARAMS */
1364 rv
= kernel_build_object(priTemplate
, pri_attr_count
+ 1,
1365 new_pri_objp
, session_p
, KERNEL_GEN_KEY
);
1366 (void) free(priTemplate
[pri_attr_count
].pValue
);
1367 if (rv
!= CRYPTO_SUCCESS
) {
1370 (void) free(pubTemplate
);
1371 (void) free(priTemplate
);
1373 new_pub_objp
->is_lib_obj
= B_TRUE
;
1374 new_pri_objp
->is_lib_obj
= B_TRUE
;
1375 new_pub_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1376 new_pri_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1377 (void) pthread_mutex_init(&new_pub_objp
->object_mutex
, NULL
);
1378 new_pub_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1379 (void) pthread_mutex_init(&new_pri_objp
->object_mutex
, NULL
);
1380 new_pri_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1384 free_attributes(obj_nkp
.nkp_in_public_attributes
,
1385 &obj_nkp
.nkp_in_public_count
);
1386 free_attributes(obj_nkp
.nkp_out_public_attributes
,
1387 &obj_nkp
.nkp_out_public_count
);
1388 free_attributes(obj_nkp
.nkp_in_private_attributes
,
1389 &obj_nkp
.nkp_in_private_count
);
1390 free_attributes(obj_nkp
.nkp_out_private_attributes
,
1391 &obj_nkp
.nkp_out_private_count
);
1392 if (pubTemplate
!= NULL
) {
1393 (void) free(pubTemplate
);
1395 if (priTemplate
!= NULL
) {
1396 (void) free(priTemplate
);
1402 C_GenerateKeyPair(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
1403 CK_ATTRIBUTE_PTR pPublicKeyTemplate
, CK_ULONG ulPublicKeyAttributeCount
,
1404 CK_ATTRIBUTE_PTR pPrivateKeyTemplate
, CK_ULONG ulPrivateKeyAttributeCount
,
1405 CK_OBJECT_HANDLE_PTR phPublicKey
, CK_OBJECT_HANDLE_PTR phPrivateKey
)
1408 kernel_session_t
*session_p
;
1409 kernel_object_t
*new_pub_objp
= NULL
;
1410 kernel_object_t
*new_pri_objp
= NULL
;
1411 kernel_slot_t
*pslot
;
1412 boolean_t ses_lock_held
= B_FALSE
;
1413 CK_BBOOL is_pri_obj1
;
1414 CK_BBOOL is_pri_obj2
;
1415 CK_BBOOL is_token_obj1
= FALSE
;
1416 CK_BBOOL is_token_obj2
= FALSE
;
1417 crypto_mech_type_t k_mech_type
;
1419 CK_RV (*func
)(CK_MECHANISM_PTR
, CK_ATTRIBUTE_PTR
, CK_ULONG
,
1420 CK_ATTRIBUTE_PTR
, CK_ULONG
, kernel_session_t
*, crypto_mech_type_t
,
1421 kernel_object_t
*, kernel_object_t
*);
1423 if (!kernel_initialized
)
1424 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
1426 /* Obtain the session pointer. */
1427 rv
= handle2session(hSession
, &session_p
);
1431 if ((pMechanism
== NULL
) || (phPublicKey
== NULL
) ||
1432 (phPrivateKey
== NULL
)) {
1433 rv
= CKR_ARGUMENTS_BAD
;
1437 if ((pPublicKeyTemplate
== NULL
) && (ulPublicKeyAttributeCount
!= 0)) {
1438 rv
= CKR_ARGUMENTS_BAD
;
1442 if ((pPrivateKeyTemplate
== NULL
) &&
1443 (ulPrivateKeyAttributeCount
!= 0)) {
1444 rv
= CKR_ARGUMENTS_BAD
;
1448 /* Get the kernel's internal mechanism number. */
1449 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
1454 /* Create an object wrapper for the public key */
1455 new_pub_objp
= calloc(1, sizeof (kernel_object_t
));
1456 if (new_pub_objp
== NULL
) {
1457 rv
= CKR_HOST_MEMORY
;
1461 /* Create an object wrapper for the private key. */
1462 new_pri_objp
= calloc(1, sizeof (kernel_object_t
));
1463 if (new_pri_objp
== NULL
) {
1464 rv
= CKR_HOST_MEMORY
;
1469 * Special Case: if token does not support object creation,
1470 * but does support key generation by value, then create a session
1471 * object and initialize with values returned by token.
1473 pslot
= slot_table
[session_p
->ses_slotid
];
1474 if (!pslot
->sl_func_list
.fl_object_create
) {
1475 switch (pMechanism
->mechanism
) {
1476 case CKM_RSA_PKCS_KEY_PAIR_GEN
:
1477 func
= key_gen_rsa_by_value
;
1480 case CKM_DH_PKCS_KEY_PAIR_GEN
:
1481 func
= key_gen_dh_by_value
;
1484 case CKM_EC_KEY_PAIR_GEN
:
1485 func
= key_gen_ec_by_value
;
1489 rv
= CKR_MECHANISM_INVALID
;
1492 rv
= (*func
)(pMechanism
, pPublicKeyTemplate
,
1493 ulPublicKeyAttributeCount
, pPrivateKeyTemplate
,
1494 ulPrivateKeyAttributeCount
, session_p
, k_mech_type
,
1495 new_pub_objp
, new_pri_objp
);
1499 crypto_object_generate_key_pair_t obj_kp
;
1501 /* Process the public key attributes. */
1502 rv
= process_object_attributes(pPublicKeyTemplate
,
1503 ulPublicKeyAttributeCount
, &obj_kp
.kp_public_attributes
,
1509 /* Cannot create a token object with a READ-ONLY session. */
1510 if (is_token_obj1
&& session_p
->ses_RO
) {
1511 free_object_attributes(obj_kp
.kp_public_attributes
,
1512 ulPublicKeyAttributeCount
);
1513 rv
= CKR_SESSION_READ_ONLY
;
1517 /* Process the private key attributes. */
1518 rv
= process_object_attributes(pPrivateKeyTemplate
,
1519 ulPrivateKeyAttributeCount
, &obj_kp
.kp_private_attributes
,
1522 free_object_attributes(obj_kp
.kp_public_attributes
,
1523 ulPublicKeyAttributeCount
);
1528 * The public key and the private key need to contain the same
1529 * attribute values for CKA_TOKEN.
1531 if (is_token_obj1
!= is_token_obj2
) {
1532 free_object_attributes(obj_kp
.kp_public_attributes
,
1533 ulPublicKeyAttributeCount
);
1534 free_object_attributes(obj_kp
.kp_private_attributes
,
1535 ulPrivateKeyAttributeCount
);
1536 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
1540 /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */
1541 obj_kp
.kp_session
= session_p
-> k_session
;
1542 obj_kp
.kp_mechanism
.cm_type
= k_mech_type
;
1543 obj_kp
.kp_mechanism
.cm_param
= pMechanism
->pParameter
;
1544 obj_kp
.kp_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1545 obj_kp
.kp_public_count
= ulPublicKeyAttributeCount
;
1546 obj_kp
.kp_private_count
= ulPrivateKeyAttributeCount
;
1548 while ((r
= ioctl(kernel_fd
, CRYPTO_GENERATE_KEY_PAIR
,
1554 rv
= CKR_FUNCTION_FAILED
;
1556 rv
= crypto2pkcs11_error_number(obj_kp
.kp_return_value
);
1558 free_object_attributes(obj_kp
.kp_public_attributes
,
1559 ulPublicKeyAttributeCount
);
1560 free_object_attributes(obj_kp
.kp_private_attributes
,
1561 ulPrivateKeyAttributeCount
);
1566 /* Get the CKA_PRIVATE value for the key pair. */
1567 rv
= get_cka_private_value(session_p
, obj_kp
.kp_public_handle
,
1573 rv
= get_cka_private_value(session_p
, obj_kp
.kp_private_handle
,
1580 * Store the kernel public key handle into the public key
1581 * object and finish the public key object initialization.
1583 new_pub_objp
->is_lib_obj
= B_FALSE
;
1584 new_pub_objp
->k_handle
= obj_kp
.kp_public_handle
;
1585 new_pub_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1586 new_pub_objp
->extra_attrlistp
= NULL
;
1589 new_pub_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
1591 new_pub_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
1594 new_pub_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
1596 new_pub_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
1598 (void) pthread_mutex_init(&new_pub_objp
->object_mutex
, NULL
);
1599 new_pub_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1602 * Store the kernel private key handle into the private key
1603 * object and finish the private key object initialization.
1605 new_pri_objp
->is_lib_obj
= B_FALSE
;
1606 new_pri_objp
->k_handle
= obj_kp
.kp_private_handle
;
1607 new_pri_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1608 new_pri_objp
->extra_attrlistp
= NULL
;
1611 new_pri_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
1613 new_pri_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
1616 new_pri_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
1618 new_pri_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
1621 (void) pthread_mutex_init(&new_pri_objp
->object_mutex
, NULL
);
1622 new_pri_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1625 * Add the new pub/pri objects to the slot's token list if they are
1626 * token objects. Otherwise, add them to the session's object list.
1628 if (is_token_obj1
) { /* is_token_obj1 == is_token_obj2 */
1629 pslot
= slot_table
[session_p
->ses_slotid
];
1630 kernel_add_token_object_to_slot(new_pub_objp
, pslot
);
1631 kernel_add_token_object_to_slot(new_pri_objp
, pslot
);
1633 kernel_add_object_to_session(new_pub_objp
, session_p
);
1634 kernel_add_object_to_session(new_pri_objp
, session_p
);
1637 *phPublicKey
= (CK_OBJECT_HANDLE
)new_pub_objp
;
1638 *phPrivateKey
= (CK_OBJECT_HANDLE
)new_pri_objp
;
1639 REFRELE(session_p
, ses_lock_held
);
1643 if (new_pub_objp
!= NULL
) {
1644 (void) free(new_pub_objp
);
1646 if (new_pri_objp
!= NULL
) {
1647 (void) free(new_pri_objp
);
1649 REFRELE(session_p
, ses_lock_held
);
1655 C_WrapKey(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
1656 CK_OBJECT_HANDLE hWrappingKey
, CK_OBJECT_HANDLE hKey
,
1657 CK_BYTE_PTR pWrappedKey
, CK_ULONG_PTR pulWrappedKeyLen
)
1660 kernel_session_t
*session_p
;
1661 boolean_t ses_lock_held
= B_FALSE
;
1662 kernel_object_t
*wrappingkey_p
;
1663 kernel_object_t
*key_p
;
1664 crypto_mech_type_t k_mech_type
;
1665 crypto_object_wrap_key_t obj_wrapkey
;
1668 if (!kernel_initialized
)
1669 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
1671 if (pulWrappedKeyLen
== NULL
|| pMechanism
== NULL
) {
1672 return (CKR_ARGUMENTS_BAD
);
1676 * Obtain the session pointer. Also, increment the session
1679 rv
= handle2session(hSession
, &session_p
);
1683 /* Get the kernel's internal mechanism number. */
1684 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
1686 REFRELE(session_p
, ses_lock_held
);
1690 /* Obtain the wrapping key object pointer. */
1691 HANDLE2OBJECT(hWrappingKey
, wrappingkey_p
, rv
);
1693 REFRELE(session_p
, ses_lock_held
);
1697 /* Obtain the to_be_wrapped key object pointer. */
1698 HANDLE2OBJECT(hKey
, key_p
, rv
);
1700 OBJ_REFRELE(wrappingkey_p
);
1701 REFRELE(session_p
, ses_lock_held
);
1705 /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */
1706 obj_wrapkey
.wk_session
= session_p
->k_session
;
1707 obj_wrapkey
.wk_mechanism
.cm_type
= k_mech_type
;
1708 obj_wrapkey
.wk_mechanism
.cm_param
= pMechanism
->pParameter
;
1709 obj_wrapkey
.wk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1710 obj_wrapkey
.wk_wrapping_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
1711 obj_wrapkey
.wk_wrapping_key
.ck_obj_id
= wrappingkey_p
->k_handle
;
1712 obj_wrapkey
.wk_object_handle
= key_p
->k_handle
;
1713 obj_wrapkey
.wk_wrapped_key_len
= *pulWrappedKeyLen
;
1714 obj_wrapkey
.wk_wrapped_key
= (char *)pWrappedKey
;
1716 while ((r
= ioctl(kernel_fd
, CRYPTO_WRAP_KEY
, &obj_wrapkey
)) < 0) {
1721 rv
= CKR_FUNCTION_FAILED
;
1723 rv
= crypto2pkcs11_error_number(obj_wrapkey
.wk_return_value
);
1727 * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen
1728 * when the applciation-supplied wrapped key buffer is too small.
1729 * The situation that the application only asks for the length of
1730 * the wrapped key is covered in rv == CKR_OK.
1732 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
) {
1733 *pulWrappedKeyLen
= obj_wrapkey
.wk_wrapped_key_len
;
1737 OBJ_REFRELE(wrappingkey_p
);
1738 REFRELE(session_p
, ses_lock_held
);
1744 C_UnwrapKey(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
1745 CK_OBJECT_HANDLE hUnwrappingKey
, CK_BYTE_PTR pWrappedKey
,
1746 CK_ULONG ulWrappedKeyLen
, CK_ATTRIBUTE_PTR pTemplate
,
1747 CK_ULONG ulAttributeCount
, CK_OBJECT_HANDLE_PTR phKey
)
1750 kernel_session_t
*session_p
;
1751 kernel_object_t
*unwrappingkey_p
;
1752 kernel_object_t
*new_objp
= NULL
;
1753 kernel_slot_t
*pslot
;
1754 boolean_t ses_lock_held
= B_FALSE
;
1755 CK_BBOOL is_pri_obj
;
1756 CK_BBOOL is_token_obj
= FALSE
;
1757 CK_MECHANISM_INFO info
;
1758 uint32_t k_mi_flags
;
1759 CK_BYTE
*clear_key_val
= NULL
;
1761 CK_ATTRIBUTE_PTR newTemplate
= NULL
;
1762 crypto_mech_type_t k_mech_type
;
1763 crypto_object_unwrap_key_t obj_unwrapkey
;
1766 if (!kernel_initialized
)
1767 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
1769 if (pMechanism
== NULL
|| pWrappedKey
== NULL
|| phKey
== NULL
) {
1770 return (CKR_ARGUMENTS_BAD
);
1773 if ((pTemplate
== NULL
) && (ulAttributeCount
!= 0)) {
1774 return (CKR_ARGUMENTS_BAD
);
1777 /* Obtain the session pointer. */
1778 rv
= handle2session(hSession
, &session_p
);
1782 /* Obtain the wrapping key object pointer. */
1783 HANDLE2OBJECT(hUnwrappingKey
, unwrappingkey_p
, rv
);
1785 REFRELE(session_p
, ses_lock_held
);
1790 * If the HW provider doesn't support C_UnwrapKey, we will try
1791 * to emulate it in the library.
1793 pslot
= slot_table
[session_p
->ses_slotid
];
1794 if ((!pslot
->sl_func_list
.fl_object_create
) &&
1795 (!pslot
->sl_func_list
.fl_key_unwrap
)) {
1796 rv
= get_mechanism_info(pslot
, pMechanism
->mechanism
, &info
,
1803 * If the mechanism flag doesn't have CKF_UNWRAP, and it's
1804 * an unwrapping of a secret key object, then help this
1805 * out with a decryption followed by an object creation.
1807 if (!(k_mi_flags
& CRYPTO_FG_UNWRAP
) &&
1808 (k_mi_flags
& CRYPTO_FG_DECRYPT
) &&
1809 (is_secret_key_template(pTemplate
, ulAttributeCount
))) {
1811 /* First allocate space for the recovered key value */
1812 clear_key_val
= malloc(ulWrappedKeyLen
);
1813 if (clear_key_val
== NULL
) {
1814 rv
= CKR_HOST_MEMORY
;
1818 rv
= kernel_decrypt_init(session_p
, unwrappingkey_p
,
1824 ulDataLen
= ulWrappedKeyLen
;
1825 rv
= kernel_decrypt(session_p
, pWrappedKey
,
1826 ulWrappedKeyLen
, clear_key_val
, &ulDataLen
);
1831 newTemplate
= grow_template(pTemplate
, ulAttributeCount
,
1832 ulAttributeCount
+ 1);
1833 if (newTemplate
== NULL
) {
1834 rv
= CKR_HOST_MEMORY
;
1837 /* Now add the CKA_VALUE attribute to template */
1838 newTemplate
[ulAttributeCount
].type
= CKA_VALUE
;
1839 newTemplate
[ulAttributeCount
].pValue
= clear_key_val
;
1840 newTemplate
[ulAttributeCount
].ulValueLen
= ulDataLen
;
1842 /* Finally create the key, based on the new template */
1843 rv
= kernel_add_object(newTemplate
,
1844 ulAttributeCount
+ 1, phKey
, session_p
);
1845 (void) free(clear_key_val
);
1846 (void) free(newTemplate
);
1847 OBJ_REFRELE(unwrappingkey_p
);
1848 REFRELE(session_p
, ses_lock_held
);
1851 rv
= CKR_FUNCTION_FAILED
;
1857 * If we come here, the HW provider must have registered the unwrapkey
1858 * entry. Therefore, the unwrap key will be performed in the HW
1861 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
1866 /* Create an object wrapper for the new key in the library first */
1867 new_objp
= calloc(1, sizeof (kernel_object_t
));
1868 if (new_objp
== NULL
) {
1869 rv
= CKR_HOST_MEMORY
;
1873 /* Process the attributes */
1874 rv
= process_object_attributes(pTemplate
, ulAttributeCount
,
1875 &obj_unwrapkey
.uk_attributes
, &is_token_obj
);
1880 /* Cannot create a token object with a READ-ONLY session. */
1881 if (is_token_obj
&& session_p
->ses_RO
) {
1882 free_object_attributes(obj_unwrapkey
.uk_attributes
,
1884 rv
= CKR_SESSION_READ_ONLY
;
1888 /* Make the CRYPTO_UNWRAP_KEY ioctl call. */
1889 obj_unwrapkey
.uk_session
= session_p
->k_session
;
1890 obj_unwrapkey
.uk_mechanism
.cm_type
= k_mech_type
;
1891 obj_unwrapkey
.uk_mechanism
.cm_param
= pMechanism
->pParameter
;
1892 obj_unwrapkey
.uk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1893 obj_unwrapkey
.uk_unwrapping_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
1894 obj_unwrapkey
.uk_unwrapping_key
.ck_obj_id
= unwrappingkey_p
->k_handle
;
1895 obj_unwrapkey
.uk_wrapped_key
= (char *)pWrappedKey
;
1896 obj_unwrapkey
.uk_wrapped_key_len
= ulWrappedKeyLen
;
1897 obj_unwrapkey
.uk_count
= ulAttributeCount
;
1899 while ((r
= ioctl(kernel_fd
, CRYPTO_UNWRAP_KEY
, &obj_unwrapkey
)) < 0) {
1904 rv
= CKR_FUNCTION_FAILED
;
1906 rv
= crypto2pkcs11_error_number(obj_unwrapkey
.uk_return_value
);
1909 free_object_attributes(obj_unwrapkey
.uk_attributes
, ulAttributeCount
);
1914 /* Get the CKA_PRIVATE value for the unwrapped key. */
1915 rv
= get_cka_private_value(session_p
, obj_unwrapkey
.uk_object_handle
,
1922 * Store the kernel object handle in the new key object wrapper and
1925 new_objp
->k_handle
= obj_unwrapkey
.uk_object_handle
;
1926 new_objp
->is_lib_obj
= B_FALSE
;
1927 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1928 new_objp
->extra_attrlistp
= NULL
;
1931 new_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
1933 new_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
1936 new_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
1938 new_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
1940 (void) pthread_mutex_init(&new_objp
->object_mutex
, NULL
);
1941 new_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1944 * Add the new object to the slot's token object list if it is a
1945 * a token object. Otherwise, add it to the session's object list.
1948 pslot
= slot_table
[session_p
->ses_slotid
];
1949 kernel_add_token_object_to_slot(new_objp
, pslot
);
1951 kernel_add_object_to_session(new_objp
, session_p
);
1954 *phKey
= (CK_OBJECT_HANDLE
)new_objp
;
1955 OBJ_REFRELE(unwrappingkey_p
);
1956 REFRELE(session_p
, ses_lock_held
);
1960 OBJ_REFRELE(unwrappingkey_p
);
1961 if (new_objp
!= NULL
)
1962 (void) free(new_objp
);
1964 if (clear_key_val
!= NULL
)
1965 (void) free(clear_key_val
);
1967 if (newTemplate
!= NULL
)
1968 (void) free(newTemplate
);
1970 REFRELE(session_p
, ses_lock_held
);
1975 * Get sufficient attributes from a base key to pass by value in a
1976 * crypto_key structure. Storage for attributes is allocated.
1977 * For EC public keys, it is CKA_EC_PARAMS and CKA_EC_POINT.
1978 * For EC private keys, it is CKA_EC_PARAMS and CKA_VALUE.
1981 get_base_key_attributes(kernel_object_t
*base_key
, crypto_key_t
*key_by_value
)
1984 crypto_object_attribute_t
*attrs
= NULL
;
1986 int i
, count
= 0, rv
;
1988 switch (base_key
->key_type
) {
1991 attrs
= malloc(count
* sizeof (crypto_object_attribute_t
));
1992 if (attrs
== NULL
) {
1993 rv
= CKR_HOST_MEMORY
;
1996 bzero(attrs
, count
* sizeof (crypto_object_attribute_t
));
1998 (void) pthread_mutex_lock(&base_key
->object_mutex
);
2000 if (!base_key
->is_lib_obj
) {
2001 rv
= CRYPTO_ARGUMENTS_BAD
;
2005 if (base_key
->class != CKO_PUBLIC_KEY
&&
2006 base_key
->class != CKO_PRIVATE_KEY
) {
2007 rv
= CRYPTO_ARGUMENTS_BAD
;
2012 * Both public and private EC keys should have
2013 * a CKA_EC_PARAMS attribute.
2015 tmp
.type
= CKA_EC_PARAMS
;
2018 /* get size of attribute */
2019 rv
= kernel_get_attribute(base_key
, &tmp
);
2024 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2025 if (tmp
.pValue
== NULL
) {
2026 rv
= CKR_HOST_MEMORY
;
2029 rv
= kernel_get_attribute(base_key
, &tmp
);
2034 attrs
[0].oa_type
= tmp
.type
;
2035 attrs
[0].oa_value
= tmp
.pValue
;
2036 attrs
[0].oa_value_len
= tmp
.ulValueLen
;
2038 switch (base_key
->class) {
2039 case CKO_PUBLIC_KEY
:
2040 big
= OBJ_PUB_EC_POINT(base_key
);
2041 tmp
.type
= CKA_EC_POINT
;
2044 case CKO_PRIVATE_KEY
:
2045 big
= OBJ_PRI_EC_VALUE(base_key
);
2046 tmp
.type
= CKA_VALUE
;
2050 rv
= CKR_ATTRIBUTE_TYPE_INVALID
;
2053 tmp
.ulValueLen
= big
->big_value_len
;
2054 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2055 if (tmp
.pValue
== NULL
) {
2056 rv
= CKR_HOST_MEMORY
;
2059 rv
= kernel_get_attribute(base_key
, &tmp
);
2064 attrs
[1].oa_type
= tmp
.type
;
2065 attrs
[1].oa_value
= tmp
.pValue
;
2066 attrs
[1].oa_value_len
= tmp
.ulValueLen
;
2067 key_by_value
->ck_attrs
= attrs
;
2068 key_by_value
->ck_count
= 2;
2073 attrs
= malloc(count
* sizeof (crypto_object_attribute_t
));
2074 if (attrs
== NULL
) {
2075 rv
= CKR_HOST_MEMORY
;
2078 bzero(attrs
, count
* sizeof (crypto_object_attribute_t
));
2080 (void) pthread_mutex_lock(&base_key
->object_mutex
);
2082 if (!base_key
->is_lib_obj
) {
2083 rv
= CRYPTO_ARGUMENTS_BAD
;
2087 if (base_key
->class != CKO_PRIVATE_KEY
) {
2088 rv
= CRYPTO_ARGUMENTS_BAD
;
2091 tmp
.type
= CKA_BASE
;
2094 /* get size of attribute */
2095 rv
= kernel_get_attribute(base_key
, &tmp
);
2100 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2101 if (tmp
.pValue
== NULL
) {
2102 rv
= CKR_HOST_MEMORY
;
2105 rv
= kernel_get_attribute(base_key
, &tmp
);
2110 attrs
[0].oa_type
= tmp
.type
;
2111 attrs
[0].oa_value
= tmp
.pValue
;
2112 attrs
[0].oa_value_len
= tmp
.ulValueLen
;
2114 tmp
.type
= CKA_PRIME
;
2117 /* get size of attribute */
2118 rv
= kernel_get_attribute(base_key
, &tmp
);
2123 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2124 if (tmp
.pValue
== NULL
) {
2125 rv
= CKR_HOST_MEMORY
;
2128 rv
= kernel_get_attribute(base_key
, &tmp
);
2133 attrs
[1].oa_type
= tmp
.type
;
2134 attrs
[1].oa_value
= tmp
.pValue
;
2135 attrs
[1].oa_value_len
= tmp
.ulValueLen
;
2137 big
= OBJ_PRI_DH_VALUE(base_key
);
2138 tmp
.type
= CKA_VALUE
;
2140 tmp
.ulValueLen
= big
->big_value_len
;
2141 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2142 if (tmp
.pValue
== NULL
) {
2143 rv
= CKR_HOST_MEMORY
;
2146 rv
= kernel_get_attribute(base_key
, &tmp
);
2151 attrs
[2].oa_type
= tmp
.type
;
2152 attrs
[2].oa_value
= tmp
.pValue
;
2153 attrs
[2].oa_value_len
= tmp
.ulValueLen
;
2154 key_by_value
->ck_attrs
= attrs
;
2155 key_by_value
->ck_count
= 3;
2159 rv
= CKR_ATTRIBUTE_TYPE_INVALID
;
2162 (void) pthread_mutex_unlock(&base_key
->object_mutex
);
2166 (void) pthread_mutex_unlock(&base_key
->object_mutex
);
2167 if (attrs
!= NULL
) {
2168 for (i
= 0; i
< count
; i
++) {
2169 free(attrs
[i
].oa_value
);
2177 derive_key_by_value(CK_MECHANISM_PTR pMechanism
, CK_ATTRIBUTE_PTR pTemplate
,
2178 CK_ULONG ulAttributeCount
, kernel_session_t
*session_p
,
2179 crypto_mech_type_t k_mech_type
, kernel_object_t
*basekey_p
,
2180 kernel_object_t
*new_objp
)
2182 crypto_nostore_derive_key_t obj_ndk
;
2183 char *key_buf
= NULL
;
2184 CK_ATTRIBUTE_PTR newTemplate
= NULL
;
2185 CK_BBOOL is_token_obj
= FALSE
;
2187 CK_ULONG secret_class
= CKO_SECRET_KEY
;
2188 ulong_t key_len
= 0;
2189 uint_t attr_count
= 0;
2191 boolean_t has_class
;
2194 obj_ndk
.ndk_in_count
= 0;
2195 obj_ndk
.ndk_out_count
= 0;
2196 obj_ndk
.ndk_base_key
.ck_count
= 0;
2198 rv
= get_key_len_from_template(pMechanism
, pTemplate
, ulAttributeCount
,
2199 basekey_p
, &key_len
);
2204 if ((key_buf
= malloc(key_len
)) == NULL
) {
2205 rv
= CKR_HOST_MEMORY
;
2209 has_class
= attribute_in_template(CKA_CLASS
, pTemplate
,
2212 attr_count
= ulAttributeCount
+ 1;
2216 newTemplate
= grow_template(pTemplate
, ulAttributeCount
, attr_count
);
2217 if (newTemplate
== NULL
) {
2218 rv
= CKR_HOST_MEMORY
;
2222 n
= ulAttributeCount
;
2224 newTemplate
[n
].type
= CKA_CLASS
;
2225 newTemplate
[n
].pValue
= (caddr_t
)&secret_class
;
2226 newTemplate
[n
].ulValueLen
= sizeof (secret_class
);
2230 /* Add CKA_VALUE to the template */
2231 newTemplate
[n
].type
= CKA_VALUE
;
2232 newTemplate
[n
].pValue
= (caddr_t
)key_buf
;
2233 newTemplate
[n
].ulValueLen
= key_len
;
2235 rv
= process_object_attributes(newTemplate
, attr_count
- 1,
2236 &obj_ndk
.ndk_in_attributes
, &is_token_obj
);
2240 obj_ndk
.ndk_in_count
= attr_count
- 1;
2242 rv
= process_object_attributes(&newTemplate
[attr_count
- 1],
2243 1, &obj_ndk
.ndk_out_attributes
, &is_token_obj
);
2247 obj_ndk
.ndk_out_count
= 1;
2249 /* Cannot create a token object with a READ-ONLY session. */
2250 if (is_token_obj
&& session_p
->ses_RO
) {
2251 rv
= CKR_SESSION_READ_ONLY
;
2255 obj_ndk
.ndk_session
= session_p
->k_session
;
2256 obj_ndk
.ndk_mechanism
.cm_type
= k_mech_type
;
2257 obj_ndk
.ndk_mechanism
.cm_param
= pMechanism
->pParameter
;
2258 obj_ndk
.ndk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
2261 * Obtain the attributes of base key and pass them by value.
2263 rv
= get_base_key_attributes(basekey_p
, &obj_ndk
.ndk_base_key
);
2268 obj_ndk
.ndk_base_key
.ck_format
= CRYPTO_KEY_ATTR_LIST
;
2270 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_DERIVE_KEY
,
2276 rv
= CKR_FUNCTION_FAILED
;
2278 rv
= crypto2pkcs11_error_number(obj_ndk
.ndk_return_value
);
2280 free_attributes(obj_ndk
.ndk_in_attributes
, &obj_ndk
.ndk_in_count
);
2281 free_attributes((caddr_t
)obj_ndk
.ndk_base_key
.ck_attrs
,
2282 &obj_ndk
.ndk_base_key
.ck_count
);
2287 rv
= get_object_attributes(&newTemplate
[attr_count
- 1],
2288 1, obj_ndk
.ndk_out_attributes
);
2289 free_attributes(obj_ndk
.ndk_out_attributes
, &obj_ndk
.ndk_out_count
);
2290 if (rv
!= CRYPTO_SUCCESS
) {
2294 removed
= remove_one_attribute(newTemplate
, CKA_VALUE_LEN
,
2295 attr_count
, B_FALSE
);
2297 rv
= kernel_build_object(newTemplate
, removed
? attr_count
- 1 :
2298 attr_count
, new_objp
, session_p
, KERNEL_GEN_KEY
);
2299 if (rv
!= CRYPTO_SUCCESS
) {
2305 new_objp
->is_lib_obj
= B_TRUE
;
2306 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
2312 free_attributes(obj_ndk
.ndk_in_attributes
, &obj_ndk
.ndk_in_count
);
2313 free_attributes(obj_ndk
.ndk_out_attributes
, &obj_ndk
.ndk_out_count
);
2314 free_attributes((caddr_t
)obj_ndk
.ndk_base_key
.ck_attrs
,
2315 &obj_ndk
.ndk_base_key
.ck_count
);
2320 C_DeriveKey(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
2321 CK_OBJECT_HANDLE hBaseKey
, CK_ATTRIBUTE_PTR pTemplate
,
2322 CK_ULONG ulAttributeCount
, CK_OBJECT_HANDLE_PTR phKey
)
2325 kernel_session_t
*session_p
;
2326 kernel_object_t
*basekey_p
;
2327 kernel_object_t
*new_objp
;
2328 kernel_slot_t
*pslot
;
2329 boolean_t ses_lock_held
= B_FALSE
;
2330 CK_BBOOL is_pri_obj
;
2331 CK_BBOOL is_token_obj
= FALSE
;
2332 crypto_mech_type_t k_mech_type
;
2335 if (!kernel_initialized
)
2336 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
2338 /* Obtain the session pointer. */
2339 rv
= handle2session(hSession
, &session_p
);
2343 if (pMechanism
== NULL
) {
2344 REFRELE(session_p
, ses_lock_held
);
2345 return (CKR_ARGUMENTS_BAD
);
2348 if ((pTemplate
== NULL
&& ulAttributeCount
!= 0) ||
2349 (pTemplate
!= NULL
&& ulAttributeCount
== 0)) {
2350 REFRELE(session_p
, ses_lock_held
);
2351 return (CKR_ARGUMENTS_BAD
);
2354 /* Obtain the base key object pointer. */
2355 HANDLE2OBJECT(hBaseKey
, basekey_p
, rv
);
2357 REFRELE(session_p
, ses_lock_held
);
2361 /* Get the kernel's internal mechanism number. */
2362 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
2367 /* Create an object wrapper in the library for the generated key. */
2368 new_objp
= calloc(1, sizeof (kernel_object_t
));
2369 if (new_objp
== NULL
) {
2370 rv
= CKR_HOST_MEMORY
;
2375 * Special Case: if token does not support object creation,
2376 * but does support key derivation by value, then create a session
2377 * object and initialize with values returned by token.
2379 pslot
= slot_table
[session_p
->ses_slotid
];
2380 if (!pslot
->sl_func_list
.fl_object_create
) {
2381 rv
= derive_key_by_value(pMechanism
, pTemplate
,
2382 ulAttributeCount
, session_p
, k_mech_type
, basekey_p
,
2387 crypto_derive_key_t obj_dk
;
2389 rv
= process_object_attributes(pTemplate
, ulAttributeCount
,
2390 &obj_dk
.dk_attributes
, &is_token_obj
);
2395 /* Cannot create a token object with a READ-ONLY session. */
2396 if (is_token_obj
&& session_p
->ses_RO
) {
2397 free_object_attributes(obj_dk
.dk_attributes
,
2399 rv
= CKR_SESSION_READ_ONLY
;
2403 obj_dk
.dk_session
= session_p
->k_session
;
2404 obj_dk
.dk_mechanism
.cm_type
= k_mech_type
;
2405 obj_dk
.dk_mechanism
.cm_param
= pMechanism
->pParameter
;
2406 obj_dk
.dk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
2407 obj_dk
.dk_base_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
2408 obj_dk
.dk_base_key
.ck_obj_id
= basekey_p
->k_handle
;
2409 obj_dk
.dk_count
= ulAttributeCount
;
2411 while ((r
= ioctl(kernel_fd
, CRYPTO_DERIVE_KEY
, &obj_dk
)) < 0) {
2416 rv
= CKR_FUNCTION_FAILED
;
2418 rv
= crypto2pkcs11_error_number(obj_dk
.dk_return_value
);
2421 free_object_attributes(obj_dk
.dk_attributes
, ulAttributeCount
);
2426 /* Get the CKA_PRIVATE value for the derived key. */
2427 rv
= get_cka_private_value(session_p
, obj_dk
.dk_object_handle
,
2434 * Store the kernel object handle into the new derived key
2435 * object and finish the object initialization.
2437 new_objp
->is_lib_obj
= B_FALSE
;
2438 new_objp
->k_handle
= obj_dk
.dk_object_handle
;
2439 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
2440 new_objp
->extra_attrlistp
= NULL
;
2443 new_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
2445 new_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
2448 new_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
2450 new_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
2452 (void) pthread_mutex_init(&new_objp
->object_mutex
, NULL
);
2453 new_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
2456 * Add the new derived object to the slot's token list if it is a
2457 * token object. Otherwise, add it to the session's object list.
2460 pslot
= slot_table
[session_p
->ses_slotid
];
2461 kernel_add_token_object_to_slot(new_objp
, pslot
);
2463 kernel_add_object_to_session(new_objp
, session_p
);
2466 *phKey
= (CK_OBJECT_HANDLE
)new_objp
;
2467 OBJ_REFRELE(basekey_p
);
2468 REFRELE(session_p
, ses_lock_held
);
2472 OBJ_REFRELE(basekey_p
);
2473 if (new_objp
!= NULL
) {
2474 (void) free(new_objp
);
2477 REFRELE(session_p
, ses_lock_held
);