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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 #include <security/cryptoki.h>
29 #include <sys/crypto/ioctl.h>
30 #include "kernelGlobal.h"
31 #include "kernelObject.h"
32 #include "kernelSession.h"
33 #include "kernelEmulate.h"
36 C_SignInit(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
37 CK_OBJECT_HANDLE hKey
)
40 kernel_session_t
*session_p
;
41 kernel_object_t
*key_p
;
42 boolean_t ses_lock_held
= B_FALSE
;
43 crypto_sign_init_t sign_init
;
44 crypto_mech_type_t k_mech_type
;
47 if (!kernel_initialized
)
48 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
50 if (pMechanism
== NULL
) {
51 return (CKR_ARGUMENTS_BAD
);
54 /* Get the kernel's internal mechanism number. */
55 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
60 /* Obtain the session pointer. */
61 rv
= handle2session(hSession
, &session_p
);
65 /* Obtain the object pointer. */
66 HANDLE2OBJECT(hKey
, key_p
, rv
);
68 REFRELE(session_p
, ses_lock_held
);
72 /* Check to see if key object supports signature. */
73 if (key_p
->is_lib_obj
&& !(key_p
->bool_attr_mask
& SIGN_BOOL_ON
)) {
74 rv
= CKR_KEY_TYPE_INCONSISTENT
;
78 (void) pthread_mutex_lock(&session_p
->session_mutex
);
79 ses_lock_held
= B_TRUE
;
82 * This active flag will remain ON until application calls either
83 * C_Sign or C_SignFinal to actually obtain the signature.
85 session_p
->sign
.flags
= CRYPTO_OPERATION_ACTIVE
;
86 sign_init
.si_session
= session_p
->k_session
;
87 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
88 ses_lock_held
= B_FALSE
;
90 if (!key_p
->is_lib_obj
) {
91 sign_init
.si_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
92 sign_init
.si_key
.ck_obj_id
= key_p
->k_handle
;
94 if (key_p
->class == CKO_SECRET_KEY
) {
95 sign_init
.si_key
.ck_format
= CRYPTO_KEY_RAW
;
96 sign_init
.si_key
.ck_data
=
97 get_symmetric_key_value(key_p
);
98 if (sign_init
.si_key
.ck_data
== NULL
) {
102 sign_init
.si_key
.ck_length
=
103 OBJ_SEC(key_p
)->sk_value_len
<< 3;
105 } else if (key_p
->key_type
== CKK_RSA
) {
106 rv
= get_rsa_private_key(key_p
, &sign_init
.si_key
);
110 } else if (key_p
->key_type
== CKK_DSA
) {
111 rv
= get_dsa_private_key(key_p
, &sign_init
.si_key
);
115 } else if (key_p
->key_type
== CKK_EC
) {
116 rv
= get_ec_private_key(key_p
, &sign_init
.si_key
);
121 rv
= CKR_KEY_TYPE_INCONSISTENT
;
126 sign_init
.si_mech
.cm_type
= k_mech_type
;
127 sign_init
.si_mech
.cm_param
= pMechanism
->pParameter
;
128 sign_init
.si_mech
.cm_param_len
= pMechanism
->ulParameterLen
;
130 while ((r
= ioctl(kernel_fd
, CRYPTO_SIGN_INIT
, &sign_init
)) < 0) {
135 rv
= CKR_FUNCTION_FAILED
;
137 rv
= crypto2pkcs11_error_number(sign_init
.si_return_value
);
140 if (rv
== CKR_OK
&& SLOT_HAS_LIMITED_HMAC(session_p
) &&
141 is_hmac(pMechanism
->mechanism
)) {
142 if (key_p
->is_lib_obj
&& key_p
->class == CKO_SECRET_KEY
) {
143 (void) pthread_mutex_lock(&session_p
->session_mutex
);
144 session_p
->sign
.flags
|= CRYPTO_EMULATE
;
145 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
146 rv
= emulate_init(session_p
, pMechanism
,
147 &(sign_init
.si_key
), OP_SIGN
);
149 rv
= CKR_ARGUMENTS_BAD
;
153 if (key_p
->is_lib_obj
) {
154 if (key_p
->class == CKO_SECRET_KEY
) {
155 free(sign_init
.si_key
.ck_data
);
157 free_key_attributes(&sign_init
.si_key
);
162 (void) pthread_mutex_lock(&session_p
->session_mutex
);
163 session_p
->sign
.flags
&= ~CRYPTO_OPERATION_ACTIVE
;
164 ses_lock_held
= B_TRUE
;
169 REFRELE(session_p
, ses_lock_held
);
175 C_Sign(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pData
, CK_ULONG ulDataLen
,
176 CK_BYTE_PTR pSignature
, CK_ULONG_PTR pulSignatureLen
)
180 kernel_session_t
*session_p
;
181 boolean_t ses_lock_held
= B_FALSE
;
185 if (!kernel_initialized
)
186 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
188 /* Obtain the session pointer */
189 rv
= handle2session(hSession
, &session_p
);
193 if (pulSignatureLen
== NULL
) {
194 rv
= CKR_ARGUMENTS_BAD
;
198 (void) pthread_mutex_lock(&session_p
->session_mutex
);
199 ses_lock_held
= B_TRUE
;
201 /* Application must call C_SignInit before calling C_Sign. */
202 if (!(session_p
->sign
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
203 REFRELE(session_p
, ses_lock_held
);
204 return (CKR_OPERATION_NOT_INITIALIZED
);
208 * C_Sign must be called without intervening C_SignUpdate
211 if (session_p
->sign
.flags
& CRYPTO_OPERATION_UPDATE
) {
213 * C_Sign can not be used to terminate a multi-part
214 * operation, so we'll leave the active sign operation
215 * flag on and let the application continue with the
216 * sign update operation.
218 REFRELE(session_p
, ses_lock_held
);
219 return (CKR_FUNCTION_FAILED
);
222 if (session_p
->sign
.flags
& CRYPTO_EMULATE
) {
223 if ((ulDataLen
< SLOT_THRESHOLD(session_p
)) ||
224 (ulDataLen
> SLOT_HMAC_MAX_INDATA_LEN(session_p
))) {
225 session_p
->sign
.flags
|= CRYPTO_EMULATE_USING_SW
;
226 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
227 ses_lock_held
= B_FALSE
;
229 rv
= do_soft_hmac_sign(get_spp(&session_p
->sign
),
231 pSignature
, pulSignatureLen
, OP_SINGLE
);
234 free_soft_ctx(get_sp(&session_p
->sign
), OP_SIGN
);
238 sign
.cs_session
= session_p
->k_session
;
239 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
240 ses_lock_held
= B_FALSE
;
242 sign
.cs_datalen
= ulDataLen
;
243 sign
.cs_databuf
= (char *)pData
;
244 sign
.cs_signlen
= *pulSignatureLen
;
245 sign
.cs_signbuf
= (char *)pSignature
;
247 while ((r
= ioctl(kernel_fd
, CRYPTO_SIGN
, &sign
)) < 0) {
252 rv
= CKR_FUNCTION_FAILED
;
254 rv
= crypto2pkcs11_error_number(sign
.cs_return_value
);
257 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
258 *pulSignatureLen
= sign
.cs_signlen
;
261 if ((rv
== CKR_BUFFER_TOO_SMALL
) ||
262 (rv
== CKR_OK
&& pSignature
== NULL
)) {
264 * We will not terminate the active sign operation flag,
265 * when the application-supplied buffer is too small, or
266 * the application asks for the length of buffer to hold
269 REFRELE(session_p
, ses_lock_held
);
275 * Terminates the active sign operation.
276 * Application needs to call C_SignInit again for next
279 (void) pthread_mutex_lock(&session_p
->session_mutex
);
280 ses_lock_held
= B_TRUE
;
282 REINIT_OPBUF(&session_p
->sign
);
283 session_p
->sign
.flags
= 0;
284 REFRELE(session_p
, ses_lock_held
);
291 C_SignUpdate(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pPart
,
296 kernel_session_t
*session_p
;
297 boolean_t ses_lock_held
= B_FALSE
;
298 crypto_sign_update_t sign_update
;
301 if (!kernel_initialized
)
302 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
304 /* Obtain the session pointer */
305 rv
= handle2session(hSession
, &session_p
);
310 rv
= CKR_ARGUMENTS_BAD
;
314 (void) pthread_mutex_lock(&session_p
->session_mutex
);
315 ses_lock_held
= B_TRUE
;
318 * Application must call C_SignInit before calling
321 if (!(session_p
->sign
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
322 REFRELE(session_p
, ses_lock_held
);
323 return (CKR_OPERATION_NOT_INITIALIZED
);
326 session_p
->sign
.flags
|= CRYPTO_OPERATION_UPDATE
;
328 if (session_p
->sign
.flags
& CRYPTO_EMULATE
) {
329 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
330 ses_lock_held
= B_FALSE
;
331 rv
= emulate_update(session_p
, pPart
, ulPartLen
, OP_SIGN
);
335 sign_update
.su_session
= session_p
->k_session
;
336 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
337 ses_lock_held
= B_FALSE
;
339 sign_update
.su_datalen
= ulPartLen
;
340 sign_update
.su_databuf
= (char *)pPart
;
342 while ((r
= ioctl(kernel_fd
, CRYPTO_SIGN_UPDATE
, &sign_update
)) < 0) {
347 rv
= CKR_FUNCTION_FAILED
;
349 rv
= crypto2pkcs11_error_number(sign_update
.su_return_value
);
354 REFRELE(session_p
, ses_lock_held
);
360 * After an error occurred, terminate the current sign
361 * operation by resetting the active and update flags.
363 (void) pthread_mutex_lock(&session_p
->session_mutex
);
364 ses_lock_held
= B_TRUE
;
365 REINIT_OPBUF(&session_p
->sign
);
366 session_p
->sign
.flags
= 0;
367 REFRELE(session_p
, ses_lock_held
);
374 C_SignFinal(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pSignature
,
375 CK_ULONG_PTR pulSignatureLen
)
379 kernel_session_t
*session_p
;
380 boolean_t ses_lock_held
= B_FALSE
;
381 crypto_sign_final_t sign_final
;
384 if (!kernel_initialized
)
385 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
387 /* Obtain the session pointer */
388 rv
= handle2session(hSession
, &session_p
);
392 if (pulSignatureLen
== NULL
) {
393 rv
= CKR_ARGUMENTS_BAD
;
397 (void) pthread_mutex_lock(&session_p
->session_mutex
);
398 ses_lock_held
= B_TRUE
;
401 * Application must call C_SignInit before calling
404 if (!(session_p
->sign
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
405 REFRELE(session_p
, ses_lock_held
);
406 return (CKR_OPERATION_NOT_INITIALIZED
);
409 /* The order of checks is important here */
410 if (session_p
->sign
.flags
& CRYPTO_EMULATE_USING_SW
) {
411 if (session_p
->sign
.flags
& CRYPTO_EMULATE_UPDATE_DONE
) {
412 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
413 ses_lock_held
= B_FALSE
;
414 rv
= do_soft_hmac_sign(get_spp(&session_p
->sign
),
415 NULL
, 0, pSignature
, pulSignatureLen
, OP_FINAL
);
418 * We end up here if an earlier C_SignFinal() call
419 * took the C_Sign() path and it had returned
420 * CKR_BUFFER_TOO_SMALL.
422 digest_buf_t
*bufp
= session_p
->sign
.context
;
423 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
424 ses_lock_held
= B_FALSE
;
425 if (bufp
== NULL
|| bufp
->buf
== NULL
) {
426 rv
= CKR_ARGUMENTS_BAD
;
429 rv
= do_soft_hmac_sign(get_spp(&session_p
->sign
),
430 bufp
->buf
, bufp
->indata_len
,
431 pSignature
, pulSignatureLen
, OP_SINGLE
);
434 } else if (session_p
->sign
.flags
& CRYPTO_EMULATE
) {
435 digest_buf_t
*bufp
= session_p
->sign
.context
;
438 * We are emulating a single-part operation now.
439 * So, clear the flag.
441 session_p
->sign
.flags
&= ~CRYPTO_OPERATION_UPDATE
;
442 if (bufp
== NULL
|| bufp
->buf
== NULL
) {
443 rv
= CKR_ARGUMENTS_BAD
;
446 REFRELE(session_p
, ses_lock_held
);
447 rv
= C_Sign(hSession
, bufp
->buf
, bufp
->indata_len
,
448 pSignature
, pulSignatureLen
);
452 sign_final
.sf_session
= session_p
->k_session
;
453 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
454 ses_lock_held
= B_FALSE
;
456 sign_final
.sf_signlen
= *pulSignatureLen
;
457 sign_final
.sf_signbuf
= (char *)pSignature
;
459 while ((r
= ioctl(kernel_fd
, CRYPTO_SIGN_FINAL
, &sign_final
)) < 0) {
464 rv
= CKR_FUNCTION_FAILED
;
466 rv
= crypto2pkcs11_error_number(sign_final
.sf_return_value
);
469 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
470 *pulSignatureLen
= sign_final
.sf_signlen
;
473 if ((rv
== CKR_BUFFER_TOO_SMALL
) ||
474 (rv
== CKR_OK
&& pSignature
== NULL
)) {
476 * We will not terminate the active sign operation flag,
477 * when the application-supplied buffer is too small, or
478 * the application asks for the length of buffer to hold
481 REFRELE(session_p
, ses_lock_held
);
486 /* Terminates the active sign operation */
487 (void) pthread_mutex_lock(&session_p
->session_mutex
);
488 ses_lock_held
= B_TRUE
;
489 REINIT_OPBUF(&session_p
->sign
);
490 session_p
->sign
.flags
= 0;
491 REFRELE(session_p
, ses_lock_held
);
498 C_SignRecoverInit(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
499 CK_OBJECT_HANDLE hKey
)
503 kernel_session_t
*session_p
;
504 kernel_object_t
*key_p
;
505 boolean_t ses_lock_held
= B_FALSE
;
506 crypto_sign_recover_init_t sr_init
;
507 crypto_mech_type_t k_mech_type
;
510 if (!kernel_initialized
)
511 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
513 if (pMechanism
== NULL
) {
514 return (CKR_ARGUMENTS_BAD
);
517 /* Get the kernel's internal mechanism number. */
518 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
522 /* Obtain the session pointer. */
523 rv
= handle2session(hSession
, &session_p
);
527 /* Obtain the object pointer. */
528 HANDLE2OBJECT(hKey
, key_p
, rv
);
530 REFRELE(session_p
, ses_lock_held
);
535 * Check to see if key object is a RSA key and if it supports
538 if (key_p
->is_lib_obj
&& !((key_p
->key_type
== CKK_RSA
) &&
539 (key_p
->bool_attr_mask
& SIGN_RECOVER_BOOL_ON
))) {
540 rv
= CKR_KEY_TYPE_INCONSISTENT
;
544 (void) pthread_mutex_lock(&session_p
->session_mutex
);
545 ses_lock_held
= B_TRUE
;
548 * This active flag will remain ON until application calls
549 * C_SignRecover to actually obtain the signature.
551 session_p
->sign
.flags
= CRYPTO_OPERATION_ACTIVE
;
553 /* Set up the key data */
554 if (!key_p
->is_lib_obj
) {
555 sr_init
.ri_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
556 sr_init
.ri_key
.ck_obj_id
= key_p
->k_handle
;
558 if (key_p
->key_type
== CKK_RSA
) {
559 if (get_rsa_private_key(key_p
, &sr_init
.ri_key
) !=
561 rv
= CKR_HOST_MEMORY
;
565 rv
= CKR_KEY_TYPE_INCONSISTENT
;
570 sr_init
.ri_session
= session_p
->k_session
;
571 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
572 ses_lock_held
= B_FALSE
;
573 sr_init
.ri_mech
.cm_type
= k_mech_type
;
574 sr_init
.ri_mech
.cm_param
= pMechanism
->pParameter
;
575 sr_init
.ri_mech
.cm_param_len
= pMechanism
->ulParameterLen
;
577 while ((r
= ioctl(kernel_fd
, CRYPTO_SIGN_RECOVER_INIT
, &sr_init
)) < 0) {
582 rv
= CKR_FUNCTION_FAILED
;
584 rv
= crypto2pkcs11_error_number(sr_init
.ri_return_value
);
587 if (key_p
->is_lib_obj
) {
588 free_key_attributes(&sr_init
.ri_key
);
592 (void) pthread_mutex_lock(&session_p
->session_mutex
);
593 session_p
->sign
.flags
&= ~CRYPTO_OPERATION_ACTIVE
;
594 ses_lock_held
= B_TRUE
;
599 REFRELE(session_p
, ses_lock_held
);
605 C_SignRecover(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pData
,
606 CK_ULONG ulDataLen
, CK_BYTE_PTR pSignature
, CK_ULONG_PTR pulSignatureLen
)
610 kernel_session_t
*session_p
;
611 boolean_t ses_lock_held
= B_FALSE
;
612 crypto_sign_recover_t sign_recover
;
615 if (!kernel_initialized
)
616 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
618 /* Obatin the session pointer */
619 rv
= handle2session(hSession
, &session_p
);
623 if (pulSignatureLen
== NULL
) {
624 rv
= CKR_ARGUMENTS_BAD
;
628 (void) pthread_mutex_lock(&session_p
->session_mutex
);
629 ses_lock_held
= B_TRUE
;
631 /* Application must call C_SignInit before calling C_Sign. */
632 if (!(session_p
->sign
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
633 REFRELE(session_p
, ses_lock_held
);
634 return (CKR_OPERATION_NOT_INITIALIZED
);
637 sign_recover
.sr_session
= session_p
->k_session
;
638 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
639 ses_lock_held
= B_FALSE
;
641 sign_recover
.sr_datalen
= ulDataLen
;
642 sign_recover
.sr_databuf
= (char *)pData
;
643 sign_recover
.sr_signlen
= *pulSignatureLen
;
644 sign_recover
.sr_signbuf
= (char *)pSignature
;
646 while ((r
= ioctl(kernel_fd
, CRYPTO_SIGN_RECOVER
, &sign_recover
)) < 0) {
651 rv
= CKR_FUNCTION_FAILED
;
653 rv
= crypto2pkcs11_error_number(sign_recover
.sr_return_value
);
656 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
657 *pulSignatureLen
= sign_recover
.sr_signlen
;
659 if ((rv
== CKR_BUFFER_TOO_SMALL
) ||
660 (rv
== CKR_OK
&& pSignature
== NULL
)) {
662 * We will not terminate the active sign operation flag,
663 * when the application-supplied buffer is too small, or
664 * the application asks for the length of buffer to hold
667 REFRELE(session_p
, ses_lock_held
);
673 * Terminates the active sign operation.
674 * Application needs to call C_SignInit again for next
677 (void) pthread_mutex_lock(&session_p
->session_mutex
);
678 ses_lock_held
= B_TRUE
;
679 session_p
->sign
.flags
= 0;
680 REFRELE(session_p
, ses_lock_held
);