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.
24 * Copyright 2018, Joyent, Inc.
30 #include <security/cryptoki.h>
31 #include <sys/crypto/ioctl.h>
32 #include "kernelGlobal.h"
33 #include "kernelSession.h"
34 #include "kernelObject.h"
37 attribute_in_template(CK_ATTRIBUTE_TYPE type
, CK_ATTRIBUTE_PTR t
, CK_ULONG cnt
)
41 for (i
= 0; i
< cnt
; i
++) {
42 if (t
[i
].type
== type
)
49 * This routine returns modulus bytes rounded up to the nearest 8 byte
50 * chunk. This is so we don't have to pass in max sized buffers for
51 * returned attributes. Every unnecessary byte that we pass in results
52 * in a kernel allocation.
55 get_modulus_bytes(CK_ATTRIBUTE_PTR t
, CK_ULONG cnt
)
60 for (i
= 0; i
< cnt
; i
++) {
61 if (t
[i
].type
== CKA_MODULUS_BITS
) {
62 get_ulong_attr_from_template(&modulus_len
, &t
[i
]);
63 /* convert from bit length to byte length */
64 modulus_len
= (modulus_len
- 1) / 64 + 1;
65 return (modulus_len
* 8);
72 * Remove specified attribute from array. Storage for the attribute's
73 * value is freed if 'free_attr' is TRUE. Attributes are shifted so they are
74 * contiguous within the array, i.e. the next attribute is shifted into
75 * the position of the removed attribute. Returns TRUE if specified
76 * attribute is removed.
79 remove_one_attribute(CK_ATTRIBUTE_PTR t
, CK_ULONG type
, uint_t count
,
84 for (i
= 0, j
= 0; i
< count
; i
++) {
85 if (t
[i
].type
== type
) {
92 t
[j
].type
= t
[i
].type
;
93 t
[j
].pValue
= t
[i
].pValue
;
94 t
[j
].ulValueLen
= t
[i
].ulValueLen
;
108 is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulAttributeCount
)
111 for (i
= 0; i
< ulAttributeCount
; i
++) {
112 if (pTemplate
[i
].type
== CKA_CLASS
&&
113 *(CK_OBJECT_CLASS
*)(pTemplate
[i
].pValue
) ==
121 * Allocate a template with space for new_count entries and copy the
122 * specified template into the new template.
124 static CK_ATTRIBUTE_PTR
125 grow_template(CK_ATTRIBUTE_PTR old_template
, CK_ULONG old_count
,
128 CK_ATTRIBUTE_PTR new_template
;
130 new_template
= malloc(new_count
* sizeof (CK_ATTRIBUTE
));
131 if (new_template
!= NULL
)
132 bcopy(old_template
, new_template
,
133 old_count
* sizeof (CK_ATTRIBUTE
));
134 return (new_template
);
138 * For fixed length keys such as DES, return the length based on
139 * the key type. For variable length keys such as AES, take the
140 * length from the CKA_VALUE_LEN attribute.
143 get_key_len_from_template(CK_MECHANISM_PTR pMechanism
,
144 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulAttributeCount
,
145 kernel_object_t
*basekey_p
, ulong_t
*key_len
)
147 boolean_t fixed_len_key
= B_FALSE
;
151 for (i
= 0; i
< ulAttributeCount
; i
++) {
152 if (pTemplate
[i
].type
== CKA_KEY_TYPE
) {
153 get_ulong_attr_from_template(&key_type
, &pTemplate
[i
]);
157 /* CKA_KEY_TYPE must be present */
158 if (i
== ulAttributeCount
)
159 return (CKR_TEMPLATE_INCOMPLETE
);
164 fixed_len_key
= B_TRUE
;
168 fixed_len_key
= B_TRUE
;
172 for (i
= 0; i
< ulAttributeCount
; i
++) {
173 if (pTemplate
[i
].type
== CKA_VALUE_LEN
) {
174 get_ulong_attr_from_template(key_len
,
179 /* CKA_VALUE_LEN must be present */
180 if (i
== ulAttributeCount
)
181 return (CKR_TEMPLATE_INCOMPLETE
);
183 case CKK_GENERIC_SECRET
:
185 * The key will not be truncated, so we need to
186 * get the max length for the mechanism.
188 if (pMechanism
->mechanism
== CKM_DH_PKCS_DERIVE
) {
191 tmp
.type
= CKA_PRIME
;
194 /* get size of attribute */
195 if (kernel_get_attribute(basekey_p
, &tmp
) != CKR_OK
) {
196 return (CKR_ARGUMENTS_BAD
);
198 *key_len
= tmp
.ulValueLen
;
199 } else if (pMechanism
->mechanism
== CKM_ECDH1_DERIVE
) {
200 *key_len
= EC_MAX_VALUE_LEN
;
202 return (CKR_ARGUMENTS_BAD
);
206 return (CKR_ATTRIBUTE_VALUE_INVALID
);
209 if (fixed_len_key
&& attribute_in_template(CKA_VALUE_LEN
,
210 pTemplate
, ulAttributeCount
))
211 return (CKR_TEMPLATE_INCONSISTENT
);
216 /* find specified attribute src template and copy to dest */
218 copy_attribute(CK_ULONG type
, CK_ATTRIBUTE_PTR src
, CK_ULONG src_cnt
,
219 CK_ATTRIBUTE_PTR dst
)
223 for (i
= 0; i
< src_cnt
; i
++) {
224 if (src
[i
].type
== type
) {
225 rv
= get_string_from_template(dst
, &src
[i
]);
230 * The public template didn't have attribute.
233 rv
= CKR_TEMPLATE_INCOMPLETE
;
239 free_attributes(caddr_t p
, uint_t
*countp
)
242 free_object_attributes(p
, *countp
);
248 key_gen_by_value(CK_MECHANISM_PTR pMechanism
, CK_ATTRIBUTE_PTR pTemplate
,
249 CK_ULONG ulCount
, kernel_session_t
*session_p
,
250 crypto_mech_type_t k_mech_type
, kernel_object_t
*new_objp
)
252 crypto_nostore_generate_key_t obj_ngk
;
253 char *key_buf
= NULL
;
254 CK_ATTRIBUTE_PTR newTemplate
= NULL
;
255 CK_BBOOL is_token_obj
= FALSE
;
261 obj_ngk
.ngk_in_count
= 0;
262 obj_ngk
.ngk_out_count
= 0;
264 rv
= get_key_len_from_template(pMechanism
, pTemplate
, ulCount
,
266 if (rv
!= CRYPTO_SUCCESS
)
269 if ((key_buf
= malloc(key_len
)) == NULL
) {
270 rv
= CKR_HOST_MEMORY
;
274 attr_count
= ulCount
+ 1;
275 newTemplate
= grow_template(pTemplate
, ulCount
, attr_count
);
276 if (newTemplate
== NULL
) {
277 rv
= CKR_HOST_MEMORY
;
281 /* Now add the CKA_VALUE attribute to template */
282 newTemplate
[ulCount
].type
= CKA_VALUE
;
283 newTemplate
[ulCount
].pValue
= (caddr_t
)key_buf
;
284 newTemplate
[ulCount
].ulValueLen
= key_len
;
286 rv
= process_object_attributes(newTemplate
, attr_count
- 1,
287 &obj_ngk
.ngk_in_attributes
, &is_token_obj
);
291 rv
= process_object_attributes(&newTemplate
[ulCount
],
292 1, &obj_ngk
.ngk_out_attributes
, &is_token_obj
);
297 /* Cannot create a token object with a READ-ONLY session. */
298 if (is_token_obj
&& session_p
->ses_RO
) {
299 rv
= CKR_SESSION_READ_ONLY
;
303 /* Call the CRYPTO_NOSTORE_GENERATE_KEY ioctl */
304 obj_ngk
.ngk_session
= session_p
->k_session
;
305 obj_ngk
.ngk_in_count
= attr_count
- 1;
306 obj_ngk
.ngk_out_count
= 1;
307 obj_ngk
.ngk_mechanism
.cm_type
= k_mech_type
;
308 obj_ngk
.ngk_mechanism
.cm_param
= pMechanism
->pParameter
;
309 obj_ngk
.ngk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
311 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_GENERATE_KEY
,
317 rv
= CKR_FUNCTION_FAILED
;
319 rv
= crypto2pkcs11_error_number(obj_ngk
.ngk_return_value
);
321 free_attributes(obj_ngk
.ngk_in_attributes
, &obj_ngk
.ngk_in_count
);
326 rv
= get_object_attributes(&newTemplate
[ulCount
], 1,
327 obj_ngk
.ngk_out_attributes
);
328 free_attributes(obj_ngk
.ngk_out_attributes
, &obj_ngk
.ngk_out_count
);
329 if (rv
!= CRYPTO_SUCCESS
) {
334 * CKA_VALUE_LEN is not stored with the secret key object,
335 * so we remove it by shifting attributes down one.
337 (void) remove_one_attribute(newTemplate
, CKA_VALUE_LEN
,
338 attr_count
, B_FALSE
);
340 rv
= kernel_build_object(newTemplate
, attr_count
- 1,
341 new_objp
, session_p
, KERNEL_GEN_KEY
);
342 if (rv
!= CRYPTO_SUCCESS
) {
345 new_objp
->is_lib_obj
= B_TRUE
;
346 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
348 freezero(key_buf
, key_len
);
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 freezero(key_buf
, key_len
);
360 C_GenerateKey(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
361 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
, CK_OBJECT_HANDLE_PTR phKey
)
364 kernel_session_t
*session_p
;
365 kernel_object_t
*new_objp
= NULL
;
366 kernel_slot_t
*pslot
;
367 boolean_t ses_lock_held
= B_FALSE
;
369 CK_BBOOL is_token_obj
= FALSE
;
370 crypto_mech_type_t k_mech_type
;
373 if (!kernel_initialized
)
374 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
376 /* Obtain the session pointer */
377 rv
= handle2session(hSession
, &session_p
);
381 if ((pMechanism
== NULL
) || (phKey
== NULL
)) {
382 rv
= CKR_ARGUMENTS_BAD
;
386 if ((pTemplate
== NULL
) && (ulCount
!= 0)) {
387 rv
= CKR_ARGUMENTS_BAD
;
391 /* Get the kernel's internal mechanism number. */
392 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
397 /* Create an object wrapper in the library first */
398 new_objp
= calloc(1, sizeof (kernel_object_t
));
399 if (new_objp
== NULL
) {
400 rv
= CKR_HOST_MEMORY
;
405 * Special Case: if token does not support object creation,
406 * but does support key generation by value, then create a session
407 * object and initialize with value returned by token.
409 pslot
= slot_table
[session_p
->ses_slotid
];
410 if (!pslot
->sl_func_list
.fl_object_create
) {
411 rv
= key_gen_by_value(pMechanism
, pTemplate
, ulCount
, session_p
,
412 k_mech_type
, new_objp
);
416 crypto_object_generate_key_t obj_gk
;
418 /* Process the attributes */
419 rv
= process_object_attributes(pTemplate
, ulCount
,
420 &obj_gk
.gk_attributes
, &is_token_obj
);
424 /* Cannot create a token object with a READ-ONLY session. */
425 if (is_token_obj
&& session_p
->ses_RO
) {
426 free_object_attributes(obj_gk
.gk_attributes
, ulCount
);
427 rv
= CKR_SESSION_READ_ONLY
;
431 /* Call the CRYPTO_GENERATE_KEY ioctl */
432 obj_gk
.gk_session
= session_p
->k_session
;
433 obj_gk
.gk_count
= ulCount
;
434 obj_gk
.gk_mechanism
.cm_type
= k_mech_type
;
435 obj_gk
.gk_mechanism
.cm_param
= pMechanism
->pParameter
;
436 obj_gk
.gk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
438 while ((r
= ioctl(kernel_fd
, CRYPTO_GENERATE_KEY
,
444 rv
= CKR_FUNCTION_FAILED
;
446 rv
= crypto2pkcs11_error_number(obj_gk
.gk_return_value
);
449 free_object_attributes(obj_gk
.gk_attributes
, ulCount
);
455 /* Get the value of the CKA_PRIVATE attribute. */
456 rv
= get_cka_private_value(session_p
, obj_gk
.gk_handle
,
463 * Store the kernel object handle in the object wrapper and
464 * initialize the library object.
466 new_objp
->k_handle
= obj_gk
.gk_handle
;
467 new_objp
->is_lib_obj
= B_FALSE
;
468 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
469 new_objp
->extra_attrlistp
= NULL
;
472 new_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
474 new_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
477 new_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
479 new_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
482 (void) pthread_mutex_init(&new_objp
->object_mutex
, NULL
);
483 new_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
486 * Add the new object to the slot's token object list if it is a
487 * a token object. Otherwise, add it to the session's object list.
490 pslot
= slot_table
[session_p
->ses_slotid
];
491 kernel_add_token_object_to_slot(new_objp
, pslot
);
493 kernel_add_object_to_session(new_objp
, session_p
);
496 *phKey
= (CK_OBJECT_HANDLE
)new_objp
;
497 REFRELE(session_p
, ses_lock_held
);
501 if (new_objp
!= NULL
) {
502 (void) free(new_objp
);
505 REFRELE(session_p
, ses_lock_held
);
510 key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism
,
511 CK_ATTRIBUTE_PTR pPublicKeyTemplate
, CK_ULONG ulPublicKeyAttributeCount
,
512 CK_ATTRIBUTE_PTR pPrivateKeyTemplate
, CK_ULONG ulPrivateKeyAttributeCount
,
513 kernel_session_t
*session_p
, crypto_mech_type_t k_mech_type
,
514 kernel_object_t
*new_pub_objp
, kernel_object_t
*new_pri_objp
)
516 crypto_nostore_generate_key_pair_t obj_nkp
;
517 CK_ATTRIBUTE_PTR pubTemplate
= NULL
;
518 CK_ATTRIBUTE_PTR priTemplate
= NULL
;
520 CK_BBOOL is_token_obj1
= FALSE
;
521 CK_BBOOL is_token_obj2
= FALSE
;
522 uint_t pub_attr_count
, pri_attr_count
;
523 uint_t pub_out_attr_count
= 0, pri_out_attr_count
= 0;
524 char public_modulus
[512];
525 char public_exponent
[8];
526 char private_exponent
[512];
527 char private_modulus
[512];
530 char exponent_1
[512];
531 char exponent_2
[512];
532 char coefficient
[512];
533 CK_ULONG pub_class
= CKO_PUBLIC_KEY
;
534 CK_ULONG pri_class
= CKO_PRIVATE_KEY
;
536 CK_ULONG modulus_bytes
;
537 boolean_t has_class
, has_key_type
, has_pub_exponent
;
540 obj_nkp
.nkp_in_public_count
= 0;
541 obj_nkp
.nkp_out_public_count
= 0;
542 obj_nkp
.nkp_in_private_count
= 0;
543 obj_nkp
.nkp_out_private_count
= 0;
545 /* modulus bits must be present when generating a RSA key pair */
546 if (!attribute_in_template(CKA_MODULUS_BITS
, pPublicKeyTemplate
,
547 ulPublicKeyAttributeCount
)) {
548 rv
= CKR_TEMPLATE_INCOMPLETE
;
552 modulus_bytes
= get_modulus_bytes(pPublicKeyTemplate
,
553 ulPublicKeyAttributeCount
);
556 * Add CKA_MODULUS to the public template.
557 * This attribute must not be in the template.
559 if (attribute_in_template(CKA_MODULUS
, pPublicKeyTemplate
,
560 ulPublicKeyAttributeCount
)) {
561 rv
= CKR_TEMPLATE_INCONSISTENT
;
564 has_class
= attribute_in_template(CKA_CLASS
, pPublicKeyTemplate
,
565 ulPublicKeyAttributeCount
);
566 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPublicKeyTemplate
,
567 ulPublicKeyAttributeCount
);
568 has_pub_exponent
= attribute_in_template(CKA_PUBLIC_EXPONENT
,
569 pPublicKeyTemplate
, ulPublicKeyAttributeCount
);
571 pub_attr_count
= ulPublicKeyAttributeCount
+ 1;
576 if (!has_pub_exponent
)
578 pubTemplate
= grow_template(pPublicKeyTemplate
,
579 ulPublicKeyAttributeCount
, pub_attr_count
);
580 if (pubTemplate
== NULL
) {
581 rv
= CKR_HOST_MEMORY
;
585 n
= ulPublicKeyAttributeCount
;
587 pubTemplate
[n
].type
= CKA_CLASS
;
588 pubTemplate
[n
].pValue
= (caddr_t
)&pub_class
;
589 pubTemplate
[n
].ulValueLen
= sizeof (pub_class
);
593 pubTemplate
[n
].type
= CKA_KEY_TYPE
;
595 pubTemplate
[n
].pValue
= (caddr_t
)&key_type
;
596 pubTemplate
[n
].ulValueLen
= sizeof (key_type
);
599 if (!has_pub_exponent
) {
600 pubTemplate
[n
].type
= CKA_PUBLIC_EXPONENT
;
601 pubTemplate
[n
].pValue
= (caddr_t
)public_exponent
;
602 pubTemplate
[n
].ulValueLen
= modulus_bytes
;
604 pub_out_attr_count
++;
606 pubTemplate
[n
].type
= CKA_MODULUS
;
607 pubTemplate
[n
].pValue
= (caddr_t
)public_modulus
;
608 pubTemplate
[n
].ulValueLen
= modulus_bytes
;
609 pub_out_attr_count
++;
611 rv
= process_object_attributes(pubTemplate
,
612 pub_attr_count
- pub_out_attr_count
,
613 &obj_nkp
.nkp_in_public_attributes
, &is_token_obj1
);
617 obj_nkp
.nkp_in_public_count
= pub_attr_count
- pub_out_attr_count
;
619 rv
= process_object_attributes(
620 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
621 pub_out_attr_count
, &obj_nkp
.nkp_out_public_attributes
,
626 obj_nkp
.nkp_out_public_count
= pub_out_attr_count
;
629 * Cannot create a token object with a READ-ONLY
632 if (is_token_obj1
&& session_p
->ses_RO
) {
633 rv
= CKR_SESSION_READ_ONLY
;
638 * Add CKA_MODULUS and CKA_PRIVATE_EXPONENT
639 * to the private template. These attributes
640 * must not be in the template.
642 if (attribute_in_template(CKA_PRIVATE_EXPONENT
,
643 pPrivateKeyTemplate
, ulPrivateKeyAttributeCount
) ||
644 attribute_in_template(CKA_MODULUS
,
645 pPrivateKeyTemplate
, ulPrivateKeyAttributeCount
)) {
646 rv
= CKR_TEMPLATE_INCONSISTENT
;
649 has_class
= attribute_in_template(CKA_CLASS
, pPrivateKeyTemplate
,
650 ulPrivateKeyAttributeCount
);
651 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPrivateKeyTemplate
,
652 ulPrivateKeyAttributeCount
);
654 pri_attr_count
= ulPrivateKeyAttributeCount
+ 7;
660 /* allocate space for CKA_PUBLIC_EXPONENT */
661 priTemplate
= grow_template(pPrivateKeyTemplate
,
662 ulPrivateKeyAttributeCount
, pri_attr_count
+ 1);
663 if (priTemplate
== NULL
) {
664 rv
= CKR_HOST_MEMORY
;
667 n
= ulPrivateKeyAttributeCount
;
669 priTemplate
[n
].type
= CKA_CLASS
;
670 priTemplate
[n
].pValue
= (caddr_t
)&pri_class
;
671 priTemplate
[n
].ulValueLen
= sizeof (pri_class
);
675 priTemplate
[n
].type
= CKA_KEY_TYPE
;
677 priTemplate
[n
].pValue
= (caddr_t
)&key_type
;
678 priTemplate
[n
].ulValueLen
= sizeof (key_type
);
681 priTemplate
[n
].type
= CKA_MODULUS
;
682 priTemplate
[n
].pValue
= (caddr_t
)private_modulus
;
683 priTemplate
[n
].ulValueLen
= modulus_bytes
;
684 pri_out_attr_count
++;
687 priTemplate
[n
].type
= CKA_PRIVATE_EXPONENT
;
688 priTemplate
[n
].pValue
= (caddr_t
)private_exponent
;
689 priTemplate
[n
].ulValueLen
= modulus_bytes
;
690 pri_out_attr_count
++;
693 priTemplate
[n
].type
= CKA_PRIME_1
;
694 priTemplate
[n
].pValue
= (caddr_t
)prime_1
;
695 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
696 pri_out_attr_count
++;
699 priTemplate
[n
].type
= CKA_PRIME_2
;
700 priTemplate
[n
].pValue
= (caddr_t
)prime_2
;
701 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
702 pri_out_attr_count
++;
705 priTemplate
[n
].type
= CKA_EXPONENT_1
;
706 priTemplate
[n
].pValue
= (caddr_t
)exponent_1
;
707 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
708 pri_out_attr_count
++;
711 priTemplate
[n
].type
= CKA_EXPONENT_2
;
712 priTemplate
[n
].pValue
= (caddr_t
)exponent_2
;
713 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
714 pri_out_attr_count
++;
717 priTemplate
[n
].type
= CKA_COEFFICIENT
;
718 priTemplate
[n
].pValue
= (caddr_t
)coefficient
;
719 priTemplate
[n
].ulValueLen
= modulus_bytes
/2;
720 pri_out_attr_count
++;
722 rv
= process_object_attributes(priTemplate
,
723 pri_attr_count
- pri_out_attr_count
,
724 &obj_nkp
.nkp_in_private_attributes
, &is_token_obj2
);
728 obj_nkp
.nkp_in_private_count
= pri_attr_count
- pri_out_attr_count
;
730 rv
= process_object_attributes(
731 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
732 pri_out_attr_count
, &obj_nkp
.nkp_out_private_attributes
,
737 obj_nkp
.nkp_out_private_count
= pri_out_attr_count
;
740 * The public key and the private key need to contain the same
741 * attribute values for CKA_TOKEN.
743 if (is_token_obj1
!= is_token_obj2
) {
744 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
748 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
749 obj_nkp
.nkp_session
= session_p
-> k_session
;
750 obj_nkp
.nkp_mechanism
.cm_type
= k_mech_type
;
751 obj_nkp
.nkp_mechanism
.cm_param
= pMechanism
->pParameter
;
752 obj_nkp
.nkp_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
754 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_GENERATE_KEY_PAIR
,
760 rv
= CKR_FUNCTION_FAILED
;
762 rv
= crypto2pkcs11_error_number(obj_nkp
.nkp_return_value
);
764 free_attributes(obj_nkp
.nkp_in_public_attributes
,
765 &obj_nkp
.nkp_in_public_count
);
766 free_attributes(obj_nkp
.nkp_in_private_attributes
,
767 &obj_nkp
.nkp_in_private_count
);
773 rv
= get_object_attributes(
774 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
775 pub_out_attr_count
, obj_nkp
.nkp_out_public_attributes
);
776 if (rv
== CRYPTO_SUCCESS
) {
777 rv
= get_object_attributes(
778 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
779 pri_out_attr_count
, obj_nkp
.nkp_out_private_attributes
);
781 free_attributes(obj_nkp
.nkp_out_public_attributes
,
782 &obj_nkp
.nkp_out_public_count
);
783 free_attributes(obj_nkp
.nkp_out_private_attributes
,
784 &obj_nkp
.nkp_out_private_count
);
785 if (rv
!= CRYPTO_SUCCESS
) {
789 /* store generated modulus and public exponent */
790 rv
= kernel_build_object(pubTemplate
, pub_attr_count
, new_pub_objp
,
791 session_p
, KERNEL_GEN_KEY
);
792 if (rv
!= CRYPTO_SUCCESS
) {
797 * Copy CKA_PUBLIC_EXPONENT from the public template
798 * to the private template.
800 rv
= copy_attribute(CKA_PUBLIC_EXPONENT
, pubTemplate
,
801 pub_attr_count
, &priTemplate
[pri_attr_count
]);
802 if (rv
!= CRYPTO_SUCCESS
) {
806 rv
= kernel_build_object(priTemplate
, pri_attr_count
+ 1, new_pri_objp
,
807 session_p
, KERNEL_GEN_KEY
);
808 (void) free(priTemplate
[pri_attr_count
].pValue
);
809 if (rv
!= CRYPTO_SUCCESS
) {
812 (void) free(pubTemplate
);
813 (void) free(priTemplate
);
815 new_pub_objp
->is_lib_obj
= B_TRUE
;
816 new_pri_objp
->is_lib_obj
= B_TRUE
;
817 new_pub_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
818 new_pri_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
819 (void) pthread_mutex_init(&new_pub_objp
->object_mutex
, NULL
);
820 new_pub_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
821 (void) pthread_mutex_init(&new_pri_objp
->object_mutex
, NULL
);
822 new_pri_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
826 free_attributes(obj_nkp
.nkp_in_public_attributes
,
827 &obj_nkp
.nkp_in_public_count
);
828 free_attributes(obj_nkp
.nkp_out_public_attributes
,
829 &obj_nkp
.nkp_out_public_count
);
830 free_attributes(obj_nkp
.nkp_in_private_attributes
,
831 &obj_nkp
.nkp_in_private_count
);
832 free_attributes(obj_nkp
.nkp_out_private_attributes
,
833 &obj_nkp
.nkp_out_private_count
);
834 if (pubTemplate
!= NULL
) {
835 (void) free(pubTemplate
);
837 if (priTemplate
!= NULL
) {
838 (void) free(priTemplate
);
844 key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism
,
845 CK_ATTRIBUTE_PTR pPublicKeyTemplate
, CK_ULONG ulPublicKeyAttributeCount
,
846 CK_ATTRIBUTE_PTR pPrivateKeyTemplate
, CK_ULONG ulPrivateKeyAttributeCount
,
847 kernel_session_t
*session_p
, crypto_mech_type_t k_mech_type
,
848 kernel_object_t
*new_pub_objp
, kernel_object_t
*new_pri_objp
)
850 crypto_nostore_generate_key_pair_t obj_nkp
;
851 CK_ATTRIBUTE_PTR pubTemplate
= NULL
;
852 CK_ATTRIBUTE_PTR priTemplate
= NULL
;
854 CK_BBOOL is_token_obj1
= FALSE
;
855 CK_BBOOL is_token_obj2
= FALSE
;
856 uint_t pub_attr_count
, pri_attr_count
;
857 uint_t pub_out_attr_count
= 0, pri_out_attr_count
= 0;
858 char public_value
[256];
859 char private_value
[256];
860 CK_ULONG pub_class
= CKO_PUBLIC_KEY
;
861 CK_ULONG pri_class
= CKO_PRIVATE_KEY
;
863 boolean_t has_class
, has_key_type
;
866 obj_nkp
.nkp_in_public_count
= 0;
867 obj_nkp
.nkp_out_public_count
= 0;
868 obj_nkp
.nkp_in_private_count
= 0;
869 obj_nkp
.nkp_out_private_count
= 0;
872 * Add CKA_VALUE to the public template.
873 * This attribute must not be in the template.
875 if (attribute_in_template(CKA_VALUE
, pPublicKeyTemplate
,
876 ulPublicKeyAttributeCount
)) {
877 rv
= CKR_TEMPLATE_INCONSISTENT
;
880 has_class
= attribute_in_template(CKA_CLASS
, pPublicKeyTemplate
,
881 ulPublicKeyAttributeCount
);
882 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPublicKeyTemplate
,
883 ulPublicKeyAttributeCount
);
885 pub_attr_count
= ulPublicKeyAttributeCount
+ 1;
890 pubTemplate
= grow_template(pPublicKeyTemplate
,
891 ulPublicKeyAttributeCount
, pub_attr_count
);
892 if (pubTemplate
== NULL
) {
893 rv
= CKR_HOST_MEMORY
;
897 n
= ulPublicKeyAttributeCount
;
899 pubTemplate
[n
].type
= CKA_CLASS
;
900 pubTemplate
[n
].pValue
= (caddr_t
)&pub_class
;
901 pubTemplate
[n
].ulValueLen
= sizeof (pub_class
);
905 pubTemplate
[n
].type
= CKA_KEY_TYPE
;
907 pubTemplate
[n
].pValue
= (caddr_t
)&key_type
;
908 pubTemplate
[n
].ulValueLen
= sizeof (key_type
);
911 pubTemplate
[n
].type
= CKA_VALUE
;
912 pubTemplate
[n
].pValue
= (caddr_t
)public_value
;
913 pubTemplate
[n
].ulValueLen
= sizeof (public_value
);
914 pub_out_attr_count
++;
916 rv
= process_object_attributes(pubTemplate
,
917 pub_attr_count
- pub_out_attr_count
,
918 &obj_nkp
.nkp_in_public_attributes
, &is_token_obj1
);
922 obj_nkp
.nkp_in_public_count
= pub_attr_count
- pub_out_attr_count
;
924 rv
= process_object_attributes(
925 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
926 pub_out_attr_count
, &obj_nkp
.nkp_out_public_attributes
,
931 obj_nkp
.nkp_out_public_count
= pub_out_attr_count
;
934 * Cannot create a token object with a READ-ONLY
937 if (is_token_obj1
&& session_p
->ses_RO
) {
938 rv
= CKR_SESSION_READ_ONLY
;
943 * CKA_BASE, CKA_PRIME, and CKA_VALUE must not appear
944 * in private template.
946 if (attribute_in_template(CKA_BASE
, pPrivateKeyTemplate
,
947 ulPrivateKeyAttributeCount
) ||
948 attribute_in_template(CKA_PRIME
, pPrivateKeyTemplate
,
949 ulPrivateKeyAttributeCount
) ||
950 attribute_in_template(CKA_VALUE
, pPrivateKeyTemplate
,
951 ulPrivateKeyAttributeCount
)) {
952 rv
= CKR_TEMPLATE_INCONSISTENT
;
956 if (attribute_in_template(CKA_VALUE
, pPrivateKeyTemplate
,
957 ulPrivateKeyAttributeCount
)) {
958 rv
= CKR_TEMPLATE_INCONSISTENT
;
961 has_class
= attribute_in_template(CKA_CLASS
, pPrivateKeyTemplate
,
962 ulPrivateKeyAttributeCount
);
963 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPrivateKeyTemplate
,
964 ulPrivateKeyAttributeCount
);
966 pri_attr_count
= ulPrivateKeyAttributeCount
+ 1;
972 /* allocate space for CKA_BASE and CKA_PRIME */
973 priTemplate
= grow_template(pPrivateKeyTemplate
,
974 ulPrivateKeyAttributeCount
, pri_attr_count
+ 2);
975 if (priTemplate
== NULL
) {
976 rv
= CKR_HOST_MEMORY
;
979 n
= ulPrivateKeyAttributeCount
;
981 priTemplate
[n
].type
= CKA_CLASS
;
982 priTemplate
[n
].pValue
= (caddr_t
)&pri_class
;
983 priTemplate
[n
].ulValueLen
= sizeof (pri_class
);
987 priTemplate
[n
].type
= CKA_KEY_TYPE
;
989 priTemplate
[n
].pValue
= (caddr_t
)&key_type
;
990 priTemplate
[n
].ulValueLen
= sizeof (key_type
);
993 priTemplate
[n
].type
= CKA_VALUE
;
994 priTemplate
[n
].pValue
= (caddr_t
)private_value
;
995 priTemplate
[n
].ulValueLen
= sizeof (private_value
);
996 pri_out_attr_count
++;
998 rv
= process_object_attributes(priTemplate
,
999 pri_attr_count
- pri_out_attr_count
,
1000 &obj_nkp
.nkp_in_private_attributes
, &is_token_obj2
);
1004 obj_nkp
.nkp_in_private_count
= pri_attr_count
- pri_out_attr_count
;
1006 rv
= process_object_attributes(
1007 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
1008 pri_out_attr_count
, &obj_nkp
.nkp_out_private_attributes
,
1013 obj_nkp
.nkp_out_private_count
= pri_out_attr_count
;
1016 * The public key and the private key need to contain the same
1017 * attribute values for CKA_TOKEN.
1019 if (is_token_obj1
!= is_token_obj2
) {
1020 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
1024 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
1025 obj_nkp
.nkp_session
= session_p
-> k_session
;
1026 obj_nkp
.nkp_mechanism
.cm_type
= k_mech_type
;
1027 obj_nkp
.nkp_mechanism
.cm_param
= pMechanism
->pParameter
;
1028 obj_nkp
.nkp_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1030 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_GENERATE_KEY_PAIR
,
1036 rv
= CKR_FUNCTION_FAILED
;
1038 rv
= crypto2pkcs11_error_number(obj_nkp
.nkp_return_value
);
1040 free_attributes(obj_nkp
.nkp_in_public_attributes
,
1041 &obj_nkp
.nkp_in_public_count
);
1042 free_attributes(obj_nkp
.nkp_in_private_attributes
,
1043 &obj_nkp
.nkp_in_private_count
);
1049 rv
= get_object_attributes(
1050 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
1051 pub_out_attr_count
, obj_nkp
.nkp_out_public_attributes
);
1052 if (rv
== CRYPTO_SUCCESS
) {
1053 rv
= get_object_attributes(
1054 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
1055 pri_out_attr_count
, obj_nkp
.nkp_out_private_attributes
);
1057 free_attributes(obj_nkp
.nkp_out_public_attributes
,
1058 &obj_nkp
.nkp_out_public_count
);
1059 free_attributes(obj_nkp
.nkp_out_private_attributes
,
1060 &obj_nkp
.nkp_out_private_count
);
1062 if (rv
!= CRYPTO_SUCCESS
) {
1066 rv
= kernel_build_object(pubTemplate
, pub_attr_count
, new_pub_objp
,
1067 session_p
, KERNEL_GEN_KEY
);
1068 if (rv
!= CRYPTO_SUCCESS
) {
1073 * Copy CKA_BASE and CKA_PRIME from the public template
1074 * to the private template.
1076 rv
= copy_attribute(CKA_BASE
, pubTemplate
, pub_attr_count
,
1077 &priTemplate
[pri_attr_count
]);
1078 if (rv
!= CRYPTO_SUCCESS
) {
1081 rv
= copy_attribute(CKA_PRIME
, pubTemplate
, pub_attr_count
,
1082 &priTemplate
[pri_attr_count
+ 1]);
1083 if (rv
!= CRYPTO_SUCCESS
) {
1084 (void) free(priTemplate
[pri_attr_count
].pValue
);
1088 /* +2 to account for CKA_BASE and CKA_PRIME */
1089 rv
= kernel_build_object(priTemplate
, pri_attr_count
+ 2,
1090 new_pri_objp
, session_p
, KERNEL_GEN_KEY
);
1091 (void) free(priTemplate
[pri_attr_count
].pValue
);
1092 (void) free(priTemplate
[pri_attr_count
+ 1].pValue
);
1093 if (rv
!= CRYPTO_SUCCESS
) {
1096 (void) free(pubTemplate
);
1097 (void) free(priTemplate
);
1099 new_pub_objp
->is_lib_obj
= B_TRUE
;
1100 new_pri_objp
->is_lib_obj
= B_TRUE
;
1101 new_pub_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1102 new_pri_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1103 (void) pthread_mutex_init(&new_pub_objp
->object_mutex
, NULL
);
1104 new_pub_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1105 (void) pthread_mutex_init(&new_pri_objp
->object_mutex
, NULL
);
1106 new_pri_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1110 free_attributes(obj_nkp
.nkp_in_public_attributes
,
1111 &obj_nkp
.nkp_in_public_count
);
1112 free_attributes(obj_nkp
.nkp_out_public_attributes
,
1113 &obj_nkp
.nkp_out_public_count
);
1114 free_attributes(obj_nkp
.nkp_in_private_attributes
,
1115 &obj_nkp
.nkp_in_private_count
);
1116 free_attributes(obj_nkp
.nkp_out_private_attributes
,
1117 &obj_nkp
.nkp_out_private_count
);
1118 if (pubTemplate
!= NULL
) {
1119 (void) free(pubTemplate
);
1121 if (priTemplate
!= NULL
) {
1122 (void) free(priTemplate
);
1128 key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism
,
1129 CK_ATTRIBUTE_PTR pPublicKeyTemplate
, CK_ULONG ulPublicKeyAttributeCount
,
1130 CK_ATTRIBUTE_PTR pPrivateKeyTemplate
, CK_ULONG ulPrivateKeyAttributeCount
,
1131 kernel_session_t
*session_p
, crypto_mech_type_t k_mech_type
,
1132 kernel_object_t
*new_pub_objp
, kernel_object_t
*new_pri_objp
)
1134 crypto_nostore_generate_key_pair_t obj_nkp
;
1135 CK_ATTRIBUTE_PTR pubTemplate
= NULL
;
1136 CK_ATTRIBUTE_PTR priTemplate
= NULL
;
1138 CK_BBOOL is_token_obj1
= FALSE
;
1139 CK_BBOOL is_token_obj2
= FALSE
;
1140 uint_t pub_attr_count
, pri_attr_count
;
1141 uint_t pub_out_attr_count
= 0, pri_out_attr_count
= 0;
1142 char value
[EC_MAX_VALUE_LEN
];
1143 char point
[EC_MAX_POINT_LEN
];
1144 CK_ULONG pub_class
= CKO_PUBLIC_KEY
;
1145 CK_ULONG pri_class
= CKO_PRIVATE_KEY
;
1147 boolean_t has_class
, has_key_type
;
1150 obj_nkp
.nkp_in_public_count
= 0;
1151 obj_nkp
.nkp_out_public_count
= 0;
1152 obj_nkp
.nkp_in_private_count
= 0;
1153 obj_nkp
.nkp_out_private_count
= 0;
1156 * Add CKA_EC_POINT to the public template.
1157 * This is the generated value Q. This attribute
1158 * must not be in the template.
1160 if (attribute_in_template(CKA_EC_POINT
, pPublicKeyTemplate
,
1161 ulPublicKeyAttributeCount
)) {
1162 rv
= CKR_TEMPLATE_INCONSISTENT
;
1165 has_class
= attribute_in_template(CKA_CLASS
, pPublicKeyTemplate
,
1166 ulPublicKeyAttributeCount
);
1167 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPublicKeyTemplate
,
1168 ulPublicKeyAttributeCount
);
1170 pub_attr_count
= ulPublicKeyAttributeCount
+ 1;
1175 pubTemplate
= grow_template(pPublicKeyTemplate
,
1176 ulPublicKeyAttributeCount
, pub_attr_count
);
1177 if (pubTemplate
== NULL
) {
1178 rv
= CKR_HOST_MEMORY
;
1182 n
= ulPublicKeyAttributeCount
;
1184 pubTemplate
[n
].type
= CKA_CLASS
;
1185 pubTemplate
[n
].pValue
= (caddr_t
)&pub_class
;
1186 pubTemplate
[n
].ulValueLen
= sizeof (pub_class
);
1189 if (!has_key_type
) {
1190 pubTemplate
[n
].type
= CKA_KEY_TYPE
;
1192 pubTemplate
[n
].pValue
= (caddr_t
)&key_type
;
1193 pubTemplate
[n
].ulValueLen
= sizeof (key_type
);
1196 pubTemplate
[n
].type
= CKA_EC_POINT
;
1197 pubTemplate
[n
].pValue
= (caddr_t
)point
;
1198 pubTemplate
[n
].ulValueLen
= sizeof (point
);
1199 pub_out_attr_count
++;
1201 rv
= process_object_attributes(pubTemplate
,
1202 pub_attr_count
- pub_out_attr_count
,
1203 &obj_nkp
.nkp_in_public_attributes
, &is_token_obj1
);
1207 obj_nkp
.nkp_in_public_count
= pub_attr_count
- pub_out_attr_count
;
1209 rv
= process_object_attributes(
1210 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
1211 pub_out_attr_count
, &obj_nkp
.nkp_out_public_attributes
,
1216 obj_nkp
.nkp_out_public_count
= pub_out_attr_count
;
1219 * Cannot create a token object with a READ-ONLY
1222 if (is_token_obj1
&& session_p
->ses_RO
) {
1223 rv
= CKR_SESSION_READ_ONLY
;
1228 * CKA_EC_PARAMS and CKA_VALUE must not appear in
1231 if (attribute_in_template(CKA_EC_PARAMS
, pPrivateKeyTemplate
,
1232 ulPrivateKeyAttributeCount
) ||
1233 attribute_in_template(CKA_VALUE
, pPrivateKeyTemplate
,
1234 ulPrivateKeyAttributeCount
)) {
1235 rv
= CKR_TEMPLATE_INCONSISTENT
;
1238 has_class
= attribute_in_template(CKA_CLASS
, pPrivateKeyTemplate
,
1239 ulPrivateKeyAttributeCount
);
1240 has_key_type
= attribute_in_template(CKA_KEY_TYPE
, pPrivateKeyTemplate
,
1241 ulPrivateKeyAttributeCount
);
1243 pri_attr_count
= ulPrivateKeyAttributeCount
+ 1;
1249 /* allocate space for CKA_EC_PARAMS */
1250 priTemplate
= grow_template(pPrivateKeyTemplate
,
1251 ulPrivateKeyAttributeCount
, pri_attr_count
+ 1);
1252 if (priTemplate
== NULL
) {
1253 rv
= CKR_HOST_MEMORY
;
1256 n
= ulPrivateKeyAttributeCount
;
1258 priTemplate
[n
].type
= CKA_CLASS
;
1259 priTemplate
[n
].pValue
= (caddr_t
)&pri_class
;
1260 priTemplate
[n
].ulValueLen
= sizeof (pri_class
);
1263 if (!has_key_type
) {
1264 priTemplate
[n
].type
= CKA_KEY_TYPE
;
1266 priTemplate
[n
].pValue
= (caddr_t
)&key_type
;
1267 priTemplate
[n
].ulValueLen
= sizeof (key_type
);
1270 priTemplate
[n
].type
= CKA_VALUE
;
1271 priTemplate
[n
].pValue
= (caddr_t
)value
;
1272 priTemplate
[n
].ulValueLen
= sizeof (value
);
1273 pri_out_attr_count
++;
1275 rv
= process_object_attributes(priTemplate
,
1276 pri_attr_count
- pri_out_attr_count
,
1277 &obj_nkp
.nkp_in_private_attributes
, &is_token_obj2
);
1281 obj_nkp
.nkp_in_private_count
= pri_attr_count
- pri_out_attr_count
;
1283 rv
= process_object_attributes(
1284 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
1285 pri_out_attr_count
, &obj_nkp
.nkp_out_private_attributes
,
1290 obj_nkp
.nkp_out_private_count
= pri_out_attr_count
;
1293 * The public key and the private key need to contain the same
1294 * attribute values for CKA_TOKEN.
1296 if (is_token_obj1
!= is_token_obj2
) {
1297 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
1301 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
1302 obj_nkp
.nkp_session
= session_p
-> k_session
;
1303 obj_nkp
.nkp_mechanism
.cm_type
= k_mech_type
;
1304 obj_nkp
.nkp_mechanism
.cm_param
= pMechanism
->pParameter
;
1305 obj_nkp
.nkp_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1307 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_GENERATE_KEY_PAIR
,
1313 rv
= CKR_FUNCTION_FAILED
;
1315 rv
= crypto2pkcs11_error_number(obj_nkp
.nkp_return_value
);
1317 free_attributes(obj_nkp
.nkp_in_public_attributes
,
1318 &obj_nkp
.nkp_in_public_count
);
1319 free_attributes(obj_nkp
.nkp_in_private_attributes
,
1320 &obj_nkp
.nkp_in_private_count
);
1326 rv
= get_object_attributes(
1327 &pubTemplate
[pub_attr_count
- pub_out_attr_count
],
1328 pub_out_attr_count
, obj_nkp
.nkp_out_public_attributes
);
1329 if (rv
== CRYPTO_SUCCESS
) {
1330 rv
= get_object_attributes(
1331 &priTemplate
[pri_attr_count
- pri_out_attr_count
],
1332 pri_out_attr_count
, obj_nkp
.nkp_out_private_attributes
);
1334 free_attributes(obj_nkp
.nkp_out_public_attributes
,
1335 &obj_nkp
.nkp_out_public_count
);
1336 free_attributes(obj_nkp
.nkp_out_private_attributes
,
1337 &obj_nkp
.nkp_out_private_count
);
1338 if (rv
!= CRYPTO_SUCCESS
) {
1342 rv
= kernel_build_object(pubTemplate
, pub_attr_count
, new_pub_objp
,
1343 session_p
, KERNEL_GEN_KEY
);
1344 if (rv
!= CRYPTO_SUCCESS
) {
1349 * Copy CKA_EC_PARAMS from the public template to the
1352 rv
= copy_attribute(CKA_EC_PARAMS
, pubTemplate
, pub_attr_count
,
1353 &priTemplate
[pri_attr_count
]);
1354 if (rv
!= CRYPTO_SUCCESS
) {
1358 /* +1 to account for CKA_EC_PARAMS */
1359 rv
= kernel_build_object(priTemplate
, pri_attr_count
+ 1,
1360 new_pri_objp
, session_p
, KERNEL_GEN_KEY
);
1361 (void) free(priTemplate
[pri_attr_count
].pValue
);
1362 if (rv
!= CRYPTO_SUCCESS
) {
1365 (void) free(pubTemplate
);
1366 (void) free(priTemplate
);
1368 new_pub_objp
->is_lib_obj
= B_TRUE
;
1369 new_pri_objp
->is_lib_obj
= B_TRUE
;
1370 new_pub_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1371 new_pri_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1372 (void) pthread_mutex_init(&new_pub_objp
->object_mutex
, NULL
);
1373 new_pub_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1374 (void) pthread_mutex_init(&new_pri_objp
->object_mutex
, NULL
);
1375 new_pri_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1379 free_attributes(obj_nkp
.nkp_in_public_attributes
,
1380 &obj_nkp
.nkp_in_public_count
);
1381 free_attributes(obj_nkp
.nkp_out_public_attributes
,
1382 &obj_nkp
.nkp_out_public_count
);
1383 free_attributes(obj_nkp
.nkp_in_private_attributes
,
1384 &obj_nkp
.nkp_in_private_count
);
1385 free_attributes(obj_nkp
.nkp_out_private_attributes
,
1386 &obj_nkp
.nkp_out_private_count
);
1387 if (pubTemplate
!= NULL
) {
1388 (void) free(pubTemplate
);
1390 if (priTemplate
!= NULL
) {
1391 (void) free(priTemplate
);
1397 C_GenerateKeyPair(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
1398 CK_ATTRIBUTE_PTR pPublicKeyTemplate
, CK_ULONG ulPublicKeyAttributeCount
,
1399 CK_ATTRIBUTE_PTR pPrivateKeyTemplate
, CK_ULONG ulPrivateKeyAttributeCount
,
1400 CK_OBJECT_HANDLE_PTR phPublicKey
, CK_OBJECT_HANDLE_PTR phPrivateKey
)
1403 kernel_session_t
*session_p
;
1404 kernel_object_t
*new_pub_objp
= NULL
;
1405 kernel_object_t
*new_pri_objp
= NULL
;
1406 kernel_slot_t
*pslot
;
1407 boolean_t ses_lock_held
= B_FALSE
;
1408 CK_BBOOL is_pri_obj1
;
1409 CK_BBOOL is_pri_obj2
;
1410 CK_BBOOL is_token_obj1
= FALSE
;
1411 CK_BBOOL is_token_obj2
= FALSE
;
1412 crypto_mech_type_t k_mech_type
;
1414 CK_RV (*func
)(CK_MECHANISM_PTR
, CK_ATTRIBUTE_PTR
, CK_ULONG
,
1415 CK_ATTRIBUTE_PTR
, CK_ULONG
, kernel_session_t
*, crypto_mech_type_t
,
1416 kernel_object_t
*, kernel_object_t
*);
1418 if (!kernel_initialized
)
1419 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
1421 /* Obtain the session pointer. */
1422 rv
= handle2session(hSession
, &session_p
);
1426 if ((pMechanism
== NULL
) || (phPublicKey
== NULL
) ||
1427 (phPrivateKey
== NULL
)) {
1428 rv
= CKR_ARGUMENTS_BAD
;
1432 if ((pPublicKeyTemplate
== NULL
) && (ulPublicKeyAttributeCount
!= 0)) {
1433 rv
= CKR_ARGUMENTS_BAD
;
1437 if ((pPrivateKeyTemplate
== NULL
) &&
1438 (ulPrivateKeyAttributeCount
!= 0)) {
1439 rv
= CKR_ARGUMENTS_BAD
;
1443 /* Get the kernel's internal mechanism number. */
1444 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
1449 /* Create an object wrapper for the public key */
1450 new_pub_objp
= calloc(1, sizeof (kernel_object_t
));
1451 if (new_pub_objp
== NULL
) {
1452 rv
= CKR_HOST_MEMORY
;
1456 /* Create an object wrapper for the private key. */
1457 new_pri_objp
= calloc(1, sizeof (kernel_object_t
));
1458 if (new_pri_objp
== NULL
) {
1459 rv
= CKR_HOST_MEMORY
;
1464 * Special Case: if token does not support object creation,
1465 * but does support key generation by value, then create a session
1466 * object and initialize with values returned by token.
1468 pslot
= slot_table
[session_p
->ses_slotid
];
1469 if (!pslot
->sl_func_list
.fl_object_create
) {
1470 switch (pMechanism
->mechanism
) {
1471 case CKM_RSA_PKCS_KEY_PAIR_GEN
:
1472 func
= key_gen_rsa_by_value
;
1475 case CKM_DH_PKCS_KEY_PAIR_GEN
:
1476 func
= key_gen_dh_by_value
;
1479 case CKM_EC_KEY_PAIR_GEN
:
1480 func
= key_gen_ec_by_value
;
1484 rv
= CKR_MECHANISM_INVALID
;
1487 rv
= (*func
)(pMechanism
, pPublicKeyTemplate
,
1488 ulPublicKeyAttributeCount
, pPrivateKeyTemplate
,
1489 ulPrivateKeyAttributeCount
, session_p
, k_mech_type
,
1490 new_pub_objp
, new_pri_objp
);
1494 crypto_object_generate_key_pair_t obj_kp
;
1496 /* Process the public key attributes. */
1497 rv
= process_object_attributes(pPublicKeyTemplate
,
1498 ulPublicKeyAttributeCount
, &obj_kp
.kp_public_attributes
,
1504 /* Cannot create a token object with a READ-ONLY session. */
1505 if (is_token_obj1
&& session_p
->ses_RO
) {
1506 free_object_attributes(obj_kp
.kp_public_attributes
,
1507 ulPublicKeyAttributeCount
);
1508 rv
= CKR_SESSION_READ_ONLY
;
1512 /* Process the private key attributes. */
1513 rv
= process_object_attributes(pPrivateKeyTemplate
,
1514 ulPrivateKeyAttributeCount
, &obj_kp
.kp_private_attributes
,
1517 free_object_attributes(obj_kp
.kp_public_attributes
,
1518 ulPublicKeyAttributeCount
);
1523 * The public key and the private key need to contain the same
1524 * attribute values for CKA_TOKEN.
1526 if (is_token_obj1
!= is_token_obj2
) {
1527 free_object_attributes(obj_kp
.kp_public_attributes
,
1528 ulPublicKeyAttributeCount
);
1529 free_object_attributes(obj_kp
.kp_private_attributes
,
1530 ulPrivateKeyAttributeCount
);
1531 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
1535 /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */
1536 obj_kp
.kp_session
= session_p
-> k_session
;
1537 obj_kp
.kp_mechanism
.cm_type
= k_mech_type
;
1538 obj_kp
.kp_mechanism
.cm_param
= pMechanism
->pParameter
;
1539 obj_kp
.kp_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1540 obj_kp
.kp_public_count
= ulPublicKeyAttributeCount
;
1541 obj_kp
.kp_private_count
= ulPrivateKeyAttributeCount
;
1543 while ((r
= ioctl(kernel_fd
, CRYPTO_GENERATE_KEY_PAIR
,
1549 rv
= CKR_FUNCTION_FAILED
;
1551 rv
= crypto2pkcs11_error_number(obj_kp
.kp_return_value
);
1553 free_object_attributes(obj_kp
.kp_public_attributes
,
1554 ulPublicKeyAttributeCount
);
1555 free_object_attributes(obj_kp
.kp_private_attributes
,
1556 ulPrivateKeyAttributeCount
);
1561 /* Get the CKA_PRIVATE value for the key pair. */
1562 rv
= get_cka_private_value(session_p
, obj_kp
.kp_public_handle
,
1568 rv
= get_cka_private_value(session_p
, obj_kp
.kp_private_handle
,
1575 * Store the kernel public key handle into the public key
1576 * object and finish the public key object initialization.
1578 new_pub_objp
->is_lib_obj
= B_FALSE
;
1579 new_pub_objp
->k_handle
= obj_kp
.kp_public_handle
;
1580 new_pub_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1581 new_pub_objp
->extra_attrlistp
= NULL
;
1584 new_pub_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
1586 new_pub_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
1589 new_pub_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
1591 new_pub_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
1593 (void) pthread_mutex_init(&new_pub_objp
->object_mutex
, NULL
);
1594 new_pub_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1597 * Store the kernel private key handle into the private key
1598 * object and finish the private key object initialization.
1600 new_pri_objp
->is_lib_obj
= B_FALSE
;
1601 new_pri_objp
->k_handle
= obj_kp
.kp_private_handle
;
1602 new_pri_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1603 new_pri_objp
->extra_attrlistp
= NULL
;
1606 new_pri_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
1608 new_pri_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
1611 new_pri_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
1613 new_pri_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
1616 (void) pthread_mutex_init(&new_pri_objp
->object_mutex
, NULL
);
1617 new_pri_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1620 * Add the new pub/pri objects to the slot's token list if they are
1621 * token objects. Otherwise, add them to the session's object list.
1623 if (is_token_obj1
) { /* is_token_obj1 == is_token_obj2 */
1624 pslot
= slot_table
[session_p
->ses_slotid
];
1625 kernel_add_token_object_to_slot(new_pub_objp
, pslot
);
1626 kernel_add_token_object_to_slot(new_pri_objp
, pslot
);
1628 kernel_add_object_to_session(new_pub_objp
, session_p
);
1629 kernel_add_object_to_session(new_pri_objp
, session_p
);
1632 *phPublicKey
= (CK_OBJECT_HANDLE
)new_pub_objp
;
1633 *phPrivateKey
= (CK_OBJECT_HANDLE
)new_pri_objp
;
1634 REFRELE(session_p
, ses_lock_held
);
1638 if (new_pub_objp
!= NULL
) {
1639 (void) free(new_pub_objp
);
1641 if (new_pri_objp
!= NULL
) {
1642 (void) free(new_pri_objp
);
1644 REFRELE(session_p
, ses_lock_held
);
1650 C_WrapKey(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
1651 CK_OBJECT_HANDLE hWrappingKey
, CK_OBJECT_HANDLE hKey
,
1652 CK_BYTE_PTR pWrappedKey
, CK_ULONG_PTR pulWrappedKeyLen
)
1655 kernel_session_t
*session_p
;
1656 boolean_t ses_lock_held
= B_FALSE
;
1657 kernel_object_t
*wrappingkey_p
;
1658 kernel_object_t
*key_p
;
1659 crypto_mech_type_t k_mech_type
;
1660 crypto_object_wrap_key_t obj_wrapkey
;
1663 if (!kernel_initialized
)
1664 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
1666 if (pulWrappedKeyLen
== NULL
|| pMechanism
== NULL
) {
1667 return (CKR_ARGUMENTS_BAD
);
1671 * Obtain the session pointer. Also, increment the session
1674 rv
= handle2session(hSession
, &session_p
);
1678 /* Get the kernel's internal mechanism number. */
1679 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
1681 REFRELE(session_p
, ses_lock_held
);
1685 /* Obtain the wrapping key object pointer. */
1686 HANDLE2OBJECT(hWrappingKey
, wrappingkey_p
, rv
);
1688 REFRELE(session_p
, ses_lock_held
);
1692 /* Obtain the to_be_wrapped key object pointer. */
1693 HANDLE2OBJECT(hKey
, key_p
, rv
);
1695 OBJ_REFRELE(wrappingkey_p
);
1696 REFRELE(session_p
, ses_lock_held
);
1700 /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */
1701 obj_wrapkey
.wk_session
= session_p
->k_session
;
1702 obj_wrapkey
.wk_mechanism
.cm_type
= k_mech_type
;
1703 obj_wrapkey
.wk_mechanism
.cm_param
= pMechanism
->pParameter
;
1704 obj_wrapkey
.wk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1705 obj_wrapkey
.wk_wrapping_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
1706 obj_wrapkey
.wk_wrapping_key
.ck_obj_id
= wrappingkey_p
->k_handle
;
1707 obj_wrapkey
.wk_object_handle
= key_p
->k_handle
;
1708 obj_wrapkey
.wk_wrapped_key_len
= *pulWrappedKeyLen
;
1709 obj_wrapkey
.wk_wrapped_key
= (char *)pWrappedKey
;
1711 while ((r
= ioctl(kernel_fd
, CRYPTO_WRAP_KEY
, &obj_wrapkey
)) < 0) {
1716 rv
= CKR_FUNCTION_FAILED
;
1718 rv
= crypto2pkcs11_error_number(obj_wrapkey
.wk_return_value
);
1722 * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen
1723 * when the applciation-supplied wrapped key buffer is too small.
1724 * The situation that the application only asks for the length of
1725 * the wrapped key is covered in rv == CKR_OK.
1727 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
) {
1728 *pulWrappedKeyLen
= obj_wrapkey
.wk_wrapped_key_len
;
1732 OBJ_REFRELE(wrappingkey_p
);
1733 REFRELE(session_p
, ses_lock_held
);
1739 C_UnwrapKey(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
1740 CK_OBJECT_HANDLE hUnwrappingKey
, CK_BYTE_PTR pWrappedKey
,
1741 CK_ULONG ulWrappedKeyLen
, CK_ATTRIBUTE_PTR pTemplate
,
1742 CK_ULONG ulAttributeCount
, CK_OBJECT_HANDLE_PTR phKey
)
1745 kernel_session_t
*session_p
;
1746 kernel_object_t
*unwrappingkey_p
;
1747 kernel_object_t
*new_objp
= NULL
;
1748 kernel_slot_t
*pslot
;
1749 boolean_t ses_lock_held
= B_FALSE
;
1750 CK_BBOOL is_pri_obj
;
1751 CK_BBOOL is_token_obj
= FALSE
;
1752 CK_MECHANISM_INFO info
;
1753 uint32_t k_mi_flags
;
1754 CK_BYTE
*clear_key_val
= NULL
;
1756 CK_ATTRIBUTE_PTR newTemplate
= NULL
;
1757 crypto_mech_type_t k_mech_type
;
1758 crypto_object_unwrap_key_t obj_unwrapkey
;
1761 if (!kernel_initialized
)
1762 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
1764 if (pMechanism
== NULL
|| pWrappedKey
== NULL
|| phKey
== NULL
) {
1765 return (CKR_ARGUMENTS_BAD
);
1768 if ((pTemplate
== NULL
) && (ulAttributeCount
!= 0)) {
1769 return (CKR_ARGUMENTS_BAD
);
1772 /* Obtain the session pointer. */
1773 rv
= handle2session(hSession
, &session_p
);
1777 /* Obtain the wrapping key object pointer. */
1778 HANDLE2OBJECT(hUnwrappingKey
, unwrappingkey_p
, rv
);
1780 REFRELE(session_p
, ses_lock_held
);
1785 * If the HW provider doesn't support C_UnwrapKey, we will try
1786 * to emulate it in the library.
1788 pslot
= slot_table
[session_p
->ses_slotid
];
1789 if ((!pslot
->sl_func_list
.fl_object_create
) &&
1790 (!pslot
->sl_func_list
.fl_key_unwrap
)) {
1791 rv
= get_mechanism_info(pslot
, pMechanism
->mechanism
, &info
,
1798 * If the mechanism flag doesn't have CKF_UNWRAP, and it's
1799 * an unwrapping of a secret key object, then help this
1800 * out with a decryption followed by an object creation.
1802 if (!(k_mi_flags
& CRYPTO_FG_UNWRAP
) &&
1803 (k_mi_flags
& CRYPTO_FG_DECRYPT
) &&
1804 (is_secret_key_template(pTemplate
, ulAttributeCount
))) {
1806 /* First allocate space for the recovered key value */
1807 clear_key_val
= malloc(ulWrappedKeyLen
);
1808 if (clear_key_val
== NULL
) {
1809 rv
= CKR_HOST_MEMORY
;
1813 rv
= kernel_decrypt_init(session_p
, unwrappingkey_p
,
1819 ulDataLen
= ulWrappedKeyLen
;
1820 rv
= kernel_decrypt(session_p
, pWrappedKey
,
1821 ulWrappedKeyLen
, clear_key_val
, &ulDataLen
);
1826 newTemplate
= grow_template(pTemplate
, ulAttributeCount
,
1827 ulAttributeCount
+ 1);
1828 if (newTemplate
== NULL
) {
1829 rv
= CKR_HOST_MEMORY
;
1832 /* Now add the CKA_VALUE attribute to template */
1833 newTemplate
[ulAttributeCount
].type
= CKA_VALUE
;
1834 newTemplate
[ulAttributeCount
].pValue
= clear_key_val
;
1835 newTemplate
[ulAttributeCount
].ulValueLen
= ulDataLen
;
1837 /* Finally create the key, based on the new template */
1838 rv
= kernel_add_object(newTemplate
,
1839 ulAttributeCount
+ 1, phKey
, session_p
);
1840 (void) free(clear_key_val
);
1841 (void) free(newTemplate
);
1842 OBJ_REFRELE(unwrappingkey_p
);
1843 REFRELE(session_p
, ses_lock_held
);
1846 rv
= CKR_FUNCTION_FAILED
;
1852 * If we come here, the HW provider must have registered the unwrapkey
1853 * entry. Therefore, the unwrap key will be performed in the HW
1856 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
1861 /* Create an object wrapper for the new key in the library first */
1862 new_objp
= calloc(1, sizeof (kernel_object_t
));
1863 if (new_objp
== NULL
) {
1864 rv
= CKR_HOST_MEMORY
;
1868 /* Process the attributes */
1869 rv
= process_object_attributes(pTemplate
, ulAttributeCount
,
1870 &obj_unwrapkey
.uk_attributes
, &is_token_obj
);
1875 /* Cannot create a token object with a READ-ONLY session. */
1876 if (is_token_obj
&& session_p
->ses_RO
) {
1877 free_object_attributes(obj_unwrapkey
.uk_attributes
,
1879 rv
= CKR_SESSION_READ_ONLY
;
1883 /* Make the CRYPTO_UNWRAP_KEY ioctl call. */
1884 obj_unwrapkey
.uk_session
= session_p
->k_session
;
1885 obj_unwrapkey
.uk_mechanism
.cm_type
= k_mech_type
;
1886 obj_unwrapkey
.uk_mechanism
.cm_param
= pMechanism
->pParameter
;
1887 obj_unwrapkey
.uk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
1888 obj_unwrapkey
.uk_unwrapping_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
1889 obj_unwrapkey
.uk_unwrapping_key
.ck_obj_id
= unwrappingkey_p
->k_handle
;
1890 obj_unwrapkey
.uk_wrapped_key
= (char *)pWrappedKey
;
1891 obj_unwrapkey
.uk_wrapped_key_len
= ulWrappedKeyLen
;
1892 obj_unwrapkey
.uk_count
= ulAttributeCount
;
1894 while ((r
= ioctl(kernel_fd
, CRYPTO_UNWRAP_KEY
, &obj_unwrapkey
)) < 0) {
1899 rv
= CKR_FUNCTION_FAILED
;
1901 rv
= crypto2pkcs11_error_number(obj_unwrapkey
.uk_return_value
);
1904 free_object_attributes(obj_unwrapkey
.uk_attributes
, ulAttributeCount
);
1909 /* Get the CKA_PRIVATE value for the unwrapped key. */
1910 rv
= get_cka_private_value(session_p
, obj_unwrapkey
.uk_object_handle
,
1917 * Store the kernel object handle in the new key object wrapper and
1920 new_objp
->k_handle
= obj_unwrapkey
.uk_object_handle
;
1921 new_objp
->is_lib_obj
= B_FALSE
;
1922 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
1923 new_objp
->extra_attrlistp
= NULL
;
1926 new_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
1928 new_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
1931 new_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
1933 new_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
1935 (void) pthread_mutex_init(&new_objp
->object_mutex
, NULL
);
1936 new_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
1939 * Add the new object to the slot's token object list if it is a
1940 * a token object. Otherwise, add it to the session's object list.
1943 pslot
= slot_table
[session_p
->ses_slotid
];
1944 kernel_add_token_object_to_slot(new_objp
, pslot
);
1946 kernel_add_object_to_session(new_objp
, session_p
);
1949 *phKey
= (CK_OBJECT_HANDLE
)new_objp
;
1950 OBJ_REFRELE(unwrappingkey_p
);
1951 REFRELE(session_p
, ses_lock_held
);
1955 OBJ_REFRELE(unwrappingkey_p
);
1956 if (new_objp
!= NULL
)
1957 (void) free(new_objp
);
1959 if (clear_key_val
!= NULL
)
1960 (void) free(clear_key_val
);
1962 if (newTemplate
!= NULL
)
1963 (void) free(newTemplate
);
1965 REFRELE(session_p
, ses_lock_held
);
1970 * Get sufficient attributes from a base key to pass by value in a
1971 * crypto_key structure. Storage for attributes is allocated.
1972 * For EC public keys, it is CKA_EC_PARAMS and CKA_EC_POINT.
1973 * For EC private keys, it is CKA_EC_PARAMS and CKA_VALUE.
1976 get_base_key_attributes(kernel_object_t
*base_key
, crypto_key_t
*key_by_value
)
1979 crypto_object_attribute_t
*attrs
= NULL
;
1981 int i
, count
= 0, rv
;
1983 switch (base_key
->key_type
) {
1986 attrs
= malloc(count
* sizeof (crypto_object_attribute_t
));
1987 if (attrs
== NULL
) {
1988 rv
= CKR_HOST_MEMORY
;
1991 bzero(attrs
, count
* sizeof (crypto_object_attribute_t
));
1993 (void) pthread_mutex_lock(&base_key
->object_mutex
);
1995 if (!base_key
->is_lib_obj
) {
1996 rv
= CRYPTO_ARGUMENTS_BAD
;
2000 if (base_key
->class != CKO_PUBLIC_KEY
&&
2001 base_key
->class != CKO_PRIVATE_KEY
) {
2002 rv
= CRYPTO_ARGUMENTS_BAD
;
2007 * Both public and private EC keys should have
2008 * a CKA_EC_PARAMS attribute.
2010 tmp
.type
= CKA_EC_PARAMS
;
2013 /* get size of attribute */
2014 rv
= kernel_get_attribute(base_key
, &tmp
);
2019 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2020 if (tmp
.pValue
== NULL
) {
2021 rv
= CKR_HOST_MEMORY
;
2024 rv
= kernel_get_attribute(base_key
, &tmp
);
2029 attrs
[0].oa_type
= tmp
.type
;
2030 attrs
[0].oa_value
= tmp
.pValue
;
2031 attrs
[0].oa_value_len
= tmp
.ulValueLen
;
2033 switch (base_key
->class) {
2034 case CKO_PUBLIC_KEY
:
2035 big
= OBJ_PUB_EC_POINT(base_key
);
2036 tmp
.type
= CKA_EC_POINT
;
2039 case CKO_PRIVATE_KEY
:
2040 big
= OBJ_PRI_EC_VALUE(base_key
);
2041 tmp
.type
= CKA_VALUE
;
2045 rv
= CKR_ATTRIBUTE_TYPE_INVALID
;
2048 tmp
.ulValueLen
= big
->big_value_len
;
2049 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2050 if (tmp
.pValue
== NULL
) {
2051 rv
= CKR_HOST_MEMORY
;
2054 rv
= kernel_get_attribute(base_key
, &tmp
);
2059 attrs
[1].oa_type
= tmp
.type
;
2060 attrs
[1].oa_value
= tmp
.pValue
;
2061 attrs
[1].oa_value_len
= tmp
.ulValueLen
;
2062 key_by_value
->ck_attrs
= attrs
;
2063 key_by_value
->ck_count
= 2;
2068 attrs
= malloc(count
* sizeof (crypto_object_attribute_t
));
2069 if (attrs
== NULL
) {
2070 rv
= CKR_HOST_MEMORY
;
2073 bzero(attrs
, count
* sizeof (crypto_object_attribute_t
));
2075 (void) pthread_mutex_lock(&base_key
->object_mutex
);
2077 if (!base_key
->is_lib_obj
) {
2078 rv
= CRYPTO_ARGUMENTS_BAD
;
2082 if (base_key
->class != CKO_PRIVATE_KEY
) {
2083 rv
= CRYPTO_ARGUMENTS_BAD
;
2086 tmp
.type
= CKA_BASE
;
2089 /* get size of attribute */
2090 rv
= kernel_get_attribute(base_key
, &tmp
);
2095 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2096 if (tmp
.pValue
== NULL
) {
2097 rv
= CKR_HOST_MEMORY
;
2100 rv
= kernel_get_attribute(base_key
, &tmp
);
2105 attrs
[0].oa_type
= tmp
.type
;
2106 attrs
[0].oa_value
= tmp
.pValue
;
2107 attrs
[0].oa_value_len
= tmp
.ulValueLen
;
2109 tmp
.type
= CKA_PRIME
;
2112 /* get size of attribute */
2113 rv
= kernel_get_attribute(base_key
, &tmp
);
2118 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2119 if (tmp
.pValue
== NULL
) {
2120 rv
= CKR_HOST_MEMORY
;
2123 rv
= kernel_get_attribute(base_key
, &tmp
);
2128 attrs
[1].oa_type
= tmp
.type
;
2129 attrs
[1].oa_value
= tmp
.pValue
;
2130 attrs
[1].oa_value_len
= tmp
.ulValueLen
;
2132 big
= OBJ_PRI_DH_VALUE(base_key
);
2133 tmp
.type
= CKA_VALUE
;
2135 tmp
.ulValueLen
= big
->big_value_len
;
2136 tmp
.pValue
= malloc(tmp
.ulValueLen
);
2137 if (tmp
.pValue
== NULL
) {
2138 rv
= CKR_HOST_MEMORY
;
2141 rv
= kernel_get_attribute(base_key
, &tmp
);
2146 attrs
[2].oa_type
= tmp
.type
;
2147 attrs
[2].oa_value
= tmp
.pValue
;
2148 attrs
[2].oa_value_len
= tmp
.ulValueLen
;
2149 key_by_value
->ck_attrs
= attrs
;
2150 key_by_value
->ck_count
= 3;
2154 rv
= CKR_ATTRIBUTE_TYPE_INVALID
;
2157 (void) pthread_mutex_unlock(&base_key
->object_mutex
);
2161 (void) pthread_mutex_unlock(&base_key
->object_mutex
);
2162 if (attrs
!= NULL
) {
2163 for (i
= 0; i
< count
; i
++) {
2164 free(attrs
[i
].oa_value
);
2172 derive_key_by_value(CK_MECHANISM_PTR pMechanism
, CK_ATTRIBUTE_PTR pTemplate
,
2173 CK_ULONG ulAttributeCount
, kernel_session_t
*session_p
,
2174 crypto_mech_type_t k_mech_type
, kernel_object_t
*basekey_p
,
2175 kernel_object_t
*new_objp
)
2177 crypto_nostore_derive_key_t obj_ndk
;
2178 char *key_buf
= NULL
;
2179 CK_ATTRIBUTE_PTR newTemplate
= NULL
;
2180 CK_BBOOL is_token_obj
= FALSE
;
2182 CK_ULONG secret_class
= CKO_SECRET_KEY
;
2183 ulong_t key_len
= 0;
2184 uint_t attr_count
= 0;
2186 boolean_t has_class
;
2189 obj_ndk
.ndk_in_count
= 0;
2190 obj_ndk
.ndk_out_count
= 0;
2191 obj_ndk
.ndk_base_key
.ck_count
= 0;
2193 rv
= get_key_len_from_template(pMechanism
, pTemplate
, ulAttributeCount
,
2194 basekey_p
, &key_len
);
2199 if ((key_buf
= malloc(key_len
)) == NULL
) {
2200 rv
= CKR_HOST_MEMORY
;
2204 has_class
= attribute_in_template(CKA_CLASS
, pTemplate
,
2207 attr_count
= ulAttributeCount
+ 1;
2211 newTemplate
= grow_template(pTemplate
, ulAttributeCount
, attr_count
);
2212 if (newTemplate
== NULL
) {
2213 rv
= CKR_HOST_MEMORY
;
2217 n
= ulAttributeCount
;
2219 newTemplate
[n
].type
= CKA_CLASS
;
2220 newTemplate
[n
].pValue
= (caddr_t
)&secret_class
;
2221 newTemplate
[n
].ulValueLen
= sizeof (secret_class
);
2225 /* Add CKA_VALUE to the template */
2226 newTemplate
[n
].type
= CKA_VALUE
;
2227 newTemplate
[n
].pValue
= (caddr_t
)key_buf
;
2228 newTemplate
[n
].ulValueLen
= key_len
;
2230 rv
= process_object_attributes(newTemplate
, attr_count
- 1,
2231 &obj_ndk
.ndk_in_attributes
, &is_token_obj
);
2235 obj_ndk
.ndk_in_count
= attr_count
- 1;
2237 rv
= process_object_attributes(&newTemplate
[attr_count
- 1],
2238 1, &obj_ndk
.ndk_out_attributes
, &is_token_obj
);
2242 obj_ndk
.ndk_out_count
= 1;
2244 /* Cannot create a token object with a READ-ONLY session. */
2245 if (is_token_obj
&& session_p
->ses_RO
) {
2246 rv
= CKR_SESSION_READ_ONLY
;
2250 obj_ndk
.ndk_session
= session_p
->k_session
;
2251 obj_ndk
.ndk_mechanism
.cm_type
= k_mech_type
;
2252 obj_ndk
.ndk_mechanism
.cm_param
= pMechanism
->pParameter
;
2253 obj_ndk
.ndk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
2256 * Obtain the attributes of base key and pass them by value.
2258 rv
= get_base_key_attributes(basekey_p
, &obj_ndk
.ndk_base_key
);
2263 obj_ndk
.ndk_base_key
.ck_format
= CRYPTO_KEY_ATTR_LIST
;
2265 while ((r
= ioctl(kernel_fd
, CRYPTO_NOSTORE_DERIVE_KEY
,
2271 rv
= CKR_FUNCTION_FAILED
;
2273 rv
= crypto2pkcs11_error_number(obj_ndk
.ndk_return_value
);
2275 free_attributes(obj_ndk
.ndk_in_attributes
, &obj_ndk
.ndk_in_count
);
2276 free_attributes((caddr_t
)obj_ndk
.ndk_base_key
.ck_attrs
,
2277 &obj_ndk
.ndk_base_key
.ck_count
);
2282 rv
= get_object_attributes(&newTemplate
[attr_count
- 1],
2283 1, obj_ndk
.ndk_out_attributes
);
2284 free_attributes(obj_ndk
.ndk_out_attributes
, &obj_ndk
.ndk_out_count
);
2285 if (rv
!= CRYPTO_SUCCESS
) {
2289 removed
= remove_one_attribute(newTemplate
, CKA_VALUE_LEN
,
2290 attr_count
, B_FALSE
);
2292 rv
= kernel_build_object(newTemplate
, removed
? attr_count
- 1 :
2293 attr_count
, new_objp
, session_p
, KERNEL_GEN_KEY
);
2294 if (rv
!= CRYPTO_SUCCESS
) {
2300 new_objp
->is_lib_obj
= B_TRUE
;
2301 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
2307 free_attributes(obj_ndk
.ndk_in_attributes
, &obj_ndk
.ndk_in_count
);
2308 free_attributes(obj_ndk
.ndk_out_attributes
, &obj_ndk
.ndk_out_count
);
2309 free_attributes((caddr_t
)obj_ndk
.ndk_base_key
.ck_attrs
,
2310 &obj_ndk
.ndk_base_key
.ck_count
);
2315 C_DeriveKey(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
2316 CK_OBJECT_HANDLE hBaseKey
, CK_ATTRIBUTE_PTR pTemplate
,
2317 CK_ULONG ulAttributeCount
, CK_OBJECT_HANDLE_PTR phKey
)
2320 kernel_session_t
*session_p
;
2321 kernel_object_t
*basekey_p
;
2322 kernel_object_t
*new_objp
;
2323 kernel_slot_t
*pslot
;
2324 boolean_t ses_lock_held
= B_FALSE
;
2325 CK_BBOOL is_pri_obj
;
2326 CK_BBOOL is_token_obj
= FALSE
;
2327 crypto_mech_type_t k_mech_type
;
2330 if (!kernel_initialized
)
2331 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
2333 /* Obtain the session pointer. */
2334 rv
= handle2session(hSession
, &session_p
);
2338 if (pMechanism
== NULL
) {
2339 REFRELE(session_p
, ses_lock_held
);
2340 return (CKR_ARGUMENTS_BAD
);
2343 if ((pTemplate
== NULL
&& ulAttributeCount
!= 0) ||
2344 (pTemplate
!= NULL
&& ulAttributeCount
== 0)) {
2345 REFRELE(session_p
, ses_lock_held
);
2346 return (CKR_ARGUMENTS_BAD
);
2349 /* Obtain the base key object pointer. */
2350 HANDLE2OBJECT(hBaseKey
, basekey_p
, rv
);
2352 REFRELE(session_p
, ses_lock_held
);
2356 /* Get the kernel's internal mechanism number. */
2357 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
2362 /* Create an object wrapper in the library for the generated key. */
2363 new_objp
= calloc(1, sizeof (kernel_object_t
));
2364 if (new_objp
== NULL
) {
2365 rv
= CKR_HOST_MEMORY
;
2370 * Special Case: if token does not support object creation,
2371 * but does support key derivation by value, then create a session
2372 * object and initialize with values returned by token.
2374 pslot
= slot_table
[session_p
->ses_slotid
];
2375 if (!pslot
->sl_func_list
.fl_object_create
) {
2376 rv
= derive_key_by_value(pMechanism
, pTemplate
,
2377 ulAttributeCount
, session_p
, k_mech_type
, basekey_p
,
2382 crypto_derive_key_t obj_dk
;
2384 rv
= process_object_attributes(pTemplate
, ulAttributeCount
,
2385 &obj_dk
.dk_attributes
, &is_token_obj
);
2390 /* Cannot create a token object with a READ-ONLY session. */
2391 if (is_token_obj
&& session_p
->ses_RO
) {
2392 free_object_attributes(obj_dk
.dk_attributes
,
2394 rv
= CKR_SESSION_READ_ONLY
;
2398 obj_dk
.dk_session
= session_p
->k_session
;
2399 obj_dk
.dk_mechanism
.cm_type
= k_mech_type
;
2400 obj_dk
.dk_mechanism
.cm_param
= pMechanism
->pParameter
;
2401 obj_dk
.dk_mechanism
.cm_param_len
= pMechanism
->ulParameterLen
;
2402 obj_dk
.dk_base_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
2403 obj_dk
.dk_base_key
.ck_obj_id
= basekey_p
->k_handle
;
2404 obj_dk
.dk_count
= ulAttributeCount
;
2406 while ((r
= ioctl(kernel_fd
, CRYPTO_DERIVE_KEY
, &obj_dk
)) < 0) {
2411 rv
= CKR_FUNCTION_FAILED
;
2413 rv
= crypto2pkcs11_error_number(obj_dk
.dk_return_value
);
2416 free_object_attributes(obj_dk
.dk_attributes
, ulAttributeCount
);
2421 /* Get the CKA_PRIVATE value for the derived key. */
2422 rv
= get_cka_private_value(session_p
, obj_dk
.dk_object_handle
,
2429 * Store the kernel object handle into the new derived key
2430 * object and finish the object initialization.
2432 new_objp
->is_lib_obj
= B_FALSE
;
2433 new_objp
->k_handle
= obj_dk
.dk_object_handle
;
2434 new_objp
->session_handle
= (CK_SESSION_HANDLE
)session_p
;
2435 new_objp
->extra_attrlistp
= NULL
;
2438 new_objp
->bool_attr_mask
|= PRIVATE_BOOL_ON
;
2440 new_objp
->bool_attr_mask
&= ~PRIVATE_BOOL_ON
;
2443 new_objp
->bool_attr_mask
|= TOKEN_BOOL_ON
;
2445 new_objp
->bool_attr_mask
&= ~TOKEN_BOOL_ON
;
2447 (void) pthread_mutex_init(&new_objp
->object_mutex
, NULL
);
2448 new_objp
->magic_marker
= KERNELTOKEN_OBJECT_MAGIC
;
2451 * Add the new derived object to the slot's token list if it is a
2452 * token object. Otherwise, add it to the session's object list.
2455 pslot
= slot_table
[session_p
->ses_slotid
];
2456 kernel_add_token_object_to_slot(new_objp
, pslot
);
2458 kernel_add_object_to_session(new_objp
, session_p
);
2461 *phKey
= (CK_OBJECT_HANDLE
)new_objp
;
2462 OBJ_REFRELE(basekey_p
);
2463 REFRELE(session_p
, ses_lock_held
);
2467 OBJ_REFRELE(basekey_p
);
2468 if (new_objp
!= NULL
) {
2469 (void) free(new_objp
);
2472 REFRELE(session_p
, ses_lock_held
);